Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGonzalo Odiard <godiard@gmail.com>2012-04-24 11:17:56 (GMT)
committer Simon Schampijer <simon@schampijer.de>2012-04-27 18:18:30 (GMT)
commitfc55d52993d7f081d8b97c139ace19a312343a79 (patch)
tree07770811245326572b06945a04cb4e2dc3e56ab3 /src
parentf28956e3d2c3c79f8ef350adba4d168f0e827886 (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.py29
-rw-r--r--src/jarabe/frame/clipboardicon.py26
-rw-r--r--src/jarabe/frame/clipboardpanelwindow.py36
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)