Merge branch 'master' of git+ssh://dev.laptop.org/git/sugar

This commit is contained in:
Marco Pesenti Gritti 2006-09-22 21:50:20 +02:00
commit fc000346e4
4 changed files with 92 additions and 23 deletions

View File

@ -10,6 +10,9 @@ PRESENCE_SERVICE_TYPE = "_presence_olpc._tcp"
BUDDY_DBUS_OBJECT_PATH = "/org/laptop/Presence/Buddies/" BUDDY_DBUS_OBJECT_PATH = "/org/laptop/Presence/Buddies/"
BUDDY_DBUS_INTERFACE = "org.laptop.Presence.Buddy" BUDDY_DBUS_INTERFACE = "org.laptop.Presence.Buddy"
_BUDDY_KEY_COLOR = 'color'
_BUDDY_KEY_CURACT = 'curact'
class NotFoundError(Exception): class NotFoundError(Exception):
pass pass
@ -85,7 +88,10 @@ class BuddyDBusHelper(dbus.service.Object):
props['owner'] = self._parent.is_owner() props['owner'] = self._parent.is_owner()
color = self._parent.get_color() color = self._parent.get_color()
if 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 return props
@ -113,6 +119,7 @@ class Buddy(object):
self._nick_name = service.get_name() self._nick_name = service.get_name()
self._address = service.get_source_address() self._address = service.get_source_address()
self._color = None self._color = None
self._current_activity = None
self._valid = False self._valid = False
self._icon = None self._icon = None
self._icon_tries = 0 self._icon_tries = 0
@ -121,6 +128,7 @@ class Buddy(object):
self._object_path = BUDDY_DBUS_OBJECT_PATH + str(self._object_id) self._object_path = BUDDY_DBUS_OBJECT_PATH + str(self._object_id)
self._dbus_helper = BuddyDBusHelper(self, bus_name, self._object_path) self._dbus_helper = BuddyDBusHelper(self, bus_name, self._object_path)
self._buddy_presence_service = None
if service is not None: if service is not None:
self.add_service(service) self.add_service(service)
@ -181,25 +189,48 @@ class Buddy(object):
service_key[1])) service_key[1]))
return False 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, logging.debug("Buddy %s added service type %s id %s" % (self._nick_name,
service.get_type(), service.get_activity_id())) service.get_type(), service.get_activity_id()))
self._services[service_key] = service self._services[service_key] = service
service.set_owner(self) service.set_owner(self)
if service.get_type() == PRESENCE_SERVICE_TYPE: if service.get_type() == PRESENCE_SERVICE_TYPE:
self._buddy_presence_service = service
# A buddy isn't valid until its official presence # A buddy isn't valid until its official presence
# service has been found and resolved # service has been found and resolved
self._valid = True 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._request_buddy_icon(service)
self._color = service.get_one_property('color') self._color = service.get_one_property(_BUDDY_KEY_COLOR)
if self._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: if self._valid:
self._dbus_helper.ServiceAppeared(service.object_path()) self._dbus_helper.ServiceAppeared(service.object_path())
return True 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): def add_activity(self, activity):
actid = activity.get_id() actid = activity.get_id()
if activity in self._activities.values(): if activity in self._activities.values():
@ -222,6 +253,13 @@ class Buddy(object):
return return
if service.get_name() != self._nick_name: if service.get_name() != self._nick_name:
return 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) service_key = self._get_service_key(service)
if self._services.has_key(service_key): if self._services.has_key(service_key):
if self._valid: if self._valid:
@ -282,6 +320,9 @@ class Buddy(object):
def get_color(self): def get_color(self):
return self._color return self._color
def get_current_activity(self):
return self._current_activity
def _set_icon(self, icon): def _set_icon(self, icon):
"""Can only set icon for other buddies. The Owner """Can only set icon for other buddies. The Owner
takes care of setting it's own icon.""" takes care of setting it's own icon."""

View File

@ -5,6 +5,7 @@ from sugar import util
import dbus, dbus.service import dbus, dbus.service
import random import random
import logging import logging
import gobject
def compose_service_name(name, activity_id): def compose_service_name(name, activity_id):
if type(name) == type(""): if type(name) == type(""):
@ -135,13 +136,19 @@ class ServiceDBusHelper(dbus.service.Object):
self._parent.set_properties(values, sender) self._parent.set_properties(values, sender)
class Service(object): class Service(gobject.GObject):
"""Encapsulates information about a specific ZeroConf/mDNS """Encapsulates information about a specific ZeroConf/mDNS
service as advertised on the network.""" 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", def __init__(self, bus_name, object_id, name, stype, domain=u"local",
address=None, port=-1, properties=None, source_address=None, address=None, port=-1, properties=None, source_address=None,
local_publisher=None): local_publisher=None):
gobject.GObject.__init__(self)
if not bus_name: if not bus_name:
raise ValueError("DBus bus name must be valid") raise ValueError("DBus bus name must be valid")
if not object_id or type(object_id) != type(1): if not object_id or type(object_id) != type(1):
@ -178,7 +185,7 @@ class Service(object):
self._domain = domain self._domain = domain
self._port = -1 self._port = -1
self.set_port(port) self.set_port(port)
self._properties = None self._properties = {}
self._dbus_helper = None self._dbus_helper = None
self._internal_set_properties(properties) self._internal_set_properties(properties)
@ -252,6 +259,11 @@ class Service(object):
properties.""" properties."""
return self._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): def set_property(self, key, value, sender=None):
"""Set one service property""" """Set one service property"""
if not self._local_publisher: if not self._local_publisher:
@ -290,8 +302,7 @@ class Service(object):
if self._local_publisher and self._avahi_entry_group: if self._local_publisher and self._avahi_entry_group:
self.__internal_update_avahi_properties() self.__internal_update_avahi_properties()
if self._dbus_helper: self.__emit_properties_changed_signal([key])
self._dbus_helper.PublishedValueChanged([key])
def set_properties(self, properties, sender=None, from_network=False): def set_properties(self, properties, sender=None, from_network=False):
"""Set all service properties in one call""" """Set all service properties in one call"""
@ -306,13 +317,13 @@ class Service(object):
python dictionary.""" python dictionary."""
if type(properties) != type({}): if type(properties) != type({}):
raise ValueError("Properties must be a dictionary.") raise ValueError("Properties must be a dictionary.")
self._properties = {}
# Make sure the properties are actually different # Make sure the properties are actually different
diff_keys = _dicts_differ(self._properties, properties) diff_keys = _dicts_differ(self._properties, properties)
if len(diff_keys) == 0: if len(diff_keys) == 0:
return return
self._properties = {}
# Set key/value pairs on internal property list # Set key/value pairs on internal property list
for key, value in properties.items(): for key, value in properties.items():
if len(key) == 0: if len(key) == 0:
@ -329,8 +340,7 @@ class Service(object):
if self._local_publisher and self._avahi_entry_group and not from_network: if self._local_publisher and self._avahi_entry_group and not from_network:
self.__internal_update_avahi_properties() self.__internal_update_avahi_properties()
if self._dbus_helper: self.__emit_properties_changed_signal(diff_keys)
self._dbus_helper.PublishedValueChanged(diff_keys)
def __internal_update_avahi_properties(self): def __internal_update_avahi_properties(self):
info = _convert_properties_to_dbus_byte_array(self._properties) info = _convert_properties_to_dbus_byte_array(self._properties)

