diff options
author | root <root@ghunt-desktop.(none)> | 2010-06-09 14:57:19 (GMT) |
---|---|---|
committer | root <root@ghunt-desktop.(none)> | 2010-06-09 14:57:19 (GMT) |
commit | 5f4860099ae80a996e2e4dee85c72c11e170fc8e (patch) | |
tree | d2eeb7f67e553ddb50d802994f045af5aca846e1 /examples/SugarCommander.activity | |
parent | 3449b69734b57b5a5c625d43e90fde241a14ca6d (diff) |
fixes to save-as
Diffstat (limited to 'examples/SugarCommander.activity')
m--------- | examples/SugarCommander.activity | 0 | ||||
-rw-r--r-- | examples/SugarCommander.activity/.gitignore | 6 | ||||
-rw-r--r-- | examples/SugarCommander.activity/MANIFEST | 5 | ||||
-rw-r--r-- | examples/SugarCommander.activity/activity/activity.info | 8 | ||||
-rw-r--r-- | examples/SugarCommander.activity/activity/scommander.svg | 88 | ||||
-rw-r--r-- | examples/SugarCommander.activity/po/SugarCommander.pot | 66 | ||||
-rwxr-xr-x | examples/SugarCommander.activity/setup.py | 21 | ||||
-rwxr-xr-x | examples/SugarCommander.activity/sugarcommander.py | 536 |
8 files changed, 730 insertions, 0 deletions
diff --git a/examples/SugarCommander.activity b/examples/SugarCommander.activity deleted file mode 160000 -Subproject 8bcdf7300169ce849221ffcd7b92791a5cd8e34 diff --git a/examples/SugarCommander.activity/.gitignore b/examples/SugarCommander.activity/.gitignore new file mode 100644 index 0000000..68d0d43 --- /dev/null +++ b/examples/SugarCommander.activity/.gitignore @@ -0,0 +1,6 @@ +.eric4project/ +.ropeproject/ +*.e4p +*.pyc +dist/ + diff --git a/examples/SugarCommander.activity/MANIFEST b/examples/SugarCommander.activity/MANIFEST new file mode 100644 index 0000000..6c3c796 --- /dev/null +++ b/examples/SugarCommander.activity/MANIFEST @@ -0,0 +1,5 @@ +sugarcommander.py +setup.py +activity/activity.info +activity/scommander.svg +po/SugarCommander.pot diff --git a/examples/SugarCommander.activity/activity/activity.info b/examples/SugarCommander.activity/activity/activity.info new file mode 100644 index 0000000..815e9c8 --- /dev/null +++ b/examples/SugarCommander.activity/activity/activity.info @@ -0,0 +1,8 @@ +[Activity] +name = Sugar Commander +service_name = org.laptop.sugar.SugarCommander +icon = scommander +exec = sugar-activity sugarcommander.SugarCommander +show_launcher = yes +activity_version = 3 +license = GPLv2+ diff --git a/examples/SugarCommander.activity/activity/scommander.svg b/examples/SugarCommander.activity/activity/scommander.svg new file mode 100644 index 0000000..67fc3b8 --- /dev/null +++ b/examples/SugarCommander.activity/activity/scommander.svg @@ -0,0 +1,88 @@ +<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd' [ + <!ENTITY stroke_color "#000000"> + <!ENTITY fill_color "#ffffff"> +]> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + enable-background="new 0 0 55 55" + height="55px" + id="Layer_1" + version="1.1" + viewBox="0 0 55 55" + width="55px" + x="0px" + xml:space="preserve" + y="0px" + sodipodi:version="0.32" + inkscape:version="0.46" + sodipodi:docname="scommander.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape"><metadata + id="metadata2457"><rdf:RDF><cc:Work + rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs + id="defs2455"><inkscape:perspective + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 27.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="55 : 27.5 : 1" + inkscape:persp3d-origin="27.5 : 18.333333 : 1" + id="perspective2459" /></defs><sodipodi:namedview + inkscape:window-height="816" + inkscape:window-width="1152" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + guidetolerance="10.0" + gridtolerance="10.0" + objecttolerance="10.0" + borderopacity="1.0" + bordercolor="#666666" + pagecolor="&fill_color;" + id="base" + showgrid="false" + inkscape:zoom="11.313708" + inkscape:cx="27.5" + inkscape:cy="27.5" + inkscape:window-x="-4" + inkscape:window-y="-4" + inkscape:current-layer="Layer_1" /><g + display="block" + id="activity-journal" + transform="translate(0.1767767,-0.7071068)" + style="display:block"> + <path + d="M 45.866,44.669 C 45.866,47.18 44.338,49 41.534,49 L 12.077,49 L 12.077,6 L 41.535,6 C 43.685,6 45.867,8.154 45.867,10.33 L 45.866,44.669 L 45.866,44.669 z" + id="path2444" + style="fill:&fill_color;;stroke:&stroke_color;;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round" /> + + <line + x1="21.341" + x2="21.341" + y1="6.1209998" + y2="48.881001" + id="line2446" + style="fill:none;stroke:&stroke_color;;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round" /> + <path + d="M 7.384,14.464 C 7.384,14.464 9.468,15.159 11.554,15.159 C 13.64,15.159 15.727,14.464 15.727,14.464" + id="path2448" + style="fill:none;stroke:&stroke_color;;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round" /> + <path + d="M 7.384,28.021 C 7.384,28.021 9.296,28.716 11.729,28.716 C 14.162,28.716 15.728,28.021 15.728,28.021" + id="path2450" + style="fill:none;stroke:&stroke_color;;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round" /> + <path + d="M 7.384,41.232 C 7.384,41.232 9.12,41.927 11.902,41.927 C 14.683,41.927 15.727,41.232 15.727,41.232" + id="path2452" + style="fill:none;stroke:&stroke_color;;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round" /> +</g><path + style="fill:none;fill-rule:evenodd;stroke:&stroke_color;;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="M 26.958446,28.660272 C 31.819805,23.091806 31.819805,23.091806 31.819805,23.091806 C 36.504388,28.129942 36.504388,28.129942 36.504388,28.129942" + id="path2469" /><path + style="fill:none;fill-rule:evenodd;stroke:&stroke_color;;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="M 26.870058,32.726136 C 31.643028,26.715729 31.643028,26.715729 31.643028,26.715729 C 35.974058,32.195806 35.974058,32.195806 35.974058,32.195806" + id="path2471" /></svg> diff --git a/examples/SugarCommander.activity/po/SugarCommander.pot b/examples/SugarCommander.activity/po/SugarCommander.pot new file mode 100644 index 0000000..844c8f9 --- /dev/null +++ b/examples/SugarCommander.activity/po/SugarCommander.pot @@ -0,0 +1,66 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2010-03-24 18:52-0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: activity/activity.info:2 +msgid "Sugar Commander" +msgstr "" + +#: sugarcommander.py:58 sugarcommander.py:102 +msgid "Title" +msgstr "" + +#: sugarcommander.py:62 +msgid "MIME" +msgstr "" + +#: sugarcommander.py:74 +msgid "Journal" +msgstr "" + +#: sugarcommander.py:86 +msgid "Save" +msgstr "" + +#: sugarcommander.py:92 +msgid "Delete" +msgstr "" + +#: sugarcommander.py:113 +msgid "Description" +msgstr "" + +#: sugarcommander.py:126 +msgid "Tags" +msgstr "" + +#: sugarcommander.py:160 +msgid "Copy File To The Journal" +msgstr "" + +#: sugarcommander.py:164 +msgid "Files" +msgstr "" + +#: sugarcommander.py:345 +msgid "Success" +msgstr "" + +#: sugarcommander.py:345 +#, python-format +msgid "%s added to Journal." +msgstr "" diff --git a/examples/SugarCommander.activity/setup.py b/examples/SugarCommander.activity/setup.py new file mode 100755 index 0000000..d3ab3a3 --- /dev/null +++ b/examples/SugarCommander.activity/setup.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python + +# Copyright (C) 2006, Red Hat, Inc.
+# +# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# +# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+# +# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ +from sugar.activity import bundlebuilder + +bundlebuilder.start() diff --git a/examples/SugarCommander.activity/sugarcommander.py b/examples/SugarCommander.activity/sugarcommander.py new file mode 100755 index 0000000..28453d0 --- /dev/null +++ b/examples/SugarCommander.activity/sugarcommander.py @@ -0,0 +1,536 @@ +# SugarCommander.py + +# Copyright (C) 2010 James D. Simmons +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +import logging +import os +import gtk +import pango +import zipfile +from sugar import mime +from sugar.activity import activity +from sugar.datastore import datastore +from sugar.graphics.alert import NotifyAlert +from sugar.graphics import style +from gettext import gettext as _ +import gobject +import dbus + +COLUMN_TITLE = 0 +COLUMN_MIME = 1 +COLUMN_JOBJECT = 2 + +DS_DBUS_SERVICE = 'org.laptop.sugar.DataStore' +DS_DBUS_INTERFACE = 'org.laptop.sugar.DataStore' +DS_DBUS_PATH = '/org/laptop/sugar/DataStore' + +_logger = logging.getLogger('sugar-commander') + +class SugarCommander(activity.Activity): + def __init__(self, handle, create_jobject=True): + "The entry point to the Activity" + activity.Activity.__init__(self, handle, False) + self.selected_journal_entry = None + self.selected_path = None + + canvas = gtk.Notebook() + canvas.props.show_border = True + canvas.props.show_tabs = True + canvas.show() + + self.ls_journal = gtk.ListStore(gobject.TYPE_STRING, + gobject.TYPE_STRING, + gobject.TYPE_PYOBJECT) + tv_journal = gtk.TreeView(self.ls_journal) + tv_journal.set_rules_hint(True) + tv_journal.set_search_column(COLUMN_TITLE) + self.selection_journal = tv_journal.get_selection() + self.selection_journal.set_mode(gtk.SELECTION_BROWSE) + self.selection_journal.connect("changed", self.selection_journal_cb) + renderer = gtk.CellRendererText() + renderer.set_property('wrap-mode', gtk.WRAP_WORD) + renderer.set_property('wrap-width', 500) + renderer.set_property('width', 500) + self.col_journal = gtk.TreeViewColumn(_('Title'), renderer, + text=COLUMN_TITLE) + self.col_journal.set_sort_column_id(COLUMN_TITLE) + tv_journal.append_column(self.col_journal) + + self.col_mime = gtk.TreeViewColumn(_('MIME'), renderer, + text=COLUMN_MIME) + self.col_mime.set_sort_column_id(COLUMN_MIME) + tv_journal.append_column(self.col_mime) + + self.list_scroller_journal = gtk.ScrolledWindow( + hadjustment=None, vadjustment=None) + self.list_scroller_journal.set_policy( + gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + self.list_scroller_journal.add(tv_journal) + + label_attributes = pango.AttrList() + label_attributes.insert(pango.AttrSize(14000, 0, -1)) + label_attributes.insert(pango.AttrForeground(65535, 65535, 65535, 0, -1)) + + tab1_label = gtk.Label(_("Journal")) + tab1_label.set_attributes(label_attributes) + tab1_label.show() + tv_journal.show() + self.list_scroller_journal.show() + + column_table = gtk.Table(rows=1, columns=2, homogeneous = False) + + image_table = gtk.Table(rows=2, columns=2, homogeneous=False) + self.image = gtk.Image() + image_table.attach(self.image, 0, 2, 0, 1, xoptions=gtk.FILL|gtk.SHRINK, + yoptions=gtk.FILL|gtk.SHRINK, xpadding=10, ypadding=10) + + self.btn_save = gtk.Button(_("Save")) + self.btn_save.connect('button_press_event', + self.save_button_press_event_cb) + image_table.attach(self.btn_save, 0, 1, 1, 2, xoptions=gtk.SHRINK, + yoptions=gtk.SHRINK, xpadding=10, ypadding=10) + self.btn_save.props.sensitive = False + self.btn_save.show() + + self.btn_delete = gtk.Button(_("Delete")) + self.btn_delete.connect('button_press_event', + self.delete_button_press_event_cb) + image_table.attach(self.btn_delete, 1, 2, 1, 2, xoptions=gtk.SHRINK, + yoptions=gtk.SHRINK, xpadding=10, ypadding=10) + self.btn_delete.props.sensitive = False + self.btn_delete.show() + + column_table.attach(image_table, 0, 1, 0, 1, + xoptions=gtk.FILL|gtk.SHRINK, + yoptions=gtk.SHRINK, xpadding=10, ypadding=10) + + entry_table = gtk.Table(rows=3, columns=2, + homogeneous=False) + + title_label = gtk.Label(_("Title")) + entry_table.attach(title_label, 0, 1, 0, 1, + xoptions=gtk.SHRINK, + yoptions=gtk.SHRINK, + xpadding=10, ypadding=10) + title_label.show() + + self.title_entry = gtk.Entry(max=0) + entry_table.attach(self.title_entry, 1, 2, 0, 1, + xoptions=gtk.FILL|gtk.SHRINK, + yoptions=gtk.SHRINK, xpadding=10, ypadding=10) + self.title_entry.connect('key_press_event', + self.key_press_event_cb) + self.title_entry.show() + + description_label = gtk.Label(_("Description")) + entry_table.attach(description_label, 0, 1, 1, 2, + xoptions=gtk.SHRINK, + yoptions=gtk.SHRINK, + xpadding=10, ypadding=10) + description_label.show() + + self.description_textview = gtk.TextView() + self.description_textview.set_wrap_mode(gtk.WRAP_WORD) + entry_table.attach(self.description_textview, 1, 2, 1, 2, + xoptions=gtk.EXPAND|gtk.FILL|gtk.SHRINK, + yoptions=gtk.EXPAND|gtk.FILL|gtk.SHRINK, + xpadding=10, ypadding=10) + self.description_textview.props.accepts_tab = False + self.description_textview.connect('key_press_event', + self.key_press_event_cb) + self.description_textview.show() + + tags_label = gtk.Label(_("Tags")) + entry_table.attach(tags_label, 0, 1, 2, 3, + xoptions=gtk.SHRINK, + yoptions=gtk.SHRINK, + xpadding=10, ypadding=10) + tags_label.show() + + self.tags_textview = gtk.TextView() + self.tags_textview.set_wrap_mode(gtk.WRAP_WORD) + entry_table.attach(self.tags_textview, 1, 2, 2, 3, + xoptions=gtk.FILL, + yoptions=gtk.EXPAND|gtk.FILL, + xpadding=10, ypadding=10) + self.tags_textview.props.accepts_tab = False + self.tags_textview.connect('key_press_event', + self.key_press_event_cb) + self.tags_textview.show() + + entry_table.show() + + self.scroller_entry = gtk.ScrolledWindow( + hadjustment=None, vadjustment=None) + self.scroller_entry.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) + self.scroller_entry.add_with_viewport(entry_table) + self.scroller_entry.show() + + column_table.attach(self.scroller_entry, 1, 2, 0, 1, + xoptions=gtk.FILL|gtk.EXPAND|gtk.SHRINK, + yoptions=gtk.FILL|gtk.EXPAND|gtk.SHRINK, + xpadding=10, ypadding=10) + image_table.show() + column_table.show() + + vbox = gtk.VBox(homogeneous=True, spacing=5) + vbox.pack_start(column_table) + vbox.pack_end(self.list_scroller_journal) + + canvas.append_page(vbox, tab1_label) + + self._filechooser = gtk.FileChooserWidget( + action=gtk.FILE_CHOOSER_ACTION_OPEN, backend=None) + self._filechooser.set_current_folder("/media") + self.copy_button = gtk.Button(_("Copy File To The Journal")) + self.copy_button.connect('clicked', self.create_journal_entry) + self.copy_button.show() + self._filechooser.set_extra_widget(self.copy_button) + preview = gtk.Image() + self._filechooser.set_preview_widget(preview) + self._filechooser.connect("update-preview", + self.update_preview_cb, preview) + tab2_label = gtk.Label(_("Files")) + tab2_label.set_attributes(label_attributes) + tab2_label.show() + canvas.append_page(self._filechooser, tab2_label) + + self.set_canvas(canvas) + self.show_all() + + toolbox = activity.ActivityToolbox(self) + activity_toolbar = toolbox.get_activity_toolbar() + activity_toolbar.keep.props.visible = False + activity_toolbar.share.props.visible = False + self.set_toolbox(toolbox) + toolbox.show() + + self.load_journal_table() + + bus = dbus.SessionBus() + remote_object = bus.get_object(DS_DBUS_SERVICE, DS_DBUS_PATH) + _datastore = dbus.Interface(remote_object, DS_DBUS_INTERFACE) + _datastore.connect_to_signal('Created', self.datastore_created_cb) + _datastore.connect_to_signal('Updated', self.datastore_updated_cb) + _datastore.connect_to_signal('Deleted', self.datastore_deleted_cb) + + self.selected_journal_entry = None + + def update_preview_cb(self, file_chooser, preview): + filename = file_chooser.get_preview_filename() + file_mimetype = mime.get_for_file(filename) + if file_mimetype.startswith('image/'): + pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(filename, + style.zoom(320), style.zoom(240)) + preview.set_from_pixbuf(pixbuf) + have_preview = True + elif file_mimetype == 'application/x-cbz': + fname = self.extract_image(filename) + pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(fname, + style.zoom(320), style.zoom(240)) + preview.set_from_pixbuf(pixbuf) + have_preview = True + os.remove(fname) + else: + have_preview = False + file_chooser.set_preview_widget_active(have_preview) + return + + def key_press_event_cb(self, entry, event): + self.btn_save.props.sensitive = True + + def save_button_press_event_cb(self, entry, event): + self.update_entry() + + def delete_button_press_event_cb(self, entry, event): + datastore.delete(self.selected_journal_entry.object_id) + + def datastore_created_cb(self, uid): + self.load_journal_table() + + def datastore_updated_cb(self, uid): + self.load_journal_table() + object_id = self.selected_journal_entry.object_id + jobject = datastore.get(object_id) + self.set_form_fields(jobject) + + def datastore_deleted_cb(self, uid): + self.load_journal_table() + object_id = self.selected_journal_entry.object_id + try: + jobject = datastore.get(object_id) + except: + if not self.selected_path is None: + self.selection_journal.select_path(self.selected_path) + else: + self.title_entry.set_text('') + description_textbuffer = self.description_textview.get_buffer() + description_textbuffer.set_text('') + tags_textbuffer = self.tags_textview.get_buffer() + tags_textbuffer.set_text('') + self.btn_save.props.sensitive = False + self.btn_delete.props.sensitive = False + self.image.clear() + self.image.show() + + def update_entry(self): + needs_update = False + needs_reload = False + + if self.selected_journal_entry is None: + return + + object_id = self.selected_journal_entry.object_id + jobject = datastore.get(object_id) + + old_title = jobject.metadata.get('title', None) + if old_title != self.title_entry.props.text: + jobject.metadata['title'] = self.title_entry.props.text + jobject.metadata['title_set_by_user'] = '1' + needs_update = True + needs_reload = True + + old_tags = jobject.metadata.get('tags', None) + new_tags = self.tags_textview.props.buffer.props.text + if old_tags != new_tags: + jobject.metadata['tags'] = new_tags + needs_update = True + + old_description = jobject.metadata.get('description', None) + new_description = self.description_textview.props.buffer.props.text + if old_description != new_description: + jobject.metadata['description'] = new_description + needs_update = True + + if needs_update: + datastore.write(jobject, update_mtime=False, + reply_handler=self.datastore_write_cb, + error_handler=self.datastore_write_error_cb) + if needs_reload: + self.load_journal_table() + + self.btn_save.props.sensitive = False + + def datastore_write_cb(self): + pass + + def datastore_write_error_cb(self, error): + logging.error('sugarcommander.datastore_write_error_cb: %r' % error) + + def close(self, skip_save=False): + "Override the close method so we don't try to create a Journal entry." + activity.Activity.close(self, True) + + def selection_journal_cb(self, selection): + self.btn_delete.props.sensitive = True + tv = selection.get_tree_view() + model = tv.get_model() + sel = selection.get_selected() + if sel: + model, iter = sel + jobject = model.get_value(iter,COLUMN_JOBJECT) + jobject = datastore.get(jobject.object_id) + self.selected_journal_entry = jobject + self.set_form_fields(jobject) + self.selected_path = model.get_path(iter) + + def set_form_fields(self, jobject): + self.title_entry.set_text(jobject.metadata['title']) + description_textbuffer = self.description_textview.get_buffer() + if jobject.metadata.has_key('description'): + description_textbuffer.set_text(jobject.metadata['description']) + else: + description_textbuffer.set_text('') + tags_textbuffer = self.tags_textview.get_buffer() + if jobject.metadata.has_key('tags'): + tags_textbuffer.set_text(jobject.metadata['tags']) + else: + tags_textbuffer.set_text('') + self.create_preview(jobject.object_id) + + def create_preview(self, object_id): + jobject = datastore.get(object_id) + + if jobject.metadata.has_key('preview'): + preview = jobject.metadata['preview'] + if preview is None or preview == '' or preview == 'None': + if jobject.metadata['mime_type'] .startswith('image/'): + filename = jobject.get_file_path() + self.show_image(filename) + return + if jobject.metadata['mime_type'] == 'application/x-cbz': + filename = jobject.get_file_path() + fname = self.extract_image(filename) + self.show_image(fname) + os.remove(fname) + return + + if jobject.metadata.has_key('preview') and \ + len(jobject.metadata['preview']) > 4: + + if jobject.metadata['preview'][1:4] == 'PNG': + preview_data = jobject.metadata['preview'] + else: + import base64 + preview_data = base64.b64decode(jobject.metadata['preview']) + + loader = gtk.gdk.PixbufLoader() + loader.write(preview_data) + scaled_buf = loader.get_pixbuf() + loader.close() + self.image.set_from_pixbuf(scaled_buf) + self.image.show() + else: + self.image.clear() + self.image.show() + + def load_journal_table(self): + self.btn_save.props.sensitive = False + self.btn_delete.props.sensitive = False + ds_mounts = datastore.mounts() + mountpoint_id = None + if len(ds_mounts) == 1 and ds_mounts[0]['id'] == 1: + pass + else: + for mountpoint in ds_mounts: + id = mountpoint['id'] + uri = mountpoint['uri'] + if uri.startswith('/home'): + mountpoint_id = id + + query = {} + if mountpoint_id is not None: + query['mountpoints'] = [ mountpoint_id ] + ds_objects, num_objects = datastore.find(query, properties=['uid', + 'title', 'mime_type']) + + self.ls_journal.clear() + for i in xrange (0, num_objects, 1): + iter = self.ls_journal.append() + title = ds_objects[i].metadata['title'] + self.ls_journal.set(iter, COLUMN_TITLE, title) + mime = ds_objects[i].metadata['mime_type'] + self.ls_journal.set(iter, COLUMN_MIME, mime) + self.ls_journal.set(iter, COLUMN_JOBJECT, ds_objects[i]) + if not self.selected_journal_entry is None and \ + self.selected_journal_entry.object_id == ds_objects[i].object_id: + self.selection_journal.select_iter(iter) + + self.ls_journal.set_sort_column_id(COLUMN_TITLE, gtk.SORT_ASCENDING) + v_adjustment = self.list_scroller_journal.get_vadjustment() + v_adjustment.value = 0 + return ds_objects[0] + + def create_journal_entry(self, widget, data=None): + filename = self._filechooser.get_filename() + journal_entry = datastore.create() + journal_entry.metadata['title'] = self.make_new_filename(filename) + journal_entry.metadata['title_set_by_user'] = '1' + journal_entry.metadata['keep'] = '0' + file_mimetype = mime.get_for_file(filename) + if not file_mimetype is None: + journal_entry.metadata['mime_type'] = file_mimetype + journal_entry.metadata['buddies'] = '' + if file_mimetype.startswith('image/'): + preview = self.create_preview_metadata(filename) + elif file_mimetype == 'application/x-cbz': + fname = self.extract_image(filename) + preview = self.create_preview_metadata(fname) + os.remove(fname) + else: + preview = '' + if not preview == '': + journal_entry.metadata['preview'] = dbus.ByteArray(preview) + else: + journal_entry.metadata['preview'] = '' + + journal_entry.file_path = filename + datastore.write(journal_entry) + self.alert(_('Success'), _('%s added to Journal.') + % self.make_new_filename(filename)) + + def alert(self, title, text=None): + alert = NotifyAlert(timeout=20) + alert.props.title = title + alert.props.msg = text + self.add_alert(alert) + alert.connect('response', self.alert_cancel_cb) + alert.show() + + def alert_cancel_cb(self, alert, response_id): + self.remove_alert(alert) + + def show_image(self, filename): + "display a resized image in a preview" + scaled_buf = gtk.gdk.pixbuf_new_from_file_at_size(filename, + style.zoom(320), style.zoom(240)) + self.image.set_from_pixbuf(scaled_buf) + self.image.show() + + def extract_image(self, filename): + zf = zipfile.ZipFile(filename, 'r') + image_files = zf.namelist() + image_files.sort() + if len(image_files) > 0: + if self.save_extracted_file(zf, image_files[0]): + fname = os.path.join(self.get_activity_root(), 'instance', + self.make_new_filename(image_files[0])) + return fname + + def save_extracted_file(self, zipfile, filename): + "Extract the file to a temp directory for viewing" + try: + filebytes = zipfile.read(filename) + except zipfile.BadZipfile, err: + print 'Error opening the zip file: %s' % (err) + return False + except KeyError, err: + self.alert('Key Error', 'Zipfile key not found: ' + + str(filename)) + return + outfn = self.make_new_filename(filename) + if (outfn == ''): + return False + fname = os.path.join(self.get_activity_root(), 'instance', outfn) + f = open(fname, 'w') + try: + f.write(filebytes) + finally: + f.close() + return True + + def make_new_filename(self, filename): + partition_tuple = filename.rpartition('/') + return partition_tuple[2] + + def create_preview_metadata(self, filename): + + file_mimetype = mime.get_for_file(filename) + if not file_mimetype.startswith('image/'): + return '' + + scaled_pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(filename, + style.zoom(320), style.zoom(240)) + preview_data = [] + + def save_func(buf, data): + data.append(buf) + + scaled_pixbuf.save_to_callback(save_func, 'png', + user_data=preview_data) + preview_data = ''.join(preview_data) + + return preview_data |