Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGonzalo Odiard <godiard@gmail.com>2013-04-04 21:49:25 (GMT)
committer Gonzalo Odiard <godiard@gmail.com>2013-04-04 21:49:25 (GMT)
commit4e923a199ff3aea1811b67b4104bcb52fd54004a (patch)
tree60b2e0e216c56ffaa32388fc9dfd69ad36bc9037
parentedca72433794bb136771dfecdb75b82051ed7056 (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.py153
-rw-r--r--server.py163
-rw-r--r--web/index.html14
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)
diff --git a/server.py b/server.py
index b55b303..72ee65b 100644
--- a/server.py
+++ b/server.py
@@ -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>" +