From 6240c1cf6fbd47da6743d4a66ebee21cf07fa6a5 Mon Sep 17 00:00:00 2001 From: Marco Pesenti Gritti Date: Tue, 16 Oct 2007 09:04:59 +0000 Subject: Cleanup the source structure --- (limited to 'lib/sugar/clipboard/clipboardservice.py') diff --git a/lib/sugar/clipboard/clipboardservice.py b/lib/sugar/clipboard/clipboardservice.py new file mode 100644 index 0000000..d975330 --- /dev/null +++ b/lib/sugar/clipboard/clipboardservice.py @@ -0,0 +1,229 @@ +"""UI class to access system-level clipboard object""" +# Copyright (C) 2007, One Laptop Per Child +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +import logging +import dbus +import gobject + +NAME_KEY = 'NAME' +PERCENT_KEY = 'PERCENT' +ICON_KEY = 'ICON' +PREVIEW_KEY = 'PREVIEW' +ACTIVITIES_KEY = 'ACTIVITIES' +FORMATS_KEY = 'FORMATS' + +TYPE_KEY = 'TYPE' +DATA_KEY = 'DATA' +ON_DISK_KEY = 'ON_DISK' + +DBUS_SERVICE = "org.laptop.Clipboard" +DBUS_INTERFACE = "org.laptop.Clipboard" +DBUS_PATH = "/org/laptop/Clipboard" + +class ClipboardService(gobject.GObject): + """GUI interfaces for the system clipboard dbus service + + This object is used to provide convenient access to the clipboard + service (see source/services/clipboard/clipboardservice.py). It + provides utility methods for adding/getting/removing objects from + the clipboard as well as generating events when such events occur. + + Meaning is source/services/clipboard/clipboardobject.py + objects when describing "objects" on the clipboard. + """ + __gsignals__ = { + 'object-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([str, str])), + 'object-deleted': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([str])), + 'object-state-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([str, str, int, str, str, object])), + } + + def __init__(self): + """Initialise the ClipboardService instance + + If the service is not yet active in the background uses + a signal watcher to connect when the service appears. + """ + gobject.GObject.__init__(self) + + self._dbus_service = None + + bus = dbus.SessionBus() + self._nameOwnerChangedHandler = bus.add_signal_receiver( + self._name_owner_changed_cb, + signal_name="NameOwnerChanged", + dbus_interface="org.freedesktop.DBus", + arg0=DBUS_SERVICE) + + self._connected = False + # Try to register to ClipboardService, if we fail, we'll try later. + try: + self._connect_clipboard_signals() + except dbus.DBusException, exception: + logging.debug(exception) + + def _connect_clipboard_signals(self): + """Connect dbus signals to our GObject signal generating callbacks""" + bus = dbus.SessionBus() + if not self._connected: + # NOTE: We need to follow_name_owner_changes here + # because we can not connect to a signal unless + # we follow the changes or we start the service + # before we connect. Starting the service here + # causes a major bottleneck during startup + proxy_obj = bus.get_object(DBUS_SERVICE, + DBUS_PATH, + follow_name_owner_changes=True) + self._dbus_service = dbus.Interface(proxy_obj, DBUS_SERVICE) + self._dbus_service.connect_to_signal('object_added', + self._object_added_cb) + self._dbus_service.connect_to_signal('object_deleted', + self._object_deleted_cb) + self._dbus_service.connect_to_signal('object_state_changed', + self._object_state_changed_cb) + self._connected = True + + bus.remove_signal_receiver(self._nameOwnerChangedHandler) + + def _name_owner_changed_cb(self, name, old, new): + """On backend service creation, connect to the server""" + if not old and new: + # ClipboardService started up + self._connect_clipboard_signals() + + def _object_added_cb(self, object_id, name): + """Emit an object-added GObject event when dbus event arrives""" + self.emit('object-added', str(object_id), name) + + def _object_deleted_cb(self, object_id): + """Emit an object-deleted GObject event when dbus event arrives""" + self.emit('object-deleted', str(object_id)) + + def _object_state_changed_cb(self, object_id, values): + """Emit an object-state-changed GObject event when dbus event arrives + + GObject event has: + + object_id + name + percent + icon + preview + activities + + From the ClipboardObject instance which is being described. + """ + self.emit('object-state-changed', str(object_id), values[NAME_KEY], + values[PERCENT_KEY], values[ICON_KEY], values[PREVIEW_KEY], + values[ACTIVITIES_KEY]) + + def add_object(self, name): + """Add a new object to the path + + returns dbus path-name for the new object's cliboard service, + this is used for all future references to the cliboard object. + + Note: + That service is actually provided by the clipboard + service object, not the ClipboardObject + """ + return str(self._dbus_service.add_object(name)) + + def add_object_format(self, object_id, formatType, data, on_disk): + """Annotate given object on the clipboard with new information + + object_id -- dbus path as returned from add_object + formatType -- XXX what should this be? mime type? + data -- storage format for the clipped object? + on_disk -- whether the data is on-disk (non-volatile) or in + memory (volatile) + + Last three arguments are just passed directly to the + clipboardobject.Format instance on the server side. + + returns None + """ + self._dbus_service.add_object_format(dbus.ObjectPath(object_id), + formatType, + data, + on_disk) + + def delete_object(self, object_id): + """Remove the given object from the clipboard + + object_id -- dbus path as returned from add_object + """ + self._dbus_service.delete_object(dbus.ObjectPath(object_id)) + + def set_object_percent(self, object_id, percent): + """Set the "percentage" for the given clipboard object + + object_id -- dbus path as returned from add_object + percentage -- numeric value from 0 to 100 inclusive + + Object percentages which are set to 100% trigger "file-completed" + operations, see the backend ClipboardService's + _handle_file_completed method for details. + + returns None + """ + self._dbus_service.set_object_percent(dbus.ObjectPath(object_id), percent) + + def get_object(self, object_id): + """Retrieve the clipboard object structure for given object + + object_id -- dbus path as returned from add_object + + Retrieves the metadata description of a given object, but + *not* the data for the object. Use get_object_data passing + one of the values in the FORMATS_KEY value in order to + retrieve the data. + + returns dictionary with + NAME_KEY: str, + PERCENT_KEY: number, + ICON_KEY: str, + PREVIEW_KEY: XXX what is it?, + ACTIVITIES_KEY: activities that can open this object, + FORMATS_KEY: list of XXX what is it? + """ + return self._dbus_service.get_object(dbus.ObjectPath(object_id),) + + def get_object_data(self, object_id, formatType): + """Retrieve object's data in the given formatType + + object_id -- dbus path as returned from add_object + formatType -- format specifier XXX of what description + + returns dictionary with + TYPE_KEY: str, + DATA_KEY: str, + ON_DISK_KEY: bool + """ + return self._dbus_service.get_object_data(dbus.ObjectPath(object_id), + formatType, + byte_arrays=True) + +_clipboard_service = None +def get_instance(): + """Retrieve this process's interface to the clipboard service""" + global _clipboard_service + if not _clipboard_service: + _clipboard_service = ClipboardService() + return _clipboard_service -- cgit v0.9.1