Merge branch 'master' of git+ssh://dev.laptop.org/git/sugar

This commit is contained in:
Marco Pesenti Gritti 2007-04-15 11:42:06 +02:00
commit ee400fa602
6 changed files with 278 additions and 3 deletions

View File

@ -0,0 +1,5 @@
"""Client-code's interface to the ClipboardService
Provides a simplified API for accessing the dbus service
which coordinates clipboard operations within Sugar.
"""

View File

@ -0,0 +1 @@
"""Hippo-based graphics/controls for use in Sugar"""

View File

@ -0,0 +1,7 @@
"""Client-code's interface to the PresenceService
Provides a simplified API for accessing the dbus service
which coordinates native network presence and sharing
information. This includes both "buddies" and "shared
activities".
"""

View File

@ -1,3 +1,4 @@
"""UI interface to an activity in the presence service"""
# Copyright (C) 2007, Red Hat, Inc. # Copyright (C) 2007, Red Hat, Inc.
# #
# This library is free software; you can redistribute it and/or # This library is free software; you can redistribute it and/or
@ -19,7 +20,19 @@ import gobject
import dbus import dbus
class Activity(gobject.GObject): class Activity(gobject.GObject):
"""UI interface for an Activity in the presence service
Activities in the presence service represent other user's
shared activities and your own activities (XXX shared or
otherwise?)
Properties:
id
color
name
type
joined
"""
__gsignals__ = { __gsignals__ = {
'buddy-joined': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, 'buddy-joined': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT])), ([gobject.TYPE_PYOBJECT])),
@ -33,6 +46,7 @@ class Activity(gobject.GObject):
_ACTIVITY_DBUS_INTERFACE = "org.laptop.Sugar.Presence.Activity" _ACTIVITY_DBUS_INTERFACE = "org.laptop.Sugar.Presence.Activity"
def __init__(self, bus, new_obj_cb, del_obj_cb, object_path): def __init__(self, bus, new_obj_cb, del_obj_cb, object_path):
"""Initialse the activity interface, connecting to service"""
gobject.GObject.__init__(self) gobject.GObject.__init__(self)
self._object_path = object_path self._object_path = object_path
self._ps_new_object = new_obj_cb self._ps_new_object = new_obj_cb
@ -50,9 +64,11 @@ class Activity(gobject.GObject):
self._joined = False self._joined = False
def object_path(self): def object_path(self):
"""Get our dbus object path"""
return self._object_path return self._object_path
def _emit_buddy_joined_signal(self, object_path): def _emit_buddy_joined_signal(self, object_path):
"""Generate buddy-joined GObject signal with presence Buddy object"""
self.emit('buddy-joined', self._ps_new_object(object_path)) self.emit('buddy-joined', self._ps_new_object(object_path))
return False return False
@ -60,6 +76,10 @@ class Activity(gobject.GObject):
gobject.idle_add(self._emit_buddy_joined_signal, object_path) gobject.idle_add(self._emit_buddy_joined_signal, object_path)
def _emit_buddy_left_signal(self, object_path): def _emit_buddy_left_signal(self, object_path):
"""Generate buddy-left GObject signal with presence Buddy object
XXX note use of _ps_new_object instead of _ps_del_object here
"""
self.emit('buddy-left', self._ps_new_object(object_path)) self.emit('buddy-left', self._ps_new_object(object_path))
return False return False
@ -67,6 +87,10 @@ class Activity(gobject.GObject):
gobject.idle_add(self._emit_buddy_left_signal, object_path) gobject.idle_add(self._emit_buddy_left_signal, object_path)
def _emit_new_channel_signal(self, object_path): def _emit_new_channel_signal(self, object_path):
"""Generate new-channel GObject signal with channel object path
New telepathy-python communications channel has been opened
"""
self.emit('new-channel', object_path) self.emit('new-channel', object_path)
return False return False
@ -74,27 +98,35 @@ class Activity(gobject.GObject):
gobject.idle_add(self._emit_new_channel_signal, object_path) gobject.idle_add(self._emit_new_channel_signal, object_path)
def get_id(self): def get_id(self):
"""Retrieve the unique identifier for this activity instance"""
# Cache activity ID, which should never change anyway # Cache activity ID, which should never change anyway
if not self._id: if not self._id:
self._id = self._activity.GetId() self._id = self._activity.GetId()
return self._id return self._id
def get_color(self): def get_color(self):
"""Retrieve the activity icon colour for this activity instance"""
if not self._color: if not self._color:
self._color = self._activity.GetColor() self._color = self._activity.GetColor()
return self._color return self._color
def get_name(self): def get_name(self):
"""Retrieve the activity name for this activity instance"""
if not self._name: if not self._name:
self._name = self._activity.GetName() self._name = self._activity.GetName()
return self._name return self._name
def get_type(self): def get_type(self):
"""Retrieve the activity/bundle type for this activity instance"""
if not self._type: if not self._type:
self._type = self._activity.GetType() self._type = self._activity.GetType()
return self._type return self._type
def get_joined_buddies(self): def get_joined_buddies(self):
"""Retrieve the set of Buddy objects attached to this activity
returns list of presence Buddy objects
"""
resp = self._activity.GetJoinedBuddies() resp = self._activity.GetJoinedBuddies()
buddies = [] buddies = []
for item in resp: for item in resp:
@ -102,15 +134,26 @@ class Activity(gobject.GObject):
return buddies return buddies
def join(self): def join(self):
"""Join this activity
XXX if these are all activities, can I join my own activity?
"""
if self._joined: if self._joined:
return return
self._activity.Join() self._activity.Join()
self._joined = True self._joined = True
def get_channels(self): def get_channels(self):
"""Retrieve communications channel descriptions for the activity
Returns (bus name, connection, channels) for the activity
XXX what are those values?
"""
(bus_name, connection, channels) = self._activity.GetChannels() (bus_name, connection, channels) = self._activity.GetChannels()
return bus_name, connection, channels return bus_name, connection, channels
def owner_has_joined(self): def owner_has_joined(self):
"""Retrieve whether the owner of the activity is active within it"""
# FIXME # FIXME
return False return False

