[Sugar-devel] [PATCH] Properly store and load friends #2331
Tomeu Vizoso
tomeu.vizoso at collabora.co.uk
Fri Sep 17 03:54:01 EDT 2010
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)
--
1.7.2.3
More information about the Sugar-devel
mailing list