View File

@ -3,12 +3,18 @@ from sugar.canvas.IconColor import IconColor
class BuddyModel: class BuddyModel:
def __init__(self, buddy=None): 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._cur_activity = None
self._pservice = PresenceService.get_instance() 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) self._pservice.connect('buddy-appeared', self.__buddy_appeared_cb)
def set_name(self, name): def set_name(self, name):
@ -24,7 +30,11 @@ class BuddyModel:
return self._color return self._color
def get_buddy(self): 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) self._buddy = self._pservice.get_buddy_by_name(self._name)
if self._buddy: if self._buddy:
self._buddy.connect('property-changed', self._buddy.connect('property-changed',
@ -32,10 +42,12 @@ class BuddyModel:
return self._buddy return self._buddy
def __buddy_appeared_cb(self, pservice, 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: if not self._buddy and buddy.get_name() == self._name:
self.get_buddy() self.get_buddy()
def __buddy_property_changed_cb(self, buddy, keys): def __buddy_property_changed_cb(self, buddy, keys):
# all we care about right now is current activity
curact = self._buddy.get_current_activity() curact = self._buddy.get_current_activity()
self._cur_activity = self._pservice.get_activity(curact) self._cur_activity = self._pservice.get_activity(curact)

View File

@ -36,7 +36,13 @@ class Buddy(gobject.GObject):
self._buddy.connect_to_signal('JoinedActivity', self._joined_activity_cb) 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('LeftActivity', self._left_activity_cb)
self._buddy.connect_to_signal('PropertyChanged', self._property_changed_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): def object_path(self):
return self._object_path return self._object_path
@ -77,7 +83,7 @@ class Buddy(gobject.GObject):
gobject.idle_add(self._emit_left_activity_signal, object_path) gobject.idle_add(self._emit_left_activity_signal, object_path)
def _handle_property_changed_signal(self, prop_list): 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) self.emit('property-changed', prop_list)
return False return False