diff options
author | Gonzalo Odiard <godiard@gmail.com> | 2013-04-04 21:49:25 (GMT) |
---|---|---|
committer | Gonzalo Odiard <godiard@gmail.com> | 2013-04-04 21:49:25 (GMT) |
commit | 4e923a199ff3aea1811b67b4104bcb52fd54004a (patch) | |
tree | 60b2e0e216c56ffaa32388fc9dfd69ad36bc9037 | |
parent | edca72433794bb136771dfecdb75b82051ed7056 (diff) |
Prepare files to be served
As the web ask is tserver can't read the datastore because is in another thread
the activity prepare the files to be served in thier /instance/
directory before the server starts. Later we need implement
updating the files when the selection is changed.
A pending task is test uploading a file from another client.
The JournalManager class was moved from server.py to activity.py
Signed-off-by: Gonzalo Odiard <gonzalo@laptop.org>
-rw-r--r-- | activity.py | 153 | ||||
-rw-r--r-- | server.py | 163 | ||||
-rw-r--r-- | web/index.html | 14 |
3 files changed, 184 insertions, 146 deletions
diff --git a/activity.py b/activity.py index dcbd562..f6d40e6 100644 --- a/activity.py +++ b/activity.py @@ -25,11 +25,17 @@ from gi.repository import WebKit import telepathy import dbus import os.path +import base64 +import json from sugar3.activity import activity from sugar3.activity.widgets import ActivityToolbarButton from sugar3.activity.widgets import StopButton from sugar3.graphics.toolbarbox import ToolbarBox +from sugar3.graphics.toolbutton import ToolButton +from sugar3.datastore import datastore +from sugar3.graphics.xocolor import XoColor +from sugar3 import profile import downloadmanager from filepicker import FilePicker @@ -41,19 +47,27 @@ JOURNAL_STREAM_SERVICE = 'journal-activity-http' # named after our pid, to inhibit suspend. POWERD_INHIBIT_DIR = '/var/run/powerd-inhibit-suspend' + class JournalShare(activity.Activity): def __init__(self, handle): activity.Activity.__init__(self, handle) + # a list with the object_id of the shared items. + # if is a only element == '*' means all the favorite items + # are selected + self._shared_items = [] + self._activity_path = activity.get_bundle_path() + self._activity_root = activity.get_activity_root() + self._jm = JournalManager(self._activity_root) + self.server_proc = None self.port = 2500 if not self.shared_activity: - activity_path = activity.get_bundle_path() - activity_root = activity.get_activity_root() #TODO: check available port - server.run_server(activity_path, activity_root, self.port) + server.run_server(self._activity_path, self._activity_root, + self._jm, self.port) toolbar_box = ToolbarBox() @@ -61,6 +75,19 @@ class JournalShare(activity.Activity): toolbar_box.toolbar.insert(activity_button, 0) activity_button.show() + add_button = ToolButton('list-add') + add_button.set_tooltip(_('Add item to share')) + add_button.show() + add_button.connect('clicked', self.__add_clicked_cb) + toolbar_box.toolbar.insert(add_button, -1) + + add_favorites_button = ToolButton('list-add') + add_favorites_button.set_tooltip(_('Add favorite items to share')) + add_favorites_button.show() + add_favorites_button.connect('clicked', + self.__add_favorites_clicked_cb) + toolbar_box.toolbar.insert(add_favorites_button, -1) + separator = Gtk.SeparatorToolItem() separator.props.draw = False separator.set_expand(True) @@ -119,6 +146,12 @@ class JournalShare(activity.Activity): self.watch_for_tubes() GObject.idle_add(self._get_view_information) + def __add_clicked_cb(self, button): + pass + + def __add_favorites_clicked_cb(self, button): + pass + def _get_view_information(self): # Pick an arbitrary tube we can try to connect to the server try: @@ -243,6 +276,13 @@ class JournalShare(activity.Activity): if self.server_proc is not None: self.server_proc.kill() self._allow_suspend() + # remove temporary files + instance_path = self._activity_root + '/instance/' + for file_name in os.listdir(instance_path): + file_path = os.path.join(instance_path, file_name) + if os.path.isfile(file_path): + os.remove(file_path) + return True # power management (almost copied from clock activity) @@ -265,3 +305,110 @@ class JournalShare(activity.Activity): return True else: return False + + +class JournalManager(): + + def __init__(self, activity_root): + self._instance_path = activity_root + '/instance/' + try: + self.nick_name = profile.get_nick_name() + except: + logging.exception('Can''t get nick_name') + self.nick_name = '' + try: + self.xo_color = profile.get_color() + except: + logging.exception('Can''t get xo_color') + self.xo_color = XoColor() + + # write json files + owner_info_file_path = self._instance_path + 'owner_info.json' + owner_info_file = open(owner_info_file_path, 'w') + owner_info_file.write(self.get_journal_owner_info()) + owner_info_file.close() + + selected_file_path = self._instance_path + 'selected.json' + selected_file = open(selected_file_path, 'w') + # TODO + selected_file.write(self.get_starred()) + selected_file.close() + + def get_journal_owner_info(self): + info = {} + info['nick_name'] = self.nick_name + info['stroke_color'] = self.xo_color.get_stroke_color() + info['fill_color'] = self.xo_color.get_fill_color() + logging.error('INFO %s', info) + return json.dumps(info) + + def create_object(self, file_path, metadata_content, preview_content): + new_dsobject = datastore.create() + #Set the file_path in the datastore. + new_dsobject.set_file_path(file_path) + if metadata_content is not None: + metadata = json.loads(metadata_content) + for key in metadata.keys(): + new_dsobject.metadata[key] = metadata[key] + if preview_content is not None and preview_content != '': + new_dsobject.metadata['preview'] = \ + dbus.ByteArray(preview_content) + # mark as favorite + new_dsobject.metadata['keep'] = '1' + datastore.write(new_dsobject) + return new_dsobject + + def get_starred(self): + logging.error('Before find datastore') + dsobjects, _nobjects = datastore.find({'keep': '1'}) + logging.error('After find datastore') + results = [] + for dsobj in dsobjects: + title = '' + desc = '' + comment = [] + object_id = dsobj.object_id + if hasattr(dsobj, 'metadata'): + if 'title' in dsobj.metadata: + title = dsobj.metadata['title'] + if 'description' in dsobj.metadata: + desc = dsobj.metadata['description'] + if 'comments' in dsobj.metadata: + try: + comment = json.loads(dsobj.metadata['comments']) + except: + comment = [] + if 'preview' in dsobj.metadata: + # TODO: copied from expandedentry.py + # is needed because record is saving the preview encoded + if dsobj.metadata['preview'][1:4] == 'PNG': + preview = dsobj.metadata['preview'] + else: + # TODO: We are close to be able to drop this. + preview = base64.b64decode( + dsobj.metadata['preview']) + preview_path = self._instance_path + 'preview_id_' + \ + object_id + preview_file = open(preview_path, 'w') + preview_file.write(preview) + preview_file.close() + if 'mime_type' in dsobj.metadata: + mime_type_path = self._instance_path + 'mime_type_id_' + \ + object_id + mime_type_file = open(mime_type_path, 'w') + mime_type_file.write(dsobj.metadata['title']) + mime_type_file.close() + + else: + logging.debug('dsobj has no metadata') + + # create a link to be read from the web server + file_path = self._instance_path + 'id_' + object_id + if os.path.isfile(file_path): + os.remove(file_path) + os.link(dsobj.file_path, file_path) + + results.append({'title': title, 'desc': desc, 'comment': comment, + 'id': object_id}) + logging.error(results) + return json.dumps(results) @@ -17,21 +17,14 @@ import os import sys import logging -import json import cgi -import dbus import BaseHTTPServer from SimpleHTTPServer import SimpleHTTPRequestHandler import SocketServer -import socket import select -from gi.repository import Gio -from sugar3 import network -from sugar3.datastore import datastore -from sugar3.graphics.xocolor import XoColor -from sugar3 import profile +from gi.repository import GObject from warnings import filterwarnings, catch_warnings @@ -181,8 +174,8 @@ class JournalHTTPRequestHandler(SimpleHTTPRequestHandler): f.close() i = i + 1 - self.jm.create_object(file_path, metadata_content, - preview_content) + GObject.add_idle(self.jm.create_object, file_path, + metadata_content, preview_content) #redirect to index.html page self.send_response(301) @@ -193,7 +186,6 @@ class JournalHTTPRequestHandler(SimpleHTTPRequestHandler): """Respond to a GET request.""" #logging.error('inside do_get dir(self) %s', dir(self)) - file_used = False if self.path: logging.error('Requested path %s', self.path) if self.path.startswith('/web'): @@ -201,37 +193,36 @@ class JournalHTTPRequestHandler(SimpleHTTPRequestHandler): self.send_header_response("text/html") # return files requested in the web directory file_path = self.activity_path + self.path - logging.error('Requested file %s', file_path) if os.path.isfile(file_path): logging.error('Opening requested file %s', file_path) - f = Gio.File.new_for_path(file_path) - _error, content, _time = f.load_contents(None) - - #logging.error('Closing requested file %s', file_path) + f = open(file_path) + content = f.read() + f.close() self.wfile.write(content) - file_used = True if self.path.startswith('/datastore'): - # queries to the datastore - if self.path == '/datastore/starred': - self.send_header_response("text/html") - self.wfile.write(self.jm.get_starred()) - logging.error('Returned datastore/starred') - elif self.path == '/datastore/owner_info': - self.send_header_response("text/html") - self.wfile.write(self.jm.get_journal_owner_info()) - elif self.path.startswith('/datastore/id='): - object_id = self.path[self.path.find('=') + 1:] - mime_type, title, content = \ - self.jm.get_object_by_id(object_id) - self.send_header_response(mime_type, title) + # return files requested in the activity instance directory + path = self.path.replace('datastore', 'instance') + file_path = self.activity_root + path + + mime_type = 'text/html' + # if is reading a file, try to read the mime_type + if file_path.find('/id_') > -1: + mime_tipe_path = file_path.replace('/id_', + '/mime_type_id_') + if os.path.isfile(mime_tipe_path): + f = open(mime_tipe_path) + mime_type = f.read() + f.close() + self.send_header_response(mime_type) + + if os.path.isfile(file_path): + logging.error('Opening requested file %s', file_path) + f = open(file_path) + content = f.read() + f.close() self.wfile.write(content) - elif self.path.startswith('/datastore/preview/id='): - object_id = self.path[self.path.find('=') + 1:] - preview = self.jm.get_preview_by_id(object_id) - self.send_header_response('image/png') - self.wfile.write(preview) def send_header_response(self, mime_type, file_name=None): self.send_response(200) @@ -278,108 +269,8 @@ class JournalHTTPServer(BaseHTTPServer.HTTPServer): self.server_port = port -class JournalManager(): - - def __init__(self): - try: - self.nick_name = profile.get_nick_name() - except: - logging.exception('Can''t get nick_name') - self.nick_name = '' - try: - self.xo_color = profile.get_color() - except: - logging.exception('Can''t get xo_color') - self.xo_color = XoColor() - - def get_journal_owner_info(self): - info = {} - info['nick_name'] = self.nick_name - info['stroke_color'] = self.xo_color.get_stroke_color() - info['fill_color'] = self.xo_color.get_fill_color() - logging.error('INFO %s', info) - return json.dumps(info) - - def create_object(self, file_path, metadata_content, preview_content): - new_dsobject = datastore.create() - #Set the file_path in the datastore. - new_dsobject.set_file_path(file_path) - if metadata_content is not None: - metadata = json.loads(metadata_content) - for key in metadata.keys(): - new_dsobject.metadata[key] = metadata[key] - if preview_content is not None and preview_content != '': - new_dsobject.metadata['preview'] = \ - dbus.ByteArray(preview_content) - # mark as favorite - new_dsobject.metadata['keep'] = '1' - datastore.write(new_dsobject) - return new_dsobject - - def get_object_by_id(self, object_id): - dsobj = datastore.get(object_id) - mime_type = '' - if 'mime_type' in dsobj.metadata: - mime_type = dsobj.metadata['mime_type'] - if mime_type == '': - # TODO: what type should we use if not available? - mime_type = 'application/x-binary' - title = None - if 'title' in dsobj.metadata: - title = dsobj.metadata['title'] - - f = open(dsobj.file_path, 'r') - # TODO: read all the file in memory? - content = f.read() - f.close() - return mime_type, title, content - - def get_preview_by_id(self, object_id): - dsobj = datastore.get(object_id) - preview = None - if 'preview' in dsobj.metadata: - # TODO: copied from expandedentry.py - # is needed because record is saving the preview encoded - if dsobj.metadata['preview'][1:4] == 'PNG': - preview = dsobj.metadata['preview'] - else: - # TODO: We are close to be able to drop this. - import base64 - preview = base64.b64decode( - dsobj.metadata['preview']) - return preview - - def get_starred(self): - logging.error('Before find datastore') - dsobjects, _nobjects = datastore.find({'keep': '1'}) - logging.error('After find datastore') - results = [] - for dsobj in dsobjects: - title = '' - desc = '' - comment = [] - object_id = dsobj.object_id - if hasattr(dsobj, 'metadata'): - if 'title' in dsobj.metadata: - title = dsobj.metadata['title'] - if 'description' in dsobj.metadata: - desc = dsobj.metadata['description'] - if 'comments' in dsobj.metadata: - try: - comment = json.loads(dsobj.metadata['comments']) - except: - comment = [] - else: - logging.debug('dsobj has no metadata') - results.append({'title': title, 'desc': desc, 'comment': comment, - 'id': object_id}) - logging.error(results) - return json.dumps(results) - - -def run_server(activity_path, activity_root, port): +def run_server(activity_path, activity_root, jm, port): # init the journal manager before start the thread - jm = JournalManager() from threading import Thread httpd = JournalHTTPServer(("", port), lambda *args: JournalHTTPRequestHandler(activity_path, activity_root, diff --git a/web/index.html b/web/index.html index 7696dd3..6b7a6e2 100644 --- a/web/index.html +++ b/web/index.html @@ -7,7 +7,7 @@ <script type="text/javascript"> function init() { - $.getJSON("/datastore/owner_info", function(owner_info) { + $.getJSON("/datastore/owner_info.json", function(owner_info) { $('#header').append("Journal of " + owner_info.nick_name); $('#header').css('color', owner_info.stroke_color); $('#header').css('background-color', owner_info.fill_color); @@ -19,17 +19,17 @@ $('#uploadarea').hide(); } - $.getJSON("/datastore/starred", function(starred) { - for (var i = 0; i < starred.length; i++) + $.getJSON("/datastore/selected.json", function(selected) { + for (var i = 0; i < selected.length; i++) { $('#journaltable').append("<tr>" + - "<td><img src=/datastore/preview/id=" + starred[i].id + "/></td>"+ + "<td><img src=/datastore/preview_id_" + selected[i].id + "></td>"+ "<td class='desc_td'>"+ "<table class='desc_table'>"+ - "<tr><td class='title'>" + starred[i].title + "</td></tr>"+ - "<tr><td>" + starred[i].desc + "</td></tr>"+ + "<tr><td class='title'>" + selected[i].title + "</td></tr>"+ + "<tr><td>" + selected[i].desc + "</td></tr>"+ (!local ? "<tr><td>"+ - "<a class='download_link' href='/datastore/id=" + starred[i].id +"'>"+ + "<a class='download_link' href='/datastore/id_" + selected[i].id +"'>"+ "Download</a></td></tr>" : "") + "</table>"+ "</td>" + |