diff options
author | Tomeu Vizoso <tomeu.vizoso@collabora.co.uk> | 2010-07-19 12:08:50 (GMT) |
---|---|---|
committer | Tomeu Vizoso <tomeu.vizoso@collabora.co.uk> | 2010-08-20 13:02:27 (GMT) |
commit | 0d79b38aa5b14f4db4c04d6c825503198c828f41 (patch) | |
tree | 6eb3c9ba4bcfce7cd87e62603a49cec7b8f37619 | |
parent | 6422268efc87bca915e5c53c4e134d9c66236365 (diff) |
Track the buddies' current activity
-rw-r--r-- | src/jarabe/desktop/meshbox.py | 70 | ||||
-rw-r--r-- | src/jarabe/model/buddy.py | 19 | ||||
-rw-r--r-- | src/jarabe/model/neighborhood.py | 145 | ||||
-rw-r--r-- | src/jarabe/view/buddymenu.py | 4 |
4 files changed, 144 insertions, 94 deletions
diff --git a/src/jarabe/desktop/meshbox.py b/src/jarabe/desktop/meshbox.py index 79954ef..cacc404 100644 --- a/src/jarabe/desktop/meshbox.py +++ b/src/jarabe/desktop/meshbox.py @@ -66,6 +66,9 @@ class ActivityView(hippo.CanvasBox): hippo.CanvasBox.__init__(self) self._model = model + self._model.connect('buddy-added', self.__buddy_added_cb) + self._model.connect('buddy-removed', self.__buddy_removed_cb) + self._icons = {} self._palette = None @@ -78,6 +81,9 @@ class ActivityView(hippo.CanvasBox): self._palette = self._create_palette() self._icon.set_palette(self._palette) + for buddy in self._model.props.buddies: + self._add_buddy(buddy) + def _create_icon(self): icon = CanvasIcon(file_name=self._model.bundle.get_icon(), xo_color=self._model.get_color(), cache=True, @@ -118,13 +124,17 @@ class ActivityView(hippo.CanvasBox): def has_buddy_icon(self, key): return self._icons.has_key(key) - def add_buddy_icon(self, key, icon): - self._icons[key] = icon + def __buddy_added_cb(self, activity, buddy): + self._add_buddy(buddy) + + def _add_buddy(self, buddy): + icon = BuddyIcon(buddy, style.STANDARD_ICON_SIZE) + self._icons[buddy.props.key] = icon self._layout.add(icon) - def remove_buddy_icon(self, key): - icon = self._icons[key] - del self._icons[key] + def __buddy_removed_cb(self, activity, buddy): + icon = self._icons[buddy.props.key] + del self._icons[buddy.props.key] icon.destroy() def _clicked_cb(self, item): @@ -430,11 +440,10 @@ class MeshBox(gtk.VBox): self._layout_box.set_layout(self._layout) for buddy_model in self._model.get_buddies(): - self._add_alone_buddy(buddy_model) + self._add_buddy(buddy_model) self._model.connect('buddy-added', self._buddy_added_cb) self._model.connect('buddy-removed', self._buddy_removed_cb) - self._model.connect('buddy-moved', self._buddy_moved_cb) for activity_model in self._model.get_activities(): self._add_activity(activity_model) @@ -458,24 +467,23 @@ class MeshBox(gtk.VBox): gtk.VBox.do_size_allocate(self, allocation) def _buddy_added_cb(self, model, buddy_model): - self._add_alone_buddy(buddy_model) + self._add_buddy(buddy_model) def _buddy_removed_cb(self, model, buddy_model): self._remove_buddy(buddy_model) - def _buddy_moved_cb(self, model, buddy_model, activity_model): - # Owner doesn't move from the center - if buddy_model.is_owner(): - return - self._move_buddy(buddy_model, activity_model) - def _activity_added_cb(self, model, activity_model): self._add_activity(activity_model) def _activity_removed_cb(self, model, activity_model): self._remove_activity(activity_model) - def _add_alone_buddy(self, buddy_model): + def _add_buddy(self, buddy_model): + logging.debug('MeshBox._add_buddy %r', buddy_model.props.key) + buddy_model.connect('notify::current-activity', + self.__buddy_notify_current_activity_cb) + if buddy_model.props.current_activity is not None: + return icon = BuddyIcon(buddy_model) if buddy_model.is_owner(): self._owner_icon = icon @@ -486,34 +494,20 @@ class MeshBox(gtk.VBox): self._buddies[buddy_model.props.key] = icon - def _remove_alone_buddy(self, buddy_model): + def _remove_buddy(self, buddy_model): + logging.debug('MeshBox._remove_buddy') icon = self._buddies[buddy_model.props.key] self._layout.remove(icon) del self._buddies[buddy_model.props.key] icon.destroy() - def _remove_buddy(self, buddy_model): - if self._buddies.has_key(buddy_model.props.key): - self._remove_alone_buddy(buddy_model) - else: - object_path = buddy_model.get_buddy().object_path() - for activity in self._activities.values(): - if activity.has_buddy_icon(object_path): - activity.remove_buddy_icon(object_path) - - def _move_buddy(self, buddy_model, activity_model): - self._remove_buddy(buddy_model) - - if activity_model == None: - self._add_alone_buddy(buddy_model) - elif activity_model.activity_id in self._activities: - activity = self._activities[activity_model.activity_id] - - icon = BuddyIcon(buddy_model, style.STANDARD_ICON_SIZE) - activity.add_buddy_icon(buddy_model.get_buddy().object_path(), icon) - - if hasattr(icon, 'set_filter'): - icon.set_filter(self._query) + def __buddy_notify_current_activity_cb(self, buddy_model, pspec): + logging.debug('MeshBox.__buddy_notify_current_activity_cb') + if buddy_model.props.current_activity is None: + if not buddy_model.props.key in self._buddies: + self._add_buddy(buddy_model) + elif buddy_model.props.key in self._buddies: + self._remove_buddy(buddy_model) def _add_activity(self, activity_model): icon = ActivityView(activity_model) diff --git a/src/jarabe/model/buddy.py b/src/jarabe/model/buddy.py index b908e10..2c2e28d 100644 --- a/src/jarabe/model/buddy.py +++ b/src/jarabe/model/buddy.py @@ -39,6 +39,7 @@ class BaseBuddyModel(gobject.GObject): self._color = None self._tags = None self._present = False + self._current_activity = None gobject.GObject.__init__(self, **kwargs) @@ -81,10 +82,16 @@ class BaseBuddyModel(gobject.GObject): tags = gobject.property(type=object, getter=get_tags) def get_current_activity(self): - raise NotImplementedError + return self._current_activity + + def set_current_activity(self, current_activity): + if self._current_activity != current_activity: + self._current_activity = current_activity + self.notify('current-activity') current_activity = gobject.property(type=object, - getter=get_current_activity) + getter=get_current_activity, + setter=set_current_activity) def is_owner(self): raise NotImplementedError @@ -164,9 +171,6 @@ class BuddyModel(BaseBuddyModel): def is_owner(self): return False - def get_current_activity(self): - return None - def get_buddy(self): raise NotImplementedError @@ -234,11 +238,6 @@ class BuddyModel(BaseBuddyModel): def is_owner(self): return False - def get_current_activity(self): - if self._buddy: - return self._buddy.props.current_activity - return None - def is_present(self): if self._buddy: return True diff --git a/src/jarabe/model/neighborhood.py b/src/jarabe/model/neighborhood.py index 56d8696..bf49073 100644 --- a/src/jarabe/model/neighborhood.py +++ b/src/jarabe/model/neighborhood.py @@ -59,6 +59,12 @@ CONNECTION_INTERFACE_BUDDY_INFO = 'org.laptop.Telepathy.BuddyInfo' CONNECTION_INTERFACE_ACTIVITY_PROPERTIES = 'org.laptop.Telepathy.ActivityProperties' class ActivityModel(gobject.GObject): + __gsignals__ = { + 'buddy-added': (gobject.SIGNAL_RUN_FIRST, + gobject.TYPE_NONE, ([object])), + 'buddy-removed': (gobject.SIGNAL_RUN_FIRST, + gobject.TYPE_NONE, ([object])), + } def __init__(self, activity_id, room_handle): gobject.GObject.__init__(self) @@ -66,6 +72,7 @@ class ActivityModel(gobject.GObject): self.room_handle = room_handle self._bundle = None self._color = None + self._buddies = [] def get_color(self): return self._color @@ -91,8 +98,20 @@ class ActivityModel(gobject.GObject): name = gobject.property(type=object, getter=get_name, setter=set_name) - def join(self): - pass + def get_buddies(self): + return self._buddies + + def add_buddy(self, buddy): + self._buddies.append(buddy) + self.notify('buddies') + self.emit('buddy-added', buddy) + + def remove_buddy(self, buddy): + self._buddies.remove(buddy) + self.notify('buddies') + self.emit('buddy-removed', buddy) + + buddies = gobject.property(type=object, getter=get_buddies) class _Account(gobject.GObject): __gsignals__ = { @@ -103,11 +122,13 @@ class _Account(gobject.GObject): 'activity-removed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([object])), 'buddy-added': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([object])), + gobject.TYPE_NONE, ([object, object, object])), 'buddy-updated': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([object, object])), 'buddy-removed': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([object])) + gobject.TYPE_NONE, ([object])), + 'current-activity-updated': (gobject.SIGNAL_RUN_FIRST, + gobject.TYPE_NONE, ([object, object])), } def __init__(self, account_path): @@ -167,6 +188,9 @@ class _Account(gobject.GObject): connection[CONNECTION_INTERFACE_BUDDY_INFO].connect_to_signal( 'ActivitiesChanged', self.__buddy_activities_changed_cb) + + connection[CONNECTION_INTERFACE_BUDDY_INFO].connect_to_signal( + 'CurrentActivityChanged', self.__current_activity_changed_cb) else: logging.warning('Connection %s does not support OLPC buddy ' 'properties', connection.object_path) @@ -217,6 +241,18 @@ class _Account(gobject.GObject): def __buddy_info_updated_cb(self, handle, properties): logging.debug('__buddy_info_updated_cb %r %r', handle, properties) + def __current_activity_changed_cb(self, contact_handle, activity_id, room_handle): + logging.debug('__current_activity_changed_cb %r %r %r', contact_handle, activity_id, room_handle) + if contact_handle in self._buddy_handles: + contact_id = self._buddy_handles[contact_handle] + self.emit('current-activity-updated', contact_id, activity_id) + + def __get_current_activity_cb(self, contact_handle, activity_id, room_handle): + logging.debug('__get_current_activity_cb %r %r %r', contact_handle, activity_id, room_handle) + logging.debug('__get_current_activity_cb %r', self._buddy_handles) + contact_id = self._buddy_handles[contact_handle] + self.emit('current-activity-updated', contact_id, activity_id) + def __buddy_activities_changed_cb(self, buddy_handle, activities): logging.debug('__buddy_activities_changed_cb %r %r', buddy_handle, activities) self._update_buddy_activities(buddy_handle, activities) @@ -247,26 +283,28 @@ class _Account(gobject.GObject): current_activity_ids = [activity_id for activity_id, room_handle in activities] for activity_id in self._activities_per_buddy[buddy_handle].copy(): if not activity_id in current_activity_ids: - self._remove_activity(buddy_handle, activity_id) + self._remove_buddy_from_activity(buddy_handle, activity_id) def __get_properties_cb(self, room_handle, properties): logging.debug('__get_properties_cb %r %r', room_handle, properties) self._update_activity(room_handle, properties) - def _remove_activity(self, buddy_handle, activity_id): + def _remove_buddy_from_activity(self, buddy_handle, activity_id): if buddy_handle in self._buddies_per_activity[activity_id]: self._buddies_per_activity[activity_id].remove(buddy_handle) - if not self._buddies_per_activity[activity_id]: - del self._buddies_per_activity[activity_id] - self._activities_per_buddy[buddy_handle].remove(activity_id) + if activity_id in self._activities_per_buddy[buddy_handle]: + self._activities_per_buddy[buddy_handle].remove(activity_id) - for room_handle in self._activity_handles.copy(): - if self._activity_handles[room_handle] == activity_id: - del self._activity_handles[room_handle] - break + if not self._buddies_per_activity[activity_id]: + del self._buddies_per_activity[activity_id] - self.emit('activity-removed', activity_id) + for room_handle in self._activity_handles.copy(): + if self._activity_handles[room_handle] == activity_id: + del self._activity_handles[room_handle] + break + + self.emit('activity-removed', activity_id) def __activity_properties_changed_cb(self, room_handle, properties): logging.debug('__activity_properties_changed_cb %r %r', room_handle, properties) @@ -298,23 +336,10 @@ class _Account(gobject.GObject): reply_handler=self.__get_contact_attributes_cb, error_handler=self.__error_handler_cb) - if CONNECTION_INTERFACE_BUDDY_INFO not in self._connection: - return - - for handle in handles: - self._connection[CONNECTION_INTERFACE_BUDDY_INFO].GetProperties( - handle, - reply_handler=partial(self.__got_buddy_info_cb, handle), - error_handler=self.__error_handler_cb, - byte_arrays=True) - - self._connection[CONNECTION_INTERFACE_BUDDY_INFO].GetActivities( - handle, - reply_handler=partial(self.__got_activities_cb, handle), - error_handler=self.__error_handler_cb) - - def __got_buddy_info_cb(self, handle, properties): + def __got_buddy_info_cb(self, handle, nick, properties): logging.debug('__got_buddy_info_cb %r', properties) + self.emit('buddy-added', self._buddy_handles[handle], nick, + properties.get('key', None)) self.emit('buddy-updated', self._buddy_handles[handle], properties) def __get_contact_attributes_cb(self, attributes): @@ -332,7 +357,26 @@ class _Account(gobject.GObject): contact_id = attributes[handle][CONNECTION + '/contact-id'] self._buddy_handles[handle] = contact_id - self.emit('buddy-added', attributes[handle]) + if CONNECTION_INTERFACE_BUDDY_INFO in self._connection: + connection = self._connection[CONNECTION_INTERFACE_BUDDY_INFO] + + connection.GetProperties( + handle, + reply_handler=partial(self.__got_buddy_info_cb, handle, nick), + error_handler=self.__error_handler_cb, + byte_arrays=True) + + connection.GetActivities( + handle, + reply_handler=partial(self.__got_activities_cb, handle), + error_handler=self.__error_handler_cb) + + connection.GetCurrentActivity( + handle, + reply_handler=partial(self.__get_current_activity_cb, handle), + error_handler=self.__error_handler_cb) + else: + self.emit('buddy-added', contact_id, nick, None) def __got_activities_cb(self, buddy_handle, activities): logging.debug('__got_activities_cb %r %r', buddy_handle, activities) @@ -346,10 +390,6 @@ class Neighborhood(gobject.GObject): gobject.TYPE_NONE, ([object])), 'buddy-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([object])), - 'buddy-moved': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ([object, - object])), 'buddy-removed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([object])) } @@ -393,6 +433,7 @@ class Neighborhood(gobject.GObject): account.connect('activity-added', self.__activity_added_cb) account.connect('activity-updated', self.__activity_updated_cb) account.connect('activity-removed', self.__activity_removed_cb) + account.connect('current-activity-updated', self.__current_activity_updated_cb) self._accounts.append(account) def _ensure_link_local_account(self, account_manager, accounts): @@ -459,20 +500,18 @@ class Neighborhood(gobject.GObject): 'jabber', params, properties) accounts.append(account) - def __buddy_added_cb(self, account, properties): - logging.debug('__buddy_added_cb %r', properties) - - contact_id = properties[CONNECTION + '/contact-id'] - assert contact_id is not None + def __buddy_added_cb(self, account, contact_id, nick, key): + logging.debug('__buddy_added_cb %r', contact_id) if contact_id in self._buddies: logging.debug('__buddy_added_cb buddy already tracked') return buddy = BuddyModel( - nick=properties[CONNECTION_INTERFACE_ALIASING + '/alias'], + nick=nick, account=account.object_path, - contact_id=contact_id) + contact_id=contact_id, + key=key) self._buddies[contact_id] = buddy self.emit('buddy-added', buddy) @@ -486,8 +525,6 @@ class Neighborhood(gobject.GObject): buddy = self._buddies[contact_id] if 'color' in properties: buddy.props.color = XoColor(properties['color']) - if 'key' in properties: - buddy.props.key = properties['key'] def __activity_added_cb(self, account, room_handle, activity_id): logging.debug('__activity_added_cb %r %r', room_handle, activity_id) @@ -531,6 +568,26 @@ class Neighborhood(gobject.GObject): del self._activities[activity_id] self.emit('activity-removed', activity) + def __current_activity_updated_cb(self, account, contact_id, activity_id): + logging.debug('__current_activity_updated_cb %r %r', contact_id, activity_id) + if contact_id not in self._buddies: + logging.debug('__current_activity_updated_cb Unknown buddy with ' + 'contact_id %r', contact_id) + return + + buddy = self._buddies[contact_id] + if buddy.props.current_activity is not None: + if buddy.props.current_activity.activity_id == activity_id: + return + buddy.props.current_activity.remove_buddy(buddy) + + if activity_id: + activity = self._activities[activity_id] + buddy.props.current_activity = activity + activity.add_buddy(buddy) + else: + buddy.props.current_activity = None + def get_activities(self): return [] diff --git a/src/jarabe/view/buddymenu.py b/src/jarabe/view/buddymenu.py index 6c67d36..9305ca1 100644 --- a/src/jarabe/view/buddymenu.py +++ b/src/jarabe/view/buddymenu.py @@ -113,9 +113,9 @@ class BuddyMenu(Palette): panel.show() def _update_invite_menu(self, activity): - buddy_activity = self._buddy.get_current_activity() + buddy_activity = self._buddy.props.current_activity if buddy_activity is not None: - buddy_activity_id = buddy_activity.props.id + buddy_activity_id = buddy_activity.activity_id else: buddy_activity_id = None |