Merge branch 'master' of git://dev.laptop.org/sugar
This commit is contained in:
commit
9a8d5ac32a
@ -29,6 +29,15 @@ class DBusGObjectMetaclass(dbus.service.InterfaceType, gobject.GObjectMeta): pas
|
|||||||
class DBusGObject(dbus.service.Object, gobject.GObject): __metaclass__ = DBusGObjectMetaclass
|
class DBusGObject(dbus.service.Object, gobject.GObject): __metaclass__ = DBusGObjectMetaclass
|
||||||
|
|
||||||
|
|
||||||
|
_PROP_ID = "id"
|
||||||
|
_PROP_NAME = "name"
|
||||||
|
_PROP_COLOR = "color"
|
||||||
|
_PROP_TYPE = "type"
|
||||||
|
_PROP_VALID = "valid"
|
||||||
|
_PROP_LOCAL = "local"
|
||||||
|
_PROP_JOINED = "joined"
|
||||||
|
_PROP_CUSTOM_PROPS = "custom-props"
|
||||||
|
|
||||||
class Activity(DBusGObject):
|
class Activity(DBusGObject):
|
||||||
"""Represents a potentially shareable activity on the network.
|
"""Represents a potentially shareable activity on the network.
|
||||||
"""
|
"""
|
||||||
@ -41,17 +50,21 @@ class Activity(DBusGObject):
|
|||||||
}
|
}
|
||||||
|
|
||||||
__gproperties__ = {
|
__gproperties__ = {
|
||||||
'id' : (str, None, None, None,
|
_PROP_ID : (str, None, None, None,
|
||||||
gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT_ONLY),
|
gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT_ONLY),
|
||||||
'name' : (str, None, None, None, gobject.PARAM_READWRITE),
|
_PROP_NAME : (str, None, None, None, gobject.PARAM_READWRITE),
|
||||||
'color' : (str, None, None, None, gobject.PARAM_READWRITE),
|
_PROP_COLOR : (str, None, None, None, gobject.PARAM_READWRITE),
|
||||||
'type' : (str, None, None, None, gobject.PARAM_READWRITE),
|
_PROP_TYPE : (str, None, None, None, gobject.PARAM_READWRITE),
|
||||||
'valid' : (bool, None, None, False, gobject.PARAM_READABLE),
|
_PROP_VALID : (bool, None, None, False, gobject.PARAM_READABLE),
|
||||||
'local' : (bool, None, None, False,
|
_PROP_LOCAL : (bool, None, None, False,
|
||||||
gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT_ONLY),
|
gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT_ONLY),
|
||||||
'joined' : (bool, None, None, False, gobject.PARAM_READABLE)
|
_PROP_JOINED : (bool, None, None, False, gobject.PARAM_READABLE),
|
||||||
|
_PROP_CUSTOM_PROPS : (object, None, None,
|
||||||
|
gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT_ONLY)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_RESERVED_PROPNAMES = __gproperties__.keys()
|
||||||
|
|
||||||
def __init__(self, bus_name, object_id, tp, **kwargs):
|
def __init__(self, bus_name, object_id, tp, **kwargs):
|
||||||
"""Initializes the activity and sets its properties to default values.
|
"""Initializes the activity and sets its properties to default values.
|
||||||
|
|
||||||
@ -85,11 +98,18 @@ class Activity(DBusGObject):
|
|||||||
self._color = None
|
self._color = None
|
||||||
self._local = False
|
self._local = False
|
||||||
self._type = None
|
self._type = None
|
||||||
|
self._custom_props = {}
|
||||||
|
|
||||||
if not kwargs.get("id"):
|
# ensure no reserved property names are in custom properties
|
||||||
|
if kwargs.get(_PROP_CUSTOM_PROPS):
|
||||||
|
(rprops, cprops) = self._split_properties(kwargs.get(_PROP_CUSTOM_PROPS))
|
||||||
|
if len(rprops.keys()) > 0:
|
||||||
|
raise ValueError("Cannot use reserved property names '%s'" % ", ".join(rprops.keys()))
|
||||||
|
|
||||||
|
if not kwargs.get(_PROP_ID):
|
||||||
raise ValueError("activity id is required")
|
raise ValueError("activity id is required")
|
||||||
if not util.validate_activity_id(kwargs['id']):
|
if not util.validate_activity_id(kwargs[_PROP_ID]):
|
||||||
raise ValueError("Invalid activity id '%s'" % kwargs['id'])
|
raise ValueError("Invalid activity id '%s'" % kwargs[_PROP_ID])
|
||||||
|
|
||||||
gobject.GObject.__init__(self, **kwargs)
|
gobject.GObject.__init__(self, **kwargs)
|
||||||
if self.props.local and not self.props.valid:
|
if self.props.local and not self.props.valid:
|
||||||
@ -107,19 +127,19 @@ class Activity(DBusGObject):
|
|||||||
returns The value of the given property.
|
returns The value of the given property.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if pspec.name == "id":
|
if pspec.name == _PROP_ID:
|
||||||
return self._id
|
return self._id
|
||||||
elif pspec.name == "name":
|
elif pspec.name == _PROP_NAME:
|
||||||
return self._name
|
return self._name
|
||||||
elif pspec.name == "color":
|
elif pspec.name == _PROP_COLOR:
|
||||||
return self._color
|
return self._color
|
||||||
elif pspec.name == "type":
|
elif pspec.name == _PROP_TYPE:
|
||||||
return self._type
|
return self._type
|
||||||
elif pspec.name == "valid":
|
elif pspec.name == _PROP_VALID:
|
||||||
return self._valid
|
return self._valid
|
||||||
elif pspec.name == "joined":
|
elif pspec.name == _PROP_JOINED:
|
||||||
return self._joined
|
return self._joined
|
||||||
elif pspec.name == "local":
|
elif pspec.name == _PROP_LOCAL:
|
||||||
return self._local
|
return self._local
|
||||||
|
|
||||||
def do_set_property(self, pspec, value):
|
def do_set_property(self, pspec, value):
|
||||||
@ -132,20 +152,29 @@ class Activity(DBusGObject):
|
|||||||
to something different later will raise a RuntimeError.
|
to something different later will raise a RuntimeError.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if pspec.name == "id":
|
if pspec.name == _PROP_ID:
|
||||||
|
if self._id:
|
||||||
|
raise RuntimeError("activity ID is already set")
|
||||||
self._id = value
|
self._id = value
|
||||||
elif pspec.name == "name":
|
elif pspec.name == _PROP_NAME:
|
||||||
self._name = value
|
self._name = value
|
||||||
elif pspec.name == "color":
|
elif pspec.name == _PROP_COLOR:
|
||||||
self._color = value
|
self._color = value
|
||||||
elif pspec.name == "type":
|
elif pspec.name == _PROP_TYPE:
|
||||||
if self._type:
|
if self._type:
|
||||||
raise RuntimeError("activity type is already set")
|
raise RuntimeError("activity type is already set")
|
||||||
self._type = value
|
self._type = value
|
||||||
elif pspec.name == "joined":
|
elif pspec.name == _PROP_JOINED:
|
||||||
self._joined = value
|
self._joined = value
|
||||||
elif pspec.name == "local":
|
elif pspec.name == _PROP_LOCAL:
|
||||||
self._local = value
|
self._local = value
|
||||||
|
elif pspec.name == _PROP_CUSTOM_PROPS:
|
||||||
|
if not value:
|
||||||
|
value = {}
|
||||||
|
(rprops, cprops) = self._split_properties(value)
|
||||||
|
self._custom_props = {}
|
||||||
|
for (key, dvalue) in cprops.items():
|
||||||
|
self._custom_props[str(key)] = str(dvalue)
|
||||||
|
|
||||||
self._update_validity()
|
self._update_validity()
|
||||||
|
|
||||||
@ -441,6 +470,11 @@ class Activity(DBusGObject):
|
|||||||
props['name'] = self._name
|
props['name'] = self._name
|
||||||
props['color'] = self._color
|
props['color'] = self._color
|
||||||
props['type'] = self._type
|
props['type'] = self._type
|
||||||
|
|
||||||
|
# Add custom properties
|
||||||
|
for (key, value) in self._custom_props.items():
|
||||||
|
props[key] = value
|
||||||
|
|
||||||
self._tp.set_activity_properties(self.props.id, props)
|
self._tp.set_activity_properties(self.props.id, props)
|
||||||
|
|
||||||
def set_properties(self, properties):
|
def set_properties(self, properties):
|
||||||
@ -450,29 +484,53 @@ class Activity(DBusGObject):
|
|||||||
|
|
||||||
Note that if any of the name, colour and/or type property values is changed from
|
Note that if any of the name, colour and/or type property values is changed from
|
||||||
what it originally was, the update_validity method will be called, resulting in
|
what it originally was, the update_validity method will be called, resulting in
|
||||||
a "validity-changed" signal being generated. (Also note that unlike with the
|
a "validity-changed" signal being generated. Called by the PresenceService
|
||||||
do_set_property method, it *is* possible to change an already-set activity type
|
on the local machine.
|
||||||
to something else; this may be a bug.) Called by the PresenceService on the
|
|
||||||
local machine.
|
|
||||||
"""
|
"""
|
||||||
changed = False
|
changed = False
|
||||||
if "name" in properties.keys():
|
# split reserved properties from activity-custom properties
|
||||||
name = properties["name"]
|
(rprops, cprops) = self._split_properties(properties)
|
||||||
|
if _PROP_NAME in rprops.keys():
|
||||||
|
name = rprops[_PROP_NAME]
|
||||||
if name != self._name:
|
if name != self._name:
|
||||||
self._name = name
|
self._name = name
|
||||||
changed = True
|
changed = True
|
||||||
|
|
||||||
if "color" in properties.keys():
|
if _PROP_COLOR in rprops.keys():
|
||||||
color = properties["color"]
|
color = rprops[_PROP_COLOR]
|
||||||
if color != self._color:
|
if color != self._color:
|
||||||
self._color = color
|
self._color = color
|
||||||
changed = True
|
changed = True
|
||||||
|
|
||||||
if "type" in properties.keys():
|
if _PROP_TYPE in rprops.keys():
|
||||||
type = properties["type"]
|
type = rprops[_PROP_TYPE]
|
||||||
if type != self._type:
|
# Type can never be changed after first set
|
||||||
self._type = type
|
if self._type:
|
||||||
changed = True
|
logging.debug("Activity type changed by network; this is illegal")
|
||||||
|
else:
|
||||||
|
if type != self._type:
|
||||||
|
self._type = type
|
||||||
|
changed = True
|
||||||
|
|
||||||
|
# Set custom properties
|
||||||
|
if len(cprops.keys()) > 0:
|
||||||
|
self.props.custom_props = cprops
|
||||||
|
|
||||||
if changed:
|
if changed:
|
||||||
self._update_validity()
|
self._update_validity()
|
||||||
|
|
||||||
|
def _split_properties(self, properties):
|
||||||
|
"""Extracts reserved properties.
|
||||||
|
|
||||||
|
properties - Dictionary object containing properties keyed by property names
|
||||||
|
|
||||||
|
returns a tuple of 2 dictionaries, reserved properties and custom properties
|
||||||
|
"""
|
||||||
|
rprops = {}
|
||||||
|
cprops = {}
|
||||||
|
for (key, value) in properties.items():
|
||||||
|
if key in self._RESERVED_PROPNAMES:
|
||||||
|
rprops[key] = value
|
||||||
|
else:
|
||||||
|
cprops[key] = value
|
||||||
|
return (rprops, cprops)
|
||||||
|
@ -560,7 +560,7 @@ class TestOwner(GenericOwner):
|
|||||||
|
|
||||||
__gtype_name__ = "TestOwner"
|
__gtype_name__ = "TestOwner"
|
||||||
|
|
||||||
def __init__(self, ps, bus_name, object_id, test_num):
|
def __init__(self, ps, bus_name, object_id, test_num, randomize):
|
||||||
self._cp = ConfigParser()
|
self._cp = ConfigParser()
|
||||||
self._section = "Info"
|
self._section = "Info"
|
||||||
self._test_activities = []
|
self._test_activities = []
|
||||||
@ -588,7 +588,9 @@ class TestOwner(GenericOwner):
|
|||||||
GenericOwner.__init__(self, ps, bus_name, object_id, key=pubkey, nick=nick,
|
GenericOwner.__init__(self, ps, bus_name, object_id, key=pubkey, nick=nick,
|
||||||
color=color, icon=icon, registered=registered, key_hash=privkey_hash)
|
color=color, icon=icon, registered=registered, key_hash=privkey_hash)
|
||||||
|
|
||||||
self._ps.connect('connection-status', self._ps_connection_status_cb)
|
# Only do the random stuff if randomize is true
|
||||||
|
if randomize:
|
||||||
|
self._ps.connect('connection-status', self._ps_connection_status_cb)
|
||||||
|
|
||||||
def _share_reply_cb(self, actid, object_path):
|
def _share_reply_cb(self, actid, object_path):
|
||||||
activity = self._ps.internal_get_activity(actid)
|
activity = self._ps.internal_get_activity(actid)
|
||||||
|
@ -51,7 +51,7 @@ class PresenceService(DBusGObject):
|
|||||||
([gobject.TYPE_BOOLEAN]))
|
([gobject.TYPE_BOOLEAN]))
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, test=0):
|
def __init__(self, test_num=0, randomize=False):
|
||||||
self._next_object_id = 0
|
self._next_object_id = 0
|
||||||
self._connected = False
|
self._connected = False
|
||||||
|
|
||||||
@ -66,8 +66,8 @@ class PresenceService(DBusGObject):
|
|||||||
|
|
||||||
# Create the Owner object
|
# Create the Owner object
|
||||||
objid = self._get_next_object_id()
|
objid = self._get_next_object_id()
|
||||||
if test > 0:
|
if test_num > 0:
|
||||||
self._owner = TestOwner(self, self._bus_name, objid, test)
|
self._owner = TestOwner(self, self._bus_name, objid, test_num, randomize)
|
||||||
else:
|
else:
|
||||||
self._owner = ShellOwner(self, self._bus_name, objid)
|
self._owner = ShellOwner(self, self._bus_name, objid)
|
||||||
self._buddies[self._owner.props.key] = self._owner
|
self._buddies[self._owner.props.key] = self._owner
|
||||||
@ -357,9 +357,9 @@ class PresenceService(DBusGObject):
|
|||||||
return self._activities[actid]
|
return self._activities[actid]
|
||||||
|
|
||||||
|
|
||||||
def main(test=False):
|
def main(test_num=0, randomize=False):
|
||||||
loop = gobject.MainLoop()
|
loop = gobject.MainLoop()
|
||||||
ps = PresenceService(test)
|
ps = PresenceService(test_num, randomize)
|
||||||
try:
|
try:
|
||||||
loop.run()
|
loop.run()
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
|
@ -24,24 +24,36 @@ import os
|
|||||||
from sugar import logger
|
from sugar import logger
|
||||||
from sugar import env
|
from sugar import env
|
||||||
|
|
||||||
|
def usage():
|
||||||
|
logging.debug("Usage: sugar-presence-service [<test buddy number (1 - 10)>] [randomize]")
|
||||||
|
|
||||||
sys.path.append(env.get_service_path('presence'))
|
sys.path.append(env.get_service_path('presence'))
|
||||||
|
|
||||||
test=0
|
test_num = 0
|
||||||
if len(sys.argv) > 1:
|
randomize = False
|
||||||
|
if len(sys.argv) in [2, 3]:
|
||||||
try:
|
try:
|
||||||
test = int(sys.argv[1])
|
test_num = int(sys.argv[1])
|
||||||
except ValueError:
|
except ValueError:
|
||||||
logging.debug("Bad test user number.")
|
logging.debug("Bad test user number.")
|
||||||
if test < 1 or test > 10:
|
if test_num < 1 or test_num > 10:
|
||||||
logging.debug("Bad test user number.")
|
logging.debug("Bad test user number.")
|
||||||
|
|
||||||
if test > 0:
|
if len(sys.argv) == 3 and sys.argv[2] == "randomize":
|
||||||
logger.start('test-%d-presenceservice' % test)
|
randomize = True
|
||||||
|
elif len(sys.argv) == 1:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
usage()
|
||||||
|
os._exit(1)
|
||||||
|
|
||||||
|
if test_num > 0:
|
||||||
|
logger.start('test-%d-presenceservice' % test_num)
|
||||||
else:
|
else:
|
||||||
logger.start('presenceservice')
|
logger.start('presenceservice')
|
||||||
|
|
||||||
import presenceservice
|
import presenceservice
|
||||||
|
|
||||||
logging.info('Starting presence service')
|
logging.info('Starting presence service...')
|
||||||
|
|
||||||
presenceservice.main(test)
|
presenceservice.main(test_num, randomize)
|
||||||
|
@ -64,6 +64,31 @@ class ActivityToolbar(gtk.Toolbar):
|
|||||||
def _activity_shared_cb(self, activity):
|
def _activity_shared_cb(self, activity):
|
||||||
self._share_button.set_sensitive(False)
|
self._share_button.set_sensitive(False)
|
||||||
|
|
||||||
|
class EditToolbar(gtk.Toolbar):
|
||||||
|
def __init__(self):
|
||||||
|
gtk.Toolbar.__init__(self)
|
||||||
|
|
||||||
|
self.undo = ToolButton('edit-undo')
|
||||||
|
self.insert(self.undo, -1)
|
||||||
|
self.undo.show()
|
||||||
|
|
||||||
|
self.redo = ToolButton('edit-redo')
|
||||||
|
self.insert(self.redo, -1)
|
||||||
|
self.redo.show()
|
||||||
|
|
||||||
|
separator = gtk.SeparatorToolItem()
|
||||||
|
separator.set_draw(True)
|
||||||
|
self.insert(separator, -1)
|
||||||
|
separator.show()
|
||||||
|
|
||||||
|
self.copy = ToolButton('edit-copy')
|
||||||
|
self.insert(self.copy, -1)
|
||||||
|
self.copy.show()
|
||||||
|
|
||||||
|
self.paste = ToolButton('edit-paste')
|
||||||
|
self.insert(self.paste, -1)
|
||||||
|
self.paste.show()
|
||||||
|
|
||||||
class ActivityToolbox(Toolbox):
|
class ActivityToolbox(Toolbox):
|
||||||
def __init__(self, activity):
|
def __init__(self, activity):
|
||||||
Toolbox.__init__(self)
|
Toolbox.__init__(self)
|
||||||
|
@ -2,6 +2,7 @@ sugardir = $(pythondir)/sugar/graphics
|
|||||||
sugar_PYTHON = \
|
sugar_PYTHON = \
|
||||||
__init__.py \
|
__init__.py \
|
||||||
animator.py \
|
animator.py \
|
||||||
|
icon.py \
|
||||||
iconbutton.py \
|
iconbutton.py \
|
||||||
canvasicon.py \
|
canvasicon.py \
|
||||||
color.py \
|
color.py \
|
||||||
@ -11,6 +12,7 @@ sugar_PYTHON = \
|
|||||||
menu.py \
|
menu.py \
|
||||||
menushell.py \
|
menushell.py \
|
||||||
roundbox.py \
|
roundbox.py \
|
||||||
|
panel.py \
|
||||||
popup.py \
|
popup.py \
|
||||||
popupcontext.py \
|
popupcontext.py \
|
||||||
snowflakebox.py \
|
snowflakebox.py \
|
||||||
|
23
sugar/graphics/panel.py
Normal file
23
sugar/graphics/panel.py
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
# Copyright (C) 2007, Red Hat, Inc.
|
||||||
|
#
|
||||||
|
# This library is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU Lesser General Public
|
||||||
|
# License as published by the Free Software Foundation; either
|
||||||
|
# version 2 of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This library is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
# Lesser General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Lesser General Public
|
||||||
|
# License along with this library; if not, write to the
|
||||||
|
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
# Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
import gtk
|
||||||
|
|
||||||
|
class Panel(gtk.VBox):
|
||||||
|
__gtype_name__ = 'SugarPanel'
|
||||||
|
def __init__(self):
|
||||||
|
gtk.VBox.__init__(self)
|
28
sugar/graphics/toggletoolbutton.py
Normal file
28
sugar/graphics/toggletoolbutton.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
# Copyright (C) 2007, Red Hat, Inc.
|
||||||
|
#
|
||||||
|
# This library is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU Lesser General Public
|
||||||
|
# License as published by the Free Software Foundation; either
|
||||||
|
# version 2 of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This library is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
# Lesser General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Lesser General Public
|
||||||
|
# License along with this library; if not, write to the
|
||||||
|
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
# Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
import gtk
|
||||||
|
|
||||||
|
from sugar.graphics.icon import Icon
|
||||||
|
|
||||||
|
class ToggleToolButton(gtk.ToggleToolButton):
|
||||||
|
def __init__(self, icon_resource=None):
|
||||||
|
gtk.ToggleToolButton.__init__(self)
|
||||||
|
|
||||||
|
icon = Icon(icon_resource)
|
||||||
|
self.set_icon_widget(icon)
|
||||||
|
icon.show()
|
@ -26,6 +26,7 @@ class Toolbox(gtk.VBox):
|
|||||||
gtk.VBox.__init__(self)
|
gtk.VBox.__init__(self)
|
||||||
|
|
||||||
self._notebook = gtk.Notebook()
|
self._notebook = gtk.Notebook()
|
||||||
|
self._notebook.set_name('sugar-toolbox-notebook')
|
||||||
self._notebook.set_tab_pos(gtk.POS_BOTTOM)
|
self._notebook.set_tab_pos(gtk.POS_BOTTOM)
|
||||||
self._notebook.set_show_border(False)
|
self._notebook.set_show_border(False)
|
||||||
self.pack_start(self._notebook)
|
self.pack_start(self._notebook)
|
||||||
|
@ -24,7 +24,7 @@ from sugar.presence import presenceservice
|
|||||||
import mockps
|
import mockps
|
||||||
|
|
||||||
def start_ps():
|
def start_ps():
|
||||||
argv = ["mockps.py", "mockps.py"]
|
argv = ["mockps.py"]
|
||||||
(pid, stdin, stdout, stderr) = gobject.spawn_async(argv, flags=gobject.SPAWN_LEAVE_DESCRIPTORS_OPEN)
|
(pid, stdin, stdout, stderr) = gobject.spawn_async(argv, flags=gobject.SPAWN_LEAVE_DESCRIPTORS_OPEN)
|
||||||
|
|
||||||
# Wait until it shows up on the bus
|
# Wait until it shows up on the bus
|
||||||
|
Loading…
Reference in New Issue
Block a user