From 8b4ccf3eb10d0563344e123f7f2c773bba120a2f Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 14 Mar 2007 00:50:06 -0400 Subject: [PATCH] Cleanup clipboard D-Bus API - The clipboard now determines each objects unique id and returns it from add_object() - The ID is opaque to the client and should not be used/accessed other than with the clipboard service - Add object type hints for dbus-python - Sugar clipboard bindings for get_object() now return a dict rather than a tuple - ClipboardIcon now retrieves the real file path and uses that to open the file - Adapt sugar bits to clipboard changes --- services/clipboard/clipboardobject.py | 6 +- services/clipboard/clipboardservice.py | 83 +++++++++++++----------- shell/view/clipboardicon.py | 12 +++- shell/view/frame/clipboardbox.py | 30 ++++----- shell/view/frame/clipboardpanelwindow.py | 4 +- sugar/clipboard/clipboardservice.py | 25 ++++--- 6 files changed, 86 insertions(+), 74 deletions(-) diff --git a/services/clipboard/clipboardobject.py b/services/clipboard/clipboardobject.py index 5fe18b7e..af8ba5f9 100644 --- a/services/clipboard/clipboardobject.py +++ b/services/clipboard/clipboardobject.py @@ -2,12 +2,12 @@ import typeregistry class ClipboardObject: - def __init__(self, id, name): - self._id = id + def __init__(self, object_path, name): + self._id = object_path self._name = name self._percent = 0 self._formats = {} - + def get_id(self): return self._id diff --git a/services/clipboard/clipboardservice.py b/services/clipboard/clipboardservice.py index 5a7e42ad..282dfd38 100644 --- a/services/clipboard/clipboardservice.py +++ b/services/clipboard/clipboardservice.py @@ -33,27 +33,35 @@ class ClipboardDBusServiceHelper(dbus.service.Object): _CLIPBOARD_DBUS_INTERFACE = "org.laptop.Clipboard" _CLIPBOARD_OBJECT_PATH = "/org/laptop/Clipboard" + _CLIPBOARD_OBJECTS_PATH = _CLIPBOARD_OBJECT_PATH + "/Objects/" def __init__(self, parent): self._parent = parent self._objects = {} + self._next_id = 0 bus = dbus.SessionBus() bus_name = dbus.service.BusName(self._CLIPBOARD_DBUS_INTERFACE, bus=bus) dbus.service.Object.__init__(self, bus_name, self._CLIPBOARD_OBJECT_PATH) + def _get_next_object_id(self): + self._next_id += 1 + return self._next_id + # dbus methods @dbus.service.method(_CLIPBOARD_DBUS_INTERFACE, - in_signature="ss", out_signature="") - def add_object(self, object_id, name): - self._objects[object_id] = ClipboardObject(object_id, name) - self.object_added(object_id, name) - logging.debug('Added object ' + object_id + ' with name ' + name) + in_signature="s", out_signature="o") + def add_object(self, name): + op = self._CLIPBOARD_OBJECTS_PATH + "%d" % self._get_next_object_id() + self._objects[op] = ClipboardObject(op, name) + self.object_added(dbus.ObjectPath(op), name) + logging.debug('Added object ' + op + ' with name ' + name) + return dbus.ObjectPath(op) @dbus.service.method(_CLIPBOARD_DBUS_INTERFACE, in_signature="ssayb", out_signature="", byte_arrays=True) - def add_object_format(self, object_id, format_type, data, on_disk): - cb_object = self._objects[object_id] + def add_object_format(self, object_path, format_type, data, on_disk): + cb_object = self._objects[str(object_path)] cb_object.add_format(Format(format_type, data, on_disk)) if on_disk: @@ -61,37 +69,36 @@ class ClipboardDBusServiceHelper(dbus.service.Object): else: logging.debug('Added in-memory format of type ' + format_type + '.') - self.object_state_changed(object_id, {NAME_KEY: cb_object.get_name(), + self.object_state_changed(object_path, {NAME_KEY: cb_object.get_name(), PERCENT_KEY: cb_object.get_percent(), ICON_KEY: cb_object.get_icon(), PREVIEW_KEY: cb_object.get_preview(), ACTIVITY_KEY: cb_object.get_activity()}) @dbus.service.method(_CLIPBOARD_DBUS_INTERFACE, - in_signature="s", out_signature="") - def delete_object(self, object_id): - del self._objects[object_id] - self.object_deleted(object_id) - logging.debug('Deleted object with object_id ' + object_id) + in_signature="o", out_signature="") + def delete_object(self, object_path): + del self._objects[str(object_path)] + self.object_deleted(object_path) + logging.debug('Deleted object with object_id ' + object_path) @dbus.service.method(_CLIPBOARD_DBUS_INTERFACE, - in_signature="si", out_signature="") - def set_object_percent(self, object_id, percent): - cb_object = self._objects[object_id] + in_signature="oi", out_signature="") + def set_object_percent(self, object_path, percent): + cb_object = self._objects[str(object_path)] + if percent < 0 or percent > 100: + raise ValueError("invalid percentage") cb_object.set_percent(percent) - self.object_state_changed(object_id, {NAME_KEY: cb_object.get_name(), - PERCENT_KEY: percent, - ICON_KEY: cb_object.get_icon(), - PREVIEW_KEY: cb_object.get_preview(), - ACTIVITY_KEY: cb_object.get_activity()}) - - logging.debug('Changed object with object_id ' + object_id + - ' with percent ' + str(percent)) + self.object_state_changed(object_path, {NAME_KEY: cb_object.get_name(), + PERCENT_KEY: percent, + ICON_KEY: cb_object.get_icon(), + PREVIEW_KEY: cb_object.get_preview(), + ACTIVITY_KEY: cb_object.get_activity()}) @dbus.service.method(_CLIPBOARD_DBUS_INTERFACE, - in_signature="s", out_signature="a{sv}") - def get_object(self, object_id): - cb_object = self._objects[object_id] + in_signature="o", out_signature="a{sv}") + def get_object(self, object_path): + cb_object = self._objects[str(object_path)] formats = cb_object.get_formats() format_types = [] @@ -104,26 +111,26 @@ class ClipboardDBusServiceHelper(dbus.service.Object): PREVIEW_KEY: cb_object.get_preview(), ACTIVITY_KEY: cb_object.get_activity(), FORMATS_KEY: format_types} - return result_dict + return dbus.Dictionary(result_dict) @dbus.service.method(_CLIPBOARD_DBUS_INTERFACE, - in_signature="ss", out_signature="ay") - def get_object_data(self, object_id, format_type): - cb_object = self._objects[object_id] + in_signature="os", out_signature="ay") + def get_object_data(self, object_path, format_type): + cb_object = self._objects[str(object_path)] formats = cb_object.get_formats() - return formats[format_type].get_data() + return dbus.ByteArray(formats[format_type].get_data()) # dbus signals - @dbus.service.signal(_CLIPBOARD_DBUS_INTERFACE, signature="ss") - def object_added(self, object_id, name): + @dbus.service.signal(_CLIPBOARD_DBUS_INTERFACE, signature="os") + def object_added(self, object_path, name): pass - @dbus.service.signal(_CLIPBOARD_DBUS_INTERFACE, signature="s") - def object_deleted(self, object_id): + @dbus.service.signal(_CLIPBOARD_DBUS_INTERFACE, signature="o") + def object_deleted(self, object_path): pass - @dbus.service.signal(_CLIPBOARD_DBUS_INTERFACE, signature="sa{sv}") - def object_state_changed(self, object_id, values): + @dbus.service.signal(_CLIPBOARD_DBUS_INTERFACE, signature="oa{sv}") + def object_state_changed(self, object_path, values): pass class ClipboardService(object): diff --git a/shell/view/clipboardicon.py b/shell/view/clipboardicon.py index 89d55ba1..7167bcec 100644 --- a/shell/view/clipboardicon.py +++ b/shell/view/clipboardicon.py @@ -16,6 +16,7 @@ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA import logging +import os from sugar.graphics.canvasicon import CanvasIcon from view.clipboardmenu import ClipboardMenu @@ -71,7 +72,16 @@ class ClipboardIcon(CanvasIcon): logging.debug("_icon_activated_cb: " + self._object_id) - activityfactory.create_with_uri(self._activity, self._object_id) + # Get the file path + cb_service = clipboardservice.get_instance() + obj = cb_service.get_object(self._object_id) + formats = obj['FORMATS'] + if len(formats) > 0: + path = cb_service.get_object_data(self._object_id, formats[0]) + if os.path.exists(path): + activityfactory.create_with_uri(self._activity, path) + else: + logging.debug("Clipboard item file path %s didn't exist" % path) def _icon_activated_cb(self, icon): self._open_file() diff --git a/shell/view/frame/clipboardbox.py b/shell/view/frame/clipboardbox.py index d5e435ea..031854aa 100644 --- a/shell/view/frame/clipboardbox.py +++ b/shell/view/frame/clipboardbox.py @@ -64,14 +64,16 @@ class ClipboardBox(hippo.CanvasBox): return None def _add_selection(self, object_id, selection): - if selection.data: - logging.debug('ClipboardBox: adding type ' + selection.type + '.') - - cb_service = clipboardservice.get_instance() - cb_service.add_object_format(object_id, - selection.type, - selection.data, - on_disk = False) + if not selection.data: + return + + logging.debug('ClipboardBox: adding type ' + selection.type + '.') + + cb_service = clipboardservice.get_instance() + cb_service.add_object_format(object_id, + selection.type, + selection.data, + on_disk = False) def _object_added_cb(self, cb_service, object_id, name): icon = ClipboardIcon(self._popup_context, object_id, name) @@ -90,7 +92,6 @@ class ClipboardBox(hippo.CanvasBox): icon_name, preview, activity): icon = self._icons[object_id] icon.set_state(name, percent, icon_name, preview, activity) - logging.debug('ClipboardBox: ' + object_id + ' state was changed.') def drag_motion_cb(self, widget, context, x, y, time): logging.debug('ClipboardBox._drag_motion_cb') @@ -99,12 +100,11 @@ class ClipboardBox(hippo.CanvasBox): def drag_drop_cb(self, widget, context, x, y, time): logging.debug('ClipboardBox._drag_drop_cb') - object_id = util.unique_id() + cb_service = clipboardservice.get_instance() + object_id = cb_service.add_object(name="") + self._context_map.add_context(context, object_id, len(context.targets)) - cb_service = clipboardservice.get_instance() - cb_service.add_object(object_id, name="") - for target in context.targets: if str(target) not in ('TIMESTAMP', 'TARGETS', 'MULTIPLE'): widget.drag_get_data(context, target, time) @@ -186,8 +186,8 @@ class ClipboardBox(hippo.CanvasBox): def _get_targets_for_dnd(self, object_id): cb_service = clipboardservice.get_instance() - (name, percent, icon, preview, activity, format_types) = \ - cb_service.get_object(object_id) + attrs = cb_service.get_object(object_id) + format_types = attrs[clipboardservice.FORMATS_KEY] targets = [] for format_type in format_types: diff --git a/shell/view/frame/clipboardpanelwindow.py b/shell/view/frame/clipboardpanelwindow.py index cfdb4d55..6ee7ab85 100644 --- a/shell/view/frame/clipboardpanelwindow.py +++ b/shell/view/frame/clipboardpanelwindow.py @@ -43,10 +43,8 @@ class ClipboardPanelWindow(PanelWindow): def _owner_change_cb(self, clipboard, event): logging.debug("owner_change_cb") - key = util.unique_id() - cb_service = clipboardservice.get_instance() - cb_service.add_object(key, name="") + key = cb_service.add_object(name="") cb_service.set_object_percent(key, percent = 100) targets = clipboard.wait_for_targets() diff --git a/sugar/clipboard/clipboardservice.py b/sugar/clipboard/clipboardservice.py index 1878cba5..c7d68e46 100644 --- a/sugar/clipboard/clipboardservice.py +++ b/sugar/clipboard/clipboardservice.py @@ -64,40 +64,37 @@ class ClipboardService(gobject.GObject): self._connect_clipboard_signals() def _object_added_cb(self, object_id, name): - self.emit('object-added', object_id, name) + self.emit('object-added', str(object_id), name) def _object_deleted_cb(self, object_id): - self.emit('object-deleted', object_id) + self.emit('object-deleted', str(object_id)) def _object_state_changed_cb(self, object_id, values): - self.emit('object-state-changed', object_id, values[NAME_KEY], + self.emit('object-state-changed', str(object_id), values[NAME_KEY], values[PERCENT_KEY], values[ICON_KEY], values[PREVIEW_KEY], values[ACTIVITY_KEY]) - def add_object(self, object_id, name): - self._dbus_service.add_object(object_id, name) + def add_object(self, name): + return str(self._dbus_service.add_object(name)) def add_object_format(self, object_id, formatType, data, on_disk): - self._dbus_service.add_object_format(object_id, + self._dbus_service.add_object_format(dbus.ObjectPath(object_id), formatType, data, on_disk) def delete_object(self, object_id): - self._dbus_service.delete_object(object_id) + self._dbus_service.delete_object(dbus.ObjectPath(object_id)) def set_object_percent(self, object_id, percent): - self._dbus_service.set_object_percent(object_id, percent) + self._dbus_service.set_object_percent(dbus.ObjectPath(object_id), percent) def get_object(self, object_id): - result_dict = self._dbus_service.get_object(object_id,) - - return (result_dict[NAME_KEY], result_dict[PERCENT_KEY], - result_dict[ICON_KEY], result_dict[PREVIEW_KEY], - result_dict[ACTIVITY_KEY], result_dict[FORMATS_KEY]) + return self._dbus_service.get_object(dbus.ObjectPath(object_id),) def get_object_data(self, object_id, formatType): - return self._dbus_service.get_object_data(object_id, formatType, + return self._dbus_service.get_object_data(dbus.ObjectPath(object_id), + formatType, byte_arrays=True) _clipboard_service = None