diff options
author | Aleksey Lim <alsroot@member.fsf.org> | 2009-04-14 17:06:17 (GMT) |
---|---|---|
committer | Aleksey Lim <alsroot@member.fsf.org> | 2009-04-14 17:06:17 (GMT) |
commit | a4c97e5c60d93cf7ce42ccf6b191dc376df383d1 (patch) | |
tree | 1cade1001a40cb7d223c607a99a8c24fb187ece4 | |
parent | 73619fff09a27ee8f0f7d72c5acd7703af33d58d (diff) |
Do not store image thoughts on disk
-rw-r--r-- | labyrinthactivity.py | 52 | ||||
-rw-r--r-- | src/BaseThought.py | 4 | ||||
-rw-r--r-- | src/DrawingThought.py | 4 | ||||
-rw-r--r-- | src/ImageThought.py | 112 | ||||
-rw-r--r-- | src/MMapArea.py | 31 | ||||
-rw-r--r-- | src/PeriodicSaveThread.py | 37 | ||||
-rw-r--r-- | src/TextThought.py | 4 |
7 files changed, 86 insertions, 158 deletions
diff --git a/labyrinthactivity.py b/labyrinthactivity.py index 45242ff..e90450e 100644 --- a/labyrinthactivity.py +++ b/labyrinthactivity.py @@ -19,9 +19,9 @@ import sys import os import logging from gettext import gettext as _ -import tarfile import tempfile import xml.dom.minidom as dom +from zipfile import ZipFile import gobject import gtk @@ -141,7 +141,6 @@ class LabyrinthActivity(activity.Activity): tool.connect('clicked', self.__zoom_original_cb) view_toolbar.insert(tool, -1) - self._save_file = None self._mode = MMapArea.MODE_TEXT self._undo = UndoManager.UndoManager (self, @@ -149,7 +148,6 @@ class LabyrinthActivity(activity.Activity): edit_toolbar.redo.child) self._undo.block () self._main_area = MMapArea.MMapArea (self._undo) - self._main_area.connect ("doc_save", self.__doc_save_cb) self._main_area.connect ("set_focus", self.__main_area_focus_cb) self._main_area.connect ("button-press-event", self.__main_area_focus_cb) self._main_area.connect ("expose_event", self.__expose) @@ -286,19 +284,16 @@ class LabyrinthActivity(activity.Activity): self._main_area.grab_focus () def read_file(self, file_path): - tar_file = tarfile.open(file_path) - map_name = tar_file.getnames()[0] - tar_file.extractall(tempfile.gettempdir()) - tar_file.close() + zip = ZipFile(file_path, 'r') - f = file (os.path.join(tempfile.gettempdir(), map_name), 'r') - doc = dom.parse (f) + doc = dom.parseString (zip.read('MANIFEST')) top_element = doc.documentElement + self.set_title(top_element.getAttribute ("title")) self._mode = int (top_element.getAttribute ("mode")) self._main_area.set_mode (self._mode) - self._main_area.load_thyself (top_element, doc) + self._main_area.load_thyself (top_element, doc, zip) if top_element.hasAttribute("scale_factor"): self._main_area.scale_fac = float (top_element.getAttribute ("scale_factor")) if top_element.hasAttribute("translation"): @@ -308,35 +303,19 @@ class LabyrinthActivity(activity.Activity): self.mods[self._mode].set_active(True) + zip.close() + def write_file(self, file_path): logging.debug('write_file') - self._main_area.save_thyself () - - if self._save_file is None: - # FIXME: Create an empty file because the Activity superclass - # always requires one - fd, self._save_file = tempfile.mkstemp(suffix='.map') - del fd - - tf = tarfile.open (file_path, "w") - tf.add (self._save_file, os.path.split(self._save_file)[1]) - for t in self._main_area.thoughts: - if isinstance(t, ImageThought.ImageThought): - tf.add (t.filename, 'images/' + os.path.split(t.filename)[1]) - - tf.close() - os.unlink(self._save_file) + zip = ZipFile(file_path, 'w') - def __doc_save_cb (self, widget, doc, top_element): - logging.debug('doc_save_cb') - save_string = self.serialize_to_xml(doc, top_element) + self._main_area.update_save(zip) + manifest = self.serialize_to_xml(self._main_area.save, + self._main_area.element) + zip.writestr('MANIFEST', manifest) - fd, self._save_file = tempfile.mkstemp(suffix='.map') - del fd - - self.save_map(self._save_file, save_string) - #self.emit ('file_saved', self._save_file, self) + zip.close() def serialize_to_xml(self, doc, top_element): top_element.setAttribute ("title", self.props.title) @@ -351,11 +330,6 @@ class LabyrinthActivity(activity.Activity): string = doc.toxml () return string.encode ("utf-8" ) - def save_map(self, filename, string): - f = file (filename, 'w') - f.write (string) - f.close () - def __link_cb(self, widget): self._main_area.link_menu_cb() diff --git a/src/BaseThought.py b/src/BaseThought.py index 6e15497..4279d49 100644 --- a/src/BaseThought.py +++ b/src/BaseThought.py @@ -186,10 +186,10 @@ class BaseThought (gobject.GObject): def draw (self, context): pass - def load (self, node): + def load (self, node, zip): pass - def update_save (self): + def update_save (self, zip): pass def copy_text (self, clip): diff --git a/src/DrawingThought.py b/src/DrawingThought.py index 357d72f..5a8448c 100644 --- a/src/DrawingThought.py +++ b/src/DrawingThought.py @@ -334,7 +334,7 @@ class DrawingThought (ResizableThought): map(lambda p : p.move_by(x,y), self.points) ResizableThought.move_content_by(self, x, y) - def update_save (self): + def update_save (self, zip): next = self.element.firstChild while next: m = next.nextSibling @@ -383,7 +383,7 @@ class DrawingThought (ResizableThought): elem.setAttribute ("color", p.color.to_string()) return - def load (self, node): + def load (self, node, zip): tmp = node.getAttribute ("ul-coords") self.ul = utils.parse_coords (tmp) tmp = node.getAttribute ("lr-coords") diff --git a/src/ImageThought.py b/src/ImageThought.py index cb21c0d..78bba20 100644 --- a/src/ImageThought.py +++ b/src/ImageThought.py @@ -26,6 +26,9 @@ import gettext _ = gettext.gettext import cairo import os +import logging +import tempfile +import cStringIO from sugar import mime @@ -50,49 +53,37 @@ class ImageThought (ResizableThought): # FIXME: Work in progress, needs at least activity self to create # tmp files/links in the right places and reference the window. - def journal_open_image (self, filename=None): - if not filename: - self.object_chooser_active = True - if hasattr(mime, 'GENERIC_TYPE_IMAGE'): - chooser = ObjectChooser(_('Choose image'), - what_filter=mime.GENERIC_TYPE_IMAGE) - else: - chooser = ObjectChooser(_('Choose image')) - - try: - result = chooser.run() - if result == gtk.RESPONSE_ACCEPT and chooser.get_selected_object(): - jobject = chooser.get_selected_object() - else: - return False - - if jobject and jobject.file_path: - fname = os.path.join(get_activity_root(), 'tmp', - os.path.basename(jobject.file_path)) - os.rename(jobject.file_path, fname) - else: - return False - finally: - chooser.destroy() - del chooser - self.object_chooser_active = False + def journal_open_image (self): + self.object_chooser_active = True + if hasattr(mime, 'GENERIC_TYPE_IMAGE'): + chooser = ObjectChooser(_('Choose image'), + what_filter=mime.GENERIC_TYPE_IMAGE) else: - fname = filename - - print "fname =",fname + chooser = ObjectChooser(_('Choose image')) try: - self.orig_pic = gtk.gdk.pixbuf_new_from_file (fname) - except: - try: - # lets see if file was imported and is already extracted - fname = utils.get_save_dir() + 'images/' + utils.strip_path_from_file_name(filename) - self.orig_pic = gtk.gdk.pixbuf_new_from_file (fname) - except: + result = chooser.run() + if result == gtk.RESPONSE_ACCEPT and chooser.get_selected_object(): + jobject = chooser.get_selected_object() + else: return False - self.filename = fname - self.text = fname[fname.rfind('/')+1:fname.rfind('.')] + if jobject and jobject.file_path: + logging.debug("journal_open_image: fname=%s" % jobject.file_path) + try: + self.orig_pic = gtk.gdk.pixbuf_new_from_file (jobject.file_path) + self.filename = os.path.basename(jobject.file_path) + except Exception, e: + logging.error("journal_open_image: %s" % e) + return False + else: + return False + finally: + chooser.destroy() + del chooser + self.object_chooser_active = False + + self.text = self.filename[0:self.filename.rfind('.')] self.recalc_edges(True) return True @@ -167,7 +158,7 @@ class ImageThought (ResizableThought): return False - def update_save (self): + def update_save (self, zip): text = self.extended_buffer.get_text () if text: self.extended_buffer.update_save() @@ -197,9 +188,12 @@ class ImageThought (ResizableThought): self.element.removeAttribute ("primary_root") except xml.dom.NotFoundErr: pass - return - def load (self, node): + arcname = self.filename.encode('cp437') + if not [i for i in zip.namelist() if i == arcname]: + zip.writestr(arcname, pixbuf2str(self.orig_pic)) + + def load (self, node, zip): tmp = node.getAttribute ("ul-coords") self.ul = utils.parse_coords (tmp) tmp = node.getAttribute ("lr-coords") @@ -223,20 +217,30 @@ class ImageThought (ResizableThought): print "Unknown: "+n.nodeName margin = utils.margin_required (utils.STYLE_NORMAL) self.pic_location = (self.ul[0]+margin[0], self.ul[1]+margin[1]) - self.okay = self.journal_open_image (self.filename) + self.orig_pic = str2pixbuf(zip.read(self.filename.encode('cp437'))) self.lr = (self.pic_location[0]+self.width+margin[2], self.pic_location[1]+self.height+margin[3]) - if not self.okay: - dialog = gtk.MessageDialog (None, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, - gtk.MESSAGE_WARNING, gtk.BUTTONS_CLOSE, - _("Error loading file")) - dialog.format_secondary_text (_("%s could not be found. Associated thought will be empty."%self.filename)) - dialog.run () - dialog.hide () - self.pic = None - self.orig_pic = None - else: - self.recalc_edges() - return + self.recalc_edges() def enter (self): self.editing = True + +def pixbuf2str(pixbuf): + def push(data, buffer): + buffer.write(data) + + buffer = cStringIO.StringIO() + pixbuf.save_to_callback(push, 'png', user_data=buffer) + + return buffer.getvalue() + +def str2pixbuf(data): + fd, path = tempfile.mkstemp() + + f = os.fdopen(fd, 'w') + f.write(data) + f.close() + + out = gtk.gdk.pixbuf_new_from_file(path) + os.unlink(path) + + return out diff --git a/src/MMapArea.py b/src/MMapArea.py index 0a127cc..dccc2e7 100644 --- a/src/MMapArea.py +++ b/src/MMapArea.py @@ -85,12 +85,6 @@ class MMapArea (gtk.DrawingArea): __gsignals__ = dict (title_changed = (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_STRING, )), - doc_save = (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - (gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT)), - doc_delete = (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ()), change_mode = (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_INT, )), @@ -1012,10 +1006,10 @@ class MMapArea (gtk.DrawingArea): self.invalidate () return True - def load_thought (self, node, type): + def load_thought (self, node, type, zip): thought = self.create_new_thought (None, type, loading = True) thought.creating = False - thought.load (node) + thought.load (node, zip) def load_link (self, node): link = Link (self.save) @@ -1025,16 +1019,16 @@ class MMapArea (gtk.DrawingArea): element = link.get_save_element () self.element.appendChild (element) - def load_thyself (self, top_element, doc): + def load_thyself (self, top_element, doc, zip): for node in top_element.childNodes: if node.nodeName == "thought": - self.load_thought (node, MODE_TEXT) + self.load_thought (node, MODE_TEXT, zip) elif node.nodeName == "image_thought": - self.load_thought (node, MODE_IMAGE) + self.load_thought (node, MODE_IMAGE, zip) elif node.nodeName == "drawing_thought": - self.load_thought (node, MODE_DRAW) + self.load_thought (node, MODE_DRAW, zip) elif node.nodeName == "res_thought": - self.load_thought (node, MODE_RESOURCE) + self.load_thought (node, MODE_RESOURCE, zip) elif node.nodeName == "link": self.load_link (node) else: @@ -1085,19 +1079,12 @@ class MMapArea (gtk.DrawingArea): for l in del_links: self.delete_link (l) - def prepare_save(self): + def update_save(self, zip): for t in self.thoughts: - t.update_save () + t.update_save (zip) for l in self.links: l.update_save () - def save_thyself (self): - self.prepare_save() - if len(self.thoughts) > 0: - self.emit ("doc_save", self.save, self.element) - else: - self.emit ("doc_delete") - def text_selection_cb (self, thought, start, end, text): self.emit ("text_selection_changed", start, end, text) diff --git a/src/PeriodicSaveThread.py b/src/PeriodicSaveThread.py deleted file mode 100644 index 1747e90..0000000 --- a/src/PeriodicSaveThread.py +++ /dev/null @@ -1,37 +0,0 @@ -# PeriodicSaveThread.py -# This file is part of Labyrinth -# -# Copyright (C) 2008 - Labyrinth-Dev-Team -# -# Labyrinth 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. -# -# Labyrinth 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 Labyrinth; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, -# Boston, MA 02110-1301 USA -# - -import threading -import time - -class PeriodicSaveThread(threading.Thread): - - def __init__(self, main_area): - threading.Thread.__init__(self) - self.main_area = main_area - self.cancel = False - - def run (self): - time.sleep (60) - while not self.cancel: - self.main_area.save_thyself () - time.sleep (60) - diff --git a/src/TextThought.py b/src/TextThought.py index 38b0ca7..3bb0599 100644 --- a/src/TextThought.py +++ b/src/TextThought.py @@ -790,7 +790,7 @@ class TextThought (ResizableThought): context.set_source_rgb (0,0,0) context.stroke () - def update_save (self): + def update_save (self, zip): next = self.element.firstChild while next: m = next.nextSibling @@ -886,7 +886,7 @@ class TextThought (ResizableThought): self.bindex = self.b_f_i (self.index) self.text = tmp - def load (self, node): + def load (self, node, zip): self.index = int (node.getAttribute ("cursor")) self.end_index = self.index tmp = node.getAttribute ("ul-coords") |