Merge branch 'master' of git+ssh://dev.laptop.org/git/sugar
This commit is contained in:
commit
fc000346e4
@ -10,6 +10,9 @@ PRESENCE_SERVICE_TYPE = "_presence_olpc._tcp"
|
||||
BUDDY_DBUS_OBJECT_PATH = "/org/laptop/Presence/Buddies/"
|
||||
BUDDY_DBUS_INTERFACE = "org.laptop.Presence.Buddy"
|
||||
|
||||
_BUDDY_KEY_COLOR = 'color'
|
||||
_BUDDY_KEY_CURACT = 'curact'
|
||||
|
||||
class NotFoundError(Exception):
|
||||
pass
|
||||
|
||||
@ -85,7 +88,10 @@ class BuddyDBusHelper(dbus.service.Object):
|
||||
props['owner'] = self._parent.is_owner()
|
||||
color = self._parent.get_color()
|
||||
if color:
|
||||
props['color'] = self._parent.get_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
|
||||
|
||||
|
||||
@ -113,6 +119,7 @@ class Buddy(object):
|
||||
self._nick_name = service.get_name()
|
||||
self._address = service.get_source_address()
|
||||
self._color = None
|
||||
self._current_activity = None
|
||||
self._valid = False
|
||||
self._icon = None
|
||||
self._icon_tries = 0
|
||||
@ -121,6 +128,7 @@ class Buddy(object):
|
||||
self._object_path = BUDDY_DBUS_OBJECT_PATH + str(self._object_id)
|
||||
self._dbus_helper = BuddyDBusHelper(self, bus_name, self._object_path)
|
||||
|
||||
self._buddy_presence_service = None
|
||||
if service is not None:
|
||||
self.add_service(service)
|
||||
|
||||
@ -181,25 +189,48 @@ class Buddy(object):
|
||||
service_key[1]))
|
||||
return False
|
||||
|
||||
if service.get_type() == PRESENCE_SERVICE_TYPE and self._buddy_presence_service:
|
||||
# already have a presence service for this buddy
|
||||
logging.debug("!!! Tried to add a buddy presence service when " \
|
||||
"one already existed.")
|
||||
return False
|
||||
|
||||
logging.debug("Buddy %s added service type %s id %s" % (self._nick_name,
|
||||
service.get_type(), service.get_activity_id()))
|
||||
self._services[service_key] = service
|
||||
service.set_owner(self)
|
||||
|
||||
if service.get_type() == PRESENCE_SERVICE_TYPE:
|
||||
self._buddy_presence_service = service
|
||||
# A buddy isn't valid until its official presence
|
||||
# service has been found and resolved
|
||||
self._valid = True
|
||||
print 'Requesting buddy icon %s' % self._nick_name
|
||||
logging.debug('Requesting buddy icon %s' % self._nick_name)
|
||||
self._request_buddy_icon(service)
|
||||
self._color = service.get_one_property('color')
|
||||
self._color = service.get_one_property(_BUDDY_KEY_COLOR)
|
||||
if self._color:
|
||||
self._dbus_helper.PropertyChanged(['color'])
|
||||
self._dbus_helper.PropertyChanged([_BUDDY_KEY_COLOR])
|
||||
# Monitor further buddy property changes, like current activity
|
||||
# and color
|
||||
service.connect('property-changed',
|
||||
self.__buddy_presence_service_property_changed_cb)
|
||||
|
||||
if self._valid:
|
||||
self._dbus_helper.ServiceAppeared(service.object_path())
|
||||
return True
|
||||
|
||||
def __buddy_presence_service_property_changed_cb(self, service, keys):
|
||||
if _BUDDY_KEY_COLOR in keys:
|
||||
new_color = service.get_one_property(_BUDDY_KEY_COLOR)
|
||||
if new_color and self._color != new_color:
|
||||
self._color = new_color
|
||||
self._dbus_helper.PropertyChanged([_BUDDY_KEY_COLOR])
|
||||
if _BUDDY_KEY_CURACT in keys:
|
||||
new_curact = service.get_one_property(_BUDDY_KEY_CURACT)
|
||||
if new_curact and self._current_activity != new_curact:
|
||||
self._current_activity = new_curact
|
||||
self._dbus_helper.PropertyChanged([_BUDDY_KEY_CURACT])
|
||||
|
||||
def add_activity(self, activity):
|
||||
actid = activity.get_id()
|
||||
if activity in self._activities.values():
|
||||
@ -222,6 +253,13 @@ class Buddy(object):
|
||||
return
|
||||
if service.get_name() != self._nick_name:
|
||||
return
|
||||
|
||||
if service.get_type() == PRESENCE_SERVICE_TYPE \
|
||||
and self._buddy_presence_service \
|
||||
and service != self._buddy_presence_service:
|
||||
logging.debug("!!! Tried to remove a spurious buddy presence service.")
|
||||
return
|
||||
|
||||
service_key = self._get_service_key(service)
|
||||
if self._services.has_key(service_key):
|
||||
if self._valid:
|
||||
@ -282,6 +320,9 @@ class Buddy(object):
|
||||
def get_color(self):
|
||||
return self._color
|
||||
|
||||
def get_current_activity(self):
|
||||
return self._current_activity
|
||||
|
||||
def _set_icon(self, icon):
|
||||
"""Can only set icon for other buddies. The Owner
|
||||
takes care of setting it's own icon."""
|
||||
|
@ -5,6 +5,7 @@ from sugar import util
|
||||
import dbus, dbus.service
|
||||
import random
|
||||
import logging
|
||||
import gobject
|
||||
|
||||
def compose_service_name(name, activity_id):
|
||||
if type(name) == type(""):
|
||||
@ -135,13 +136,19 @@ class ServiceDBusHelper(dbus.service.Object):
|
||||
self._parent.set_properties(values, sender)
|
||||
|
||||
|
||||
class Service(object):
|
||||
class Service(gobject.GObject):
|
||||
"""Encapsulates information about a specific ZeroConf/mDNS
|
||||
service as advertised on the network."""
|
||||
|
||||
__gsignals__ = {
|
||||
'property-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
([gobject.TYPE_PYOBJECT]))
|
||||
}
|
||||
|
||||
def __init__(self, bus_name, object_id, name, stype, domain=u"local",
|
||||
address=None, port=-1, properties=None, source_address=None,
|
||||
local_publisher=None):
|
||||
gobject.GObject.__init__(self)
|
||||
if not bus_name:
|
||||
raise ValueError("DBus bus name must be valid")
|
||||
if not object_id or type(object_id) != type(1):
|
||||
@ -178,7 +185,7 @@ class Service(object):
|
||||
self._domain = domain
|
||||
self._port = -1
|
||||
self.set_port(port)
|
||||
self._properties = None
|
||||
self._properties = {}
|
||||
self._dbus_helper = None
|
||||
self._internal_set_properties(properties)
|
||||
|
||||
@ -252,6 +259,11 @@ class Service(object):
|
||||
properties."""
|
||||
return self._properties
|
||||
|
||||
def __emit_properties_changed_signal(self, keys):
|
||||
if self._dbus_helper:
|
||||
self._dbus_helper.PublishedValueChanged(keys)
|
||||
self.emit('property-changed', keys)
|
||||
|
||||
def set_property(self, key, value, sender=None):
|
||||
"""Set one service property"""
|
||||
if not self._local_publisher:
|
||||
@ -290,8 +302,7 @@ class Service(object):
|
||||
if self._local_publisher and self._avahi_entry_group:
|
||||
self.__internal_update_avahi_properties()
|
||||
|
||||
if self._dbus_helper:
|
||||
self._dbus_helper.PublishedValueChanged([key])
|
||||
self.__emit_properties_changed_signal([key])
|
||||
|
||||
def set_properties(self, properties, sender=None, from_network=False):
|
||||
"""Set all service properties in one call"""
|
||||
@ -306,13 +317,13 @@ class Service(object):
|
||||
python dictionary."""
|
||||
if type(properties) != type({}):
|
||||
raise ValueError("Properties must be a dictionary.")
|
||||
self._properties = {}
|
||||
|
||||
# Make sure the properties are actually different
|
||||
diff_keys = _dicts_differ(self._properties, properties)
|
||||
if len(diff_keys) == 0:
|
||||
return
|
||||
|
||||
self._properties = {}
|
||||
# Set key/value pairs on internal property list
|
||||
for key, value in properties.items():
|
||||
if len(key) == 0:
|
||||
@ -329,8 +340,7 @@ class Service(object):
|
||||
if self._local_publisher and self._avahi_entry_group and not from_network:
|
||||
self.__internal_update_avahi_properties()
|
||||
|
||||
if self._dbus_helper:
|
||||
self._dbus_helper.PublishedValueChanged(diff_keys)
|
||||
self.__emit_properties_changed_signal(diff_keys)
|
||||
|
||||
def __internal_update_avahi_properties(self):
|
||||
info = _convert_properties_to_dbus_byte_array(self._properties)
|
||||
|
@ -3,12 +3,18 @@ from sugar.canvas.IconColor import IconColor
|
||||
|
||||
class BuddyModel:
|
||||
def __init__(self, buddy=None):
|
||||
if buddy:
|
||||
self.set_name(buddy.get_name())
|
||||
self.set_color(buddy.get_color())
|
||||
self._buddy = buddy
|
||||
self._cur_activity = None
|
||||
self._pservice = PresenceService.get_instance()
|
||||
|
||||
self._buddy = buddy
|
||||
if self._buddy:
|
||||
self.set_name(self._buddy.get_name())
|
||||
self.set_color(self._buddy.get_color())
|
||||
self._buddy.connect('property-changed',
|
||||
self.__buddy_property_changed_cb)
|
||||
else:
|
||||
# if we don't have a buddy yet, connect to the PS
|
||||
# and wait until the buddy pops up on the network
|
||||
self._pservice.connect('buddy-appeared', self.__buddy_appeared_cb)
|
||||
|
||||
def set_name(self, name):
|
||||
@ -24,7 +30,11 @@ class BuddyModel:
|
||||
return self._color
|
||||
|
||||
def get_buddy(self):
|
||||
if not self._buddy:
|
||||
# If we have a buddy already, just return
|
||||
if self._buddy:
|
||||
return self._buddy
|
||||
|
||||
# Otherwise try to get the buddy from the PS
|
||||
self._buddy = self._pservice.get_buddy_by_name(self._name)
|
||||
if self._buddy:
|
||||
self._buddy.connect('property-changed',
|
||||
@ -32,10 +42,12 @@ class BuddyModel:
|
||||
return self._buddy
|
||||
|
||||
def __buddy_appeared_cb(self, pservice, buddy):
|
||||
# FIXME: use public key rather than buddy name
|
||||
if not self._buddy and buddy.get_name() == self._name:
|
||||
self.get_buddy()
|
||||
|
||||
def __buddy_property_changed_cb(self, buddy, keys):
|
||||
# all we care about right now is current activity
|
||||
curact = self._buddy.get_current_activity()
|
||||
self._cur_activity = self._pservice.get_activity(curact)
|
||||
|
||||
|
@ -36,7 +36,13 @@ 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._properties = self._buddy.getProperties()
|
||||
self._properties = self._get_properties_helper()
|
||||
|
||||
def _get_properties_helper(self):
|
||||
props = self._buddy.getProperties()
|
||||
if not props:
|
||||
return {}
|
||||
return props
|
||||
|
||||
def object_path(self):
|
||||
return self._object_path
|
||||
@ -77,7 +83,7 @@ class Buddy(gobject.GObject):
|
||||
gobject.idle_add(self._emit_left_activity_signal, object_path)
|
||||
|
||||
def _handle_property_changed_signal(self, prop_list):
|
||||
self._properties = self._buddy.getProperties()
|
||||
self._properties = self._get_properties_helper()
|
||||
self.emit('property-changed', prop_list)
|
||||
return False
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user