View File

@ -1,3 +1,4 @@
"""UI interface to a buddy in the presence service"""
# Copyright (C) 2007, Red Hat, Inc. # Copyright (C) 2007, Red Hat, Inc.
# #
# This library is free software; you can redistribute it and/or # This library is free software; you can redistribute it and/or
@ -20,13 +21,33 @@ import gtk
import dbus import dbus
def _bytes_to_string(bytes): def _bytes_to_string(bytes):
"""Convertes an short-int (char) array to a string
returns string or None for a null sequence
"""
if len(bytes): if len(bytes):
# if there's an internal buffer, we could use
# ctypes to pull it out without this...
return ''.join([chr(item) for item in bytes]) return ''.join([chr(item) for item in bytes])
return None return None
class Buddy(gobject.GObject): class Buddy(gobject.GObject):
"""UI interface for a Buddy in the presence service
Each buddy interface tracks a set of activities and properties
that can be queried to provide UI controls for manipulating
the presence interface.
Properties Dictionary:
'key': public key,
'nick': nickname ,
'color': color (XXX what format),
'current-activity': (XXX dbus path?),
'owner': (XXX dbus path?),
'icon': (XXX pixel data for an icon?)
See __gproperties__
"""
__gsignals__ = { __gsignals__ = {
'icon-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, 'icon-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([])), ([])),
@ -51,6 +72,13 @@ class Buddy(gobject.GObject):
_BUDDY_DBUS_INTERFACE = "org.laptop.Sugar.Presence.Buddy" _BUDDY_DBUS_INTERFACE = "org.laptop.Sugar.Presence.Buddy"
def __init__(self, bus, new_obj_cb, del_obj_cb, object_path): def __init__(self, bus, new_obj_cb, del_obj_cb, object_path):
"""Initialise the reference to the buddy
bus -- dbus bus object
new_obj_cb -- callback to call when this buddy joins an activity
del_obj_cb -- callback to call when this buddy leaves an activity
object_path -- path to the buddy object
"""
gobject.GObject.__init__(self) gobject.GObject.__init__(self)
self._object_path = object_path self._object_path = object_path
self._ps_new_object = new_obj_cb self._ps_new_object = new_obj_cb
@ -68,12 +96,19 @@ class Buddy(gobject.GObject):
self._icon = None self._icon = None
def _get_properties_helper(self): def _get_properties_helper(self):
"""Retrieve the Buddy's property dictionary from the service object
"""
props = self._buddy.GetProperties() props = self._buddy.GetProperties()
if not props: if not props:
return {} return {}
return props return props
def do_get_property(self, pspec): def do_get_property(self, pspec):
"""Retrieve a particular property from our property dictionary
pspec -- XXX some sort of GTK specifier object with attributes
including 'name', 'active' and 'icon-name'
"""
if pspec.name == "key": if pspec.name == "key":
return self._properties["key"] return self._properties["key"]
elif pspec.name == "nick": elif pspec.name == "nick":
@ -97,48 +132,79 @@ class Buddy(gobject.GObject):
return self._icon return self._icon
def object_path(self): def object_path(self):
"""Retrieve our dbus object path"""
return self._object_path return self._object_path
def _emit_icon_changed_signal(self, bytes): def _emit_icon_changed_signal(self, bytes):
"""Emit GObject signal when icon has changed"""
self._icon = _bytes_to_string(bytes) self._icon = _bytes_to_string(bytes)
self.emit('icon-changed') self.emit('icon-changed')
return False return False
def _icon_changed_cb(self, icon_data): def _icon_changed_cb(self, icon_data):
"""Handle dbus signal by emitting a GObject signal"""
gobject.idle_add(self._emit_icon_changed_signal, icon_data) gobject.idle_add(self._emit_icon_changed_signal, icon_data)
def _emit_joined_activity_signal(self, object_path): def _emit_joined_activity_signal(self, object_path):
"""Emit activity joined signal with Activity object"""
self.emit('joined-activity', self._ps_new_object(object_path)) self.emit('joined-activity', self._ps_new_object(object_path))
return False return False
def _joined_activity_cb(self, object_path): def _joined_activity_cb(self, object_path):
"""Handle dbus signal by emitting a GObject signal
Stores the activity in activities dictionary as well
"""
if not self._activities.has_key(object_path): if not self._activities.has_key(object_path):
self._activities[object_path] = self._ps_new_object(object_path) self._activities[object_path] = self._ps_new_object(object_path)
gobject.idle_add(self._emit_joined_activity_signal, object_path) gobject.idle_add(self._emit_joined_activity_signal, object_path)
def _emit_left_activity_signal(self, object_path): def _emit_left_activity_signal(self, object_path):
"""Emit activity left signal with Activity object
XXX this calls self._ps_new_object instead of self._ps_del_object,
which would seem to be the incorrect callback?
"""
self.emit('left-activity', self._ps_new_object(object_path)) self.emit('left-activity', self._ps_new_object(object_path))
return False return False
def _left_activity_cb(self, object_path): def _left_activity_cb(self, object_path):
"""Handle dbus signal by emitting a GObject signal
Also removes from the activities dictionary
"""
if self._activities.has_key(object_path): if self._activities.has_key(object_path):
del self._activities[object_path] del self._activities[object_path]
gobject.idle_add(self._emit_left_activity_signal, object_path) gobject.idle_add(self._emit_left_activity_signal, object_path)
def _handle_property_changed_signal(self, prop_list): def _handle_property_changed_signal(self, prop_list):
"""Emit property-changed signal with property dictionary
Generates a property-changed signal with the results of
_get_properties_helper()
"""
self._properties = self._get_properties_helper() self._properties = self._get_properties_helper()
# FIXME: don't leak unexposed property names # FIXME: don't leak unexposed property names
self.emit('property-changed', prop_list) self.emit('property-changed', prop_list)
return False return False
def _property_changed_cb(self, prop_list): def _property_changed_cb(self, prop_list):
"""Handle dbus signal by emitting a GObject signal"""
gobject.idle_add(self._handle_property_changed_signal, prop_list) gobject.idle_add(self._handle_property_changed_signal, prop_list)
def get_icon_pixbuf(self): def get_icon_pixbuf(self):
"""Retrieve Buddy's icon as a GTK pixel buffer
XXX Why aren't the icons coming in as SVG?
"""
if self.props.icon and len(self.props.icon): if self.props.icon and len(self.props.icon):
pbl = gtk.gdk.PixbufLoader() pbl = gtk.gdk.PixbufLoader()
icon_data = "" icon_data = ""
for item in self.props.icon: for item in self.props.icon:
# XXX this is a slow way to convert the data
# under Python 2.5 and below, collect in a
# list and then join with "", see
# _bytes_to_string in this module
icon_data = icon_data + chr(item) icon_data = icon_data + chr(item)
pbl.write(icon_data) pbl.write(icon_data)
pbl.close() pbl.close()
@ -147,6 +213,14 @@ class Buddy(gobject.GObject):
return None return None
def get_joined_activities(self): def get_joined_activities(self):
"""Retrieve the set of all activities which this buddy has joined
Uses the GetJoinedActivities method on the service
object to produce object paths, wraps each in an
Activity object.
returns list of presence Activity objects
"""
try: try:
resp = self._buddy.GetJoinedActivities() resp = self._buddy.GetJoinedActivities()
except dbus.exceptions.DBusException: except dbus.exceptions.DBusException:

