Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--services/presence/Buddy.py70
-rw-r--r--services/presence/PresenceService.py22
-rw-r--r--shell/model/BuddyModel.py29
-rw-r--r--shell/view/BuddyActivityView.py40
-rw-r--r--sugar/presence/Buddy.py27
5 files changed, 148 insertions, 40 deletions
diff --git a/services/presence/Buddy.py b/services/presence/Buddy.py
index 2d6f35d..7232eea 100644
--- a/services/presence/Buddy.py
+++ b/services/presence/Buddy.py
@@ -39,6 +39,11 @@ class BuddyDBusHelper(dbus.service.Object):
pass
@dbus.service.signal(BUDDY_DBUS_INTERFACE,
+ signature="ao")
+ def CurrentActivityChanged(self, activities):
+ pass
+
+ @dbus.service.signal(BUDDY_DBUS_INTERFACE,
signature="")
def IconChanged(self):
pass
@@ -94,11 +99,15 @@ class BuddyDBusHelper(dbus.service.Object):
color = self._parent.get_color()
if color:
props[_BUDDY_KEY_COLOR] = self._parent.get_color()
- curact = self._parent.get_current_activity()
- if curact:
- props[_BUDDY_KEY_CURACT] = self._parent.get_current_activity()
return props
+ @dbus.service.method(BUDDY_DBUS_INTERFACE,
+ in_signature="", out_signature="o")
+ def getCurrentActivity(self):
+ activity = self._parent.get_current_activity()
+ if not activity:
+ raise NotFoundError()
+ return activity.object_path()
class Buddy(object):
"""Represents another person on the network and keeps track of the
@@ -226,8 +235,7 @@ class Buddy(object):
self._valid = True
self._get_buddy_icon(service)
self._color = service.get_one_property(_BUDDY_KEY_COLOR)
- if self._color:
- self._dbus_helper.PropertyChanged([_BUDDY_KEY_COLOR])
+ self._current_activity = service.get_one_property(_BUDDY_KEY_CURACT)
# Monitor further buddy property changes, like current activity
# and color
service.connect('property-changed',
@@ -244,26 +252,50 @@ class Buddy(object):
self._color = new_color
self._dbus_helper.PropertyChanged([_BUDDY_KEY_COLOR])
if _BUDDY_KEY_CURACT in keys:
+ # Three cases here:
+ # 1) Buddy didn't publish a 'curact' key at all; we do nothing
+ # 2) Buddy published a blank/zero-length 'curact' key; we send
+ # a current-activity-changed signal for no activity
+ # 3) Buddy published a non-zero-length 'curact' key; we send
+ # a current-activity-changed signal if we know about the
+ # activity already, if not we postpone until the activity
+ # is found on the network and added to the buddy
new_curact = service.get_one_property(_BUDDY_KEY_CURACT)
if new_curact and self._current_activity != new_curact:
+ if not len(new_curact):
+ new_curact = None
self._current_activity = new_curact
- self._dbus_helper.PropertyChanged([_BUDDY_KEY_CURACT])
+ if self._activities.has_key(self._current_activity):
+ # Case (3) above, valid activity id
+ activity = self._activities[self._current_activity]
+ if activity.is_valid():
+ self._dbus_helper.CurrentActivityChanged([activity.object_path()])
+ elif not self._current_activity:
+ # Case (2) above, no current activity
+ self._dbus_helper.CurrentActivityChanged([])
+
+ def __find_service_by_activity_id(self, actid):
+ for serv in self._services.values():
+ if serv.get_activity_id() == actid:
+ return serv
+ return None
def add_activity(self, activity):
- actid = activity.get_id()
if activity in self._activities.values():
raise RuntimeError("Tried to add activity twice")
- found = False
- for serv in self._services.values():
- if serv.get_activity_id() == activity.get_id():
- found = True
- break
- if not found:
+ actid = activity.get_id()
+ if not self.__find_service_by_activity_id(actid):
raise RuntimeError("Tried to add activity for which we had no service")
self._activities[actid] = activity
if activity.is_valid():
self._dbus_helper.JoinedActivity(activity.object_path())
+ # If when we received a current activity update from the buddy,
+ # but didn't know about that activity yet, and now we do know about
+ # it, we need to send out the changed activity signal
+ if actid == self._current_activity:
+ self._dbus_helper.CurrentActivityChanged([activity.object_path()])
+
def remove_service(self, service):
"""Remove a service from a buddy; ie, the activity was closed
or the buddy went away."""
@@ -296,6 +328,12 @@ class Buddy(object):
if activity.is_valid():
self._dbus_helper.LeftActivity(activity.object_path())
+ # If we just removed the buddy's current activity,
+ # send out a signal
+ if actid == self._current_activity:
+ self._current_activity = None
+ self._dbus_helper.CurrentActivityChanged([])
+
def get_joined_activities(self):
acts = []
for act in self._activities.values():
@@ -340,7 +378,11 @@ class Buddy(object):
return self._color
def get_current_activity(self):
- return self._current_activity
+ if not self._current_activity:
+ return None
+ if not self._activities.has_key(self._current_activity):
+ return None
+ return self._activities[self._current_activity]
def _set_icon(self, icon):
"""Can only set icon for other buddies. The Owner
diff --git a/services/presence/PresenceService.py b/services/presence/PresenceService.py
index 77c67ee..b43506e 100644
--- a/services/presence/PresenceService.py
+++ b/services/presence/PresenceService.py
@@ -451,6 +451,16 @@ class PresenceService(object):
if activity:
activity.add_service(service)
+ # Add the activity to its buddy
+ # FIXME: use something other than name to attribute to buddy
+ name = service.get_name()
+ buddy = None
+ try:
+ buddy = self._buddies[name]
+ buddy.add_activity(activity)
+ except KeyError:
+ pass
+
if not was_valid and activity.is_valid():
self._dbus_helper.ActivityAppeared(activity.object_path())
@@ -460,7 +470,19 @@ class PresenceService(object):
return
if not self._activities.has_key(actid):
return
+
activity = self._activities[actid]
+
+ # Remove the activity from its buddy
+ # FIXME: use something other than name to attribute to buddy
+ name = service.get_name()
+ buddy = None
+ try:
+ buddy = self._buddies[name]
+ buddy.remove_activity(activity)
+ except KeyError:
+ pass
+
activity.remove_service(service)
if len(activity.get_services()) == 0:
# Kill the activity
diff --git a/shell/model/BuddyModel.py b/shell/model/BuddyModel.py
index 9fea19b..0a4f1c9 100644
--- a/shell/model/BuddyModel.py
+++ b/shell/model/BuddyModel.py
@@ -26,8 +26,8 @@ class BuddyModel(gobject.GObject):
self._pc_handler = None
self._dis_handler = None
self._bic_handler = None
+ self._cac_handler = None
- self._cur_activity = None
self._pservice = PresenceService.get_instance()
self._buddy = None
@@ -62,8 +62,15 @@ class BuddyModel(gobject.GObject):
def get_buddy(self):
return self._buddy
+ def is_present(self):
+ if self._buddy:
+ return True
+ return False
+
def get_current_activity(self):
- return self._cur_activity
+ if self._buddy:
+ return self._buddy.get_current_activity()
+ return None
def __update_buddy(self, buddy):
if not buddy:
@@ -76,6 +83,7 @@ class BuddyModel(gobject.GObject):
self._pc_handler = self._buddy.connect('property-changed', self.__buddy_property_changed_cb)
self._dis_handler = self._buddy.connect('disappeared', self.__buddy_disappeared_cb)
self._bic_handler = self._buddy.connect('icon-changed', self.__buddy_icon_changed_cb)
+ self._cac_handler = self._buddy.connect('current-activity-changed', self.__buddy_current_activity_changed_cb)
def __buddy_appeared_cb(self, pservice, buddy):
# FIXME: use public key rather than buddy name
@@ -94,12 +102,6 @@ class BuddyModel(gobject.GObject):
def __buddy_property_changed_cb(self, buddy, keys):
if not self._buddy:
return
-
- # all we care about right now is current activity
- if 'curact' in keys:
- curact = self._buddy.get_current_activity()
- self._cur_activity = self._pservice.get_activity(curact)
- self.emit('current-activity-changed', self._cur_activity)
if 'color' in keys:
self.__set_color_from_string(self._buddy.get_color())
self.emit('color-changed', self.get_color())
@@ -110,11 +112,18 @@ class BuddyModel(gobject.GObject):
self._buddy.disconnect(self._pc_handler)
self._buddy.disconnect(self._dis_handler)
self._buddy.disconnect(self._bic_handler)
+ self._buddy.disconnect(self._cac_handler)
self.__set_color_from_string(_NOT_PRESENT_COLOR)
- self._cur_activity = None
- self.emit('current-activity-changed', self._cur_activity)
self.emit('disappeared')
self._buddy = None
def __buddy_icon_changed_cb(self, buddy):
self.emit('icon-changed')
+
+ def __buddy_current_activity_changed_cb(self, buddy, activity=None):
+ if not self._buddy:
+ return
+ if activity:
+ self.emit('current-activity-changed', activity)
+ else:
+ self.emit('current-activity-changed')
diff --git a/shell/view/BuddyActivityView.py b/shell/view/BuddyActivityView.py
index f5bc348..0fc74d4 100644
--- a/shell/view/BuddyActivityView.py
+++ b/shell/view/BuddyActivityView.py
@@ -24,14 +24,13 @@ class BuddyActivityView(goocanvas.Group):
self._activity_icon = IconItem(x=offset_x, y=offset_y, size=48)
self._activity_icon_visible = False
- curact = self._buddy.get_current_activity()
- if curact:
- self.__buddy_activity_changed_cb(self._buddy, activity=curact)
+ if self._buddy.is_present():
+ self.__buddy_appeared_cb(buddy)
self._buddy.connect('current-activity-changed', self.__buddy_activity_changed_cb)
- self._buddy.connect('appeared', self.__buddy_presence_change_cb)
- self._buddy.connect('disappeared', self.__buddy_presence_change_cb)
- self._buddy.connect('color-changed', self.__buddy_presence_change_cb)
+ self._buddy.connect('appeared', self.__buddy_appeared_cb)
+ self._buddy.connect('disappeared', self.__buddy_disappeared_cb)
+ self._buddy.connect('color-changed', self.__buddy_color_changed_cb)
def get_size_request(self):
bi_size = self._buddy_icon.props.size
@@ -52,19 +51,34 @@ class BuddyActivityView(goocanvas.Group):
return act.get_icon()
return None
- def __buddy_activity_changed_cb(self, buddy, activity=None):
- if not activity:
+ def __remove_activity_icon(self):
+ if self._activity_icon_visible:
self.remove_child(self._activity_icon)
self._activity_icon_visible = False
+
+ def __buddy_activity_changed_cb(self, buddy, activity=None):
+ if not activity:
+ self.__remove_activity_icon()
return
+ # FIXME: use some sort of "unknown activity" icon rather
+ # than hiding the icon?
name = self._get_new_icon_name(activity)
if name:
self._activity_icon.props.icon_name = name
- self._activity_icon.props.color = self._buddy_icon.props.color
- if not self._activity_icon_visible:
- self.add_child(self._activity_icon)
- self._activity_icon_visible = True
+ self._activity_icon.props.color = buddy.get_color()
+ if not self._activity_icon_visible:
+ self.add_child(self._activity_icon)
+ self._activity_icon_visible = True
+ else:
+ self.__remove_activity_icon()
+
+ def __buddy_appeared_cb(self, buddy):
+ activity = self._buddy.get_current_activity()
+ self.__buddy_activity_changed_cb(buddy, activity)
+
+ def __buddy_disappeared_cb(self, buddy):
+ self.__buddy_activity_changed_cb(buddy, None)
- def __buddy_presence_change_cb(self, buddy, color=None):
+ def __buddy_color_changed_cb(self, buddy, color):
self._activity_icon.props.color = buddy.get_color()
diff --git a/sugar/presence/Buddy.py b/sugar/presence/Buddy.py
index a0d3fd1..5e31157 100644
--- a/sugar/presence/Buddy.py
+++ b/sugar/presence/Buddy.py
@@ -18,6 +18,8 @@ class Buddy(gobject.GObject):
'left-activity': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT])),
'property-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
+ ([gobject.TYPE_PYOBJECT])),
+ 'current-activity-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT]))
}
@@ -39,8 +41,15 @@ class Buddy(gobject.GObject):
self._buddy.connect_to_signal('JoinedActivity', self._joined_activity_cb)
self._buddy.connect_to_signal('LeftActivity', self._left_activity_cb)
self._buddy.connect_to_signal('PropertyChanged', self._property_changed_cb)
+ self._buddy.connect_to_signal('CurrentActivityChanged', self._current_activity_changed_cb)
self._properties = self._get_properties_helper()
+ self._current_activity = None
+ try:
+ self._current_activity = self._buddy.getCurrentActivity()
+ except Exception, e:
+ pass
+
def _get_properties_helper(self):
props = self._buddy.getProperties()
if not props:
@@ -99,6 +108,18 @@ class Buddy(gobject.GObject):
def _property_changed_cb(self, prop_list):
gobject.idle_add(self._handle_property_changed_signal, prop_list)
+ def _handle_current_activity_changed_signal(self, act_list):
+ if len(act_list) == 0:
+ self._current_activity = None
+ self.emit('current-activity-changed')
+ else:
+ self._current_activity = act_list[0]
+ self.emit('current-activity-changed', self._ps_new_object(act_list[0]))
+ return False
+
+ def _current_activity_changed_cb(self, act_list):
+ gobject.idle_add(self._handle_current_activity_changed_signal, act_list)
+
def get_name(self):
return self._properties['name']
@@ -115,9 +136,9 @@ class Buddy(gobject.GObject):
return self._buddy.getIcon()
def get_current_activity(self):
- if self._properties.has_key('curact'):
- return self._properties['curact']
- return None
+ if not self._current_activity:
+ return None
+ return self._ps_new_object(self._current_activity)
def get_icon_pixbuf(self):
icon = self._buddy.getIcon()