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
This commit is contained in:
Dan Williams 2007-03-14 00:50:06 -04:00
parent bfe04c2073
commit 8b4ccf3eb1
6 changed files with 86 additions and 74 deletions

View File

@ -2,8 +2,8 @@ import typeregistry
class ClipboardObject: class ClipboardObject:
def __init__(self, id, name): def __init__(self, object_path, name):
self._id = id self._id = object_path
self._name = name self._name = name
self._percent = 0 self._percent = 0
self._formats = {} self._formats = {}

View File

@ -33,27 +33,35 @@ class ClipboardDBusServiceHelper(dbus.service.Object):
_CLIPBOARD_DBUS_INTERFACE = "org.laptop.Clipboard" _CLIPBOARD_DBUS_INTERFACE = "org.laptop.Clipboard"
_CLIPBOARD_OBJECT_PATH = "/org/laptop/Clipboard" _CLIPBOARD_OBJECT_PATH = "/org/laptop/Clipboard"
_CLIPBOARD_OBJECTS_PATH = _CLIPBOARD_OBJECT_PATH + "/Objects/"
def __init__(self, parent): def __init__(self, parent):
self._parent = parent self._parent = parent
self._objects = {} self._objects = {}
self._next_id = 0
bus = dbus.SessionBus() bus = dbus.SessionBus()
bus_name = dbus.service.BusName(self._CLIPBOARD_DBUS_INTERFACE, bus=bus) bus_name = dbus.service.BusName(self._CLIPBOARD_DBUS_INTERFACE, bus=bus)
dbus.service.Object.__init__(self, bus_name, self._CLIPBOARD_OBJECT_PATH) 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 methods
@dbus.service.method(_CLIPBOARD_DBUS_INTERFACE, @dbus.service.method(_CLIPBOARD_DBUS_INTERFACE,
in_signature="ss", out_signature="") in_signature="s", out_signature="o")
def add_object(self, object_id, name): def add_object(self, name):
self._objects[object_id] = ClipboardObject(object_id, name) op = self._CLIPBOARD_OBJECTS_PATH + "%d" % self._get_next_object_id()
self.object_added(object_id, name) self._objects[op] = ClipboardObject(op, name)
logging.debug('Added object ' + object_id + ' with name ' + 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, @dbus.service.method(_CLIPBOARD_DBUS_INTERFACE,
in_signature="ssayb", out_signature="", byte_arrays=True) in_signature="ssayb", out_signature="", byte_arrays=True)
def add_object_format(self, object_id, format_type, data, on_disk): def add_object_format(self, object_path, format_type, data, on_disk):
cb_object = self._objects[object_id] cb_object = self._objects[str(object_path)]
cb_object.add_format(Format(format_type, data, on_disk)) cb_object.add_format(Format(format_type, data, on_disk))
if on_disk: if on_disk:
@ -61,37 +69,36 @@ class ClipboardDBusServiceHelper(dbus.service.Object):
else: else:
logging.debug('Added in-memory format of type ' + format_type + '.') 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(), PERCENT_KEY: cb_object.get_percent(),
ICON_KEY: cb_object.get_icon(), ICON_KEY: cb_object.get_icon(),
PREVIEW_KEY: cb_object.get_preview(), PREVIEW_KEY: cb_object.get_preview(),
ACTIVITY_KEY: cb_object.get_activity()}) ACTIVITY_KEY: cb_object.get_activity()})
@dbus.service.method(_CLIPBOARD_DBUS_INTERFACE, @dbus.service.method(_CLIPBOARD_DBUS_INTERFACE,
in_signature="s", out_signature="") in_signature="o", out_signature="")
def delete_object(self, object_id): def delete_object(self, object_path):
del self._objects[object_id] del self._objects[str(object_path)]
self.object_deleted(object_id) self.object_deleted(object_path)
logging.debug('Deleted object with object_id ' + object_id) logging.debug('Deleted object with object_id ' + object_path)
@dbus.service.method(_CLIPBOARD_DBUS_INTERFACE, @dbus.service.method(_CLIPBOARD_DBUS_INTERFACE,
in_signature="si", out_signature="") in_signature="oi", out_signature="")
def set_object_percent(self, object_id, percent): def set_object_percent(self, object_path, percent):
cb_object = self._objects[object_id] cb_object = self._objects[str(object_path)]
if percent < 0 or percent > 100:
raise ValueError("invalid percentage")
cb_object.set_percent(percent) cb_object.set_percent(percent)
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: percent, PERCENT_KEY: percent,
ICON_KEY: cb_object.get_icon(), ICON_KEY: cb_object.get_icon(),
PREVIEW_KEY: cb_object.get_preview(), PREVIEW_KEY: cb_object.get_preview(),
ACTIVITY_KEY: cb_object.get_activity()}) ACTIVITY_KEY: cb_object.get_activity()})
logging.debug('Changed object with object_id ' + object_id +
' with percent ' + str(percent))
@dbus.service.method(_CLIPBOARD_DBUS_INTERFACE, @dbus.service.method(_CLIPBOARD_DBUS_INTERFACE,
in_signature="s", out_signature="a{sv}") in_signature="o", out_signature="a{sv}")
def get_object(self, object_id): def get_object(self, object_path):
cb_object = self._objects[object_id] cb_object = self._objects[str(object_path)]
formats = cb_object.get_formats() formats = cb_object.get_formats()
format_types = [] format_types = []
@ -104,26 +111,26 @@ class ClipboardDBusServiceHelper(dbus.service.Object):
PREVIEW_KEY: cb_object.get_preview(), PREVIEW_KEY: cb_object.get_preview(),
ACTIVITY_KEY: cb_object.get_activity(), ACTIVITY_KEY: cb_object.get_activity(),
FORMATS_KEY: format_types} FORMATS_KEY: format_types}
return result_dict return dbus.Dictionary(result_dict)
@dbus.service.method(_CLIPBOARD_DBUS_INTERFACE, @dbus.service.method(_CLIPBOARD_DBUS_INTERFACE,
in_signature="ss", out_signature="ay") in_signature="os", out_signature="ay")
def get_object_data(self, object_id, format_type): def get_object_data(self, object_path, format_type):
cb_object = self._objects[object_id] cb_object = self._objects[str(object_path)]
formats = cb_object.get_formats() formats = cb_object.get_formats()
return formats[format_type].get_data() return dbus.ByteArray(formats[format_type].get_data())
# dbus signals # dbus signals
@dbus.service.signal(_CLIPBOARD_DBUS_INTERFACE, signature="ss") @dbus.service.signal(_CLIPBOARD_DBUS_INTERFACE, signature="os")
def object_added(self, object_id, name): def object_added(self, object_path, name):
pass pass
@dbus.service.signal(_CLIPBOARD_DBUS_INTERFACE, signature="s") @dbus.service.signal(_CLIPBOARD_DBUS_INTERFACE, signature="o")
def object_deleted(self, object_id): def object_deleted(self, object_path):
pass pass
@dbus.service.signal(_CLIPBOARD_DBUS_INTERFACE, signature="sa{sv}") @dbus.service.signal(_CLIPBOARD_DBUS_INTERFACE, signature="oa{sv}")
def object_state_changed(self, object_id, values): def object_state_changed(self, object_path, values):
pass pass
class ClipboardService(object): class ClipboardService(object):

