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:
parent
bfe04c2073
commit
8b4ccf3eb1
@ -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 = {}
|
||||||
|
@ -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):
|
||||||
|
@ -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()
|
||||||
|
@ -64,7 +64,9 @@ 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:
|
||||||
|
return
|
||||||
|
|
||||||
logging.debug('ClipboardBox: adding type ' + selection.type + '.')
|
logging.debug('ClipboardBox: adding type ' + selection.type + '.')
|
||||||
|
|
||||||
cb_service = clipboardservice.get_instance()
|
cb_service = clipboardservice.get_instance()
|
||||||
@ -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:
|
||||||
|
@ -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()
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user