Fix buddy & activity visibility leaks if they are not yet valid; add Activity color attribute and don't make activity valid until we get the color

This commit is contained in:
Dan Williams 2006-08-25 14:55:19 -04:00
parent 6b232d97d8
commit ef47f6e4c5
4 changed files with 76 additions and 15 deletions

View File

@ -41,6 +41,11 @@ class ActivityDBusHelper(dbus.service.Object):
def getId(self): def getId(self):
return self._parent.get_id() return self._parent.get_id()
@dbus.service.method(ACTIVITY_DBUS_INTERFACE,
in_signature="", out_signature="s")
def getColor(self):
return self._parent.get_color()
@dbus.service.method(ACTIVITY_DBUS_INTERFACE, @dbus.service.method(ACTIVITY_DBUS_INTERFACE,
in_signature="", out_signature="ao") in_signature="", out_signature="ao")
def getJoinedBuddies(self): def getJoinedBuddies(self):
@ -81,6 +86,8 @@ class Activity(object):
self._buddies = [] self._buddies = []
self._services = {} # service type -> list of Services self._services = {} # service type -> list of Services
self._color = None
self._valid = False
self._object_id = object_id self._object_id = object_id
self._object_path = "/org/laptop/Presence/Activities/%d" % self._object_id self._object_path = "/org/laptop/Presence/Activities/%d" % self._object_id
@ -91,9 +98,16 @@ class Activity(object):
def object_path(self): def object_path(self):
return dbus.ObjectPath(self._object_path) return dbus.ObjectPath(self._object_path)
def is_valid(self):
"""An activity is only valid when it's color is available."""
return self._valid
def get_id(self): def get_id(self):
return self._activity_id return self._activity_id
def get_color(self):
return self._color
def get_services(self): def get_services(self):
ret = [] ret = []
for serv_list in self._services.values(): for serv_list in self._services.values():
@ -112,7 +126,7 @@ class Activity(object):
for serv_list in self._services.values(): for serv_list in self._services.values():
for serv in serv_list: for serv in serv_list:
owner = serv.get_owner() owner = serv.get_owner()
if not owner in buddies: if not owner in buddies and owner.is_valid():
buddies.append(owner) buddies.append(owner)
return buddies return buddies
@ -121,11 +135,17 @@ class Activity(object):
if not self._services.has_key(stype): if not self._services.has_key(stype):
self._services[stype] = [] self._services[stype] = []
if not self._color:
color = service.get_one_property('color')
if color:
self._color = color
self._valid = True
# Send out the BuddyJoined signal if this is the first # Send out the BuddyJoined signal if this is the first
# service from the buddy that we've seen # service from the buddy that we've seen
buddies = self.get_joined_buddies() buddies = self.get_joined_buddies()
serv_owner = service.get_owner() serv_owner = service.get_owner()
if serv_owner and serv_owner not in buddies: if serv_owner and serv_owner not in buddies and serv_owner.is_valid():
self._dbus_helper.BuddyJoined(serv_owner.object_path()) self._dbus_helper.BuddyJoined(serv_owner.object_path())
serv_owner.add_activity(self) serv_owner.add_activity(self)
@ -146,6 +166,6 @@ class Activity(object):
# service from the buddy # service from the buddy
buddies = self.get_joined_buddies() buddies = self.get_joined_buddies()
serv_owner = service.get_owner() serv_owner = service.get_owner()
if serv_owner and serv_owner not in buddies: if serv_owner and serv_owner not in buddies and serv_owner.is_valid():
serv_owner.remove_activity(self) serv_owner.remove_activity(self)
self._dbus_helper.BuddyLeft(serv_owner.object_path()) self._dbus_helper.BuddyLeft(serv_owner.object_path())

View File

