diff options
author | Simon Schampijer <simon@schampijer.de> | 2011-08-12 17:58:02 (GMT) |
---|---|---|
committer | Simon Schampijer <simon@schampijer.de> | 2011-08-15 17:34:41 (GMT) |
commit | 2148b47c2a5910eeb14fe827059585bef09fc111 (patch) | |
tree | ac18555ae984bd5fce78f07cccbe39b6e131eeed /src/jarabe/journal/palettes.py | |
parent | dca42c10d1ddf4c7e79ab18bbf742305925bde2c (diff) |
Add duplicate functionality to the Journal and enhance copy functionality
This patch adds a duplicate option to the Journal entry palette and
the entry detail view. This will replace the keep button functionality
from the activity toolbar. The keep button will be deprecated in another
patch for the toolkit.
The copy option which copied previously to the clipboard by default
has been enhanced to allow: copying to the clipboard, copying to an
external device, copying from an external device to the Journal and
copying between external devices. Copying to the clipboard is now
a visible option in the menu. In the detail view the palette pops up
when doing a left click and showing the available options instead of
copying directly to the clipboard.
The design discussion has been taking place
at: http://lists.sugarlabs.org/archive/sugar-devel/2011-May/031316.html
Signed-off-by: Simon Schampijer <simon@laptop.org>
Acked-By: Sascha Silbe <silbe@activitycentral.com>
Diffstat (limited to 'src/jarabe/journal/palettes.py')
-rw-r--r-- | src/jarabe/journal/palettes.py | 174 |
1 files changed, 153 insertions, 21 deletions
diff --git a/src/jarabe/journal/palettes.py b/src/jarabe/journal/palettes.py index 7091378..0812475 100644 --- a/src/jarabe/journal/palettes.py +++ b/src/jarabe/journal/palettes.py @@ -21,6 +21,7 @@ import os import gobject import gtk import gconf +import gio from sugar.graphics import style from sugar.graphics.palette import Palette @@ -43,16 +44,18 @@ class ObjectPalette(Palette): __gsignals__ = { 'detail-clicked': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([str])), + 'volume-error': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([str, str])), } def __init__(self, metadata, detail=False): self._metadata = metadata - self._temp_file_path = None activity_icon = Icon(icon_size=gtk.ICON_SIZE_LARGE_TOOLBAR) activity_icon.props.file = misc.get_icon_name(metadata) - activity_icon.props.xo_color = misc.get_icon_color(metadata) + color = misc.get_icon_color(metadata) + activity_icon.props.xo_color = color if 'title' in metadata: title = gobject.markup_escape_text(metadata['title']) @@ -86,15 +89,24 @@ class ObjectPalette(Palette): self.menu.append(menu_item) menu_item.show() - client = gconf.client_get_default() - color = XoColor(client.get_string('/desktop/sugar/user/color')) - menu_item = MenuItem(_('Copy')) + menu_item = MenuItem(_('Copy to')) icon = Icon(icon_name='edit-copy', xo_color=color, icon_size=gtk.ICON_SIZE_MENU) menu_item.set_image(icon) - menu_item.connect('activate', self.__copy_activate_cb) self.menu.append(menu_item) menu_item.show() + copy_menu = CopyMenu(metadata) + copy_menu.connect('volume-error', self.__volume_error_cb) + menu_item.set_submenu(copy_menu) + + if self._metadata['mountpoint'] == '/': + menu_item = MenuItem(_('Duplicate')) + icon = Icon(icon_name='edit-duplicate', xo_color=color, + icon_size=gtk.ICON_SIZE_MENU) + menu_item.set_image(icon) + menu_item.connect('activate', self.__duplicate_activate_cb) + self.menu.append(menu_item) + menu_item.show() menu_item = MenuItem(_('Send to'), 'document-send') self.menu.append(menu_item) @@ -118,21 +130,15 @@ class ObjectPalette(Palette): def __start_activate_cb(self, menu_item): misc.resume(self._metadata) - def __copy_activate_cb(self, menu_item): - clipboard = gtk.Clipboard() - clipboard.set_with_data([('text/uri-list', 0, 0)], - self.__clipboard_get_func_cb, - self.__clipboard_clear_func_cb) - - def __clipboard_get_func_cb(self, clipboard, selection_data, info, data): - # Get hold of a reference so the temp file doesn't get deleted - self._temp_file_path = model.get_file(self._metadata['uid']) - logging.debug('__clipboard_get_func_cb %r', self._temp_file_path) - selection_data.set_uris(['file://' + self._temp_file_path]) - - def __clipboard_clear_func_cb(self, clipboard, data): - # Release and delete the temp file - self._temp_file_path = None + def __duplicate_activate_cb(self, menu_item): + file_path = model.get_file(self._metadata['uid']) + try: + model.copy(self._metadata, '/') + except IOError, e: + logging.exception('Error while copying the entry. %s', e.strerror) + self.emit('volume-error', + _('Error while copying the entry. %s') % e.strerror, + _('Error')) def __erase_activate_cb(self, menu_item): model.delete(self._metadata['uid']) @@ -140,6 +146,9 @@ class ObjectPalette(Palette): def __detail_activate_cb(self, menu_item): self.emit('detail-clicked', self._metadata['uid']) + def __volume_error_cb(self, menu_item, message, severity): + self.emit('volume-error', message, severity) + def __friend_selected_cb(self, menu_item, buddy): logging.debug('__friend_selected_cb') file_name = model.get_file(self._metadata['uid']) @@ -162,6 +171,129 @@ class ObjectPalette(Palette): mime_type) +class CopyMenu(gtk.Menu): + __gtype_name__ = 'JournalCopyMenu' + + __gsignals__ = { + 'volume-error': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([str, str])), + } + + def __init__(self, metadata): + gobject.GObject.__init__(self) + + self._metadata = metadata + + clipboard_menu = ClipboardMenu(self._metadata) + clipboard_menu.set_image(Icon(icon_name='toolbar-edit', + icon_size=gtk.ICON_SIZE_MENU)) + clipboard_menu.connect('volume-error', self.__volume_error_cb) + self.append(clipboard_menu) + clipboard_menu.show() + + if self._metadata['mountpoint'] != '/': + client = gconf.client_get_default() + color = XoColor(client.get_string('/desktop/sugar/user/color')) + journal_menu = VolumeMenu(self._metadata, _('Journal'), '/') + journal_menu.set_image(Icon(icon_name='activity-journal', + xo_color=color, + icon_size=gtk.ICON_SIZE_MENU)) + journal_menu.connect('volume-error', self.__volume_error_cb) + self.append(journal_menu) + journal_menu.show() + + volume_monitor = gio.volume_monitor_get() + icon_theme = gtk.icon_theme_get_default() + for mount in volume_monitor.get_mounts(): + if self._metadata['mountpoint'] == mount.get_root().get_path(): + continue + volume_menu = VolumeMenu(self._metadata, mount.get_name(), + mount.get_root().get_path()) + for name in mount.get_icon().props.names: + if icon_theme.has_icon(name): + volume_menu.set_image(Icon(icon_name=name, + icon_size=gtk.ICON_SIZE_MENU)) + break + volume_menu.connect('volume-error', self.__volume_error_cb) + self.append(volume_menu) + volume_menu.show() + + def __volume_error_cb(self, menu_item, message, severity): + self.emit('volume-error', message, severity) + + +class VolumeMenu(MenuItem): + __gtype_name__ = 'JournalVolumeMenu' + + __gsignals__ = { + 'volume-error': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([str, str])), + } + + def __init__(self, metadata, label, mount_point): + MenuItem.__init__(self, label) + self._metadata = metadata + self.connect('activate', self.__copy_to_volume_cb, mount_point) + + def __copy_to_volume_cb(self, menu_item, mount_point): + file_path = model.get_file(self._metadata['uid']) + + if not file_path or not os.path.exists(file_path): + logging.warn('Entries without a file cannot be copied.') + self.emit('volume-error', + _('Entries without a file cannot be copied.'), + _('Warning')) + return + + try: + model.copy(self._metadata, mount_point) + except IOError, e: + logging.exception('Error while copying the entry. %s', e.strerror) + self.emit('volume-error', + _('Error while copying the entry. %s') % e.strerror, + _('Error')) + + +class ClipboardMenu(MenuItem): + __gtype_name__ = 'JournalClipboardMenu' + + __gsignals__ = { + 'volume-error': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([str, str])), + } + + def __init__(self, metadata): + MenuItem.__init__(self, _('Clipboard')) + + self._temp_file_path = None + self._metadata = metadata + self.connect('activate', self.__copy_to_clipboard_cb) + + def __copy_to_clipboard_cb(self, menu_item): + file_path = model.get_file(self._metadata['uid']) + if not file_path or not os.path.exists(file_path): + logging.warn('Entries without a file cannot be copied.') + self.emit('volume-error', + _('Entries without a file cannot be copied.'), + _('Warning')) + return + + clipboard = gtk.Clipboard() + clipboard.set_with_data([('text/uri-list', 0, 0)], + self.__clipboard_get_func_cb, + self.__clipboard_clear_func_cb) + + def __clipboard_get_func_cb(self, clipboard, selection_data, info, data): + # Get hold of a reference so the temp file doesn't get deleted + self._temp_file_path = model.get_file(self._metadata['uid']) + logging.debug('__clipboard_get_func_cb %r', self._temp_file_path) + selection_data.set_uris(['file://' + self._temp_file_path]) + + def __clipboard_clear_func_cb(self, clipboard, data): + # Release and delete the temp file + self._temp_file_path = None + + class FriendsMenu(gtk.Menu): __gtype_name__ = 'JournalFriendsMenu' |