diff options
author | Gonzalo Odiard <godiard@gmail.com> | 2012-04-24 11:17:56 (GMT) |
---|---|---|
committer | Simon Schampijer <simon@schampijer.de> | 2012-04-27 18:18:30 (GMT) |
commit | fc55d52993d7f081d8b97c139ace19a312343a79 (patch) | |
tree | 07770811245326572b06945a04cb4e2dc3e56ab3 /src | |
parent | f28956e3d2c3c79f8ef350adba4d168f0e827886 (diff) |
Only add one time every object to the clipboard, SL #3371
This patch changes the behaviour of the clipboard tray,
every object is only added one time, if it already exists,
the already added object is selected and a notification is displayed
(showing a flashing icon in the lower left corner).
A hash over the data in the object is used to determine if the object
is already present in the Journal. When the object is an uri,
a md5sum is calculated over the file and the hash is done over the result.
We need check if the object is already in the clipboard
because a bad interaction between the clipboard in write and
the text to speech feature. See the ticket for more information.
Signed-off-by: Gonzalo Odiard <gonzalo@laptop.org>
Acked-by: Simon Schampijer <simon@laptop.org>
Diffstat (limited to 'src')
-rw-r--r-- | src/jarabe/frame/clipboard.py | 29 | ||||
-rw-r--r-- | src/jarabe/frame/clipboardicon.py | 26 | ||||
-rw-r--r-- | src/jarabe/frame/clipboardpanelwindow.py | 36 |
3 files changed, 78 insertions, 13 deletions
diff --git a/src/jarabe/frame/clipboard.py b/src/jarabe/frame/clipboard.py index be2b902..5ce0e7e 100644 --- a/src/jarabe/frame/clipboard.py +++ b/src/jarabe/frame/clipboard.py @@ -36,7 +36,9 @@ class Clipboard(gobject.GObject): 'object-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([object])), 'object-deleted': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([int])), + ([long])), + 'object-selected': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([long])), 'object-state-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([object])), } @@ -51,9 +53,28 @@ class Clipboard(gobject.GObject): self._next_id += 1 return self._next_id - def add_object(self, name): - logging.debug('Clipboard.add_object') - object_id = self._get_next_object_id() + def add_object(self, name, data_hash=None): + """ Add a object to the clipboard + + Keyword arguments: + name -- object name + data_hash -- hash to check if the object is already + in the clipboard, generated with hash() + over the data to be added + + Return: object_id or None if the object is not added + + """ + logging.debug('Clipboard.add_object: hash %s', data_hash) + if data_hash is None: + object_id = self._get_next_object_id() + else: + object_id = data_hash + if object_id in self._objects: + logging.debug('Clipboard.add_object: object already in clipboard,' + ' selecting previous entry instead') + self.emit('object-selected', object_id) + return None self._objects[object_id] = ClipboardObject(object_id, name) self.emit('object-added', self._objects[object_id]) return object_id diff --git a/src/jarabe/frame/clipboardicon.py b/src/jarabe/frame/clipboardicon.py index aa72d8a..315cdaa 100644 --- a/src/jarabe/frame/clipboardicon.py +++ b/src/jarabe/frame/clipboardicon.py @@ -57,6 +57,7 @@ class ClipboardIcon(RadioToolButton): cb_service = clipboard.get_instance() cb_service.connect('object-state-changed', self._object_state_changed_cb) + cb_service.connect('object-selected', self._object_selected_cb) child = self.get_child() child.connect('drag_data_get', self._drag_data_get_cb) @@ -128,17 +129,26 @@ class ClipboardIcon(RadioToolButton): # Clipboard object became complete. Make it the active one. if self._current_percent < 100 and cb_object.get_percent() == 100: self.props.active = True + self.show_notification() - self._notif_icon = NotificationIcon() - self._notif_icon.props.icon_name = self._icon.props.icon_name - self._notif_icon.props.xo_color = \ - XoColor('%s,%s' % (self._icon.props.stroke_color, - self._icon.props.fill_color)) - frame = jarabe.frame.get_view() - frame.add_notification(self._notif_icon, - gtk.CORNER_BOTTOM_LEFT) self._current_percent = cb_object.get_percent() + def _object_selected_cb(self, cb_service, object_id): + if object_id != self._cb_object.get_id(): + return + self.props.active = True + self.show_notification() + logging.debug('ClipboardIcon: %r was selected', object_id) + + def show_notification(self): + self._notif_icon = NotificationIcon() + self._notif_icon.props.icon_name = self._icon.props.icon_name + self._notif_icon.props.xo_color = \ + XoColor('%s,%s' % (self._icon.props.stroke_color, + self._icon.props.fill_color)) + frame = jarabe.frame.get_view() + frame.add_notification(self._notif_icon, gtk.CORNER_BOTTOM_LEFT) + def _drag_begin_cb(self, widget, context): # TODO: We should get the pixbuf from the icon, with colors, etc. icon_theme = gtk.icon_theme_get_default() diff --git a/src/jarabe/frame/clipboardpanelwindow.py b/src/jarabe/frame/clipboardpanelwindow.py index b73572e..6811c0d 100644 --- a/src/jarabe/frame/clipboardpanelwindow.py +++ b/src/jarabe/frame/clipboardpanelwindow.py @@ -16,6 +16,7 @@ import logging from urlparse import urlparse +import hashlib import gtk @@ -59,23 +60,56 @@ class ClipboardPanelWindow(FrameWindow): targets = x_clipboard.wait_for_targets() cb_selections = [] + if targets is None: + return + + target_is_uri = False for target in targets: if target not in ('TIMESTAMP', 'TARGETS', 'MULTIPLE', 'SAVE_TARGETS'): logging.debug('Asking for target %s.', target) + if target == 'text/uri-list': + target_is_uri = True + selection = x_clipboard.wait_for_contents(target) if not selection: logging.warning('no data for selection target %s.', target) continue cb_selections.append(selection) + if target_is_uri: + uri = selection.data + filename = uri[len('file://'):].strip() + md5 = self._md5_for_file(filename) + data_hash = hash(md5) + else: + data_hash = hash(selection.data) + if len(cb_selections) > 0: - key = cb_service.add_object(name="") + key = cb_service.add_object(name="", data_hash=data_hash) + if key is None: + return cb_service.set_object_percent(key, percent=0) for selection in cb_selections: self._add_selection(key, selection) cb_service.set_object_percent(key, percent=100) + def _md5_for_file(self, file_name): + '''Calculate md5 for file data + + Calculating block wise to prevent issues with big files in memory + ''' + block_size = 8192 + md5 = hashlib.md5() + f = open(file_name, 'r') + while True: + data = f.read(block_size) + if not data: + break + md5.update(data) + f.close() + return md5.digest() + def _add_selection(self, key, selection): if not selection.data: logging.warning('no data for selection target %s.', selection.type) |