diff options
Diffstat (limited to 'toolkit/src/sugar/presence/buddy.py')
-rw-r--r-- | toolkit/src/sugar/presence/buddy.py | 246 |
1 files changed, 246 insertions, 0 deletions
diff --git a/toolkit/src/sugar/presence/buddy.py b/toolkit/src/sugar/presence/buddy.py new file mode 100644 index 0000000..0a72a36 --- /dev/null +++ b/toolkit/src/sugar/presence/buddy.py @@ -0,0 +1,246 @@ +# Copyright (C) 2007, Red Hat, Inc. +# Copyright (C) 2010 Collabora Ltd. <http://www.collabora.co.uk/> +# +# 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. + +"""UI interface to a buddy in the presence service + +STABLE. +""" + +import logging + +import gobject +import dbus +import gconf +from telepathy.interfaces import CONNECTION, \ + CONNECTION_INTERFACE_ALIASING, \ + CONNECTION_INTERFACE_CONTACTS +from telepathy.constants import HANDLE_TYPE_CONTACT + +from sugar.presence.connectionmanager import get_connection_manager + +ACCOUNT_MANAGER_SERVICE = 'org.freedesktop.Telepathy.AccountManager' +CONN_INTERFACE_BUDDY_INFO = 'org.laptop.Telepathy.BuddyInfo' + +_logger = logging.getLogger('sugar.presence.buddy') + + +class BaseBuddy(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?), + """ + + __gtype_name__ = 'PresenceBaseBuddy' + + __gsignals__ = { + 'joined-activity': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([gobject.TYPE_PYOBJECT])), + 'left-activity': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([gobject.TYPE_PYOBJECT])), + 'property-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([gobject.TYPE_PYOBJECT])), + } + + def __init__(self): + gobject.GObject.__init__(self) + + self._key = None + self._nick = None + self._color = None + self._current_activity = None + self._owner = False + self._ip4_address = None + self._tags = None + + def get_key(self): + return self._key + + def set_key(self, key): + self._key = key + + key = gobject.property(type=str, getter=get_key, setter=set_key) + + def get_nick(self): + return self._nick + + def set_nick(self, nick): + self._nick = nick + + nick = gobject.property(type=str, getter=get_nick, setter=set_nick) + + def get_color(self): + return self._color + + def set_color(self, color): + self._color = color + + color = gobject.property(type=str, getter=get_color, setter=set_color) + + def get_current_activity(self): + if self._current_activity is None: + return None + for activity in self._activities.values(): + if activity.props.id == self._current_activity: + return activity + return None + + current_activity = gobject.property(type=object, + getter=get_current_activity) + + def get_owner(self): + return self._owner + + def set_owner(self, owner): + self._owner = owner + + owner = gobject.property(type=bool, getter=get_owner, setter=set_owner, + default=False) + + def get_ip4_address(self): + return self._ip4_address + + def set_ip4_address(self, ip4_address): + self._ip4_address = ip4_address + + ip4_address = gobject.property(type=str, getter=get_ip4_address, + setter=set_ip4_address) + + def get_tags(self): + return self._tags + + def set_tags(self, tags): + self._tags = tags + + tags = gobject.property(type=str, getter=get_tags, setter=set_tags) + + def object_path(self): + """Retrieve our dbus object path""" + return None + + +class Buddy(BaseBuddy): + __gtype_name__ = 'PresenceBuddy' + def __init__(self, account_path, contact_id): + _logger.debug('Buddy.__init__') + BaseBuddy.__init__(self) + + self._account_path = account_path + self.contact_id = contact_id + self.contact_handle = None + + connection_manager = get_connection_manager() + connection = connection_manager.get_connection(account_path) + + connection_name = connection.object_path.replace('/', '.')[1:] + + bus = dbus.SessionBus() + obj = bus.get_object(connection_name, connection.object_path) + handles = obj.RequestHandles(HANDLE_TYPE_CONTACT, [self.contact_id], + dbus_interface=CONNECTION) + self.contact_handle = handles[0] + + self._get_properties_call = bus.call_async( + connection_name, + connection.object_path, + CONN_INTERFACE_BUDDY_INFO, + 'GetProperties', + 'u', + (self.contact_handle,), + reply_handler=self.__got_properties_cb, + error_handler=self.__error_handler_cb, + utf8_strings=True, + byte_arrays=True) + + self._get_attributes_call = bus.call_async( + connection_name, + connection.object_path, + CONNECTION_INTERFACE_CONTACTS, + 'GetContactAttributes', + 'auasb', + ([self.contact_handle], [CONNECTION_INTERFACE_ALIASING], False), + reply_handler=self.__got_attributes_cb, + error_handler=self.__error_handler_cb) + + def __got_properties_cb(self, properties): + _logger.debug('__got_properties_cb %r', properties) + self._get_properties_call = None + self._update_properties(properties) + + def __got_attributes_cb(self, attributes): + _logger.debug('__got_attributes_cb %r', attributes) + self._get_attributes_call = None + self._update_attributes(attributes[self.contact_handle]) + + def __error_handler_cb(self, error): + _logger.debug('__error_handler_cb %r', error) + + def __properties_changed_cb(self, new_props): + _logger.debug('%r: Buddy properties changed to %r', self, new_props) + self._update_properties(new_props) + + def _update_properties(self, properties): + if 'key' in properties: + self.props.key = properties['key'] + if 'color' in properties: + self.props.color = properties['color'] + if 'current-activity' in properties: + self.props.current_activity = properties['current-activity'] + if 'owner' in properties: + self.props.owner = properties['owner'] + if 'ip4-address' in properties: + self.props.ip4_address = properties['ip4-address'] + if 'tags' in properties: + self.props.tags = properties['tags'] + + def _update_attributes(self, attributes): + nick_key = CONNECTION_INTERFACE_ALIASING + '/alias' + if nick_key in attributes: + self.props.nick = attributes[nick_key] + + def do_get_property(self, pspec): + if pspec.name == 'nick' and self._get_attributes_call is not None: + _logger.debug('%r: Blocking on GetContactAttributes() because ' + 'someone wants property nick', self) + self._get_attributes_call.block() + elif pspec.name != 'nick' and self._get_properties_call is not None: + _logger.debug('%r: Blocking on GetProperties() because someone ' + 'wants property %s', self, pspec.name) + self._get_properties_call.block() + + return BaseBuddy.do_get_property(self, pspec) + + +class Owner(BaseBuddy): + + __gtype_name__ = 'PresenceOwner' + + def __init__(self): + BaseBuddy.__init__(self) + + client = gconf.client_get_default() + self.props.nick = client.get_string("/desktop/sugar/user/nick") + self.props.color = client.get_string("/desktop/sugar/user/color") |