View File

@ -16,6 +16,7 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
import logging import logging
import os
from sugar.graphics.canvasicon import CanvasIcon from sugar.graphics.canvasicon import CanvasIcon
from view.clipboardmenu import ClipboardMenu from view.clipboardmenu import ClipboardMenu
@ -71,7 +72,16 @@ class ClipboardIcon(CanvasIcon):
logging.debug("_icon_activated_cb: " + self._object_id) 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): def _icon_activated_cb(self, icon):
self._open_file() self._open_file()

View File

@ -64,14 +64,16 @@ class ClipboardBox(hippo.CanvasBox):
return None return None
def _add_selection(self, object_id, selection): def _add_selection(self, object_id, selection):
if selection.data: if not selection.data:
logging.debug('ClipboardBox: adding type ' + selection.type + '.') return
cb_service = clipboardservice.get_instance() logging.debug('ClipboardBox: adding type ' + selection.type + '.')
cb_service.add_object_format(object_id,
selection.type, cb_service = clipboardservice.get_instance()
selection.data, cb_service.add_object_format(object_id,
on_disk = False) selection.type,
selection.data,
on_disk = False)
def _object_added_cb(self, cb_service, object_id, name): def _object_added_cb(self, cb_service, object_id, name):
icon = ClipboardIcon(self._popup_context, object_id, name) icon = ClipboardIcon(self._popup_context, object_id, name)
@ -90,7 +92,6 @@ class ClipboardBox(hippo.CanvasBox):
icon_name, preview, activity): icon_name, preview, activity):
icon = self._icons[object_id] icon = self._icons[object_id]
icon.set_state(name, percent, icon_name, preview, activity) 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): def drag_motion_cb(self, widget, context, x, y, time):
logging.debug('ClipboardBox._drag_motion_cb') logging.debug('ClipboardBox._drag_motion_cb')
@ -99,11 +100,10 @@ class ClipboardBox(hippo.CanvasBox):
def drag_drop_cb(self, widget, context, x, y, time): def drag_drop_cb(self, widget, context, x, y, time):
logging.debug('ClipboardBox._drag_drop_cb') logging.debug('ClipboardBox._drag_drop_cb')
object_id = util.unique_id()
self._context_map.add_context(context, object_id, len(context.targets))
cb_service = clipboardservice.get_instance() cb_service = clipboardservice.get_instance()
cb_service.add_object(object_id, name="") object_id = cb_service.add_object(name="")
self._context_map.add_context(context, object_id, len(context.targets))
for target in context.targets: for target in context.targets:
if str(target) not in ('TIMESTAMP', 'TARGETS', 'MULTIPLE'): if str(target) not in ('TIMESTAMP', 'TARGETS', 'MULTIPLE'):
@ -186,8 +186,8 @@ class ClipboardBox(hippo.CanvasBox):
def _get_targets_for_dnd(self, object_id): def _get_targets_for_dnd(self, object_id):
cb_service = clipboardservice.get_instance() cb_service = clipboardservice.get_instance()
(name, percent, icon, preview, activity, format_types) = \ attrs = cb_service.get_object(object_id)
cb_service.get_object(object_id) format_types = attrs[clipboardservice.FORMATS_KEY]
targets = [] targets = []
for format_type in format_types: for format_type in format_types:

View File

@ -43,10 +43,8 @@ class ClipboardPanelWindow(PanelWindow):
def _owner_change_cb(self, clipboard, event): def _owner_change_cb(self, clipboard, event):
logging.debug("owner_change_cb") logging.debug("owner_change_cb")
key = util.unique_id()
cb_service = clipboardservice.get_instance() 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) cb_service.set_object_percent(key, percent = 100)
targets = clipboard.wait_for_targets() targets = clipboard.wait_for_targets()

View File

@ -64,40 +64,37 @@ class ClipboardService(gobject.GObject):
self._connect_clipboard_signals() self._connect_clipboard_signals()
def _object_added_cb(self, object_id, name): 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): 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): 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[PERCENT_KEY], values[ICON_KEY], values[PREVIEW_KEY],
values[ACTIVITY_KEY]) values[ACTIVITY_KEY])
def add_object(self, object_id, name): def add_object(self, name):
self._dbus_service.add_object(object_id, name) return str(self._dbus_service.add_object(name))
def add_object_format(self, object_id, formatType, data, on_disk): 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, formatType,
data, data,
on_disk) on_disk)
def delete_object(self, object_id): 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): 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): def get_object(self, object_id):
result_dict = self._dbus_service.get_object(object_id,) return self._dbus_service.get_object(dbus.ObjectPath(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])
def get_object_data(self, object_id, formatType): 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) byte_arrays=True)
_clipboard_service = None _clipboard_service = None