View File

@ -1,3 +1,4 @@
"""UI class to access system-level presence object"""
# Copyright (C) 2007, Red Hat, Inc. # Copyright (C) 2007, Red Hat, Inc.
# #
# This library is free software; you can redistribute it and/or # This library is free software; you can redistribute it and/or
@ -18,24 +19,78 @@
import dbus, dbus.glib, gobject import dbus, dbus.glib, gobject
import logging import logging
# XXX use absolute imports
# from sugar.presence import buddy, activity
# this *kind* of relative import is deprecated
# with an explicit relative import slated to be
# introduced (available in Python 2.5 with a __future__
# import), that would read as:
# from . import buddy, activity
# see PEP: http://docs.python.org/whatsnew/pep-328.html
import buddy, activity import buddy, activity
class ObjectCache(object): class ObjectCache(object):
"""Path to Activity/Buddy object cache
On notification of a new object of either type the
PresenceService client stores the object's representation
in this object.
XXX Why not just sub-class dict? We're only adding two
methods then and we would have all of the other
standard operations on dictionaries.
"""
def __init__(self): def __init__(self):
"""Initialise the cache"""
self._cache = {} self._cache = {}
def get(self, object_path): def get(self, object_path):
"""Retrieve specified object from the cache
object_path -- full dbus path to the object
returns a presence.buddy.Buddy or presence.activity.Activity
instance or None if the object_path is not yet cached.
XXX could be written as return self._cache.get( object_path )
"""
try: try:
return self._cache[object_path] return self._cache[object_path]
except KeyError: except KeyError:
return None return None
def add(self, obj): def add(self, obj):
"""Adds given presence object to the cache
obj -- presence Buddy or Activity representation, the object's
object_path() method is used as the key for storage
returns None
XXX should raise an error on collisions, shouldn't it? or
return True/False to say whether the item was actually
added
"""
op = obj.object_path() op = obj.object_path()
if not self._cache.has_key(op): if not self._cache.has_key(op):
self._cache[op] = obj self._cache[op] = obj
def remove(self, object_path): def remove(self, object_path):
"""Remove the given presence object from the cache
object_path -- full dbus path to the object
returns None
XXX does two checks instead of one with a try:except for the
keyerror, normal case of deleting existing penalised as
a result.
try:
return self._cache.pop( key )
except KeyError:
return None
"""
if self._cache.has_key(object_path): if self._cache.has_key(object_path):
del self._cache[object_path] del self._cache[object_path]
@ -46,7 +101,13 @@ DBUS_PATH = "/org/laptop/Sugar/Presence"
class PresenceService(gobject.GObject): class PresenceService(gobject.GObject):
"""UI-side interface to the dbus presence service
This class provides UI programmers with simplified access
to the dbus service of the same name. It allows for observing
various events from the presence service as GObject events,
as well as some basic introspection queries.
"""
__gsignals__ = { __gsignals__ = {
'buddy-appeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, 'buddy-appeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT])), ([gobject.TYPE_PYOBJECT])),
@ -71,6 +132,7 @@ class PresenceService(gobject.GObject):
def __init__(self): def __init__(self):
"""Initialise the service and connect to events"""
gobject.GObject.__init__(self) gobject.GObject.__init__(self)
self._objcache = ObjectCache() self._objcache = ObjectCache()
self._bus = dbus.SessionBus() self._bus = dbus.SessionBus()
@ -84,6 +146,17 @@ class PresenceService(gobject.GObject):
self._ps.connect_to_signal('PrivateInvitation', self._private_invitation_cb) self._ps.connect_to_signal('PrivateInvitation', self._private_invitation_cb)
def _new_object(self, object_path): def _new_object(self, object_path):
"""Turn new object path into (cached) Buddy/Activity instance
object_path -- full dbus path of the new object, must be
prefixed with either of _PS_BUDDY_OP or _PS_ACTIVITY_OP
Note that this method is called throughout the class whenever
the representation of the object is required, it is not only
called when the object is first discovered.
returns presence Buddy or Activity representation
"""
obj = self._objcache.get(object_path) obj = self._objcache.get(object_path)
if not obj: if not obj:
if object_path.startswith(self._PS_BUDDY_OP): if object_path.startswith(self._PS_BUDDY_OP):
@ -102,52 +175,79 @@ class PresenceService(gobject.GObject):
pass pass
def _emit_buddy_appeared_signal(self, object_path): def _emit_buddy_appeared_signal(self, object_path):
"""Emit GObject event with presence.buddy.Buddy object"""
self.emit('buddy-appeared', self._new_object(object_path)) self.emit('buddy-appeared', self._new_object(object_path))
return False return False
def _buddy_appeared_cb(self, op): def _buddy_appeared_cb(self, op):
"""Callback for dbus event (forwards to method to emit GObject event)"""
gobject.idle_add(self._emit_buddy_appeared_signal, op) gobject.idle_add(self._emit_buddy_appeared_signal, op)
def _emit_buddy_disappeared_signal(self, object_path): def _emit_buddy_disappeared_signal(self, object_path):
"""Emit GObject event with presence.buddy.Buddy object"""
self.emit('buddy-disappeared', self._new_object(object_path)) self.emit('buddy-disappeared', self._new_object(object_path))
return False return False
def _buddy_disappeared_cb(self, object_path): def _buddy_disappeared_cb(self, object_path):
"""Callback for dbus event (forwards to method to emit GObject event)"""
gobject.idle_add(self._emit_buddy_disappeared_signal, object_path) gobject.idle_add(self._emit_buddy_disappeared_signal, object_path)
def _emit_activity_invitation_signal(self, object_path): def _emit_activity_invitation_signal(self, object_path):
"""Emit GObject event with presence.activity.Activity object"""
self.emit('activity-invitation', self._new_object(object_path)) self.emit('activity-invitation', self._new_object(object_path))
return False return False
def _activity_invitation_cb(self, object_path): def _activity_invitation_cb(self, object_path):
"""Callback for dbus event (forwards to method to emit GObject event)"""
gobject.idle_add(self._emit_activity_invitation_signal, object_path) gobject.idle_add(self._emit_activity_invitation_signal, object_path)
def _emit_private_invitation_signal(self, bus_name, connection, channel): def _emit_private_invitation_signal(self, bus_name, connection, channel):
"""Emit GObject event with bus_name, connection and channel
XXX This seems to generate the wrong GObject event? It generates
'service-disappeared' instead of private-invitation for some
reason. That event doesn't even seem to be registered?
"""
self.emit('service-disappeared', bus_name, connection, channel) self.emit('service-disappeared', bus_name, connection, channel)
return False return False
def _private_invitation_cb(self, bus_name, connection, channel): def _private_invitation_cb(self, bus_name, connection, channel):
"""Callback for dbus event (forwards to method to emit GObject event)"""
gobject.idle_add(self._emit_service_disappeared_signal, bus_name, gobject.idle_add(self._emit_service_disappeared_signal, bus_name,
connection, channel) connection, channel)
def _emit_activity_appeared_signal(self, object_path): def _emit_activity_appeared_signal(self, object_path):
"""Emit GObject event with presence.activity.Activity object"""
self.emit('activity-appeared', self._new_object(object_path)) self.emit('activity-appeared', self._new_object(object_path))
return False return False
def _activity_appeared_cb(self, object_path): def _activity_appeared_cb(self, object_path):
"""Callback for dbus event (forwards to method to emit GObject event)"""
gobject.idle_add(self._emit_activity_appeared_signal, object_path) gobject.idle_add(self._emit_activity_appeared_signal, object_path)
def _emit_activity_disappeared_signal(self, object_path): def _emit_activity_disappeared_signal(self, object_path):
"""Emit GObject event with presence.activity.Activity object"""
self.emit('activity-disappeared', self._new_object(object_path)) self.emit('activity-disappeared', self._new_object(object_path))
return False return False
def _activity_disappeared_cb(self, object_path): def _activity_disappeared_cb(self, object_path):
"""Callback for dbus event (forwards to method to emit GObject event)"""
gobject.idle_add(self._emit_activity_disappeared_signal, object_path) gobject.idle_add(self._emit_activity_disappeared_signal, object_path)
def get(self, object_path): def get(self, object_path):
"""Retrieve given object path as a Buddy/Activity object
XXX This is basically just an alias for _new_object, i.e. it
just adds an extra function-call to the operation.
"""
return self._new_object(object_path) return self._new_object(object_path)
def get_activities(self): def get_activities(self):
"""Retrieve set of all activities from service
returns list of Activity objects for all object paths
the service reports exist (using GetActivities)
"""
resp = self._ps.GetActivities() resp = self._ps.GetActivities()
acts = [] acts = []
for item in resp: for item in resp:
@ -155,6 +255,13 @@ class PresenceService(gobject.GObject):
return acts return acts
def get_activity(self, activity_id): def get_activity(self, activity_id):
"""Retrieve single Activity object for the given unique id
activity_id -- unique ID for the activity
returns single Activity object or None if the activity
is not found using GetActivityById on the service
"""
try: try:
act_op = self._ps.GetActivityById(activity_id) act_op = self._ps.GetActivityById(activity_id)
except dbus.exceptions.DBusException: except dbus.exceptions.DBusException:
@ -162,6 +269,11 @@ class PresenceService(gobject.GObject):
return self._new_object(act_op) return self._new_object(act_op)
def get_buddies(self): def get_buddies(self):
"""Retrieve set of all buddies from service
returns list of Buddy objects for all object paths
the service reports exist (using GetBuddies)
"""
resp = self._ps.GetBuddies() resp = self._ps.GetBuddies()
buddies = [] buddies = []
for item in resp: for item in resp:
@ -169,6 +281,14 @@ class PresenceService(gobject.GObject):
return buddies return buddies
def get_buddy(self, key): def get_buddy(self, key):
"""Retrieve single Buddy object for the given public key
key -- buddy's public encryption key
returns single Buddy object or None if the activity
is not found using GetBuddyByPublicKey on the
service
"""
try: try:
buddy_op = self._ps.GetBuddyByPublicKey(dbus.ByteArray(key)) buddy_op = self._ps.GetBuddyByPublicKey(dbus.ByteArray(key))
except dbus.exceptions.DBusException: except dbus.exceptions.DBusException:
@ -176,6 +296,12 @@ class PresenceService(gobject.GObject):
return self._new_object(buddy_op) return self._new_object(buddy_op)
def get_owner(self): def get_owner(self):
"""Retrieves "owner" as a Buddy
XXX check that it really is a Buddy that's produced, what is
this the owner of? Shouldn't it be getting an activity
and then asking who the owner of that is?
"""
try: try:
owner_op = self._ps.GetOwner() owner_op = self._ps.GetOwner()
except dbus.exceptions.DBusException: except dbus.exceptions.DBusException:
@ -183,13 +309,27 @@ class PresenceService(gobject.GObject):
return self._new_object(owner_op) return self._new_object(owner_op)
def _share_activity_cb(self, activity, op): def _share_activity_cb(self, activity, op):
"""Notify with GObject event of successful sharing of activity"""
self.emit("activity-shared", True, self._new_object(op), None) self.emit("activity-shared", True, self._new_object(op), None)
def _share_activity_error_cb(self, activity, err): def _share_activity_error_cb(self, activity, err):
"""Notify with GObject event of unsuccessful sharing of activity"""
logging.debug("Error sharing activity %s: %s" % (activity.get_id(), err)) logging.debug("Error sharing activity %s: %s" % (activity.get_id(), err))
self.emit("activity-shared", False, None, err) self.emit("activity-shared", False, None, err)
def share_activity(self, activity, properties={}): def share_activity(self, activity, properties={}):
"""Ask presence service to ask the activity to share itself
Uses the ShareActivity method on the service to ask for the
sharing of the given activity. Arranges to emit activity-shared
event with:
(success, Activity, err)
on success/failure.
returns None
"""
actid = activity.get_id() actid = activity.get_id()
atype = activity.get_service_name() atype = activity.get_service_name()
name = activity.props.title name = activity.props.title
@ -199,6 +339,10 @@ class PresenceService(gobject.GObject):
class _MockPresenceService(gobject.GObject): class _MockPresenceService(gobject.GObject):
"""Test fixture allowing testing of items that use PresenceService
See PresenceService for usage and purpose
"""
__gsignals__ = { __gsignals__ = {
'buddy-appeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, 'buddy-appeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT])), ([gobject.TYPE_PYOBJECT])),
@ -238,6 +382,7 @@ class _MockPresenceService(gobject.GObject):
_ps = None _ps = None
def get_instance(): def get_instance():
"""Retrieve this process' view of the PresenceService"""
global _ps global _ps
if not _ps: if not _ps:
_ps = PresenceService() _ps = PresenceService()