diff --git a/services/shell/activityregistryservice.py b/services/shell/activityregistryservice.py index 21c6d866..c379071a 100644 --- a/services/shell/activityregistryservice.py +++ b/services/shell/activityregistryservice.py @@ -32,6 +32,7 @@ class ActivityRegistry(dbus.service.Object): bundle_registry = bundleregistry.get_registry() bundle_registry.connect('bundle-added', self._bundle_added_cb) + bundle_registry.connect('bundle-removed', self._bundle_removed_cb) @dbus.service.method(_ACTIVITY_REGISTRY_IFACE, in_signature='s', out_signature='b') @@ -48,6 +49,16 @@ class ActivityRegistry(dbus.service.Object): registry = bundleregistry.get_registry() return registry.add_bundle(bundle_path) + @dbus.service.method(_ACTIVITY_REGISTRY_IFACE, + in_signature='s', out_signature='b') + def RemoveBundle(self, bundle_path): + '''Unregister the activity bundle with the global registry + + bundle_path -- path to the activity bundle root directory + ''' + registry = bundleregistry.get_registry() + return registry.remove_bundle(bundle_path) + @dbus.service.method(_ACTIVITY_REGISTRY_IFACE, in_signature='', out_signature='aa{sv}') def GetActivities(self): @@ -94,6 +105,10 @@ class ActivityRegistry(dbus.service.Object): def ActivityAdded(self, activity_info): pass + @dbus.service.signal(_ACTIVITY_REGISTRY_IFACE, signature='a{sv}') + def ActivityRemoved(self, activity_info): + pass + def _bundle_to_dict(self, bundle): return {'name': bundle.get_name(), 'icon': bundle.get_icon(), @@ -104,6 +119,9 @@ class ActivityRegistry(dbus.service.Object): def _bundle_added_cb(self, bundle_registry, bundle): self.ActivityAdded(self._bundle_to_dict(bundle)) + def _bundle_removed_cb(self, bundle_registry, bundle): + self.ActivityRemoved(self._bundle_to_dict(bundle)) + _instance = None def get_instance(): diff --git a/services/shell/bundleregistry.py b/services/shell/bundleregistry.py index 9a1cda6a..54d52970 100644 --- a/services/shell/bundleregistry.py +++ b/services/shell/bundleregistry.py @@ -73,12 +73,17 @@ class _ServiceManager(object): util.write_service(bundle.get_service_name(), bundle.get_command(), self._path) + def remove(self, bundle): + util.delete_service(bundle.get_service_name(), self._path) + class BundleRegistry(gobject.GObject): """Service that tracks the available activity bundles""" __gsignals__ = { 'bundle-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT])) + ([gobject.TYPE_PYOBJECT])), + 'bundle-removed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([gobject.TYPE_PYOBJECT])) } def __init__(self): @@ -133,6 +138,15 @@ class BundleRegistry(gobject.GObject): self.emit('bundle-added', bundle) return True + def remove_bundle(self, bundle_path): + for bundle in self._bundles: + if bundle.get_path() == bundle_path: + self._bundles.remove(bundle) + self._service_manager.remove(bundle) + self.emit('bundle-removed', bundle) + return True + return False + def get_activities_for_type(self, mime_type): result = [] for bundle in self._bundles: diff --git a/shell/view/frame/activitiestray.py b/shell/view/frame/activitiestray.py index e4bbffcb..e2a89dd8 100644 --- a/shell/view/frame/activitiestray.py +++ b/shell/view/frame/activitiestray.py @@ -65,6 +65,7 @@ class ActivitiesTray(hippo.CanvasBox): registry.get_activities_async(reply_handler=self._get_activities_cb) registry.connect('activity-added', self._activity_added_cb) + registry.connect('activity-removed', self._activity_removed_cb) for invite in self._invites: self.add_invite(invite) @@ -120,16 +121,22 @@ class ActivitiesTray(hippo.CanvasBox): def _invite_removed_cb(self, invites, invite): self.remove_invite(invite) - def _activity_removed_cb(self, item): + def _remove_activity_cb(self, item): self._tray.remove_item(item) def _activity_added_cb(self, activity_registry, activity_info): self.add_activity(activity_info) + def _activity_removed_cb(self, activity_registry, activity_info): + for item in self._tray.get_children(): + if item.get_bundle_id() == activity_info.service_name: + self._tray.remove_item(item) + return + def add_activity(self, activity_info): item = ActivityButton(activity_info) item.connect('clicked', self._activity_clicked_cb) - item.connect('remove_activity', self._activity_removed_cb) + item.connect('remove_activity', self._remove_activity_cb) self._tray.add_item(item, -1) item.show() diff --git a/sugar/activity/registry.py b/sugar/activity/registry.py index 39c2b3c4..8b1d440d 100644 --- a/sugar/activity/registry.py +++ b/sugar/activity/registry.py @@ -43,6 +43,8 @@ class ActivityInfo(object): class ActivityRegistry(gobject.GObject): __gsignals__ = { 'activity-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([gobject.TYPE_PYOBJECT])), + 'activity-removed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])) } def __init__(self): @@ -60,6 +62,7 @@ class ActivityRegistry(gobject.GObject): follow_name_owner_changes = True) self._registry = dbus.Interface(bus_object, _ACTIVITY_REGISTRY_IFACE) self._registry.connect_to_signal('ActivityAdded', self._activity_added_cb) + self._registry.connect_to_signal('ActivityRemoved', self._activity_removed_cb) # Two caches fo saving some travel across dbus. self._service_name_to_activity_info = {} @@ -133,6 +136,15 @@ class ActivityRegistry(gobject.GObject): self._mime_type_to_activities.clear() self.emit('activity-added', _activity_info_from_dict(info_dict)) + def remove_bundle(self, bundle_path): + return self._registry.RemoveBundle(bundle_path) + + def _activity_removed_cb(self, info_dict): + logging.debug('ActivityRegistry._activity_removed_cb: flushing caches') + self._service_name_to_activity_info.clear() + self._mime_type_to_activities.clear() + self.emit('activity-removed', _activity_info_from_dict(info_dict)) + _registry = None def get_registry(): diff --git a/sugar/bundle/activitybundle.py b/sugar/bundle/activitybundle.py index d13f93c3..0d5a5b45 100644 --- a/sugar/bundle/activitybundle.py +++ b/sugar/bundle/activitybundle.py @@ -280,6 +280,7 @@ class ActivityBundle(Bundle): os.remove(path) self._uninstall(install_path) - - # FIXME: notify shell + + if not activity.get_registry().remove_bundle(install_path): + raise RegistrationException diff --git a/sugar/util.py b/sugar/util.py index 5f018483..2780427a 100644 --- a/sugar/util.py +++ b/sugar/util.py @@ -106,6 +106,20 @@ def write_service(name, bin, path): service_cp.write(fileobject) fileobject.close() +def delete_service(name, path): + """Delete a D-BUS service definition file + + Deletes a D-BUS service file previously + created by write_service(). + + name -- D-BUS service name, must be a valid + filename/D-BUS name + path -- directory containing the name.service + file + """ + + os.remove(os.path.join(path, name + '.service')) + def set_proc_title(title): """Sets the process title so ps and top show more descriptive names. This does not modify argv[0]