r6906 - in bigboard/trunk/bigboard: . stocks/people



Author: otaylor
Date: 2007-11-13 16:17:26 -0600 (Tue, 13 Nov 2007)
New Revision: 6906

Modified:
   bigboard/trunk/bigboard/people_tracker.py
   bigboard/trunk/bigboard/stocks/people/PeopleStock.py
   bigboard/trunk/bigboard/stocks/people/peoplebrowser.py
   bigboard/trunk/bigboard/stocks/people/peoplewidgets.py
Log:
people_tracker.py: 
 - Switch over to new rule-based properties
 - create a Person GObject that wraps either a user or a buddy resource
   and exposes common properties between the two with change notification.

PeopleStock.py peoplebrowser.py peoplewidgets.py: Switch over
  to new PeopleTracker API.


Modified: bigboard/trunk/bigboard/people_tracker.py
===================================================================
--- bigboard/trunk/bigboard/people_tracker.py	2007-11-13 22:15:33 UTC (rev 6905)
+++ bigboard/trunk/bigboard/people_tracker.py	2007-11-13 22:17:26 UTC (rev 6906)
@@ -18,117 +18,255 @@
 
 def _canonicalize_aim(aim):
     return aim.replace(" ", "").lower()
-        
-class UserList(gobject.GObject):
-    """A list of users with change notification
 
-    The UserList object represents an (unordered) set of users with change notification
-    when users are added and removed from it via the 'added' and 'removed' GObject signals.
-    The object also supports the standard Python iteration protocol.
+class Person(gobject.GObject):
+    """Wrapper around buddy and user resources
 
+    A Person wraps a buddy resource or user resource and provides convenience APIs for
+    things that are shared between the two resource types.
     """
     __gsignals__ = {
-        "added": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,)),
-        "removed": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,)),
+        "display-name-changed": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()),
+        "icon-url-changed": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()),
+        "aim-changed": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()),
+        "aim-buddy-changed": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()),
+        "xmpp-changed": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()),
+        "xmpp-buddy-changed": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()),
+        "local-buddy-changed": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()),
     }
+    
+    def __init__(self, resource):
+        gobject.GObject.__init__(self)
+        self.resource = resource
+        self.is_user = self.resource.class_id == "http://mugshot.org/p/o/user";
 
-    def __init__(self):
-        super(UserList, self).__init__()
+        if self.is_user:
+            self.resource.connect(self.__user_name_changed, "name")
+            self.resource.connect(self.__user_photo_url_changed, "photoUrl")
+            self.resource.connect(self.__user_aim_changed, "aim")
+            self.resource.connect(self.__user_xmpp_changed, "xmpp")
+            self.resource.connect(self.__user_aim_buddy_changed, "aimBuddy")
+            self.resource.connect(self.__user_xmpp_buddy_changed, "xmppBuddy")
+            self.resource.connect(self.__user_local_buddy_changed, "mugshotLocalBuddy")
 
-        self.__users = {}
+            self.__user_name_changed(resource)
+            self.__user_photo_url_changed(resource)
+            self.__user_aim_changed(resource)
+            self.__user_xmpp_changed(resource)
+            self.__user_aim_buddy_changed(resource)
+            self.__user_xmpp_buddy_changed(resource)
+        else:
+            if resource.protocol == 'aim':
+                self.aim = resource.name
+                self.aim_buddy = resource
+            else:
+                self.aim = None
+                self.aim_buddy = None
 
-    def _update(self, users):
-        old_users = copy.copy(self.__users)
+            if resource.protocol == 'xmpp':
+                self.xmpp = resource.name
+                self.xmpp_buddy = resource
+            else:
+                self.xmpp = None
+                self.xmpp_buddy = None
 
-        for user in users:
-            if user.resource_id in old_users:
-                del old_users[user.resource_id]
+            if resource.protocol == 'mugshot-local':
+                self.local_buddy = resource
             else:
-                self.__users[user.resource_id] = user
+                self.local_buddy = None
 
-        for id in old_users:
-            del self.__users[id]
+            self.resource.connect(self.__buddy_alias_changed, "alias")
+            self.resource.connect(self.__buddy_icon_changed, "icon")
+
+            self.__buddy_alias_changed(resource)
+            self.__buddy_icon_changed(resource)
+
+    def __user_name_changed(self, resource):
+        try:
+            self.display_name = resource.name
+        except AttributeError:
+            # FIXME: why does this happen
+            self.display_name = "NO_NAME"
             
-        for id in self.__users:
-            if not id in old_users:
-                self.emit('added', self.__users[id])
+        self.emit("display-name-changed")
+
+    def __user_photo_url_changed(self, resource):
+        try:
+            self.icon_url = resource.photoUrl
+        except AttributeError:
+            self.icon_url = None
             
-        for id in old_users:
-            self.emit('removed', old_users[id])
+        self.emit("icon-url-changed")
 
-    def _add(self, user):
-        self.__users[user.resource_id] = user
-        self.emit('added', user)
+    def __user_aim_changed(self, resource):
+        try:
+            self.aim = resource.aim
+        except AttributeError:
+            self.aim = None
 
-    def _remove(self, user):
-        del self.__users[user.resource_id]
-        self.emit('removed', user)
+        self.emit("aim-changed")
 
-    def __str__(self):
-        return self.__users.values().__str__()
+    def __user_xmpp_changed(self, resource):
+        try:
+            self.xmpp = resource.xmpp
+        except AttributeError:
+            self.xmpp = None
 
-    def __iter__(self):
-        return self.__users.itervalues()
+        self.emit("xmpp-changed")
 
-class _MultiDict(object):
-    """A map from key => [ value, value, ... ]"""
-    
-    def __init__(self):
-        self.__forward = {}
-        self.__reverse = {}
-
-    def add(self, key, value):
+    def __user_aim_buddy_changed(self, resource):
         try:
-            self.__forward[key].append(value)
-        except KeyError:
-            self.__forward[key] = [ value ]
-            
-        self.__reverse[value] = key
+            self.aim_buddy = resource.aimBuddy
+        except AttributeError:
+            self.aim_buddy = None
 
-    def contains_value(self, value):
-        return value in self.__reverse
+        self.emit("aim-buddy-changed")
 
-    def contains_key(self, key):
-        return key in self.__forward
+    def __user_xmpp_buddy_changed(self, resource):
+        try:
+            self.xmpp_buddy = resource.xmppBuddy
+        except AttributeError:
+            self.xmpp_buddy = None
 
-    def remove_value(self, value):
-        key = self.__reverse[value]
-        values = self.__forward[key]
-        values.remove(value)
-        if len(values) == 0:
-            del self.__forward[key]
-        del self.__reverse[value]
+        self.emit("xmpp-buddy-changed")
 
-    def iterkeys(self):
-        return self.__forward.iterkeys()
-        
-    def itervalues(self):
-        return self.__reverse.iterkeys()
+    def __user_local_buddy_changed(self, resource):
+        try:
+            self.local_buddy = resource.mugshotLocalBuddy
+        except AttributeError:
+            self.local_buddy = None
 
-    def lookup_value(self, value):
-        return self.__reverse[value]
-        
-    def lookup(self, key):
+        self.emit("local-buddy-changed")
+
+    def __buddy_alias_changed(self, resource):
         try:
-            return self.__forward[key]
-        except KeyError:
-            return []
+            self.display_name = resource.alias
+        except AttributeError:
+            self.display_name = None
 
-    def lookup_first(self, key):
+        if self.display_name == None:
+            self.display_name = resource.name
+
+        self.emit("display-name-changed")
+
+    def __buddy_icon_changed(self, resource):
         try:
-            return self.__forward[key][0]
-        except KeyError:
-            return None
-        except IndexError:
-            return None
+            self.icon_url = resource.icon
+        except AttributeError:
+            self.icon_url = None
+        self.emit("icon-url-changed")
 
-    def clear(self):
-        self.__forward = {}
-        self.__reverse = {}
+    def __hash__(self):
+        return hash(self.resource)
 
+    def __eq__(self, other):
+        if isinstance(other, Person):
+            return self.resource == other.resource
+        else:
+            return self.resource == other
+
+class PersonSet(gobject.GObject):
+    """A list of Person objects with change notification
+
+    The PersonSet object represents an (unordered) set of person objects with change notification
+    when person objects are added and removed from it via the 'added' and 'removed' GObject signals.
+    The object also supports the standard Python iteration protocol.
+
+    """
+    __gsignals__ = {
+        "added": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,)),
+        "removed": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,)),
+    }
+
+class SinglePersonSet(PersonSet):
+    def __init__(self):
+        PersonSet.__init__(self)
+
+        self.__resources = set()
+        self.__resolved = set()
+
+    def _update(self, resources):
+        for resource in self.__resources:
+            if resource.class_id == "online-desktop:/p/o/buddy" and resource not in resources:
+                resource.disconnect(self.__buddy_user_changed)
+
+        for resource in resources:
+            if resource.class_id == "online-desktop:/p/o/buddy" and resource not in self.__resources:
+                    resource.connect(self.__buddy_user_changed, "user")
+
+        self.__resources = resources
+        self.__update_resolved()
+
+    def __update_resolved(self):
+        resolved = set()
+
+        for resource in self.__resources:
+            if resource.class_id == "online-desktop:/p/o/buddy":
+                try:
+                    user = resource.user
+                except:
+                    user = None
+                    
+                if user != None:
+                    resource = user
+
+            try:
+                person = resource.__person
+            except AttributeError:
+                person = resource.__person = Person(resource)
+                
+            resolved.add(person)
+
+        old_resolved = self.__resolved
+        self.__resolved = resolved
+        
+        for resource in old_resolved:
+            if resource not in self.__resolved:
+                self.emit('removed', resource)
+                
+        for resource in self.__resolved:
+            if resource not in old_resolved:
+                self.emit('added', resource)
+
+    def __buddy_user_changed(self, resource):
+        self.__update_resolved()
+
     def __str__(self):
-        return self.__forward.__str__()
+        return self.__resolved.__str__()
 
+    def __iter__(self):
+        return self.__resolved.__iter__()
+
+class UnionPersonSet(PersonSet):
+    def __init__(self, *args):
+        PersonSet.__init__(self)
+        self.__items = {}
+        for s in args:
+            s.connect('added', self.__on_added)
+            s.connect('removed', self.__on_removed)
+
+            for item in s:
+                self.__on_added(self, s, item)
+
+    def __on_added(self, s, item):
+        if item in self.__items:
+            self.__items[item] += 1
+        else:
+            self.__items[item] = 1
+            self.emit('added', item)
+
+    def __on_removed(self, s, item):
+        self.__items[item] -= 1
+        if self.__items[item] == 0:
+            del self.__items[item]
+            self.emit('removed', item)
+
+    def __str__(self):
+        return self.__items.values().__str__()
+
+    def __iter__(self):
+        return self.__items.itervalues()
+
 class PeopleTracker(Singleton):
     """Singleton object for tracking available users and contacts
 
