diff --git a/bin/sugar-activity b/bin/sugar-activity index 1b859807..825802fd 100755 --- a/bin/sugar-activity +++ b/bin/sugar-activity @@ -20,6 +20,7 @@ import sys import os from ConfigParser import ConfigParser +from sugar.activity import ActivityRegistry from sugar import env # Setup the environment so that we run inside the Sugar shell @@ -33,7 +34,6 @@ import gtk import dbus import dbus.glib -from sugar.activity import bundleregistry from sugar.activity import activityfactory from sugar.activity import activityfactoryservice @@ -48,13 +48,15 @@ def _error_cb(handler, err): def print_help(self): sys.exit(0) -bundle = None +activity_info = None if len(sys.argv) > 1: - registry = bundleregistry.get_registry() - bundle = registry.find_bundle(sys.argv[1]) + registry = ActivityRegistry() + activities = registry.get_activities_for_name(sys.argv[1]) + if len(activities) > 0: + activity_info = activities[0] -if bundle == None: +if activity_info == None: print 'Usage:\n\n' \ 'sugar-activity [bundle]\n\n' \ 'Bundle can be a part of the service name or of bundle name.' @@ -64,16 +66,16 @@ bus = dbus.SessionBus() bus_object = bus.get_object('org.freedesktop.DBus', '/org/freedesktop/DBus') try: name = bus_object.GetNameOwner( - bundle.get_service_name(), dbus_interface='org.freedesktop.DBus') + activity_info.service_name, dbus_interface='org.freedesktop.DBus') except dbus.DBusException: name = None if name: print '%s is already running, creating a new instance.' % bundle.get_service_name() else: - activityfactoryservice.run(bundle.get_path()) + activityfactoryservice.run(activity_info.path) -handler = activityfactory.create(bundle.get_service_name()) +handler = activityfactory.create(activity_info.service_name) handler.connect('success', _success_cb, name != None) handler.connect('error', _error_cb) diff --git a/shell/model/Makefile.am b/shell/model/Makefile.am index 9e24dc49..fcc936b8 100644 --- a/shell/model/Makefile.am +++ b/shell/model/Makefile.am @@ -4,6 +4,7 @@ sugardir = $(pkgdatadir)/shell/model sugar_PYTHON = \ __init__.py \ accesspointmodel.py \ + bundleregistry.py \ BuddyModel.py \ Friends.py \ Invites.py \ diff --git a/shell/model/MeshModel.py b/shell/model/MeshModel.py index 93e2a237..ed92ae0e 100644 --- a/shell/model/MeshModel.py +++ b/shell/model/MeshModel.py @@ -18,7 +18,8 @@ import gobject from sugar.graphics.xocolor import XoColor from sugar.presence import presenceservice -from sugar.activity import bundleregistry + +from model import bundleregistry from model.BuddyModel import BuddyModel from model.accesspointmodel import AccessPointModel from hardware import hardwaremanager diff --git a/sugar/activity/bundleregistry.py b/shell/model/bundleregistry.py similarity index 76% rename from sugar/activity/bundleregistry.py rename to shell/model/bundleregistry.py index 0cad4b25..1771fa83 100644 --- a/sugar/activity/bundleregistry.py +++ b/shell/model/bundleregistry.py @@ -1,19 +1,18 @@ -# Copyright (C) 2007, Red Hat, Inc. +# Copyright (C) 2006, 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 program is free software; you can redistribute it and/or modify +# it under the terms of the GNU 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, +# This program 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. +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU 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. +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA import os @@ -74,18 +73,6 @@ class BundleRegistry(gobject.GObject): self._search_path = [] self._service_manager = _ServiceManager() - def find_bundle(self, key): - """Find a bundle in the registry""" - key = key.lower() - - for bundle in self._bundles.values(): - name = bundle.get_name().lower() - service_name = bundle.get_service_name().lower() - if name.find(key) != -1 or service_name.find(key) != -1: - return bundle - - return None - def get_bundle(self, service_name): """Returns an bundle given his service name""" if self._bundles.has_key(service_name): diff --git a/shell/model/homemodel.py b/shell/model/homemodel.py index 92afc23f..9b995180 100644 --- a/shell/model/homemodel.py +++ b/shell/model/homemodel.py @@ -22,7 +22,7 @@ import dbus from model.homeactivity import HomeActivity from model.homerawwindow import HomeRawWindow -from sugar.activity import bundleregistry +from model import bundleregistry _SERVICE_NAME = "org.laptop.Activity" _SERVICE_PATH = "/org/laptop/Activity" diff --git a/shell/shellservice.py b/shell/shellservice.py index 3b42940b..4e8f469f 100644 --- a/shell/shellservice.py +++ b/shell/shellservice.py @@ -1,11 +1,30 @@ +# Copyright (C) 2006, Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + """D-bus service providing access to the shell's functionality""" import dbus -from sugar.activity import bundleregistry +from sugar.activity import ActivityRegistry +from sugar.activity import ActivityInfo + +from model import bundleregistry _DBUS_SERVICE = "org.laptop.Shell" -_DBUS_INTERFACE = "org.laptop.Shell" -_DBUS_OWNER_INTERFACE = "org.laptop.Shell.Owner" +_DBUS_ACTIVITY_REGISTRY_IFACE = "org.laptop.Shell.ActivityRegistry" +_DBUS_OWNER_IFACE = "org.laptop.Shell.Owner" _DBUS_PATH = "/org/laptop/Shell" class ShellService(dbus.service.Object): @@ -35,14 +54,16 @@ class ShellService(dbus.service.Object): self._owner.connect('color-changed', self._owner_color_changed_cb) self._home_model = self._shell_model.get_home() - self._home_model.connect('active-activity-changed', self._cur_activity_changed_cb) + self._home_model.connect('active-activity-changed', + self._cur_activity_changed_cb) bus = dbus.SessionBus() bus_name = dbus.service.BusName(_DBUS_SERVICE, bus=bus) dbus.service.Object.__init__(self, bus_name, _DBUS_PATH) - @dbus.service.method(_DBUS_INTERFACE, in_signature="s", out_signature="b") - def add_bundle(self, bundle_path): + @dbus.service.method(_DBUS_ACTIVITY_REGISTRY_IFACE, + in_signature="s", out_signature="b") + def AddBundle(self, bundle_path): """Register the activity bundle with the global registry bundle_path -- path to the activity bundle's root directory, @@ -55,28 +76,42 @@ class ShellService(dbus.service.Object): registry = bundleregistry.get_registry() return registry.add_bundle(bundle_path) - @dbus.service.signal(_DBUS_OWNER_INTERFACE, signature="s") + @dbus.service.method(_DBUS_ACTIVITY_REGISTRY_IFACE, + in_signature="s", out_signature="aa{sv}") + def GetActivitiesForName(self, name): + result = [] + key = name.lower() + + for bundle in bundleregistry.get_registry(): + name = bundle.get_name().lower() + service_name = bundle.get_service_name().lower() + if name.find(key) != -1 or service_name.find(key) != -1: + result.append(self._get_activity_info(bundle).to_dict()) + + return result + + @dbus.service.signal(_DBUS_OWNER_IFACE, signature="s") def ColorChanged(self, color): pass def _owner_color_changed_cb(self, new_color): self.ColorChanged(new_color.to_string()) - @dbus.service.signal(_DBUS_OWNER_INTERFACE, signature="s") + @dbus.service.signal(_DBUS_OWNER_IFACE, signature="s") def NickChanged(self, nick): pass def _owner_nick_changed_cb(self, new_nick): self.NickChanged(new_nick) - @dbus.service.signal(_DBUS_OWNER_INTERFACE, signature="ay") + @dbus.service.signal(_DBUS_OWNER_IFACE, signature="ay") def IconChanged(self, icon_data): pass def _owner_icon_changed_cb(self, new_icon): self.IconChanged(dbus.ByteArray(new_icon)) - @dbus.service.signal(_DBUS_OWNER_INTERFACE, signature="s") + @dbus.service.signal(_DBUS_OWNER_IFACE, signature="s") def CurrentActivityChanged(self, activity_id): pass @@ -85,3 +120,7 @@ class ShellService(dbus.service.Object): if new_activity: new_id = new_activity.get_activity_id() self.CurrentActivityChanged(new_id) + + def _get_activity_info(self, bundle): + return ActivityInfo(bundle.get_name(), bundle.get_icon(), + bundle.get_service_name(), bundle.get_path()) diff --git a/shell/view/Shell.py b/shell/view/Shell.py index f2827e0e..0f3b629f 100644 --- a/shell/view/Shell.py +++ b/shell/view/Shell.py @@ -20,14 +20,16 @@ import logging import gobject import wnck -from view.home.HomeWindow import HomeWindow from sugar.activity.activityhandle import ActivityHandle from sugar.graphics.popupcontext import PopupContext +from sugar.activity import activityfactory +import sugar + from view.ActivityHost import ActivityHost -from sugar.activity import activityfactory, bundleregistry from view.frame.frame import Frame from view.keyhandler import KeyHandler -import sugar +from view.home.HomeWindow import HomeWindow +from model import bundleregistry class Shell(gobject.GObject): def __init__(self, model): diff --git a/shell/view/frame/ActivitiesBox.py b/shell/view/frame/ActivitiesBox.py index 77bf0939..a755b4ea 100644 --- a/shell/view/frame/ActivitiesBox.py +++ b/shell/view/frame/ActivitiesBox.py @@ -20,9 +20,10 @@ import logging from sugar.graphics import units from sugar.graphics.xocolor import XoColor from sugar.graphics.iconbutton import IconButton -from sugar.activity import bundleregistry from sugar import profile +from model import bundleregistry + class ActivityButton(IconButton): def __init__(self, activity, popup_context): IconButton.__init__(self, icon_name=activity.get_icon(), diff --git a/shell/view/home/FriendView.py b/shell/view/home/FriendView.py index 5dc98a59..317ca661 100644 --- a/shell/view/home/FriendView.py +++ b/shell/view/home/FriendView.py @@ -17,11 +17,12 @@ import hippo import gobject -from view.BuddyIcon import BuddyIcon from sugar.graphics.canvasicon import CanvasIcon from sugar.graphics import units from sugar.presence import presenceservice -from sugar.activity import bundleregistry + +from model import bundleregistry +from view.BuddyIcon import BuddyIcon class FriendView(hippo.CanvasBox): def __init__(self, shell, menu_shell, buddy, **kwargs): diff --git a/sugar/activity/Makefile.am b/sugar/activity/Makefile.am index d11a3474..d6ea9a48 100644 --- a/sugar/activity/Makefile.am +++ b/sugar/activity/Makefile.am @@ -8,4 +8,4 @@ sugar_PYTHON = \ activityservice.py \ bundle.py \ bundlebuilder.py \ - bundleregistry.py + registry.py diff --git a/sugar/activity/__init__.py b/sugar/activity/__init__.py index 524cdfc5..84539a3b 100644 --- a/sugar/activity/__init__.py +++ b/sugar/activity/__init__.py @@ -10,16 +10,7 @@ takes a small dictionary with values corresponding to a sugar.activity.activityhandle.ActivityHandle -describing an individual instance of the activity. The -ActivityFactory service is registered with dbus using the -global - - sugar.activity.bundleregistry.BundleRegistry - -service, which creates dbus .service files in a well known -directory. Those files tell dbus what executable to run -in order to load the ActivityFactory which will provide -the creation service. +describing an individual instance of the activity. Each activity so registered is described by a @@ -45,3 +36,6 @@ class. This class allows for querying the ID of the root window, requesting sharing across the network, and basic "what type of application are you" queries. """ + +from sugar.activity.registry import ActivityRegistry +from sugar.activity.registry import ActivityInfo diff --git a/sugar/activity/activity.py b/sugar/activity/activity.py index 3dba4c71..dbcbd603 100644 --- a/sugar/activity/activity.py +++ b/sugar/activity/activity.py @@ -28,7 +28,6 @@ import gtk, gobject from sugar.presence import presenceservice from sugar.activity.activityservice import ActivityService -from sugar.activity import bundleregistry from sugar.graphics.window import Window from sugar.graphics.toolbox import Toolbox from sugar.graphics.toolbutton import ToolButton @@ -209,7 +208,6 @@ class Activity(Window, gtk.Container): self.jobject = datastore.create() self.jobject['title'] = '%s %s' % (get_bundle_name(), 'Activity') self.jobject['activity'] = self.get_service_name() - self.jobject['icon'] = self._get_icon() self.jobject['keep'] = '0' self.jobject['buddies'] = '' self.jobject['preview'] = '' @@ -332,10 +330,6 @@ class Activity(Window, gtk.Container): raise self.destroy() - def _get_icon(self): - registry = bundleregistry.get_registry() - return registry.get_bundle(self.get_service_name()).get_icon() - def get_bundle_name(): """Return the bundle name for the current process' bundle """ diff --git a/sugar/activity/activityfactory.py b/sugar/activity/activityfactory.py index f9c3d6ff..809a74d0 100644 --- a/sugar/activity/activityfactory.py +++ b/sugar/activity/activityfactory.py @@ -89,8 +89,7 @@ class ActivityCreationHandler(gobject.GObject): The specific service which creates new instances of this particular type of activity is created during the activity - registration process in - sugar.activity.bundleregistry.BundleRegistry which creates + registration process in shell bundle registry which creates service definition files for each registered bundle type. """ gobject.GObject.__init__(self) diff --git a/sugar/activity/bundle.py b/sugar/activity/bundle.py index 1ef30dda..9410f249 100644 --- a/sugar/activity/bundle.py +++ b/sugar/activity/bundle.py @@ -151,10 +151,6 @@ class Bundle: """Get the activity service name""" return self._service_name - def get_object_path(self): - """Get the path to the service object""" - return '/' + self._service_name.replace('.', '/') - def get_icon(self): """Get the activity icon name""" return self._icon diff --git a/sugar/activity/registry.py b/sugar/activity/registry.py new file mode 100644 index 00000000..1efda458 --- /dev/null +++ b/sugar/activity/registry.py @@ -0,0 +1,58 @@ +# Copyright (C) 2006, 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 dbus + +_SHELL_SERVICE = "org.laptop.Shell" +_SHELL_PATH = "/org/laptop/Shell" +_REGISTRY_IFACE = "org.laptop.Shell.ActivityRegistry" + +def _activity_info_from_dict(info_dict): + return ActivityInfo(info_dict['name'], info_dict['icon'], + info_dict['service_name'], info_dict['path']) + +class ActivityInfo(object): + def __init__(self, name, icon, service_name, path): + self.name = name + self.icon = icon + self.service_name = service_name + self.path = path + + def to_dict(self): + return { 'name' : self.name, + 'icon' : self.icon, + 'service_name' : self.service_name, + 'path' : self.path + } + +class ActivityRegistry(object): + def __init__(self): + bus = dbus.SessionBus() + bus_object = bus.get_object(_SHELL_SERVICE, _SHELL_PATH) + self._registry = dbus.Interface(bus_object, _REGISTRY_IFACE) + + def get_activities_for_name(self, name): + result = [] + + activities = self._registry.GetActivitiesForName(name) + for info_dict in activities: + result.append(_activity_info_from_dict(info_dict)) + + return result + + def get_activities_for_type(self, mime_type): + pass