diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/jarabe/journal/journalactivity.py | 1 | ||||
-rw-r--r-- | src/jarabe/journal/journaltoolbox.py | 116 | ||||
-rw-r--r-- | src/jarabe/journal/listview.py | 13 | ||||
-rw-r--r-- | src/jarabe/journal/model.py | 2 | ||||
-rw-r--r-- | src/jarabe/journal/palettes.py | 174 |
5 files changed, 230 insertions, 76 deletions
diff --git a/src/jarabe/journal/journalactivity.py b/src/jarabe/journal/journalactivity.py index a33038a..bb1c7f6 100644 --- a/src/jarabe/journal/journalactivity.py +++ b/src/jarabe/journal/journalactivity.py @@ -171,6 +171,7 @@ class JournalActivity(JournalWindow): self._list_view = ListView() self._list_view.connect('detail-clicked', self.__detail_clicked_cb) self._list_view.connect('clear-clicked', self.__clear_clicked_cb) + self._list_view.connect('volume-error', self.__volume_error_cb) self._main_view.pack_start(self._list_view) self._list_view.show() diff --git a/src/jarabe/journal/journaltoolbox.py b/src/jarabe/journal/journaltoolbox.py index d825bc9..77334b4 100644 --- a/src/jarabe/journal/journaltoolbox.py +++ b/src/jarabe/journal/journaltoolbox.py @@ -26,6 +26,7 @@ import gobject import gio import gtk +from sugar.graphics.palette import Palette from sugar.graphics.toolbox import Toolbox from sugar.graphics.toolcombobox import ToolComboBox from sugar.graphics.toolbutton import ToolButton @@ -37,11 +38,12 @@ from sugar.graphics.xocolor import XoColor from sugar.graphics import iconentry from sugar.graphics import style from sugar import mime -from sugar import profile from jarabe.model import bundleregistry from jarabe.journal import misc from jarabe.journal import model +from jarabe.journal.palettes import ClipboardMenu +from jarabe.journal.palettes import VolumeMenu _AUTOSEARCH_TIMEOUT = 1000 @@ -370,19 +372,23 @@ class EntryToolbar(gtk.Toolbar): self.add(self._resume) self._resume.show() - self._copy = ToolButton() - client = gconf.client_get_default() color = XoColor(client.get_string('/desktop/sugar/user/color')) + self._copy = ToolButton() icon = Icon(icon_name='edit-copy', xo_color=color) self._copy.set_icon_widget(icon) icon.show() - - self._copy.set_tooltip(_('Copy')) + self._copy.set_tooltip(_('Copy to')) self._copy.connect('clicked', self._copy_clicked_cb) self.add(self._copy) self._copy.show() + self._duplicate = ToolButton() + icon = Icon(icon_name='edit-duplicate', xo_color=color) + self._copy.set_icon_widget(icon) + self._duplicate.set_tooltip(_('Duplicate')) + self.add(self._duplicate) + separator = gtk.SeparatorToolItem() self.add(separator) separator.show() @@ -396,25 +402,24 @@ class EntryToolbar(gtk.Toolbar): def set_metadata(self, metadata): self._metadata = metadata self._refresh_copy_palette() + self._refresh_duplicate_palette() self._refresh_resume_palette() def _resume_clicked_cb(self, button): misc.resume(self._metadata) def _copy_clicked_cb(self, button): - 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']) - 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 + button.palette.popup(immediate=True, state=Palette.SECONDARY) + + def _duplicate_clicked_cb(self, button): + file_path = model.get_file(self._metadata['uid']) + try: + model.copy(self._metadata, '/') + except IOError, e: + logging.exception('Error while copying the entry.') + self.emit('volume-error', + _('Error while copying the entry. %s') % (e.strerror, ), + _('Error')) def _erase_button_clicked_cb(self, button): registry = bundleregistry.get_registry() @@ -427,24 +432,6 @@ class EntryToolbar(gtk.Toolbar): def _resume_menu_item_activate_cb(self, menu_item, service_name): misc.resume(self._metadata, service_name) - def _copy_menu_item_activate_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')) - def _refresh_copy_palette(self): palette = self._copy.get_palette() @@ -452,35 +439,54 @@ class EntryToolbar(gtk.Toolbar): palette.menu.remove(menu_item) menu_item.destroy() + 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) + palette.menu.append(clipboard_menu) + clipboard_menu.show() + if self._metadata['mountpoint'] != '/': - journal_item = MenuItem(_('Journal')) - journal_item.set_image(Icon( - icon_name='activity-journal', - xo_color=profile.get_color(), - icon_size=gtk.ICON_SIZE_MENU)) - journal_item.connect('activate', - self._copy_menu_item_activate_cb, '/') - journal_item.show() - palette.menu.append(journal_item) + 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) + palette.menu.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 - menu_item = MenuItem(mount.get_name()) - - icon_theme = gtk.icon_theme_get_default() + 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): - menu_item.set_image(Icon(icon_name=name, - icon_size=gtk.ICON_SIZE_MENU)) + volume_menu.set_image(Icon(icon_name=name, + icon_size=gtk.ICON_SIZE_MENU)) break + volume_menu.connect('volume-error', self.__volume_error_cb) + palette.menu.append(volume_menu) + volume_menu.show() + + def _refresh_duplicate_palette(self): + color = misc.get_icon_color(self._metadata) + self._copy.get_icon_widget().props.xo_color = color + if self._metadata['mountpoint'] == '/': + self._duplicate.connect('clicked', self._duplicate_clicked_cb) + self._duplicate.show() + icon = self._duplicate.get_icon_widget() + icon.props.xo_color = color + icon.show() + else: + self._duplicate.hide() - menu_item.connect('activate', - self._copy_menu_item_activate_cb, - mount.get_root().get_path()) - palette.menu.append(menu_item) - menu_item.show() + def __volume_error_cb(self, menu_item, message, severity): + self.emit('volume-error', message, severity) def _refresh_resume_palette(self): if self._metadata.get('activity_id', ''): diff --git a/src/jarabe/journal/listview.py b/src/jarabe/journal/listview.py index 70ab701..a9f5a53 100644 --- a/src/jarabe/journal/listview.py +++ b/src/jarabe/journal/listview.py @@ -476,6 +476,8 @@ class ListView(BaseListView): __gsignals__ = { 'detail-clicked': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([object])), + 'volume-error': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([str, str])), } def __init__(self): @@ -491,6 +493,7 @@ class ListView(BaseListView): self.cell_icon.connect('clicked', self.__icon_clicked_cb) self.cell_icon.connect('detail-clicked', self.__detail_clicked_cb) + self.cell_icon.connect('volume-error', self.__volume_error_cb) cell_detail = CellRendererDetail(self.tree_view) cell_detail.connect('clicked', self.__detail_cell_clicked_cb) @@ -532,6 +535,9 @@ class ListView(BaseListView): def __detail_clicked_cb(self, cell, uid): self.emit('detail-clicked', uid) + def __volume_error_cb(self, cell, message, severity): + self.emit('volume-error', message, severity) + def __icon_clicked_cb(self, cell, path): row = self.tree_view.get_model()[path] metadata = model.get(row[ListModel.COLUMN_UID]) @@ -586,6 +592,8 @@ class CellRendererActivityIcon(CellRendererIcon): __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, tree_view): @@ -610,11 +618,16 @@ class CellRendererActivityIcon(CellRendererIcon): palette = ObjectPalette(metadata, detail=True) palette.connect('detail-clicked', self.__detail_clicked_cb) + palette.connect('volume-error', + self.__volume_error_cb) return palette def __detail_clicked_cb(self, palette, uid): self.emit('detail-clicked', uid) + def __volume_error_cb(self, palette, message, severity): + self.emit('volume-error', message, severity) + def set_show_palette(self, show_palette): self._show_palette = show_palette diff --git a/src/jarabe/journal/model.py b/src/jarabe/journal/model.py index 4ea6b7e..ddf9c07 100644 --- a/src/jarabe/journal/model.py +++ b/src/jarabe/journal/model.py @@ -621,6 +621,8 @@ def copy(metadata, mount_point): client = gconf.client_get_default() metadata['icon-color'] = client.get_string('/desktop/sugar/user/color') file_path = get_file(metadata['uid']) + if file_path is None: + file_path = '' metadata['mountpoint'] = mount_point del metadata['uid'] 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' |