[Sugar-devel] [PATCH] Only add one time every object in the clipboard v5 - SL #3371

Anish Mangal anish at activitycentral.com
Tue Apr 24 08:17:59 EDT 2012


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Tue 24 Apr 2012 04:47:56 PM IST, godiard at sugarlabs.org wrote:
> From: Gonzalo Odiard <godiard at gmail.com>
>
> This patch change the behaviour of the clipboard tray,
> every object is added only one time, if already exist,
> 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 a 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 at laptop.org>
>
> ----
>
> v2: Select the already added object if needed, as sugested by Sascha.
> v3: Show the notification when copy a already existing object, as sugested by Gary
> v4: Check targets is not None
> v5: Chages acording to Sascha review and management of uri from the journal
> ---
>  src/jarabe/frame/clipboard.py            |   22 +++++++++++++++---
>  src/jarabe/frame/clipboardicon.py        |   26 +++++++++++++++-------
>  src/jarabe/frame/clipboardpanelwindow.py |   34 +++++++++++++++++++++++++++++-
>  3 files changed, 69 insertions(+), 13 deletions(-)
>
> diff --git a/src/jarabe/frame/clipboard.py b/src/jarabe/frame/clipboard.py
> index be2b902..f3da89f 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,21 @@ 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.
> +        data_hash is a long used to check if the object is already
> +        in the clipboard, generated with hash() over the data to be added.
> +        Return the 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('Duplicate entry, 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..c91e578 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,54 @@ class ClipboardPanelWindow(FrameWindow):
>
>          targets = x_clipboard.wait_for_targets()
>          cb_selections = []
> +        if targets is None:
> +            return
> +
> +        target_is_uri = False
>          for target in targets:
> +            logging.error('TARGET: %s', target)
>              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)
> +            logging.error('Target is a uri %s', uri)
> +            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):
> +        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)

Tested on f16-jhbuild:
* Duplicate entries are NOT created, if items are copied from the
journal.
* Rest of the functionality remains the same
* Tried with the write activity (text and image clippings) and from the
journal (image clipping). Duplicate entries not created.

Tested-by: Anish Mangal <anish at activitycentral.com>
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.12 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iQEcBAEBAgAGBQJPlpnzAAoJEBoxUdDHDZVpCskH/3Z+X/Y/alOBa7DqEtnwS8io
U038fYftYuMVi92evNRnSxGFhmV4dqPvGM6eQ88nJ+KebEDqB0vnObXrAvDNmXgp
6KCM/4BBK1STtDr/kqe3v7eY3wmryZQz61tikUwcEjZtdbBqZo2RSoATA4usblN7
vlcCj+B6yTAULYBsIQipIMCx8Rvn1KiGaMRWaL7uRRG+p5Q0km1xzSW56kVTeK43
dVlAczTczsJaSpr5k00BYhqKyya/tzQMsvLItXbgM9ZbqxCPdUSyfp0e5HZLzOjv
Eusod2ysieH0ZwaGP2fpoBBxzx/KpUnAOETM82wBaqk8GecwNKpqZyuqLNPPzYE=
=E2FE
-----END PGP SIGNATURE-----



More information about the Sugar-devel mailing list