@@ -138,29 +276,19 @@
     Lists of different types of users are available as the contacts, aim_users and local_users
     attributes of the singleton; these are UserList objects, and have signals for tracking
     changes as well as allowing iteration through the users.
-
-    The PeopleTracker object also injects artificial aimBuddy and localBuddy resource
-    properties into the user objects it tracks, as if they were provided from the
-    data model.
     """
     
     def __init__(self):
         self.__model = DataModel(bigboard.globals.server_name)
         self.__model.add_ready_handler(self.__on_ready)
 
-        self.__myself = None
-        self.__globalResource = None
-
-        self.contacts = UserList()
-        self.aim_users = UserList()
-        self.local_users = UserList()
-
-        self.__aim_buddies = _MultiDict()
-        self.__local_buddies = _MultiDict()
-
-        self.__users_by_aim = _MultiDict()
-        self.__users_by_resource_id = _MultiDict()
+        self.contacts = SinglePersonSet()
+        self.aim_people = SinglePersonSet()
+        self.xmpp_people = SinglePersonSet()
+        self.local_people = SinglePersonSet()
         
+        self.people = UnionPersonSet(self.contacts, self.aim_people, self.xmpp_people, self.local_people)
+
         if self.__model.ready:
             self.__on_ready()
         
@@ -168,242 +296,73 @@
 
         # When we disconnect from the server we freeze existing content, then on reconnect
         # we clear everything and start over.
-        
-        self.__clear_users()
-        
-        if self.__myself != None:
-            self.__set_new_contacts([])
-            self.__myself.disconnect(self.__on_contacts_changed)
 
-            self.__myself = None
-        
-        query = self.__model.query_resource(self.__model.self_resource, "contacts [+;aim;email;contactStatus]")
+        query = self.__model.query_resource(self.__model.self_resource, "contacts [+;aim;aimBuddy +;mugshotLocalBuddy +;xmpp;xmppBuddy +;email;contactStatus]")
         query.add_handler(self.__on_got_self)
         query.execute()
         
-        if self.__globalResource != None:
-            self.__set_new_buddies([])
-            self.__globalResource.disconnect(self.__on_buddies_changed)
-
-            self.__globalResource = None
-
-        query = self.__model.query_resource(self.__model.global_resource, "onlineBuddies +")
-        query.add_handler(self.__on_got_buddies)
+        query = self.__model.query_resource(self.__model.global_resource, "aimBuddies [+;user [+;aim;aimBuddy +;mugshotLocalBuddy +;xmpp;xmppBuddy +;email;contactStatus]];xmppBuddies [+;user [+;aim;aimBuddy +;mugshotLocalBuddy +;xmpp;xmppBuddy +;email;contactStatus]];mugshotLocalBuddies [+;user [+;aim;aimBuddy +;mugshotLocalBuddy +;xmpp;xmppBuddy +;email;contactStatus]]")
+        query.add_handler(self.__on_got_global)
         query.execute()
-        
-    def __on_got_self(self, myself):
-        self.__myself = myself
-        myself.connect(self.__on_contacts_changed, "contacts")
-        self.__on_contacts_changed(myself)
 
-    def __on_contacts_changed(self, myself):
-        self.__set_new_contacts(myself.contacts)
-
-    def __set_new_contacts(self, contacts):
-        for user in contacts:
-            self.__add_user(user)
-            
-        self.contacts._update(contacts)
-        
-    def __on_got_buddies(self, globalResource):
-        self.__globalResource = globalResource
-        globalResource.connect(self.__on_buddies_changed, "onlineBuddies")
-        self.__on_buddies_changed(globalResource)
-
-    def __on_buddies_changed(self, globalResource):
+    def __ensure_list_property(self, resource, property):
+        # Workaround for lack of schema support currently; if the property doesn't
+        # exist, make it empty
         try:
-            self.__set_new_buddies(globalResource.onlineBuddies)
-        except AttributeError, e:
-            ## globalResource.onlineBuddies may not exist yet before the query reply arrives
-            pass
-
-    def __set_new_buddies(self, buddies):
-        _logger.debug("Got new buddy list from the server: %s", buddies)
+            resource.get(property)
+        except AttributeError:
+            resource._update_property(property,
+                                      ddm.Resource.UPDATE_CLEAR, ddm.Resource.CARDINALITY_N,
+                                      None)
         
-        old_aim_buddies = self.__aim_buddies
-        old_local_buddies = self.__local_buddies
-        new_aim_buddies = _MultiDict()
-        new_local_buddies = _MultiDict()
+    def __on_got_self(self, self_resource):
+        self.__ensure_list_property(self_resource, ("http://mugshot.org/p/o/user";, "contacts"))
+        self_resource.connect(self.__on_contacts_changed, "contacts")
+        self.__on_contacts_changed(self_resource)
 
-        for buddy in buddies:
-            if buddy.protocol == "aim":
-                new_aim_buddies.add(_canonicalize_aim(buddy.name), buddy)
-            elif buddy.protocol == "mugshot-local":
-                new_local_buddies.add(buddy.name, buddy)
+    def __on_contacts_changed(self, self_resource):
+        new_contacts = set()
+        for user in self_resource.contacts:
+            new_contacts.add(user)
 
-        self.__aim_buddies = new_aim_buddies
-        self.__local_buddies = new_local_buddies
-
-        for aim in new_aim_buddies.iterkeys():
-            first_buddy = new_aim_buddies.lookup_first(aim)
-            
-            if not old_aim_buddies.contains_key(aim) or \
-               old_aim_buddies.lookup_first(aim) != first_buddy:
-                self.__update_buddy_for_aim(aim)
-            
-        for aim in old_aim_buddies.iterkeys():
-            if not new_aim_buddies.contains_key(aim):
-                self.__update_buddy_for_aim(aim)
+        self.contacts._update(new_contacts)
         
-        for resource_id in new_local_buddies.iterkeys():
-            first_buddy = new_local_buddies.lookup_first(resource_id)
-            
-            if not old_local_buddies.contains_key(resource_id) or \
-               old_local_buddies.lookup_first(resource_id) != first_buddy:
-                self.__update_buddy_for_resource_id(resource_id)
-            
-                query = self.__model.query_resource(resource_id, "+;aim;email")
-                query.add_handler(self.__on_got_local_user)
-                query.execute()
-                
-        for resource_id in old_local_buddies.iterkeys():
-            if not new_local_buddies.contains_key(resource_id):
-                self.__update_buddy_for_resource_id(resource_id)
-
-        _logger.debug("Aim buddy list is now %s", self.__aim_buddies)
-        _logger.debug("Local buddy list is now %s", self.__local_buddies)
-
-        self.__update_user_list(self.aim_users, self.__aim_buddies, self.__users_by_aim)
-        _logger.debug("Aim user list is now %s", self.aim_users)
-        self.__update_user_list(self.local_users, self.__local_buddies, self.__users_by_resource_id)
-        _logger.debug("Local user list is now %s", self.local_users)
+    def __on_got_global(self, global_resource):
+        self.__ensure_list_property(global_resource, ("online-desktop:/p/o/global", "aimBuddies"))
+        self.__ensure_list_property(global_resource, ("online-desktop:/p/o/global", "xmppBuddies"))
+        self.__ensure_list_property(global_resource, ("online-desktop:/p/o/global", "mugshotLocalBuddies"))
+        global_resource.connect(self.__on_aim_buddies_changed, "aimBuddies")
+        global_resource.connect(self.__on_local_buddies_changed, "mugshotLocalBuddies")
+        global_resource.connect(self.__on_xmpp_buddies_changed, "xmppBuddies")
         
-    def __on_got_local_user(self, user):
-        self.__add_user(user)
-        
-    def __update_buddy_for_aim(self, aim):
-        for user in self.__users_by_aim.lookup(aim):
-            self.__update_user_aim_buddy(self, user)
-    
-    def __update_user_aim_buddy(self, user):
-        try:
-            buddy = self.__aim_buddies.lookup_first(_canonicalize_aim(user.aim))
-        except AttributeError:
-            buddy = None
-            
-        notifications = NotificationSet(self.__model)
-        
-        if buddy != None:
-            user._update_property(('http://mugshot.org/p/bigboard/user', 'aimBuddy'),
-                                  ddm.Resource.UPDATE_REPLACE, ddm.Resource.CARDINALITY_01,
-                                  buddy, notifications)
-        else:
-            user._update_property(('http://mugshot.org/p/bigboard/user', 'aimBuddy'),
-                                  ddm.Resource.UPDATE_CLEAR, ddm.Resource.CARDINALITY_01,
-                                  None, notifications)
-        notifications.send()
+        self.__on_aim_buddies_changed(global_resource)
+        self.__on_local_buddies_changed(global_resource)
+        self.__on_xmpp_buddies_changed(global_resource)
 
-    def __update_buddy_for_resource_id(self, resource_id):
-        for user in self.__users_by_resource_id.lookup(resource_id):
-            self.__update_user_local_buddy(user)
-    
-    def __update_user_local_buddy(self, user):
-        buddy = self.__local_buddies.lookup_first(user.resource_id)
-        notifications = NotificationSet(self.__model)
-        
-        if buddy != None:
-            user._update_property(('http://mugshot.org/p/bigboard/user', 'localBuddy'),
-                                  ddm.Resource.UPDATE_REPLACE, ddm.Resource.CARDINALITY_01,
-                                  buddy, notifications)
-        else:
-            user._update_property(('http://mugshot.org/p/bigboard/user', 'localBuddy'),
-                                  ddm.Resource.UPDATE_CLEAR, ddm.Resource.CARDINALITY_01,
-                                  None, notifications)
-        notifications.send()
+    def __on_aim_buddies_changed(self, global_resource):
+        self.aim_people._update(global_resource.aimBuddies)
 
-    def __update_user_list(self, list, buddies, key_to_user):
-        new_users = []
-        for key in buddies.iterkeys():
-            user = key_to_user.lookup_first(key)
-            if user != None:
-                new_users.append(user)
+    def __on_local_buddies_changed(self, global_resource):
+        self.local_people._update(global_resource.mugshotLocalBuddies)
 
-        list._update(new_users)
+    def __on_xmpp_buddies_changed(self, global_resource):
+        self.xmpp_people._update(global_resource.xmppBuddies)
 
-    def __on_user_aim_changed(self, user):
+def sort_people(a,b):
+    if a.is_user:
         try:
-            old_aim = self.__users_by_aim.lookup_value(user)
-        except KeyError:
-            old_aim = None
+            statusA = a.resource.contactStatus
+        except AttributeError:
+            statusA = 0
+    else:
+        statusA = 0
 
+    if b.is_user:
         try:
-            new_aim = _canonicalize_aim(user.aim)
+            statusB = b.resource.contactStatus
         except AttributeError:
-            new_aim = None
-
-        if old_aim != None:
-            if self.__aim_buddies.contains_key(old_aim):
-                old_first_user = self.__users_by_aim.lookup_first(old_aim)
-            self.__users_by_aim.remove_value(user)
-            if self.__aim_buddies.contains_key(old_aim):
-                new_first_user = self.__users_by_aim.lookup_first(old_aim)
-
-                if old_first_user != new_first_user:
-                    if old_first_user != None:
-                        self.aim_users._remove(old_first_user)
-                    if new_first_user != None:
-                        self.aim_users._add(new_first_user)
-                    _logger.debug("aim users is now %s", self.aim_users)                        
-
-        _logger.debug("aim for %s changed from %s to %s", user, old_aim, new_aim)
-                
-        if new_aim != None:
-            if self.__aim_buddies.contains_key(new_aim):
-                old_first_user = self.__users_by_aim.lookup_first(new_aim)
-            self.__users_by_aim.add(new_aim, user)
-            if self.__aim_buddies.contains_key(new_aim):
-                new_first_user = self.__users_by_aim.lookup_first(new_aim)
-
-                if old_first_user != new_first_user:
-                    if old_first_user != None:
-                        self.aim_users._remove(old_first_user)
-                    if new_first_user != None:
-                        self.aim_users._add(new_first_user)
-                    _logger.debug("aim users is now %s", self.aim_users)
-
-        self.__update_user_aim_buddy(user)
-
-    def __add_user(self, user):
-        _logger.debug("Adding user %s into global map", user.name)
-        
-        if self.__users_by_resource_id.contains_key(user.resource_id):
-            return
-
-        if self.__local_buddies.contains_key(user.resource_id):
-            old_first_user = self.__users_by_resource_id.lookup_first(user.resource_id)
-        
-        self.__users_by_resource_id.add(user.resource_id, user)
-        self.__update_user_local_buddy(user)
-
-        if self.__local_buddies.contains_key(user.resource_id):
-            new_first_user = self.__users_by_resource_id.lookup_first(user.resource_id)
-        
-        user.connect(self.__on_user_aim_changed, 'aim')
-        self.__on_user_aim_changed(user)
-
-        if self.__local_buddies.contains_key(user.resource_id):
-            if old_first_user != new_first_user:
-                if old_first_user != None:
-                    self.local_users._remove(old_first_user)
-                if new_first_user != None:
-                    self.local_users._add(new_first_user)
-
-    def __clear_users(self):
-        for user in self.__users_by_resource_id.itervalues():
-            user.disconnect(self.__on_user_aim_changed)
-            
-        self.__users_by_aim.clear()
-        self.__users_by_resource_id.clear()
-
-def sort_users(a,b):
-    try:
-        statusA = a.contactStatus
-    except AttributeError:
-        statusA = 0
-        
-    try:
-        statusB = b.contactStatus
-    except AttributeError:
+            statusB = 0
+    else:
         statusB = 0
 
     if statusA == 0:
@@ -414,5 +373,5 @@
     if statusA != statusB:
         return statusB - statusA
 
-    return bignative.utf8_collate(a.name, b.name)
+    return bignative.utf8_collate(a.display_name, b.display_name)
 

Modified: bigboard/trunk/bigboard/stocks/people/PeopleStock.py
===================================================================
--- bigboard/trunk/bigboard/stocks/people/PeopleStock.py	2007-11-13 22:15:33 UTC (rev 6905)
+++ bigboard/trunk/bigboard/stocks/people/PeopleStock.py	2007-11-13 22:17:26 UTC (rev 6906)
@@ -4,7 +4,7 @@
 from ddm import DataModel
 
 import bigboard
-from bigboard.people_tracker import PeopleTracker, sort_users
+from bigboard.people_tracker import PeopleTracker, sort_people
 from bigboard.stock import AbstractMugshotStock
 import bigboard.globals
 import bigboard.slideout
@@ -46,16 +46,16 @@
         self.__tracker = PeopleTracker()
         self.__tracker.contacts.connect("added", self.__on_contact_added)
         self.__tracker.contacts.connect("removed", self.__on_contact_removed)
-        self.__tracker.local_users.connect("added", self.__on_local_user_added)
-        self.__tracker.local_users.connect("removed", self.__on_local_user_removed)
+        self.__tracker.local_people.connect("added", self.__on_local_person_added)
+        self.__tracker.local_people.connect("removed", self.__on_local_person_removed)
 
         self.__model = DataModel(bigboard.globals.server_name)
 
-        for user in self.__tracker.contacts:
-            self.__on_contact_added(self.__tracker.contacts, user)
+        for person in self.__tracker.contacts:
+            self.__on_contact_added(self.__tracker.contacts, person)
             
-        for user in self.__tracker.local_users:
-            self.__on_local_user_added(self.__tracker.local_users, user)
+        for person in self.__tracker.local_people:
+            self.__on_local_person_added(self.__tracker.local_people, person)
 
         ## add a new search provider (FIXME never gets disabled)
         search.enable_search_provider('people',
@@ -83,52 +83,53 @@
         show_separator = len(self.__local_items) != 0 and len(self.__contact_items) != 0
         self.__box.set_child_visible(self.__separator, show_separator)
 
-    def __add_user(self, user, box, map):
-        self._logger.debug("user added to people stock %s" % (user.name))
-        if map.has_key(user.resource_id):
+    def __add_person(self, person, box, map):
+        self._logger.debug("person added to people stock %s" % (person.display_name))
+        if map.has_key(person):
             return
         
-        item = PersonItem(user)
-        box.insert_sorted(item, hippo.PACK_IF_FITS, lambda a,b: sort_users(a.resource, b.resource))
+        item = PersonItem(person)
+        box.insert_sorted(item, hippo.PACK_IF_FITS, lambda a,b: sort_people(a.person, b.person))
 
-        def resort(resource):
+        def resort(*args):
             box.remove(item)
-            box.insert_sorted(item, hippo.PACK_IF_FITS, lambda a,b: sort_users(a.resource, b.resource))
+            box.insert_sorted(item, hippo.PACK_IF_FITS, lambda a,b: sort_people(a.person, b.person))
+
+        if person.is_user:
+            person.resource.connect(resort, 'contactStatus')
+        person.connect('display-name-changed', resort)
         
-        user.connect(resort, 'contactStatus')
-        user.connect(resort, 'name')
-        
-        map[user.resource_id] = item
+        map[person] = item
         self.__set_item_size(item, self.get_size())
         item.connect('activated', self.__handle_item_pressed)
 
         self.__update_separators()
 
-    def __remove_user(self, user, box, map):
+    def __remove_person(self, person, box, map):
         try:
-            item = map[user.resource_id]
+            item = map[person]
         except KeyError:
             return
         
         item.destroy()
-        del map[user.resource_id]
+        del map[person]
         
         self.__update_separators()
 
     def __on_contact_added(self, list, contact):
-        self.__add_user(contact, self.__contact_box, self.__contact_items)
+        self.__add_person(contact, self.__contact_box, self.__contact_items)
         
     def __on_contact_removed(self, list, contact):
-        self.__remove_user(contact, self.__contact_box, self.__contact_items)
+        self.__remove_person(contact, self.__contact_box, self.__contact_items)
         
-    def __on_local_user_added(self, list, user):
-        if user == self.__model.self_resource:
+    def __on_local_person_added(self, list, person):
+        if person == self.__model.self_resource:
             return
         
-        self.__add_user(user, self.__local_box, self.__local_items)
+        self.__add_person(person, self.__local_box, self.__local_items)
         
-    def __on_local_user_removed(self, list, user):
-        self.__remove_user(user, self.__local_box, self.__local_items)
+    def __on_local_person_removed(self, list, person):
+        self.__remove_person(person, self.__local_box, self.__local_items)
         
     def __close_slideout(self, *args):
         if self.__slideout:
@@ -147,7 +148,7 @@
         coords = item.get_screen_coords()
         self.__slideout.slideout_from(coords[0] + item.get_allocation()[0] + 4, coords[1])
 
-        p = ProfileItem(item.get_user(),
+        p = ProfileItem(item.get_person(),
                         border=1,
                         border_color = 0x0000000ff)
 
@@ -203,24 +204,21 @@
             #_logger.debug("contact: " + str(p))
 
             email = None
-            try:
-                email = p.email
-            except AttributeError:
-                email = None
+            if person.is_user:
+                try:
+                    email = p.resource.email
+                except AttributeError:
+                    pass
 
-            aim = None
-            try:
-                aim = p.aim
-            except AttributeError:
-                aim = None
+            aim = p.aim
             
-            if query in p.name or (email and (query in email)) or (aim and (query in aim)):
+            if query in p.display_name or (email and (query in email)) or (p.aim and (query in p.aim)):
                 results.append(PeopleSearchResult(self, p))
                 
-        for p in self.__tracker.aim_users:
+        for p in self.__tracker.aim_people:
             #_logger.debug("aim: " + str(p))
             pass ## FIXME
-        for p in self.__tracker.local_users:
+        for p in self.__tracker.local_people:
             #_logger.debug("local: " + str(p))
             pass ## FIXME            
 

Modified: bigboard/trunk/bigboard/stocks/people/peoplebrowser.py
===================================================================
--- bigboard/trunk/bigboard/stocks/people/peoplebrowser.py	2007-11-13 22:15:33 UTC (rev 6905)
+++ bigboard/trunk/bigboard/stocks/people/peoplebrowser.py	2007-11-13 22:17:26 UTC (rev 6906)
@@ -9,7 +9,7 @@
 import bigboard.libbig as libbig
 from bigboard.big_widgets import CanvasMugshotURLImage, CanvasHBox, CanvasVBox, ActionLink, PrelightingCanvasBox
 from bigboard.overview_table import OverviewTable
-from bigboard.people_tracker import PeopleTracker, sort_users
+from bigboard.people_tracker import PeopleTracker, sort_people
 
 from peoplewidgets import PersonItem, ProfileItem
 
@@ -17,10 +17,14 @@
 
 LOCAL_PEOPLE = 0
 CONTACTS = 1
+AIM_PEOPLE = 2
+XMPP_PEOPLE = 3
 
 SECTIONS = {
     LOCAL_PEOPLE : "Local People",
-    CONTACTS : "Contacts"
+    CONTACTS : "Contacts",
+    AIM_PEOPLE : "AIM Buddies",
+    XMPP_PEOPLE : "Jabber/Google Talk/XMPP Contacts"
 }
 
 class PeopleList(OverviewTable):
@@ -43,42 +47,43 @@
         self.__selected_item = None
         self.__search = None
 
-    def add_user(self, user, section):
-        if user.resource_id in self.__items[section]:
+    def add_person(self, person, section):
+        if person in self.__items[section]:
             return
         
-        item = PersonItem(user)
+        item = PersonItem(person)
         item.connect("button-press-event", self.__on_item_click)
                 
-        self.add_column_item(section, item, lambda a,b: sort_users(a.resource, b.resource))
+        self.add_column_item(section, item, lambda a,b: sort_people(a.person, b.person))
         self.__section_counts[section] += 1
         if self.__section_counts[section] == 1:
             self.__section_headers[section].set_visible(True)
                     
         def resort(resource):
             self.remove(item)
-            self.add_column_item(section, item, lambda a,b: sort_users(a.resource, b.resource))
-            
-        user.connect(resort, 'contactStatus')
-        user.connect(resort, 'name')
+            self.add_column_item(section, item, lambda a,b: sort_people(a.person, b.person))
+
+        if person.is_user:
+            person.resource.connect(resort, 'contactStatus')
+        person.connect('display-name-changed', resort)
         
         self.__update_visibility(section, item)
 
-        self.__items[section][user.resource_id] = item
+        self.__items[section][person] = item
 
-    def remove_user(self, user, section):
+    def remove_person(self, person, section):
         try:
-            item = self.__items[section][user.resource_id]
+            item = self.__items[section][person]
         except KeyError:
             return
         
         item.destroy()
-        del self.__items[section][user.resource_id]
+        del self.__items[section][person]
 
     def __update_visibility(self, section, item):
         was_visible = item.get_visible()
         
-        visible = self.__search == None or item.resource.name.lower().find(self.__search) >= 0
+        visible = self.__search == None or item.person.display_name.lower().find(self.__search) >= 0
 
         if visible != was_visible:
             if visible:
@@ -113,13 +118,13 @@
             
         self.__selected_item = item
         self.__selected_item.set_force_prelight(True)
-        self.emit("selected", item.resource)
+        self.emit("selected", item.person)
 
     def __on_item_click(self, item, event):
          if event.count == 1:
              self.__select_item(item)
 
-    def select_single_visible_user(self):
+    def select_single_visible_person(self):
         visible_item = None
         
         for section in SECTIONS:
@@ -129,7 +134,7 @@
                 if item.get_visible():
                     if visible_item == None:
                         visible_item = item
-                    elif visible_item.resource != item.resource:
+                    elif visible_item.person != item.person:
                         return # Two visible
                     
         if visible_item != None:
@@ -163,7 +168,7 @@
 
         self.__profile_box = CanvasVBox(border=1, border_color=0x999999FF, background_color=0xFFFFFFFF)
         self.__left_box.append(self.__profile_box)
-        self.__set_profile_user(None)
+        self.__set_profile_person(None)
     
         self.__right_scroll = hippo.CanvasScrollbars()
         self.__right_scroll.set_policy(hippo.ORIENTATION_HORIZONTAL,
@@ -174,7 +179,7 @@
         self.__people_list = PeopleList()
         self.__right_box.append(self.__people_list, hippo.PACK_EXPAND)
 
-        self.__people_list.connect("selected", self.__on_user_selected)
+        self.__people_list.connect("selected", self.__on_person_selected)
         
         self.__right_scroll.set_root(self.__right_box)        
         
@@ -187,24 +192,34 @@
         self.__tracker = PeopleTracker()
         self.__tracker.contacts.connect("added", self.__on_contact_added)
         self.__tracker.contacts.connect("removed", self.__on_contact_removed)
-        self.__tracker.local_users.connect("added", self.__on_local_user_added)
-        self.__tracker.local_users.connect("removed", self.__on_local_user_removed)
+        self.__tracker.local_people.connect("added", self.__on_local_person_added)
+        self.__tracker.local_people.connect("removed", self.__on_local_person_removed)
+        self.__tracker.aim_people.connect("added", self.__on_aim_person_added)
+        self.__tracker.aim_people.connect("removed", self.__on_aim_person_removed)
+        self.__tracker.xmpp_people.connect("added", self.__on_xmpp_person_added)
+        self.__tracker.xmpp_people.connect("removed", self.__on_xmpp_person_removed)
 
         self.__model = DataModel(bigboard.globals.server_name)
 
-        for user in self.__tracker.contacts:
-            self.__on_contact_added(self.__tracker.contacts, user)
+        for person in self.__tracker.contacts:
+            self.__on_contact_added(self.__tracker.contacts, person)
             
-        for user in self.__tracker.local_users:
-            self.__on_local_user_added(self.__tracker.local_users, user)
+        for person in self.__tracker.local_people:
+            self.__on_local_person_added(self.__tracker.local_people, person)
 
-    def __set_profile_user(self, user):
+        for person in self.__tracker.aim_people:
+            self.__on_aim_person_added(self.__tracker.aim_people, person)
+
+        for person in self.__tracker.xmpp_people:
+            self.__on_xmpp_person_added(self.__tracker.xmpp_people, person)
+
+    def __set_profile_person(self, person):
         self.__profile_box.clear()
-        if user == None:
+        if person == None:
             self.__profile_box.set_property("box-height", 300)
         else:
             self.__profile_box.set_property("box_height", -1)
-            self.__profile_box.append(ProfileItem(user))
+            self.__profile_box.append(ProfileItem(person))
 
     def __reset(self):
         self.__search_input.set_property('text', '')
@@ -228,22 +243,41 @@
         
     def __on_search_keypress(self, entry, event):
         if event.key == hippo.KEY_RETURN:
-            self.__people_list.select_single_visible_user()
+            self.__people_list.select_single_visible_person()
 
-    def __on_user_selected(self, list, user):
-         self.__set_profile_user(user)
+    def __on_person_selected(self, list, person):
+         self.__set_profile_person(person)
          
     def __on_contact_added(self, list, contact):
-        self.__people_list.add_user(contact, CONTACTS)
+        self.__people_list.add_person(contact, CONTACTS)
         
     def __on_contact_removed(self, list, contact):
-        self.__people_list.remove_user(contact, CONTACTS)
+        self.__people_list.remove_person(contact, CONTACTS)
         
-    def __on_local_user_added(self, list, user):
-        if user == self.__model.self_resource:
+    def __on_local_person_added(self, list, person):
+        if person == self.__model.self_resource:
             return
         
-        self.__people_list.add_user(user, LOCAL_PEOPLE)
+        self.__people_list.add_person(person, LOCAL_PEOPLE)
         
-    def __on_local_user_removed(self, list, user):
-        self.__people_list.remove_user(user, LOCAL_PEOPLE)
+    def __on_local_person_removed(self, list, person):
+        self.__people_list.remove_person(person, LOCAL_PEOPLE)
+
+    def __on_aim_person_added(self, list, person):
+        if person == self.__model.self_resource:
+            return
+        
+        self.__people_list.add_person(person, AIM_PEOPLE)
+        
+    def __on_aim_person_removed(self, list, person):
+        self.__people_list.remove_person(person, AIM_PEOPLE)
+
+    def __on_xmpp_person_added(self, list, person):
+        if person == self.__model.self_resource:
+            return
+        
+        self.__people_list.add_person(person, XMPP_PEOPLE)
+        
+    def __on_xmpp_person_removed(self, list, person):
+        self.__people_list.remove_person(person, XMPP_PEOPLE)
+        

Modified: bigboard/trunk/bigboard/stocks/people/peoplewidgets.py
===================================================================
--- bigboard/trunk/bigboard/stocks/people/peoplewidgets.py	2007-11-13 22:15:33 UTC (rev 6905)
+++ bigboard/trunk/bigboard/stocks/people/peoplewidgets.py	2007-11-13 22:17:26 UTC (rev 6906)
@@ -18,6 +18,10 @@
 def _open_aim(aim):
     os.spawnlp(os.P_NOWAIT, 'gnome-open', 'gnome-open', 'aim:GoIM?screenname=' + cgi.escape(aim))
 
+def _open_xmpp(xmpp):
+    # FIXME
+    pass
+
 def _open_webdav(url):
     # We pass around WebDAV URL's using the standard http:// scheme, but nautilus wants dav://
     # instead.
@@ -27,10 +31,10 @@
     
     os.spawnlp(os.P_NOWAIT, 'gnome-open', 'gnome-open', url)
 
-class PersonItem(PhotoContentItem, DataBoundItem):
-    def __init__(self, user, **kwargs):
+class PersonItem(PhotoContentItem):
+    def __init__(self, person, **kwargs):
         PhotoContentItem.__init__(self, **kwargs)
-        DataBoundItem.__init__(self, user)
+        self.person = person
         
         model = DataModel(bigboard.globals.server_name)
 
@@ -66,18 +70,22 @@
         self.__current_track = None
         self.__current_track_timeout = None
 
-        query = model.query_resource(self.resource, "currentTrack +;currentTrackPlayTime")
-        query.add_handler(self.__update_current_track)
-        query.execute()
+        if self.person.is_user:
+            query = model.query_resource(self.person.resource, "currentTrack +;currentTrackPlayTime")
+            query.add_handler(self.__update_current_track)
+            query.execute()
 
-        self.connect_resource(self.__update, 'name')
-        self.connect_resource(self.__update, 'photoUrl')
-        self.connect_resource(self.__update_aim_buddy, 'aimBuddy')
-        self.connect_resource(self.__update_current_track, 'currentTrack')
-        self.connect_resource(self.__update_current_track, 'currentTrackPlayTime')
-        self.__update(self.resource)
-        self.__update_aim_buddy(self.resource)
-        self.__update_current_track(self.resource)
+            self.person.resource.connect(self.__update_current_track, 'currentTrack')
+            self.person.resource.connect(self.__update_current_track, 'currentTrackPlayTime')
+            self.__update_current_track(self.person.resource)
+            
+        self.person.connect('display-name-changed', self.__update)
+        self.person.connect('icon-url-changed', self.__update)
+        
+        self.person.connect('aim-buddy-changed', self.__update_aim_buddy)
+        
+        self.__update(self.person)
+        self.__update_aim_buddy(self.person)
 
     def __update_color(self):
         if self.__pressed:
@@ -103,8 +111,8 @@
 
         return False
 
-    def get_user(self):
-        return self.resource
+    def get_person(self):
+        return self.person
 
     def set_size(self, size):
         if size == bigboard.stock.SIZE_BULL:
@@ -116,32 +124,29 @@
             self.__photo.set_property('xalign', hippo.ALIGNMENT_CENTER)
             self.__photo.set_property('yalign', hippo.ALIGNMENT_CENTER)
 
-    def __update(self, user):
-        self.__name.set_property("text", self.resource.name)
-        self.__photo.set_url(self.resource.photoUrl)
+    def __update(self, person):
+        self.__name.set_property("text", self.person.display_name)
+        self.__photo.set_url(self.person.icon_url)
 
-    def __update_aim_buddy(self, user):
-        if self.__aim_icon:
-            self.__aim_icon.destroy()
-            self.__aim_icon = None
+    def __update_aim_buddy(self, person):
+        if person.aim_buddy:
+            if not self.__aim_icon:
+                self.__aim_icon = AimIcon(person.aim_buddy)
+                self.__presence_box.append(self.__aim_icon)
+        else:
+            if self.__aim_icon:
+                self.__aim_icon.destroy()
+                self.__aim_icon = None
 
-        try:
-            buddy = self.resource.aimBuddy
-        except AttributeError:
-            return
-
-        self.__aim_icon = AimIcon(buddy)
-        self.__presence_box.append(self.__aim_icon)
-
     def __timeout_track(self):
         self.__current_track_timeout = None
-        self.__update_current_track(self.resource)
+        self.__update_current_track(self.person.resource)
         return False
 
-    def __update_current_track(self, user):
+    def __update_current_track(self, person):
         try:
-            current_track = self.resource.currentTrack
-            current_track_play_time = self.resource.currentTrackPlayTime / 1000.
+            current_track = self.person.resource.currentTrack
+            current_track_play_time = self.person.resource.currentTrackPlayTime / 1000.
         except AttributeError:
             current_track = None
             current_track_play_time = -1
@@ -221,7 +226,7 @@
         self.__acct = acct
         self.__acct.connect(self.__sync)
         self.__sync()
-        
+         
     def __sync(self):
         self.__img.set_url(self.__acct.iconUrl)
         
@@ -386,15 +391,15 @@
     def __open_webdav(self, object):
         _open_webdav(self.__get_url())
 
-class ProfileItem(hippo.CanvasBox, DataBoundItem):
+class ProfileItem(hippo.CanvasBox):
     __gsignals__ = {
         "close": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ())
        }
         
-    def __init__(self, user, **kwargs):
+    def __init__(self, person, **kwargs):
         kwargs['orientation'] = hippo.ORIENTATION_VERTICAL
         hippo.CanvasBox.__init__(self, **kwargs)
-        DataBoundItem.__init__(self, user)
+        self.person = person
 
         self.__header = hippo.CanvasGradient(orientation=hippo.ORIENTATION_HORIZONTAL,
                                              start_color=0xf2f2f2f2,
@@ -403,9 +408,10 @@
         self.__name = hippo.CanvasText(font="22px", padding=6)
         self.__header.append(self.__name)
 
-        mugshot_link = ActionLink(text="Mugshot", padding=6)
-        self.__header.append(mugshot_link, flags=hippo.PACK_END)
-        mugshot_link.connect("activated", self.__on_activate_web)
+        if person.is_user:
+            mugshot_link = ActionLink(text="Mugshot", padding=6)
+            self.__header.append(mugshot_link, flags=hippo.PACK_END)
+            mugshot_link.connect("activated", self.__on_activate_web)
 
         self.__top_box = hippo.CanvasBox(orientation=hippo.ORIENTATION_HORIZONTAL)
         self.append(self.__top_box)
@@ -413,8 +419,10 @@
         self.__photo = CanvasMugshotURLImage(scale_width=60,
                                             scale_height=60,
                                             border=5)
-        self.__photo.set_clickable(True)
-        self.__photo.connect("activated", self.__on_activate_web)
+
+        if person.is_user:
+            self.__photo.set_clickable(True)
+            self.__photo.connect("activated", self.__on_activate_web)
         self.__top_box.append(self.__photo)
 
         self.__address_box = hippo.CanvasBox(orientation=hippo.ORIENTATION_VERTICAL)
@@ -440,19 +448,26 @@
         
         self.__local_files_link = None
 
-        self.connect_resource(self.__update)
-        self.connect_resource(self.__update_contact_status, "contactStatus")
-        self.connect_resource(self.__update_loved_accounts, "lovedAccounts")
-        self.connect_resource(self.__update_local_buddy, "localBuddy")
+        self.person.connect('display-name-changed', self.__update)
+        self.person.connect('icon-url-changed', self.__update)
+        self.person.connect('aim-changed', self.__update)
+        self.person.connect('local-buddy-changed', self.__update_local_buddy)
+        self.person.connect('xmpp-changed', self.__update)
+        if person.is_user:
+            self.person.resource.connect(lambda *args: self.__update(self.person), 'email')
+            self.person.resource.connect(self.__update_contact_status, "contactStatus")
+            self.person.resource.connect(self.__update_loved_accounts, "lovedAccounts")
         
-        query = DataModel(bigboard.globals.server_name).query_resource(self.resource, "lovedAccounts +")
+        query = DataModel(bigboard.globals.server_name).query_resource(self.person.resource, "lovedAccounts +")
         query.add_handler(self.__update_loved_accounts)
         query.execute()
+
+        self.__update(self.person)
+        self.__update_local_buddy(self.person)
         
-        self.__update(self.resource)
-        self.__update_contact_status(self.resource)
-        self.__update_loved_accounts(self.resource)
-        self.__update_local_buddy(self.resource)
+        if self.person.is_user:
+            self.__update_contact_status(self.person.resource)
+            self.__update_loved_accounts(self.person.resource)
 
     def __add_status_link(self, text, current_status, new_status):
         if current_status == new_status:
@@ -461,7 +476,7 @@
             def set_new_status(object):
                 model = DataModel(bigboard.globals.server_name)
                 query = model.update(("http://mugshot.org/p/contacts";, "setContactStatus"),
-                                     user=self.resource,
+                                     person=self.person.resource,
                                      status=new_status)
                 query.execute()
         
@@ -470,10 +485,10 @@
         
         self.__contact_status_box.append(link)
         
-    def __update_contact_status(self, user):
+    def __update_contact_status(self, person):
         self.__contact_status_box.remove_all()
         try:
-            status = self.resource.contactStatus
+            status = self.person.resource.contactStatus
         except AttributeError:
             status = 0
 
@@ -486,9 +501,9 @@
         self.__add_status_link("Auto", status, 3)
         self.__add_status_link("Never", status, 2)
 
-    def __update_loved_accounts(self, user):
+    def __update_loved_accounts(self, person):
         try:
-            accounts = self.resource.lovedAccounts
+            accounts = self.person.resource.lovedAccounts
         except AttributeError:
             accounts = []
         
@@ -497,59 +512,61 @@
             icon = ExternalAccountIcon(a)
             self.__ribbon_bar.append(icon)
 
-    def __update_local_buddy(self, user):
+    def __update_local_buddy(self, person):
         if self.__local_files_link:
             self.__local_files_link.destroy()
             self.__local_files_link = None
 
         try:
-            buddy = self.resource.localBuddy
+            buddy = person.local_buddy
         except AttributeError:
             return
 
-        self.__local_files_link = LocalFilesLink(buddy)
-        self.__link_box.append(self.__local_files_link)
+        if buddy != None:
+            self.__local_files_link = LocalFilesLink(buddy)
+            self.__link_box.append(self.__local_files_link)
 
-    def __update(self, user):
-        self.__name.set_property('text', self.resource.name)
-        self.__photo.set_url(self.resource.photoUrl)
+    def __update(self, person):
+        self.__name.set_property('text', self.person.display_name)
+        self.__photo.set_url(self.person.icon_url)
 
-#         if profile.get_online():
-#             self.__online.set_property('text', 'Online')
-#         else:
-#             self.__online.set_property('text', 'Offline')
-
         self.__address_box.remove_all()
 
-        try:
-            email = self.resource.email
-        except AttributeError:
-            email = None
+        email = None
+        if person.is_user:
+            try:
+                email = self.person.resource.email
+            except AttributeError:
+                pass
          
-        try:
-            aim = self.resource.aim
-        except AttributeError:
-            aim = None
-         
         if email != None:
             email = hippo.CanvasLink(text=email, xalign=hippo.ALIGNMENT_START)
             email.connect('activated', self.__on_activate_email)
             self.__address_box.append(email)
 
-        if aim != None:
-            aim = hippo.CanvasLink(text=aim, xalign=hippo.ALIGNMENT_START)
+        if person.aim != None:
+            aim = hippo.CanvasLink(text=person.aim, xalign=hippo.ALIGNMENT_START)
             aim.connect('activated', self.__on_activate_aim)
             self.__address_box.append(aim)
 
+        if person.xmpp != None:
+            aim = hippo.CanvasLink(text=person.aim, xalign=hippo.ALIGNMENT_START)
+            aim.connect('activated', self.__on_activate_xmpp)
+            self.__address_box.append(xmpp)
+
     def __on_activate_web(self, canvas_item):
         self.emit("close")
-        libbig.show_url(self.resource.homeUrl)
+        libbig.show_url(self.person.resource.homeUrl)
 
     def __on_activate_email(self, canvas_item):
         self.emit("close")
         # email should probably cgi.escape except it breaks if you escape the @
-        os.spawnlp(os.P_NOWAIT, 'gnome-open', 'gnome-open', 'mailto:' + self.resource.email)
+        os.spawnlp(os.P_NOWAIT, 'gnome-open', 'gnome-open', 'mailto:' + self.person.resource.email)
 
     def __on_activate_aim(self, canvas_item):
         self.emit("close")
-        _open_aim(self.resource.aim)
+        _open_aim(self.person.aim)
+        
+    def __on_activate_xmpp(self, canvas_item):
+        self.emit("close")
+        _open_xmpp(self.person.xmpp)



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]