From 9a0b3b51888f4ddfe834bd093b6147b3ea1bd7ec Mon Sep 17 00:00:00 2001 From: Tomeu Vizoso Date: Thu, 16 Sep 2010 16:35:32 +0000 Subject: Properly store and load friends #2331 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. --- 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 a7e43f0..6f73bfe 100644 --- a/src/jarabe/model/neighborhood.py +++ b/src/jarabe/model/neighborhood.py @@ -160,7 +160,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, @@ -538,7 +539,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): @@ -589,7 +590,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, @@ -812,7 +813,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: @@ -823,7 +824,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) @@ -948,6 +950,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) -- cgit v0.9.1