@ -65,6 +65,8 @@ class BuddyDBusHelper(dbus.service.Object):
in_signature="", out_signature="ao") in_signature="", out_signature="ao")
def getJoinedActivities(self): def getJoinedActivities(self):
acts = [] acts = []
for act in self._parent.get_joined_activities():
acts.append(act.object_path())
return acts return acts
@dbus.service.method(BUDDY_DBUS_INTERFACE, @dbus.service.method(BUDDY_DBUS_INTERFACE,
@ -181,7 +183,8 @@ class Buddy(object):
if not found: if not found:
raise RuntimeError("Tried to add activity for which we had no service") raise RuntimeError("Tried to add activity for which we had no service")
self._activities[actid] = activity self._activities[actid] = activity
self._dbus_helper.JoinedActivity(activity.object_path()) if activity.is_valid():
self._dbus_helper.JoinedActivity(activity.object_path())
def remove_service(self, service): def remove_service(self, service):
"""Remove a service from a buddy; ie, the activity was closed """Remove a service from a buddy; ie, the activity was closed
@ -204,8 +207,15 @@ class Buddy(object):
if not self._activities.has_key(actid): if not self._activities.has_key(actid):
return return
del self._activities[actid] del self._activities[actid]
print "Buddy (%s) left activity %s." % (self._nick_name, actid) if activity.is_valid():
self._dbus_helper.LeftActivity(activity.object_path()) self._dbus_helper.LeftActivity(activity.object_path())
def get_joined_activities(self):
acts = []
for act in self._activities.values():
if act.is_valid():
acts.append(act)
return acts
def get_service_of_type(self, stype=None, activity=None): def get_service_of_type(self, stype=None, activity=None):
"""Return a service of a certain type, or None if the buddy """Return a service of a certain type, or None if the buddy
@ -213,6 +223,9 @@ class Buddy(object):
if not stype: if not stype:
raise RuntimeError("Need to specify a service type.") raise RuntimeError("Need to specify a service type.")
if activity and not activity.is_valid():
raise RuntimeError("Activity is not yet valid.")
if activity: if activity:
actid = activity.get_id() actid = activity.get_id()
for service in self._services.values(): for service in self._services.values():

View File

@ -302,24 +302,36 @@ class PresenceService(object):
return ret return ret
def get_activities(self): def get_activities(self):
return self._activities.values() # Only return valid activities
ret = []
for act in self._activities.values():
if act.is_valid():
ret.append(act)
return ret
def get_activity(self, actid): def get_activity(self, actid):
if self._activities.has_key(actid): if self._activities.has_key(actid):
return self._activities[actid] act = self._activities[actid]
if act.is_valid():
return act
return None return None
def get_buddies(self): def get_buddies(self):
return self._buddies.values() buddies = []
for buddy in self._buddies.values():
if buddy.is_valid():
buddies.append(buddy)
return buddies
def get_buddy_by_name(self, name): def get_buddy_by_name(self, name):
if self._buddies.has_key(name): if self._buddies.has_key(name):
return self._buddies[name] if self._buddies[name].is_valid():
return self._buddies[name]
return None return None
def get_buddy_by_address(self, address): def get_buddy_by_address(self, address):
for buddy in self._buddies.values(): for buddy in self._buddies.values():
if buddy.get_address() == address: if buddy.get_address() == address and buddy.is_valid():
return buddy return buddy
return None return None
@ -379,17 +391,21 @@ class PresenceService(object):
if not actid: if not actid:
return return
activity = None activity = None
was_valid = False
if not self._activities.has_key(actid): if not self._activities.has_key(actid):
objid = self._get_next_object_id() objid = self._get_next_object_id()
activity = Activity.Activity(self._bus_name, objid, service) activity = Activity.Activity(self._bus_name, objid, service)
self._activities[actid] = activity self._activities[actid] = activity
self._dbus_helper.ActivityAppeared(activity.object_path())
else: else:
activity = self._activities[actid] activity = self._activities[actid]
was_valid = activity.is_valid()
if activity: if activity:
activity.add_service(service) activity.add_service(service)
if not was_valid and activity.is_valid():
self._dbus_helper.ActivityAppeared(activity.object_path())
def _handle_remove_activity_service(self, service): def _handle_remove_activity_service(self, service):
actid = service.get_activity_id() actid = service.get_activity_id()
if not actid: if not actid:
@ -596,7 +612,11 @@ class PresenceService(object):
if not len(services): if not len(services):
raise NotFoundError("The service type %s was not present within the activity %s" % (stype, activity.object_path())) raise NotFoundError("The service type %s was not present within the activity %s" % (stype, activity.object_path()))
act_service = services[0] act_service = services[0]
return self._share_activity(activity.get_id(), stype, act_service.get_properties(), props = act_service.get_properties()
color = activity.get_color()
if color:
props['color'] = color
return self._share_activity(activity.get_id(), stype, properties,
act_service.get_address(), act_service.get_port(), act_service.get_domain()) act_service.get_address(), act_service.get_port(), act_service.get_domain())
def share_activity(self, activity_id, stype, properties=None, address=None, port=-1, domain=u"local"): def share_activity(self, activity_id, stype, properties=None, address=None, port=-1, domain=u"local"):
@ -616,6 +636,10 @@ class PresenceService(object):
if port and port != -1 and (type(port) != type(1) or port <= 1024 or port >= 65535): if port and port != -1 and (type(port) != type(1) or port <= 1024 or port >= 65535):
raise ValueError("port must be a number between 1024 and 65535") raise ValueError("port must be a number between 1024 and 65535")
color = self._owner.get_color()
if color:
properties['color'] = color
logging.debug('Share activity %s, type %s, address %s, port %d, properties %s' % (activity_id, stype, address, port, properties)) logging.debug('Share activity %s, type %s, address %s, port %d, properties %s' % (activity_id, stype, address, port, properties))
return self.register_service(real_name, stype, properties, address, port, domain) return self.register_service(real_name, stype, properties, address, port, domain)
@ -699,6 +723,7 @@ class PresenceService(object):
def main(): def main():
from sugar import TracebackUtils from sugar import TracebackUtils
env.read_profile()
loop = gobject.MainLoop() loop = gobject.MainLoop()
ps = PresenceService() ps = PresenceService()
tbh = TracebackUtils.TracebackHelper() tbh = TracebackUtils.TracebackHelper()

View File

@ -30,6 +30,7 @@ class Activity(gobject.GObject):
self._activity.connect_to_signal('ServiceDisappeared', self._service_disappeared_cb) self._activity.connect_to_signal('ServiceDisappeared', self._service_disappeared_cb)
self._id = None self._id = None
self._color = None
def object_path(self): def object_path(self):
return self._object_path return self._object_path
@ -68,8 +69,10 @@ class Activity(gobject.GObject):
self._id = self._activity.getId() self._id = self._activity.getId()
return self._id return self._id
def get_icon(self): def get_color(self):
return self._buddy.getIcon() if not self._color:
self._color = self._activity.getColor()
return self._color
def get_services(self): def get_services(self):
resp = self._activity.getServices() resp = self._activity.getServices()