[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