Package sugar :: Package presence :: Module buddy
[hide private]
[frames] | no frames]

Source Code for Module sugar.presence.buddy

  1  # Copyright (C) 2007, Red Hat, Inc. 
  2  # 
  3  # This library is free software; you can redistribute it and/or 
  4  # modify it under the terms of the GNU Lesser General Public 
  5  # License as published by the Free Software Foundation; either 
  6  # version 2 of the License, or (at your option) any later version. 
  7  # 
  8  # This library is distributed in the hope that it will be useful, 
  9  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 10  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
 11  # Lesser General Public License for more details. 
 12  # 
 13  # You should have received a copy of the GNU Lesser General Public 
 14  # License along with this library; if not, write to the 
 15  # Free Software Foundation, Inc., 59 Temple Place - Suite 330, 
 16  # Boston, MA 02111-1307, USA. 
 17   
 18  """UI interface to a buddy in the presence service 
 19   
 20  STABLE. 
 21  """ 
 22   
 23  import gobject 
 24  import gtk 
 25  import dbus 
 26   
 27   
28 -class Buddy(gobject.GObject):
29 """UI interface for a Buddy in the presence service 30 31 Each buddy interface tracks a set of activities and properties 32 that can be queried to provide UI controls for manipulating 33 the presence interface. 34 35 Properties Dictionary: 36 'key': public key, 37 'nick': nickname , 38 'color': color (XXX what format), 39 'current-activity': (XXX dbus path?), 40 'owner': (XXX dbus path?), 41 'icon': (XXX pixel data for an icon?) 42 See __gproperties__ 43 """ 44 45 __gsignals__ = { 46 'icon-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])), 47 'joined-activity': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, 48 ([gobject.TYPE_PYOBJECT])), 49 'left-activity': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, 50 ([gobject.TYPE_PYOBJECT])), 51 'property-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, 52 ([gobject.TYPE_PYOBJECT])), 53 } 54 55 __gproperties__ = { 56 'key': (str, None, None, None, gobject.PARAM_READABLE), 57 'icon': (str, None, None, None, gobject.PARAM_READABLE), 58 'nick': (str, None, None, None, gobject.PARAM_READABLE), 59 'color': (str, None, None, None, gobject.PARAM_READABLE), 60 'current-activity': (object, None, None, gobject.PARAM_READABLE), 61 'owner': (bool, None, None, False, gobject.PARAM_READABLE), 62 'ip4-address': (str, None, None, None, gobject.PARAM_READABLE), 63 'tags': (str, None, None, None, gobject.PARAM_READABLE), 64 } 65 66 _PRESENCE_SERVICE = "org.laptop.Sugar.Presence" 67 _BUDDY_DBUS_INTERFACE = "org.laptop.Sugar.Presence.Buddy" 68
69 - def __init__(self, bus, new_obj_cb, del_obj_cb, object_path):
70 """Initialise the reference to the buddy 71 72 bus -- dbus bus object 73 new_obj_cb -- callback to call when this buddy joins an activity 74 del_obj_cb -- callback to call when this buddy leaves an activity 75 object_path -- path to the buddy object 76 """ 77 gobject.GObject.__init__(self) 78 self._object_path = object_path 79 self._ps_new_object = new_obj_cb 80 self._ps_del_object = del_obj_cb 81 self._properties = {} 82 self._activities = {} 83 84 bobj = bus.get_object(self._PRESENCE_SERVICE, object_path) 85 self._buddy = dbus.Interface(bobj, self._BUDDY_DBUS_INTERFACE) 86 87 self._icon_changed_signal = self._buddy.connect_to_signal( 88 'IconChanged', self._icon_changed_cb, byte_arrays=True) 89 self._joined_activity_signal = self._buddy.connect_to_signal( 90 'JoinedActivity', self._joined_activity_cb) 91 self._left_activity_signal = self._buddy.connect_to_signal( 92 'LeftActivity', self._left_activity_cb) 93 self._property_changed_signal = self._buddy.connect_to_signal( 94 'PropertyChanged', self._property_changed_cb) 95 96 self._properties = self._get_properties_helper() 97 98 activities = self._buddy.GetJoinedActivities() 99 for op in activities: 100 self._activities[op] = self._ps_new_object(op) 101 self._icon = None
102
103 - def destroy(self):
104 self._icon_changed_signal.remove() 105 self._joined_activity_signal.remove() 106 self._left_activity_signal.remove() 107 self._property_changed_signal.remove()
108
109 - def _get_properties_helper(self):
110 """Retrieve the Buddy's property dictionary from the service object 111 """ 112 props = self._buddy.GetProperties(byte_arrays=True) 113 if not props: 114 return {} 115 return props
116
117 - def do_get_property(self, pspec):
118 """Retrieve a particular property from our property dictionary 119 120 pspec -- XXX some sort of GTK specifier object with attributes 121 including 'name', 'active' and 'icon-name' 122 """ 123 if pspec.name == "key": 124 return self._properties["key"] 125 elif pspec.name == "nick": 126 return self._properties["nick"] 127 elif pspec.name == "color": 128 return self._properties["color"] 129 elif pspec.name == "tags": 130 return self._properties["tags"] 131 elif pspec.name == "current-activity": 132 if not self._properties.has_key("current-activity"): 133 return None 134 curact = self._properties["current-activity"] 135 if not len(curact): 136 return None 137 for activity in self._activities.values(): 138 if activity.props.id == curact: 139 return activity 140 return None 141 elif pspec.name == "owner": 142 return self._properties["owner"] 143 elif pspec.name == "icon": 144 if not self._icon: 145 self._icon = str(self._buddy.GetIcon(byte_arrays=True)) 146 return self._icon 147 elif pspec.name == "ip4-address": 148 # IPv4 address will go away quite soon 149 if not self._properties.has_key("ip4-address"): 150 return None 151 return self._properties["ip4-address"]
152
153 - def object_path(self):
154 """Retrieve our dbus object path""" 155 return self._object_path
156
157 - def _emit_icon_changed_signal(self, icon_data):
158 """Emit GObject signal when icon has changed""" 159 self._icon = str(icon_data) 160 self.emit('icon-changed') 161 return False
162
163 - def _icon_changed_cb(self, icon_data):
164 """Handle dbus signal by emitting a GObject signal""" 165 gobject.idle_add(self._emit_icon_changed_signal, icon_data)
166
167 - def _emit_joined_activity_signal(self, object_path):
168 """Emit activity joined signal with Activity object""" 169 self.emit('joined-activity', self._ps_new_object(object_path)) 170 return False
171
172 - def _joined_activity_cb(self, object_path):
173 """Handle dbus signal by emitting a GObject signal 174 175 Stores the activity in activities dictionary as well 176 """ 177 if not self._activities.has_key(object_path): 178 self._activities[object_path] = self._ps_new_object(object_path) 179 gobject.idle_add(self._emit_joined_activity_signal, object_path)
180
181 - def _emit_left_activity_signal(self, object_path):
182 """Emit activity left signal with Activity object 183 184 XXX this calls self._ps_new_object instead of self._ps_del_object, 185 which would seem to be the incorrect callback? 186 """ 187 self.emit('left-activity', self._ps_new_object(object_path)) 188 return False
189
190 - def _left_activity_cb(self, object_path):
191 """Handle dbus signal by emitting a GObject signal 192 193 Also removes from the activities dictionary 194 """ 195 if self._activities.has_key(object_path): 196 del self._activities[object_path] 197 gobject.idle_add(self._emit_left_activity_signal, object_path)
198
199 - def _handle_property_changed_signal(self, prop_list):
200 """Emit property-changed signal with property dictionary 201 202 Generates a property-changed signal with the results of 203 _get_properties_helper() 204 """ 205 self._properties = self._get_properties_helper() 206 # FIXME: don't leak unexposed property names 207 self.emit('property-changed', prop_list) 208 return False
209
210 - def _property_changed_cb(self, prop_list):
211 """Handle dbus signal by emitting a GObject signal""" 212 gobject.idle_add(self._handle_property_changed_signal, prop_list)
213
214 - def get_icon_pixbuf(self):
215 """Retrieve Buddy's icon as a GTK pixel buffer 216 217 XXX Why aren't the icons coming in as SVG? 218 """ 219 if self.props.icon and len(self.props.icon): 220 pbl = gtk.gdk.PixbufLoader() 221 pbl.write(self.props.icon) 222 pbl.close() 223 return pbl.get_pixbuf() 224 else: 225 return None
226
227 - def get_joined_activities(self):
228 """Retrieve the set of all activities which this buddy has joined 229 230 Uses the GetJoinedActivities method on the service 231 object to produce object paths, wraps each in an 232 Activity object. 233 234 returns list of presence Activity objects 235 """ 236 try: 237 resp = self._buddy.GetJoinedActivities() 238 except dbus.exceptions.DBusException: 239 return [] 240 acts = [] 241 for item in resp: 242 acts.append(self._ps_new_object(item)) 243 return acts
244