[Sugar-devel] [PATCH] Properly store and load friends #2331

Simon Schampijer simon at schampijer.de
Mon Sep 20 06:51:29 EDT 2010


On 09/17/2010 09:54 AM, Tomeu Vizoso wrote:
> Because FriendBuddyModel has a different life cycle than BuddyModel
> (are tracked also when online), we need to store the key and nick
> so we can represent them in the UI when the contact are not online
> and also so we can relate to the contact when it becomes online.
>
> * src/jarabe/model/buddy.py: Move out FriendBuddyModel and add a
>    handle property to BuddyModel.
>
> * src/jarabe/model/filetransfer.py: Ask neighborhood.py for the
>    buddy associated to a handle.
>
> * src/jarabe/model/friends.py: Add FriendBuddyModel.
>
> * src/jarabe/model/neighborhood.py: Set the contact handle on the
>    BuddyModel.
> ---
>   src/jarabe/frame/activitiestray.py |    4 +-
>   src/jarabe/model/buddy.py          |   23 +++---------
>   src/jarabe/model/filetransfer.py   |   28 ++-------------
>   src/jarabe/model/friends.py        |   68 ++++++++++++++++++++++++++++++++++-
>   src/jarabe/model/neighborhood.py   |   24 ++++++++++---
>   5 files changed, 97 insertions(+), 50 deletions(-)
>
> diff --git a/src/jarabe/frame/activitiestray.py b/src/jarabe/frame/activitiestray.py
> index 9a1a9da..6bd2a1b 100644
> --- a/src/jarabe/frame/activitiestray.py
> +++ b/src/jarabe/frame/activitiestray.py
> @@ -371,7 +371,7 @@ class IncomingTransferButton(BaseTransferButton):
>                   self.notif_icon.props.icon_name = icon_name
>                   break
>
> -        icon_color = XoColor(file_transfer.buddy.props.color)
> +        icon_color = file_transfer.buddy.props.color
>           self.props.icon_widget.props.xo_color = icon_color
>           self.notif_icon.props.xo_color = icon_color
>
> @@ -396,7 +396,7 @@ class IncomingTransferButton(BaseTransferButton):
>               self._ds_object.metadata['buddies'] = ''
>               self._ds_object.metadata['preview'] = ''
>               self._ds_object.metadata['icon-color'] = \
> -                    file_transfer.buddy.props.color
> +                    file_transfer.buddy.props.color.to_string()
>               self._ds_object.metadata['mime_type'] = file_transfer.mime_type
>           elif file_transfer.props.state == filetransfer.FT_STATE_COMPLETED:
>               logging.debug('__notify_state_cb COMPLETED')
> diff --git a/src/jarabe/model/buddy.py b/src/jarabe/model/buddy.py
> index 531d7ea..5f3176e 100644
> --- a/src/jarabe/model/buddy.py
> +++ b/src/jarabe/model/buddy.py
> @@ -28,8 +28,6 @@ from sugar.profile import get_profile
>
>   from jarabe.util.telepathy import connection_watcher
>
> -_NOT_PRESENT_COLOR = "#d5d5d5,#FFFFFF"
> -
>   CONNECTION_INTERFACE_BUDDY_INFO = 'org.laptop.Telepathy.BuddyInfo'
>
>   class BaseBuddyModel(gobject.GObject):
> @@ -40,20 +38,10 @@ class BaseBuddyModel(gobject.GObject):
>           self._nick = None
>           self._color = None
>           self._tags = None
> -        self._present = False
>           self._current_activity = None
>
>           gobject.GObject.__init__(self, **kwargs)
>
> -    def is_present(self):
> -        return self._present
> -
> -    def set_present(self, present):
> -        self._present = present
> -
> -    present = gobject.property(type=bool, default=False, getter=is_present,
> -                               setter=set_present)
> -
>       def get_nick(self):
>           return self._nick
>
> @@ -103,7 +91,6 @@ class OwnerBuddyModel(BaseBuddyModel):
>       __gtype_name__ = 'SugarOwnerBuddyModel'
>       def __init__(self):
>           BaseBuddyModel.__init__(self)
> -        self.props.present = True
>
>           client = gconf.client_get_default()
>           self.props.nick = client.get_string('/desktop/sugar/user/nick')
> @@ -207,6 +194,7 @@ class BuddyModel(BaseBuddyModel):
>
>           self._account = None
>           self._contact_id = None
> +        self._handle = None
>
>           BaseBuddyModel.__init__(self, **kwargs)
>
> @@ -231,9 +219,10 @@ class BuddyModel(BaseBuddyModel):
>       contact_id = gobject.property(type=object, getter=get_contact_id,
>                                     setter=set_contact_id)
>
> +    def get_handle(self):
> +        return self._handle
>
> -class FriendBuddyModel(BuddyModel):
> -    __gtype_name__ = 'SugarFriendBuddyModel'
> -    def __init__(self, nick, key):
> -        BuddyModel.__init__(self, nick=nick, key=key)
> +    def set_handle(self, handle):
> +        self._handle = handle
>
> +    handle = gobject.property(type=object, getter=get_handle, setter=set_handle)
> diff --git a/src/jarabe/model/filetransfer.py b/src/jarabe/model/filetransfer.py
> index e0809bb..0d21793 100644
> --- a/src/jarabe/model/filetransfer.py
> +++ b/src/jarabe/model/filetransfer.py
> @@ -31,6 +31,7 @@ from sugar.presence import presenceservice
>   from sugar import dispatch
>
>   from jarabe.util.telepathy import connection_watcher
> +from jarabe.model import neighborhood
>
>   FT_STATE_NONE = 0
>   FT_STATE_PENDING = 1
> @@ -140,11 +141,7 @@ class BaseFileTransfer(gobject.GObject):
>           self.mime_type = props['ContentType']
>
>           handle = channel_properties.Get(CHANNEL, 'TargetHandle')
> -        presence_service = presenceservice.get_instance()
> -        self.buddy = presence_service.get_buddy_by_telepathy_handle(
> -                self._connection.service_name,
> -                self._connection.object_path,
> -                handle)
> +        self.buddy = neighborhood.get_model().get_buddy_by_handle(handle)
>
>       def __transferred_bytes_changed_cb(self, transferred_bytes):
>           logging.debug('__transferred_bytes_changed_cb %r', transferred_bytes)
> @@ -240,20 +237,18 @@ class OutgoingFileTransfer(BaseFileTransfer):
>           self._splicer = None
>           self._output_stream = None
>
> -        self.buddy = buddy.get_buddy()
> +        self.buddy = buddy
>           self.title = title
>           self.file_size = os.stat(file_name).st_size
>           self.description = description
>           self.mime_type = mime_type
>
>       def __connection_ready_cb(self, connection):
> -        handle = self._get_buddy_handle()
> -
>           requests = connection[CONNECTION_INTERFACE_REQUESTS]
>           object_path, properties_ = requests.CreateChannel({
>               CHANNEL + '.ChannelType': CHANNEL_TYPE_FILE_TRANSFER,
>               CHANNEL + '.TargetHandleType': CONNECTION_HANDLE_TYPE_CONTACT,
> -            CHANNEL + '.TargetHandle': handle,
> +            CHANNEL + '.TargetHandle': self.buddy.handle,
>               CHANNEL_TYPE_FILE_TRANSFER + '.ContentType': self.mime_type,
>               CHANNEL_TYPE_FILE_TRANSFER + '.Filename': self.title,
>               CHANNEL_TYPE_FILE_TRANSFER + '.Size': self.file_size,
> @@ -267,21 +262,6 @@ class OutgoingFileTransfer(BaseFileTransfer):
>                   SOCKET_ADDRESS_TYPE_UNIX, SOCKET_ACCESS_CONTROL_LOCALHOST, '',
>                   byte_arrays=True)
>
> -    def _get_buddy_handle(self):
> -        object_path = self.buddy.object_path()
> -
> -        bus = dbus.SessionBus()
> -        remote_object = bus.get_object('org.laptop.Sugar.Presence', object_path)
> -        ps_buddy = dbus.Interface(remote_object,
> -                                  'org.laptop.Sugar.Presence.Buddy')
> -
> -        handles = ps_buddy.GetTelepathyHandles()
> -        logging.debug('_get_buddy_handle %r', handles)
> -
> -        bus_name, object_path, handle = handles[0]
> -
> -        return handle
> -
>       def __notify_state_cb(self, file_transfer, pspec):
>           logging.debug('__notify_state_cb %r', self.props.state)
>           if self.props.state == FT_STATE_OPEN:
> diff --git a/src/jarabe/model/friends.py b/src/jarabe/model/friends.py
> index fb5323c..98bff96 100644
> --- a/src/jarabe/model/friends.py
> +++ b/src/jarabe/model/friends.py
> @@ -21,8 +21,71 @@ from ConfigParser import ConfigParser
>   import gobject
>   import dbus
>
> -from jarabe.model.buddy import BuddyModel
>   from sugar import env
> +from sugar.graphics.xocolor import XoColor
> +
> +from jarabe.model.buddy import BuddyModel
> +from jarabe.model import neighborhood
> +
> +class FriendBuddyModel(BuddyModel):
> +    __gtype_name__ = 'SugarFriendBuddyModel'
> +
> +    _NOT_PRESENT_COLOR = "#D5D5D5,#FFFFFF"
> +
> +    def __init__(self, nick, key):
> +        self._online_buddy = None
> +
> +        BuddyModel.__init__(self, nick=nick, key=key)
> +
> +        neighborhood_model = neighborhood.get_model()
> +        neighborhood_model.connect('buddy-added', self.__buddy_added_cb)
> +        neighborhood_model.connect('buddy-removed', self.__buddy_removed_cb)
> +
> +        buddy = neighborhood_model.get_buddy_by_key(key)
> +        if buddy is not None:
> +            self._set_online_buddy(buddy)
> +
> +    def __buddy_added_cb(self, neighborhood, buddy):
> +        if buddy.key != self.key:
> +            return
> +        self._set_online_buddy(buddy)
> +
> +    def _set_online_buddy(self, buddy):
> +        self._online_buddy = buddy
> +        self._online_buddy.connect('notify::color', self.__notify_color_cb)
> +        self.notify('color')
> +        self.notify('present')
> +
> +    def __buddy_removed_cb(self, neighborhood, buddy):
> +        if buddy.key != self.key:
> +            return
> +        self._online_buddy = None
> +        self.notify('color')
> +        self.notify('present')
> +
> +    def __notify_color_cb(self, buddy, pspec):
> +        self.notify('color')
> +
> +    def is_present(self):
> +        return self._online_buddy is not None
> +
> +    present = gobject.property(type=bool, default=False, getter=is_present)
> +
> +    def get_color(self):
> +        if self._online_buddy is not None:
> +            return self._online_buddy.color
> +        else:
> +            return XoColor(FriendBuddyModel._NOT_PRESENT_COLOR)
> +
> +    color = gobject.property(type=object, getter=get_color)
> +
> +    def get_handle(self):
> +        if self._online_buddy is not None:
> +            return self._online_buddy.handle
> +        else:
> +            return None
> +
> +    handle = gobject.property(type=object, getter=get_handle)
>
>   class Friends(gobject.GObject):
>       __gsignals__ = {
> @@ -49,6 +112,7 @@ class Friends(gobject.GObject):
>
>       def make_friend(self, buddy):
>           if not self.has_buddy(buddy):
> +            buddy = FriendBuddyModel(key=buddy.key, nick=buddy.nick)
>               self.add_friend(buddy)
>               self.save()
>
> @@ -70,7 +134,7 @@ class Friends(gobject.GObject):
>                       # HACK: don't screw up on old friends files
>                       if len(key)<  20:
>                           continue
> -                    buddy = BuddyModel(key=key, nick=cp.get(key, 'nick'))
> +                    buddy = FriendBuddyModel(key=key, nick=cp.get(key, 'nick'))
>                       self.add_friend(buddy)
>           except Exception:
>               logging.exception('Error parsing friends file')
> diff --git a/src/jarabe/model/neighborhood.py b/src/jarabe/model/neighborhood.py
> index a457ff7..eabdbc0 100644
> --- a/src/jarabe/model/neighborhood.py
> +++ b/src/jarabe/model/neighborhood.py
> @@ -156,7 +156,8 @@ class _Account(gobject.GObject):
>           'activity-removed':     (gobject.SIGNAL_RUN_FIRST,
>                                    gobject.TYPE_NONE, ([object])),
>           'buddy-added':          (gobject.SIGNAL_RUN_FIRST,
> -                                 gobject.TYPE_NONE, ([object, object, object])),
> +                                 gobject.TYPE_NONE,
> +                                 ([object, object, object, object])),
>           'buddy-updated':        (gobject.SIGNAL_RUN_FIRST,
>                                    gobject.TYPE_NONE, ([object, object])),
>           'buddy-removed':        (gobject.SIGNAL_RUN_FIRST,
> @@ -517,7 +518,7 @@ class _Account(gobject.GObject):
>       def __got_buddy_info_cb(self, handle, nick, properties):
>           logging.debug('_Account.__got_buddy_info_cb %r', properties)
>           self.emit('buddy-added', self._buddy_handles[handle], nick,
> -                  properties.get('key', None))
> +                  properties.get('key', None), handle)
>           self.emit('buddy-updated', self._buddy_handles[handle], properties)
>
>       def __get_contact_attributes_cb(self, attributes):
> @@ -568,7 +569,7 @@ class _Account(gobject.GObject):
>                                                 'BuddyInfo.GetCurrentActivity'),
>                           timeout=_QUERY_DBUS_TIMEOUT)
>                   else:
> -                    self.emit('buddy-added', contact_id, nick, None)
> +                    self.emit('buddy-added', contact_id, nick, None, handle)
>
>       def __got_activities_cb(self, buddy_handle, activities):
>           logging.debug('_Account.__got_activities_cb %r %r', buddy_handle,
> @@ -791,7 +792,7 @@ class Neighborhood(gobject.GObject):
>           if needs_reconnect:
>               account.Reconnect()
>
> -    def __buddy_added_cb(self, account, contact_id, nick, key):
> +    def __buddy_added_cb(self, account, contact_id, nick, key, handle):
>           logging.debug('__buddy_added_cb %r', contact_id)
>
>           if contact_id in self._buddies:
> @@ -802,7 +803,8 @@ class Neighborhood(gobject.GObject):
>                   nick=nick,
>                   account=account.object_path,
>                   contact_id=contact_id,
> -                key=key)
> +                key=key,
> +                handle=handle)
>           self._buddies[contact_id] = buddy
>
>           self.emit('buddy-added', buddy)
> @@ -927,6 +929,18 @@ class Neighborhood(gobject.GObject):
>       def get_buddies(self):
>           return self._buddies.values()
>
> +    def get_buddy_by_key(self, key):
> +        for buddy in self._buddies.values():
> +            if buddy.key == key:
> +                return buddy
> +        return None
> +
> +    def get_buddy_by_handle(self, contact_handle):
> +        for buddy in self._buddies.values():
> +            if not buddy.is_owner() and buddy.handle == contact_handle:
> +                return buddy
> +        return None
> +
>       def get_activity(self, activity_id):
>           return self._activities.get(activity_id, None)
>

Just in case anyone else reads this - reviewed on irc and Tomeu pushed 
it already.

Regards,
    Simon


More information about the Sugar-devel mailing list