diff options
author | Walter Bender <walter.bender@gmail.com> | 2011-06-10 13:06:21 (GMT) |
---|---|---|
committer | Walter Bender <walter.bender@gmail.com> | 2011-06-10 13:06:21 (GMT) |
commit | 5138f2678da9af91cff2c15911ebefc012a9b18b (patch) | |
tree | 4dbaccf9586b5994a733c2f588e1619dc097ac4d | |
parent | e2cbb4b0a12ceda80e7ea8d77fa5325a778ec2c2 (diff) |
added file system IO
-rw-r--r-- | edit_app.py | 161 | ||||
-rw-r--r-- | mdnames.py | 1 |
2 files changed, 153 insertions, 9 deletions
diff --git a/edit_app.py b/edit_app.py index 2c4c7f0..07b7130 100644 --- a/edit_app.py +++ b/edit_app.py @@ -21,11 +21,15 @@ from groupthink import sugar_tools, gtk_tools from gettext import gettext as _ +import os import gtk import pango import time import gtksourceview2 as gtksourceview +import logging +_logger = logging.getLogger('edit-activity') + from sugar.activity import activity try: # Can use 'New' toolbar design? @@ -40,10 +44,33 @@ if _HAVE_TOOLBOX: from sugar.graphics import style from sugar.activity.activity import EditToolbar +from sugar.graphics.toolbutton import ToolButton +from sugar.graphics.alert import Alert +from sugar.graphics.icon import Icon import mdnames +def _button_factory(icon_name, tooltip, callback, toolbar, cb_arg=None, + accelerator=None): + '''Factory for making toolbar buttons''' + my_button = ToolButton(icon_name) + my_button.set_tooltip(tooltip) + my_button.props.sensitive = True + if accelerator is not None: + my_button.props.accelerator = accelerator + if cb_arg is not None: + my_button.connect('clicked', callback, cb_arg) + else: + my_button.connect('clicked', callback) + if hasattr(toolbar, 'insert'): # the main toolbar + toolbar.insert(my_button, -1) + else: # or a secondary toolbar + toolbar.props.page.insert(my_button, -1) + my_button.show() + return my_button + + class EditActivity(sugar_tools.GroupActivity): '''A text editor for Sugar pylint says I need a docstring. Here you go. @@ -68,6 +95,8 @@ class EditActivity(sugar_tools.GroupActivity): sure there's early_setup, but that's not early enough ''' + self._object_id = handle.object_id + self.buffer = gtksourceview.Buffer() self.refresh_buffer = False @@ -78,6 +107,13 @@ class EditActivity(sugar_tools.GroupActivity): sugar_tools.GroupActivity.__init__(self, handle) + self.gnome_folder = os.environ['HOME'] + if mdnames.gnomefilename_md in self.metadata: + self.gnome_filename = self.metadata[mdnames.gnomefilename_md] + else: + self.gnome_filename = None + + def fix_mimetype(self): '''We must have a mimetype. Sometimes, we don't (when we get launched newly.) This fixes that.''' @@ -121,6 +157,17 @@ class EditActivity(sugar_tools.GroupActivity): self.edit_toolbar.copy.connect('clicked', self.copybutton_cb) self.edit_toolbar.paste.connect('clicked', self.pastebutton_cb) + # Only enable file open dialogs if this is a new, unshared instance + if self._object_id is None: + self._new_file_from_gnome = _button_factory( + 'user-document-open', _('New file from GNOME'), + self._new_file_from_gnome_cb, toolbar) + + # But always enable save as to GNOME + self._save_file_to_gnome = _button_factory( + 'user-document-save', _('Save file to GNOME'), + self._save_as_file_to_gnome_cb, toolbar) + if _HAVE_TOOLBOX: separator = gtk.SeparatorToolItem() separator.props.draw = False @@ -191,24 +238,117 @@ class EditActivity(sugar_tools.GroupActivity): #Return the main widget. our parents take care of GTK stuff return self.scrollwindow - def save_to_journal(self, filename, cloudstring): - '''Saves to the journal. - We use metadata magic to keep the collab. stuff''' - self.metadata[mdnames.cloudstring_md] = cloudstring + def _new_file_from_gnome_cb(self, button=None): + ''' Opens a chooser dialog to file system for loading ''' + text = self._get_text() + if len(text) > 0: + discard_alert = Alert() + discard_alert.props.title = _('You have been typing. Discard?') + discard_alert.props.msg = self._get_text()[0:min(25, len(text))] +\ + '...' + cancel_icon = Icon(icon_name='dialog-cancel') + discard_alert.add_button(gtk.RESPONSE_CANCEL, _('Cancel'), + cancel_icon) + cancel_icon.show() + discard_icon = Icon(icon_name='dialog-ok') + discard_alert.add_button(gtk.RESPONSE_APPLY, _('Discard'), + discard_icon) + discard_icon.show() + self.add_alert(discard_alert) + discard_alert.connect('response', self.__discard_cb) + discard_alert.show() + else: + self._open_dialog() + + def __discard_cb(self, alert, response_id): + ''' Callback for positive response to discard alert ''' + if response_id is gtk.RESPONSE_APPLY: + self._open_dialog() + self.remove_alert(alert) + + def _open_dialog(self): + dialog = gtk.FileChooserDialog( + _('Load...'), None, gtk.FILE_CHOOSER_ACTION_OPEN, + (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, + gtk.RESPONSE_OK)) + dialog.set_default_response(gtk.RESPONSE_OK) + dialog.set_current_folder(self.gnome_folder) + response = dialog.run() + if response == gtk.RESPONSE_OK: + self.load_from_journal(dialog.get_filename()) + self.gnome_folder = dialog.get_current_folder() + self.gnome_filename = dialog.get_filename() + self.metadata['title'] = self.gnome_filename + self.metadata[mdnames.gnomefilename_md] = self.gnome_filename + dialog.destroy() + + def _save_as_file_to_gnome_cb(self, button=None): + ''' Opens a chooser dialog to file system for save as ''' + dialog = gtk.FileChooserDialog( + _('Save as...'), None, gtk.FILE_CHOOSER_ACTION_OPEN, + (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_SAVE_AS, + gtk.RESPONSE_OK)) + dialog.set_default_response(gtk.RESPONSE_OK) + dialog.set_current_folder(self.gnome_folder) + if self.gnome_filename is not None: + dialog.set_filename(self.gnome_filename) + response = dialog.run() + if response == gtk.RESPONSE_OK: + self.gnome_folder = dialog.get_current_folder() + self.gnome_filename = dialog.get_filename() + self.metadata['title'] = self.gnome_filename + self.metadata[mdnames.gnomefilename_md] = self.gnome_filename + if os.path.exists(dialog.get_filename()): + exists_alert = Alert() + exists_alert.props.title = _('File exists. Overwrite?') + exists_alert.props.msg = dialog.get_filename() + cancel_icon = Icon(icon_name='dialog-cancel') + exists_alert.add_button(gtk.RESPONSE_CANCEL, _('Cancel'), + cancel_icon) + cancel_icon.show() + save_icon = Icon(icon_name='dialog-ok') + exists_alert.add_button(gtk.RESPONSE_APPLY, _('Overwrite'), + save_icon) + save_icon.show() + self.add_alert(exists_alert) + exists_alert.connect('response', self.__overwrite_cb) + exists_alert.show() + else: + self._write_to_file(self.gnome_filename) + dialog.destroy() - #Also write to file: - fhandle = open(filename, "w") + def __overwrite_cb(self, alert, response_id): + ''' Callback for positive response to overwrite alert ''' + if response_id is gtk.RESPONSE_APPLY: + self._write_to_file(self.gnome_filename) + self.remove_alert(alert) + def _get_text(self): + ''' Get text from edit buffer ''' bounds = self.buffer.get_bounds() - text = self.buffer.get_text(bounds[0], bounds[1]) + return self.buffer.get_text(bounds[0], bounds[1]) + + def _write_to_file(self, filename): + ''' Write text to file, either in the datastore or file system ''' + fhandle = open(filename, "w") + + text = self._get_text() fhandle.write(text) fhandle.close() + return text - self.fix_mimetype() + def save_to_journal(self, filename, cloudstring): + '''Saves to the journal. + We use metadata magic to keep the collab. stuff''' + + # TODO: Only save cloudstring_md if we have been sharing. + self.metadata[mdnames.cloudstring_md] = cloudstring #We can do full-text search on all Edit documents, yay - self.metadata[mdnames.contents_md] = text + self.metadata[mdnames.contents_md] = self._write_to_file(filename) + + self.fix_mimetype() #If we edit the file in another way, we need to reload the contents #we fudge the timestamp forwards by 5 seconds @@ -218,6 +358,7 @@ class EditActivity(sugar_tools.GroupActivity): def load_from_journal(self, filename): '''Load the file. Duh.''' + _logger.debug('loading %s' % (filename)) if mdnames.cloudstring_md in self.metadata: if self.checkts(): #if we were edited in another program @@ -240,6 +381,8 @@ class EditActivity(sugar_tools.GroupActivity): def when_shared(self): self._edit_toolbar.undo.set_sensitive(False) self._edit_toolbar.redo.set_sensitive(False) + self._new_file_from_journal.set_sensitive(False) + self._new_file_from_gnome.set_sensitive(False) def undobutton_cb(self, button): if self.buffer.can_undo(): @@ -5,3 +5,4 @@ cloudtimestamp_md = "org.laptop.Edit.cloudtimestamp" cloudstring_md = "org.laptop.Edit.cloudstring" contents_md = "org.laptop.Edit.contents:text" mimetype_md = "mime_type" +gnomefilename_md = "gnome_filename" |