From dfdb11cce654a48daed91ddf09135e0fbb2c3fef Mon Sep 17 00:00:00 2001 From: Juergen Hasch Date: Fri, 1 Aug 2014 23:19:17 +0200 Subject: [PATCH] Use contents service Use new contents service to upload graphics, replacing the separate websocket server. --- usability/chrome_clipboard.js | 239 ++++++------- usability/dragdrop/50-start-drag-and-drop.ipy | 14 - usability/dragdrop/drag-and-drop.js | 328 ++++++++---------- usability/dragdrop/drag-and-drop.py | 164 --------- usability/dragdrop/drag_and_drop.py | 147 -------- 5 files changed, 267 insertions(+), 625 deletions(-) delete mode 100644 usability/dragdrop/50-start-drag-and-drop.ipy delete mode 100644 usability/dragdrop/drag-and-drop.py delete mode 100644 usability/dragdrop/drag_and_drop.py diff --git a/usability/chrome_clipboard.js b/usability/chrome_clipboard.js index 78ad42a..7eb3a75 100644 --- a/usability/chrome_clipboard.js +++ b/usability/chrome_clipboard.js @@ -2,137 +2,126 @@ // works with images and notebook cells (MIME-type 'notebook-cell/json') "using strict"; +define( function () { + var load_ipython_extension = function () { + if (window.chrome == undefined) return; -chrome_clipboard = function() { + /* http://stackoverflow.com/questions/3231459/create-unique-id-with-javascript */ + function uniqueid(){ + // always start with a letter (for DOM friendlyness) + var idstr=String.fromCharCode(Math.floor((Math.random()*25)+65)); + do { + // between numbers and characters (48 is 0 and 90 is Z (42-48 = 90) + var ascicode=Math.floor((Math.random()*42)+48); + if (ascicode<58 || ascicode>64){ + // exclude all chars between : (58) and @ (64) + idstr+=String.fromCharCode(ascicode); + } + } while (idstr.length<32); - if (window.chrome == undefined) return; - - /* http://stackoverflow.com/questions/3231459/create-unique-id-with-javascript */ - function uniqueid(){ - // always start with a letter (for DOM friendlyness) - var idstr=String.fromCharCode(Math.floor((Math.random()*25)+65)); - do { - // between numbers and characters (48 is 0 and 90 is Z (42-48 = 90) - var ascicode=Math.floor((Math.random()*42)+48); - if (ascicode<58 || ascicode>64){ - // exclude all chars between : (58) and @ (64) - idstr+=String.fromCharCode(ascicode); - } - } while (idstr.length<32); - - return (idstr); - } - - /* receive url of graphics from websocket */ - dragdrop_event = function(evt){ - console.log("Websock-Event:", evt); - var obj = $.parseJSON(evt.data); - if (obj.status == "OK") { - var new_cell = IPython.notebook.insert_cell_below('markdown'); - var filename = obj.name; - var str = ''; - new_cell.set_text(str); - new_cell.rendered = false; - new_cell.render(); + return (idstr); } - } - - /* - * override clipboard 'paste' and insert new cell from json data in clipboard - */ - window.addEventListener('paste', function(event){ - var cell = IPython.notebook.get_selected_cell(); - if (cell.mode == "command" ) { - event.preventDefault(); - var items = event.clipboardData.items; - for (var i = 0; i < items.length; i++) { - console.log("items:", items[i].type); - if (items[i].type == 'notebook-cell/json') { - /* json data adds a new notebook cell */ - var data = event.clipboardData.getData('notebook-cell/json'); - var new_cell_data = JSON.parse(data); - var new_cell = IPython.notebook.insert_cell_below(new_cell_data.cell_type); - new_cell.fromJSON(new_cell_data); - } else if (items[i].type.indexOf('image/') !== -1) { - /* images are transferred to the server as file and linked to */ - var blob = items[i].getAsFile(); - var reader = new FileReader(); - reader.onload = ( function(evt) { - var filename = uniqueid(); - var msg = JSON.stringify({"type":"file", - "name":filename, - "path":IPython.notebook.notebook_path, - "url" : "", - "data": evt.target.result}); - IPython.notebook.ws_dragdrop.send(msg); - event.preventDefault(); - } ); - reader.readAsDataURL(blob); + + send_to_server = function(name,path,msg) { + if (name == '') { + name = uniqueid() + '.' + msg.match(/data:image\/(\S+);/)[1]; + } + var url = 'http://' + location.host + '/api/contents/' + path + '/' + name; + var img = msg.replace(/(^\S+,)/, ''); // strip header +// console.log("send_to_server:", url, msg); + data = {'name': name, 'format':'base64', 'content': img, 'type': 'file'} + var settings = { + processData : false, + cache : false, + type : "PUT", + dataType : "json", + data : JSON.stringify(data), + headers : {'Content-Type': 'text/plain'}, + async : false, + success : function (data, status, xhr) { + var new_cell = IPython.notebook.insert_cell_below('markdown'); + var str = ''; + new_cell.set_text(str); + new_cell.execute(); + //new_cell.select(); + }, + error : function() {console.log('fail'); }, + }; + $.ajax(url, settings); + } + /* + * override clipboard 'paste' and insert new cell from json data in clipboard + */ + window.addEventListener('paste', function(event){ + var cell = IPython.notebook.get_selected_cell(); + if (cell.mode == "command" ) { + event.preventDefault(); + var items = event.clipboardData.items; + for (var i = 0; i < items.length; i++) { + console.log("items:", items[i].type); + if (items[i].type == 'notebook-cell/json') { + /* json data adds a new notebook cell */ + var data = event.clipboardData.getData('notebook-cell/json'); + var new_cell_data = JSON.parse(data); + var new_cell = IPython.notebook.insert_cell_below(new_cell_data.cell_type); + new_cell.fromJSON(new_cell_data); + } else if (items[i].type.indexOf('image/') !== -1) { + /* images are transferred to the server as file and linked to */ + var blob = items[i].getAsFile(); + var reader = new FileReader(); + reader.onload = ( function(evt) { + var filename = ''; + send_to_server(filename, IPython.notebook.notebook_path, evt.target.result); + event.preventDefault(); + } ); + reader.readAsDataURL(blob); + } } } - } - }); + }); - /* - * override clipboard 'copy' and copy current cell as json and text to clipboard - */ - window.addEventListener('copy', function(event){ - - var cell = IPython.notebook.get_selected_cell(); - if (cell.mode == "command") { - var sel = window.getSelection(); - if (sel.type == "Range") return; /* default: copy marked text */ - event.preventDefault(); - var j = cell.toJSON(); - var json = JSON.stringify(j); - var text = cell.code_mirror.getValue(); - /* copy cell as json and cell contents as text */ - event.clipboardData.setData('notebook-cell/json',json); - event.clipboardData.setData("Text", text); - } - }); + /* + * override clipboard 'copy' and copy current cell as json and text to clipboard + */ + window.addEventListener('copy', function(event){ + + var cell = IPython.notebook.get_selected_cell(); + if (cell.mode == "command") { + var sel = window.getSelection(); + if (sel.type == "Range") return; /* default: copy marked text */ + event.preventDefault(); + var j = cell.toJSON(); + var json = JSON.stringify(j); + var text = cell.code_mirror.getValue(); + /* copy cell as json and cell contents as text */ + event.clipboardData.setData('notebook-cell/json',json); + event.clipboardData.setData("Text", text); + } + }); - /* - * override clipboard 'cut' and copy current cell as json and text to clipboard - */ - window.addEventListener('cut', function(event){ - - var cell = IPython.notebook.get_selected_cell(); - if (cell.mode == "command" ) { - var sel = window.getSelection(); - if (sel.type == "Range") return; /* default: cut marked text */ - event.preventDefault(); - var j = cell.toJSON(); - var json = JSON.stringify(j); - var text = cell.code_mirror.getValue(); - /* copy cell as json and cell contents as text */ - event.clipboardData.setData('notebook-cell/json',json); - event.clipboardData.setData("Text", text); - IPython.notebook.delete_cell(IPython.notebook.find_cell_index(cell)); - } - }); + /* + * override clipboard 'cut' and copy current cell as json and text to clipboard + */ + window.addEventListener('cut', function(event){ + + var cell = IPython.notebook.get_selected_cell(); + if (cell.mode == "command" ) { + var sel = window.getSelection(); + if (sel.type == "Range") return; /* default: cut marked text */ + event.preventDefault(); + var j = cell.toJSON(); + var json = JSON.stringify(j); + var text = cell.code_mirror.getValue(); + /* copy cell as json and cell contents as text */ + event.clipboardData.setData('notebook-cell/json',json); + event.clipboardData.setData("Text", text); + IPython.notebook.delete_cell(IPython.notebook.find_cell_index(cell)); + } + }); + }; - function callback(out_data) - { - var ul = out_data.content.data; - var webport = eval(ul['text/plain']) - console.log("webport:",webport); - var wsUri = "ws://" + document.domain + ":" + webport + "/"+ "websocket"; - var ws_dragdrop = new WebSocket(wsUri); - IPython.notebook.ws_dragdrop = ws_dragdrop; - ws_dragdrop.onmessage = dragdrop_event; - } + return { + load_ipython_extension : load_ipython_extension, + }; +}); - function getport() - { - var code = 'drag_and_drop_webport'; - var callbacks = { iopub : { output: callback } }; - - IPython.notebook.kernel.execute(code, callbacks, {silent: false}); - } - - - $([IPython.events]).on('create.Cell',create_cell); - $([IPython.events]).on('status_started.Kernel',function() { getport();}); - -}(); diff --git a/usability/dragdrop/50-start-drag-and-drop.ipy b/usability/dragdrop/50-start-drag-and-drop.ipy deleted file mode 100644 index 7125f6b..0000000 --- a/usability/dragdrop/50-start-drag-and-drop.ipy +++ /dev/null @@ -1,14 +0,0 @@ -# start websocket server for drag-and-drop extension - -drag_and_drop_webport = get_ipython().config['DragDrop']['port'] - -def start_drag_and_drop(): - c = get_ipython() - nb_dir = get_ipython().config['FileNotebookManager']['notebook_dir'] - newpath = os.path.normpath(c.config['NotebookApp']['extra_static_paths'][0]+'/custom/dragdrop/') - sys.path.insert(0, newpath) - - import drag_and_drop - drag_and_drop.start_server(drag_and_drop_webport, nb_dir) - -start_drag_and_drop() diff --git a/usability/dragdrop/drag-and-drop.js b/usability/dragdrop/drag-and-drop.js index 2a64487..70a0dbc 100644 --- a/usability/dragdrop/drag-and-drop.js +++ b/usability/dragdrop/drag-and-drop.js @@ -1,80 +1,108 @@ -// add drag&drop functionality +// Allow drag&drop of images into a notebook // Tested with Firefox and Chrome - "using strict"; +define( function () { + var load_ipython_extension = function () { -drag_and_drop = function() { - - - /* http://stackoverflow.com/questions/3231459/create-unique-id-with-javascript */ - function uniqueid(){ - // always start with a letter (for DOM friendlyness) - var idstr=String.fromCharCode(Math.floor((Math.random()*25)+65)); - do { - // between numbers and characters (48 is 0 and 90 is Z (42-48 = 90) - var ascicode=Math.floor((Math.random()*42)+48); - if (ascicode<58 || ascicode>64){ - // exclude all chars between : (58) and @ (64) - idstr+=String.fromCharCode(ascicode); - } - } while (idstr.length<32); + /* http://stackoverflow.com/questions/3231459/create-unique-id-with-javascript */ + function uniqueid(){ + // always start with a letter (for DOM friendlyness) + var idstr=String.fromCharCode(Math.floor((Math.random()*25)+65)); + do { + // between numbers and characters (48 is 0 and 90 is Z (42-48 = 90) + var ascicode=Math.floor((Math.random()*42)+48); + if (ascicode<58 || ascicode>64){ + // exclude all chars between : (58) and @ (64) + idstr+=String.fromCharCode(ascicode); + } + } while (idstr.length<32); - return (idstr); - } - - /* receive url of graphics from websocket */ - dragdrop_event = function(evt){ - console.log("Websock-Event:", evt); - var obj = $.parseJSON(evt.data); - if (obj.status == "OK") { - var new_cell = IPython.notebook.insert_cell_below('markdown'); - var filename = obj.name; - var str = ''; - new_cell.set_text(str); - new_cell.rendered = false; - new_cell.render(); + return (idstr); } - } - - /* the dragover event needs to be canceled to allow firing the drop event */ - window.addEventListener('dragover', function(event){ - if (event.preventDefault) { event.preventDefault(); }; - }); - - /* allow dropping an image in notebook */ - window.addEventListener('drop', function(event){ - if (IPython.notebook.mode === "edit") return; -// console.log("drop event x:",event); - var cell = IPython.notebook.get_selected_cell(); - event.preventDefault(); - if(event.stopPropagation) {event.stopPropagation();} - if (event.dataTransfer.items != undefined) { - /* Chrome here */ - var items = event.dataTransfer.items; - for (var i = 0; i < items.length; i++) { - /* data coming from local file system, must be an image to allow dropping*/ - if (items[i].kind == 'file' && items[i].type.indexOf('image/') !== -1) { - var blob = items[i].getAsFile(); - var filename = blob.name; - var reader = new FileReader(); - reader.onload = ( function(evt) { - console.log("name:",filename) - var msg = JSON.stringify({"type":"file", - "name":filename, - "path":IPython.notebook.notebook_path, - "url" : "", - "data": evt.target.result}); - IPython.notebook.ws_dragdrop.send(msg); - event.preventDefault(); + + send_to_server = function(name,path,msg) { + if (name == '') { + name = uniqueid() + '.' + msg.match(/data:image\/(\S+);/)[1]; + } + var url = 'http://' + location.host + '/api/contents/' + path + '/' + name; + var img = msg.replace(/(^\S+,)/, ''); // strip header + //console.log("send_to_server:", url, img); + data = {'name': name, 'format':'base64', 'content': img, 'type': 'file'} + var settings = { + processData : false, + cache : false, + type : "PUT", + dataType : "json", + data : JSON.stringify(data), + headers : {'Content-Type': 'text/plain'}, + async : false, + success : function (data, status, xhr) { + var new_cell = IPython.notebook.insert_cell_below('markdown'); + var str = ''; + new_cell.set_text(str); + new_cell.execute(); + //new_cell.select(); + }, + error : function() {console.log('fail'); }, + }; + $.ajax(url, settings); + } + + /* the dragover event needs to be canceled to allow firing the drop event */ + window.addEventListener('dragover', function(event){ + if (event.preventDefault) { event.preventDefault(); }; + }); + + /* allow dropping an image in notebook */ + window.addEventListener('drop', function(event){ + // console.log("drop event x:",event); + var cell = IPython.notebook.get_selected_cell(); + event.preventDefault(); + if(event.stopPropagation) {event.stopPropagation();} + if (event.dataTransfer.items != undefined) { + /* Chrome here */ + var items = event.dataTransfer.items; + for (var i = 0; i < items.length; i++) { + /* data coming from local file system, must be an image to allow dropping*/ + if (items[i].kind == 'file' && items[i].type.indexOf('image/') !== -1) { + var blob = items[i].getAsFile(); + var filename = blob.name; + var reader = new FileReader(); + reader.onload = ( function(evt) { + send_to_server(filename, IPython.notebook.notebook_path, evt.target.result); + event.preventDefault(); } ); - reader.readAsDataURL(blob); - } else if (items[i].kind == 'string') { - /* data coming from browser */ + reader.readAsDataURL(blob); + } else if (items[i].kind == 'string') { + /* data coming from browser */ + var data = event.dataTransfer.getData('text/plain'); + if (data[0] == 'd') { + url = ""; + filename = ''; + } else { + url = data; + data = ""; + } + /* data coming from browser: + * url - image is given as an url + * data - image is a base64 blob + */ + //console.log("file"," name:", filename," path:", IPython.notebook.notebook_path," url:", url); + send_to_server(filename, IPython.notebook.notebook_path, data); + event.preventDefault(); + return; + } + } + } else { + /* Firefox here */ + var files = event.dataTransfer.files; + if (files.length == 0) { + var filename = event.dataTransfer.getData('application/x-moz-file-promise-dest-filename'); var data = event.dataTransfer.getData('text/plain'); - if (data[0] == 'd') { + if (filename.length == 0) { url = ""; - filename = uniqueid(); + filename = ''; } else { url = data; data = ""; @@ -83,116 +111,66 @@ drag_and_drop = function() { * url - image is given as an url * data - image is a base64 blob */ - var msg = JSON.stringify({"type":"url", - "name":filename, - "path":IPython.notebook.notebook_path, - "url" : url, - "data": data}); - IPython.notebook.ws_dragdrop.send(msg); + //console.log("type:",url," name:", filename," path:", IPython.notebook.notebook_path," url:", url); + send_to_server(filename, IPython.notebook.notebook_path, data); event.preventDefault(); return; - } - } - } else { - /* Firefox here */ - var files = event.dataTransfer.files; - if (files.length == 0) { - var filename = event.dataTransfer.getData('application/x-moz-file-promise-dest-filename'); - var data = event.dataTransfer.getData('text/plain'); - if (filename.length == 0) { - url = ""; - filename = uniqueid(); - } else { - url = data; - data = ""; + } + /* data coming from local file system, must be an image to allow dropping*/ + for (var i=0; i < files.length; i++) { + var blob = event.dataTransfer.files[0]; + if (blob.type.indexOf('image/') !== -1) { + var filename = blob.name; + var url = event.view.location.origin; + var reader = new FileReader(); + reader.onload = ( function(evt) { + //console.log("file"," name:", filename," path:", IPython.notebook.notebook_path," url:", url); + send_to_server(filename, IPython.notebook.notebook_path, evt.target.result); + event.preventDefault(); + } ); + reader.readAsDataURL(blob); + } } - /* data coming from browser: - * url - image is given as an url - * data - image is a base64 blob - */ - console.log("type:",url," name:", filename," path:", IPython.notebook.notebook_path," url:", url); - var msg = JSON.stringify({"type":"url", - "name":filename, - "path":IPython.notebook.notebook_path, - "url" : url, - "data": data}); - IPython.notebook.ws_dragdrop.send(msg); - event.preventDefault(); - return; - } - /* data coming from local file system, must be an image to allow dropping*/ - for (var i=0; i < files.length; i++) { - var blob = event.dataTransfer.files[0]; - if (blob.type.indexOf('image/') !== -1) { - var filename = blob.name; - var url = event.view.location.origin; - var reader = new FileReader(); - reader.onload = ( function(evt) { - console.log("file"," name:", filename," path:", IPython.notebook.notebook_path," url:", url); - var msg = JSON.stringify({"type":"file", - "name":filename, - "path":IPython.notebook.notebook_path, - "url" : url, - "data": evt.target.result}); - IPython.notebook.ws_dragdrop.send(msg); - event.preventDefault(); - } ); - reader.readAsDataURL(blob); - } - } - } - }); - - /* - * make sure we do not drop images into a codemirror text field - */ - checktype = function(cm,event) { - if (event.dataTransfer.items != undefined) - { - evt.codemirrorIgnore = true; } - var blob = evt.dataTransfer.files[0]; - - if (blob.type.indexOf('image/') !== -1) { - evt.codemirrorIgnore = true; + }); + + /* + * make sure we do not drop images into a codemirror text field + */ + checktype = function(cm,event) { + if (event.dataTransfer.items != undefined) + { + evt.codemirrorIgnore = true; + } + var blob = evt.dataTransfer.files[0]; + + if (blob.type.indexOf('image/') !== -1) { + evt.codemirrorIgnore = true; + } + } + + create_cell = function (event,nbcell,nbindex) { + var cell = nbcell.cell; + if ((cell instanceof IPython.CodeCell)) { + cell.code_mirror.on('drop', checktype); } - } - - create_cell = function (event,nbcell,nbindex) { - var cell = nbcell.cell; - if ((cell instanceof IPython.CodeCell)) { - cell.code_mirror.on('drop', checktype); - } - }; - - var cells = IPython.notebook.get_cells(); - for(var i in cells){ - var cell = cells[i]; - if ((cell instanceof IPython.CodeCell)) { - cell.code_mirror.on('drop', checktype); - } - }; - - function callback(out_data) - { - var ul = out_data.content.data; - var webport = eval(ul['text/plain']) - console.log("Graphics webport:",webport); - var wsUri = "ws://" + document.domain + ":" + webport + "/"+ "websocket"; - var ws_dragdrop = new WebSocket(wsUri); - IPython.notebook.ws_dragdrop = ws_dragdrop; - ws_dragdrop.onmessage = dragdrop_event; - } - - function getport() - { - var code = 'drag_and_drop_webport'; - var callbacks = { iopub : { output: callback } }; - - IPython.notebook.kernel.execute(code, callbacks, {silent: false}); - } - + }; - $([IPython.events]).on('create.Cell',create_cell); - $([IPython.events]).on('status_started.Kernel',function() { getport();}); -}(); + var cells = IPython.notebook.get_cells(); + for(var i in cells){ + var cell = cells[i]; + if ((cell instanceof IPython.CodeCell)) { + cell.code_mirror.on('drop', checktype); + } + }; + + $([IPython.events]).on('create.Cell',create_cell); + }; + + return { + load_ipython_extension : load_ipython_extension, + }; +}); + + + diff --git a/usability/dragdrop/drag-and-drop.py b/usability/dragdrop/drag-and-drop.py deleted file mode 100644 index 7eaa2fb..0000000 --- a/usability/dragdrop/drag-and-drop.py +++ /dev/null @@ -1,164 +0,0 @@ -# -*- coding: utf-8 -*- -""" -# Copyright (C) 2013 - -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. - -@author: juhasch -""" - -""" -Tornado web server to - push value received from Pyzmq pull messages - to web browser using a webscocket connection - - Configuration in ipython_notebook_config.py: - c.DragDrop.port = 8901 - -""" - -import time -import os.path -import sys, getopt - -import numpy as np - -import tornado.web -import tornado.websocket -import tornado.ioloop - -import random -import json -import base64 -import hashlib - -from zmq.eventloop import ioloop, zmqstream - -webport = 0 -nb_dir = '' - -GLOBALS={ - 'sockets': [] -} - -# http://stackoverflow.com/questions/273192/check-if-a-directory-exists-and-create-it-if-necessary -def ensure_dir(f): - d = os.path.dirname(f) - if not os.path.exists(d): - os.makedirs(d) - -def md5sum(fname, block_size=2**20): - f = open(fname, 'rb') - md5 = hashlib.md5() - while True: - data = f.read(block_size) - if not data: - break - md5.update(data) - f.close() - return md5.hexdigest() - -class WebSocketHandler(tornado.websocket.WebSocketHandler): - def open(self): - print "open socket" - GLOBALS['sockets'].append(self) - - def on_close(self): - print "on_close" - GLOBALS['sockets'].remove(self) - - def on_message(self, message): - x=json.loads(message) - print "Data received" - url = x['url'] - if len(url) == 0: - print "Base64" - filename = x['name'] - print "Filename: %s" % filename - - path = nb_dir + u'\\' + x['path'] + u'\\images\\' - print "Path: %s" %path - - ensure_dir(path) - png_b64 = x['data'] - data = png_b64.split(',') # [0] is header, [1] b64 data - png = base64.b64decode(data[1]) - print "Filename: %s" % filename - # check if file exists - if os.path.exists(path+filename): - print('File %s already exists') - # compare md5sum - md5_file = md5sum(path+filename) -# print('md5sum of file is %s' % md5_file) - d = hashlib.md5() - d.update(png) - md5_websocket = d.hexdigest() -# print('md5sum of dropped image is is %s' % md5_websocket) - if md5_file != md5_websocket: - i = 0 - while True: - - if not os.path.exists('%s%0d_%s' % (path, i, filename)): - break - filename = '%0d_%s' % (i, filename) - f = open(path+filename, 'wb') - f.write(png) - f.close() - else: - f = open(path+filename, 'wb') - f.write(png) - f.close() - status = "OK" - reply = {"status": status, "name": 'images/' + filename } - self.write_message(reply) - else: - status = "OK" - reply = {"status": status, "name": url } - self.write_message(reply) - -application = tornado.web.Application([ - (r"/websocket", WebSocketHandler), -]) - - -def main(argv): - global webport, nb_dir - #try: - opts, args = getopt.getopt(argv,"hp:d:",["port=","directory="]) - if opts == []: - print 'drag-and-drop.py -p -d ' - sys.exit(2) - - for opt, arg in opts: - if opt == '-h': - print 'drag-and-drop.py -p -d ' - sys.exit() - elif opt in ("-p", "--port"): - webport = int(arg) - elif opt in ("-d", "--directory"): - nb_dir = arg - - - print 'webport is "', webport - print 'notebook directory is "', nb_dir - - if webport < 1000 or webport > 65535: - print('Illegal webport adress %d' % webport) - sys.exit(2) - - if not os.path.exists(nb_dir): - print('Directory %s does not exist' % nb_dir) - sys.exit(2) - - ioloop.install() - try: - application.listen(webport) - except: - print('Port %d already in use!' % webport) - exit() - main_loop = tornado.ioloop.IOLoop.instance() - main_loop.start() - -if __name__ == "__main__": - main(sys.argv[1:]) diff --git a/usability/dragdrop/drag_and_drop.py b/usability/dragdrop/drag_and_drop.py deleted file mode 100644 index c06d146..0000000 --- a/usability/dragdrop/drag_and_drop.py +++ /dev/null @@ -1,147 +0,0 @@ -# -*- coding: utf-8 -*- -""" -# Copyright (C) 2014 -# Distributed under the terms of the BSD License. -""" - -""" -Tornado websocket server to save images received from web browser and reply -with URL of stored image. -This is required for drag&drop of images in the IPython notebook - -The websocket port can be configured in ipython_notebook_config.py: - c.DragDrop.port = 8901 - -""" - -import time -import os.path -import sys, getopt - -import numpy as np - -import tornado.web -import tornado.websocket -import tornado.ioloop - -import random -import json -import base64 -import hashlib -from multiprocessing import Process -from zmq.eventloop import ioloop, zmqstream - -webport = 0 -nb_dir = '' - -GLOBALS={ - 'sockets': [] -} - -# http://stackoverflow.com/questions/273192/check-if-a-directory-exists-and-create-it-if-necessary -def ensure_dir(f): - d = os.path.dirname(f) - if not os.path.exists(d): - os.makedirs(d) - -def md5sum(fname, block_size=2**20): - f = open(fname, 'rb') - md5 = hashlib.md5() - while True: - data = f.read(block_size) - if not data: - break - md5.update(data) - f.close() - return md5.hexdigest() - -class WebSocketHandler(tornado.websocket.WebSocketHandler): - """ Handle websocket connections from web browser - """ - def open(self): - GLOBALS['sockets'].append(self) - - def on_close(self): - GLOBALS['sockets'].remove(self) - - def on_message(self, message): - """ Receive image from web browser - Save it to the local 'images' directory under it's name. - If filename already exists, md5-check if identical, otherwise rename. - If no filename is given, create unique ID. - """ - x=json.loads(message) - url = x['url'] - eventtype = x['type'] - - if eventtype == 'file': - filename = x['name'] - path = nb_dir + u'\\' + x['path'] + u'\\images\\' - ensure_dir(path) - data = x['data'].split(',') # [0] is header, [1] b64 data - png = base64.b64decode(data[1]) - # check if file exists: skip if identical, rename if new - if os.path.exists(path+filename): -# print('File %s already exists' % filename) - # compare md5sum - md5_file = md5sum(path+filename) - d = hashlib.md5() - d.update(png) - md5_websocket = d.hexdigest() - if md5_file != md5_websocket: - i = 0 - while True: - if not os.path.exists('%s%0d_%s' % (path, i, filename)): - break - filename = '%0d_%s' % (i, filename) - f = open(path+filename, 'wb') - f.write(png) - f.close() - else: - f = open(path+filename, 'wb') - f.write(png) - f.close() - status = "OK" - #reply = {"status": status, "name": 'images/' + filename } - # send url instead of file path, otherwise it won't work for nbconvert - url_path = url + '/notebooks' + x['path'] + '/images/' + filename - reply = {"status": status, "name": url_path} - self.write_message(reply) - else: - # just reply already existing url - status = "OK" - reply = {"status": status, "name": url } - self.write_message(reply) - -application = tornado.web.Application([ - (r"/websocket", WebSocketHandler), -]) - - -def websocket_server(webport, nbdir): - global nb_dir - nb_dir = nbdir - ioloop.install() - try: - application.listen(webport) - except: -# print('Port %d already in use!' % webport) - sys.exit(2) - main_loop = tornado.ioloop.IOLoop.instance() - main_loop.start() - - -def start_server(webport,nb_dir): - print('webport is %s' % webport) - print('notebook directory is %s' % nb_dir) - - if webport < 1000 or webport > 65535: - print('Illegal webport adress %d' % webport) - sys.exit(2) - - if not os.path.exists(nb_dir): - print('Directory %s does not exist' % nb_dir) - sys.exit(2) - - p = Process(target=websocket_server, args=(webport,nb_dir)) - p.start()