Update Owner properties on signals from the Shell

Listen to the shell's D-Bus service for property updates
of the Owner, and push those into the presence service.

Add test code to randomly change the properties, useful
when running the PS standalone without a shell.
This commit is contained in:
Dan Williams 2007-03-09 16:28:35 -05:00
parent f5c60b44c1
commit d299cd4032

View File

@ -15,9 +15,12 @@
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
import os
import gobject import gobject
import dbus, dbus.service import dbus, dbus.service
from sugar import profile from sugar import profile
from sugar import env
_BUDDY_PATH = "/org/laptop/Sugar/Presence/Buddies/" _BUDDY_PATH = "/org/laptop/Sugar/Presence/Buddies/"
_BUDDY_INTERFACE = "org.laptop.Sugar.Presence.Buddy" _BUDDY_INTERFACE = "org.laptop.Sugar.Presence.Buddy"
@ -40,13 +43,17 @@ class Buddy(DBusGObject):
__gsignals__ = { __gsignals__ = {
'validity-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, 'validity-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_BOOLEAN])) ([gobject.TYPE_BOOLEAN])),
'property-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT])),
'icon-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT]))
} }
__gproperties__ = { __gproperties__ = {
'key' : (str, None, None, None, 'key' : (str, None, None, None,
gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT_ONLY), gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT_ONLY),
'icon' : (str, None, None, None, gobject.PARAM_READWRITE), 'icon' : (object, None, None, gobject.PARAM_READWRITE),
'nick' : (str, None, None, None, gobject.PARAM_READWRITE), 'nick' : (str, None, None, None, gobject.PARAM_READWRITE),
'color' : (str, None, None, None, gobject.PARAM_READWRITE), 'color' : (str, None, None, None, gobject.PARAM_READWRITE),
'current-activity' : (str, None, None, None, gobject.PARAM_READWRITE), 'current-activity' : (str, None, None, None, gobject.PARAM_READWRITE),
@ -100,9 +107,10 @@ class Buddy(DBusGObject):
def do_set_property(self, pspec, value): def do_set_property(self, pspec, value):
if pspec.name == "icon": if pspec.name == "icon":
if value != self._icon: if str(value) != self._icon:
self._icon = value self._icon = str(value)
self.IconChanged(value) self.IconChanged(self._icon)
self.emit('icon-changed', self._icon)
elif pspec.name == "nick": elif pspec.name == "nick":
self._nick = value self._nick = value
elif pspec.name == "color": elif pspec.name == "color":
@ -189,16 +197,32 @@ class Buddy(DBusGObject):
return acts return acts
def set_properties(self, properties): def set_properties(self, properties):
changed = False
if "nick" in properties.keys(): if "nick" in properties.keys():
self._nick = properties["nick"] nick = properties["nick"]
if nick != self._nick:
self._nick = nick
changed = True
if "color" in properties.keys(): if "color" in properties.keys():
self._color = properties["color"] color = properties["color"]
if color != self._color:
self._color = color
changed = True
if "current-activity" in properties.keys():
curact = properties["current-activity"]
if curact != self._current_activity:
self._current_activity = curact
changed = True
if not changed:
return
# Try emitting PropertyChanged before updating validity # Try emitting PropertyChanged before updating validity
# to avoid leaking a PropertyChanged signal before the buddy is # to avoid leaking a PropertyChanged signal before the buddy is
# actually valid the first time after creation # actually valid the first time after creation
if self._valid: if self._valid:
self.PropertyChanged(properties) self.PropertyChanged(properties)
self.emit('property-changed', properties)
self._update_validity() self._update_validity()
@ -219,22 +243,150 @@ class Buddy(DBusGObject):
class Owner(Buddy): class Owner(Buddy):
"""Class representing the owner of the machine. This is the client """Class representing the owner of the machine. This is the client
portion of the Owner, paired with the server portion in Owner.py.""" portion of the Owner, paired with the server portion in Owner.py."""
_SHELL_SERVICE = "org.laptop.Shell"
_SHELL_OWNER_INTERFACE = "org.laptop.Shell.Owner"
_SHELL_PATH = "/org/laptop/Shell"
def __init__(self, bus_name, object_id): def __init__(self, bus_name, object_id):
key = profile.get_pubkey() key = profile.get_pubkey()
nick = profile.get_nick_name() nick = profile.get_nick_name()
color = profile.get_color().to_string() color = profile.get_color().to_string()
Buddy.__init__(self, bus_name, object_id, key=key, nick=nick, color=color) icon_file = os.path.join(env.get_profile_path(), "buddy-icon.jpg")
f = open(icon_file, "r")
icon = f.read()
f.close()
self._bus = dbus.SessionBus()
self._bus.add_signal_receiver(self._name_owner_changed_handler,
signal_name="NameOwnerChanged",
dbus_interface="org.freedesktop.DBus")
# Connect to the shell to get notifications on Owner object
# property changes
try:
self._connect_to_shell()
except dbus.DBusException:
pass
Buddy.__init__(self, bus_name, object_id, key=key, nick=nick, color=color,
icon=icon)
self._owner = True self._owner = True
# dbus methods # enable this to change random buddy properties
@dbus.service.method(_OWNER_INTERFACE, if False:
in_signature="ay", out_signature="") gobject.timeout_add(5000, self._update_something)
def SetIcon(self, icon_data):
self.props.icon = icon_data
@dbus.service.method(_OWNER_INTERFACE, def _update_something(self):
in_signature="a{sv}", out_signature="") import random
def SetProperties(self, prop): it = random.randint(0, 3)
self.set_properties(self, prop) if it == 0:
data = get_random_image()
self._icon_changed_cb(data)
elif it == 1:
from sugar.graphics import xocolor
xo = xocolor.XoColor()
self._color_changed_cb(xo.to_string())
elif it == 2:
names = ["Liam", "Noel", "Guigsy", "Whitey", "Bonehead"]
foo = random.randint(0, len(names) - 1)
self._nick_changed_cb(names[foo])
elif it == 3:
bork = random.randint(25, 65)
it = ""
for i in range(0, bork):
it += chr(random.randint(40, 127))
from sugar import util
self._cur_activity_changed_cb(util.unique_id(it))
return True
def _name_owner_changed_handler(self, name, old, new):
if name != self._SHELL_SERVICE:
return
if (old and len(old)) and (not new and not len(new)):
# shell went away
self._shell_owner = None
elif (not old and not len(old)) and (new and len(new)):
# shell started
self._connect_to_shell()
def _connect_to_shell(self):
obj = self._bus.get_object(self._SHELL_SERVICE, self._SHELL_PATH)
self._shell_owner = dbus.Interface(obj, self._SHELL_OWNER_INTERFACE)
self._shell_owner.connect_to_signal('IconChanged', self._icon_changed_cb)
self._shell_owner.connect_to_signal('ColorChanged', self._color_changed_cb)
self._shell_owner.connect_to_signal('NickChanged', self._nick_changed_cb)
self._shell_owner.connect_to_signal('CurrentActivityChanged',
self._cur_activity_changed_cb)
def _icon_changed_cb(self, icon):
self.props.icon = icon
def _color_changed_cb(self, color):
props = {'color': color}
self.set_properties(props)
def _nick_changed_cb(self, nick):
props = {'nick': nick}
self.set_properties(props)
def _cur_activity_changed_cb(self, activity_id):
if not self._activities.has_key(activity_id):
return
props = {'current-activity': activity_id}
self.set_properties(props)
def get_random_image():
import cairo, math, random, gtk
def rand():
return random.random()
SIZE = 200
s = cairo.ImageSurface(cairo.FORMAT_ARGB32, SIZE, SIZE)
cr = cairo.Context(s)
# background gradient
cr.save()
g = cairo.LinearGradient(0, 0, 1, 1)
g.add_color_stop_rgba(1, rand(), rand(), rand(), rand())
g.add_color_stop_rgba(0, rand(), rand(), rand(), rand())
cr.set_source(g)
cr.rectangle(0, 0, SIZE, SIZE);
cr.fill()
cr.restore()
# random path
cr.set_line_width(10 * rand() + 5)
cr.move_to(SIZE * rand(), SIZE * rand())
cr.line_to(SIZE * rand(), SIZE * rand())
cr.rel_line_to(SIZE * rand() * -1, 0)
cr.close_path()
cr.stroke()
# a circle
cr.set_source_rgba(rand(), rand(), rand(), rand())
cr.arc(SIZE * rand(), SIZE * rand(), 100 * rand() + 30, 0, 2 * math.pi)
cr.fill()
# another circle
cr.set_source_rgba(rand(), rand(), rand(), rand())
cr.arc(SIZE * rand(), SIZE * rand(), 100 * rand() + 30, 0, 2 * math.pi)
cr.fill()
def img_convert_func(buf, data):
data[0] += buf
return True
data = [""]
pixbuf = gtk.gdk.pixbuf_new_from_data(s.get_data(), gtk.gdk.COLORSPACE_RGB,
True, 8, s.get_width(), s.get_height(), s.get_stride())
pixbuf.save_to_callback(img_convert_func, "jpeg", {"quality": "90"}, data)
del pixbuf
return str(data[0])