Merge branch 'master' of git+ssh://dev.laptop.org/git/sugar
This commit is contained in:
commit
32ecdd8ad6
@ -32,13 +32,14 @@ class ActivityRegistry(dbus.service.Object):
|
|||||||
|
|
||||||
bundle_registry = bundleregistry.get_registry()
|
bundle_registry = bundleregistry.get_registry()
|
||||||
bundle_registry.connect('bundle-added', self._bundle_added_cb)
|
bundle_registry.connect('bundle-added', self._bundle_added_cb)
|
||||||
|
bundle_registry.connect('bundle-removed', self._bundle_removed_cb)
|
||||||
|
|
||||||
@dbus.service.method(_ACTIVITY_REGISTRY_IFACE,
|
@dbus.service.method(_ACTIVITY_REGISTRY_IFACE,
|
||||||
in_signature='s', out_signature='b')
|
in_signature='s', out_signature='b')
|
||||||
def AddBundle(self, bundle_path):
|
def AddBundle(self, bundle_path):
|
||||||
'''Register the activity bundle with the global registry
|
'''Register the activity bundle with the global registry
|
||||||
|
|
||||||
bundle_path -- path to the activity bundle's root directory,
|
bundle_path -- path to the root directory of the activity bundle,
|
||||||
that is, the directory with activity/activity.info as a
|
that is, the directory with activity/activity.info as a
|
||||||
child of the directory.
|
child of the directory.
|
||||||
|
|
||||||
@ -48,6 +49,16 @@ class ActivityRegistry(dbus.service.Object):
|
|||||||
registry = bundleregistry.get_registry()
|
registry = bundleregistry.get_registry()
|
||||||
return registry.add_bundle(bundle_path)
|
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,
|
@dbus.service.method(_ACTIVITY_REGISTRY_IFACE,
|
||||||
in_signature='', out_signature='aa{sv}')
|
in_signature='', out_signature='aa{sv}')
|
||||||
def GetActivities(self):
|
def GetActivities(self):
|
||||||
@ -94,6 +105,10 @@ class ActivityRegistry(dbus.service.Object):
|
|||||||
def ActivityAdded(self, activity_info):
|
def ActivityAdded(self, activity_info):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@dbus.service.signal(_ACTIVITY_REGISTRY_IFACE, signature='a{sv}')
|
||||||
|
def ActivityRemoved(self, activity_info):
|
||||||
|
pass
|
||||||
|
|
||||||
def _bundle_to_dict(self, bundle):
|
def _bundle_to_dict(self, bundle):
|
||||||
return {'name': bundle.get_name(),
|
return {'name': bundle.get_name(),
|
||||||
'icon': bundle.get_icon(),
|
'icon': bundle.get_icon(),
|
||||||
@ -104,6 +119,9 @@ class ActivityRegistry(dbus.service.Object):
|
|||||||
def _bundle_added_cb(self, bundle_registry, bundle):
|
def _bundle_added_cb(self, bundle_registry, bundle):
|
||||||
self.ActivityAdded(self._bundle_to_dict(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
|
_instance = None
|
||||||
|
|
||||||
def get_instance():
|
def get_instance():
|
||||||
|
@ -73,11 +73,16 @@ class _ServiceManager(object):
|
|||||||
util.write_service(bundle.get_service_name(),
|
util.write_service(bundle.get_service_name(),
|
||||||
bundle.get_command(), self._path)
|
bundle.get_command(), self._path)
|
||||||
|
|
||||||
|
def remove(self, bundle):
|
||||||
|
util.delete_service(bundle.get_service_name(), self._path)
|
||||||
|
|
||||||
class BundleRegistry(gobject.GObject):
|
class BundleRegistry(gobject.GObject):
|
||||||
"""Service that tracks the available activity bundles"""
|
"""Service that tracks the available activity bundles"""
|
||||||
|
|
||||||
__gsignals__ = {
|
__gsignals__ = {
|
||||||
'bundle-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
'bundle-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||||
|
([gobject.TYPE_PYOBJECT])),
|
||||||
|
'bundle-removed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||||
([gobject.TYPE_PYOBJECT]))
|
([gobject.TYPE_PYOBJECT]))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,6 +138,15 @@ class BundleRegistry(gobject.GObject):
|
|||||||
self.emit('bundle-added', bundle)
|
self.emit('bundle-added', bundle)
|
||||||
return True
|
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):
|
def get_activities_for_type(self, mime_type):
|
||||||
result = []
|
result = []
|
||||||
for bundle in self._bundles:
|
for bundle in self._bundles:
|
||||||
|
@ -65,6 +65,7 @@ class ActivitiesTray(hippo.CanvasBox):
|
|||||||
registry.get_activities_async(reply_handler=self._get_activities_cb)
|
registry.get_activities_async(reply_handler=self._get_activities_cb)
|
||||||
|
|
||||||
registry.connect('activity-added', self._activity_added_cb)
|
registry.connect('activity-added', self._activity_added_cb)
|
||||||
|
registry.connect('activity-removed', self._activity_removed_cb)
|
||||||
|
|
||||||
for invite in self._invites:
|
for invite in self._invites:
|
||||||
self.add_invite(invite)
|
self.add_invite(invite)
|
||||||
@ -120,16 +121,22 @@ class ActivitiesTray(hippo.CanvasBox):
|
|||||||
def _invite_removed_cb(self, invites, invite):
|
def _invite_removed_cb(self, invites, invite):
|
||||||
self.remove_invite(invite)
|
self.remove_invite(invite)
|
||||||
|
|
||||||
def _activity_removed_cb(self, item):
|
def _remove_activity_cb(self, item):
|
||||||
self._tray.remove_item(item)
|
self._tray.remove_item(item)
|
||||||
|
|
||||||
def _activity_added_cb(self, activity_registry, activity_info):
|
def _activity_added_cb(self, activity_registry, activity_info):
|
||||||
self.add_activity(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):
|
def add_activity(self, activity_info):
|
||||||
item = ActivityButton(activity_info)
|
item = ActivityButton(activity_info)
|
||||||
item.connect('clicked', self._activity_clicked_cb)
|
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)
|
self._tray.add_item(item, -1)
|
||||||
item.show()
|
item.show()
|
||||||
|
|
||||||
|
@ -43,6 +43,8 @@ class ActivityInfo(object):
|
|||||||
class ActivityRegistry(gobject.GObject):
|
class ActivityRegistry(gobject.GObject):
|
||||||
__gsignals__ = {
|
__gsignals__ = {
|
||||||
'activity-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
'activity-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||||
|
([gobject.TYPE_PYOBJECT])),
|
||||||
|
'activity-removed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||||
([gobject.TYPE_PYOBJECT]))
|
([gobject.TYPE_PYOBJECT]))
|
||||||
}
|
}
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@ -60,6 +62,7 @@ class ActivityRegistry(gobject.GObject):
|
|||||||
follow_name_owner_changes = True)
|
follow_name_owner_changes = True)
|
||||||
self._registry = dbus.Interface(bus_object, _ACTIVITY_REGISTRY_IFACE)
|
self._registry = dbus.Interface(bus_object, _ACTIVITY_REGISTRY_IFACE)
|
||||||
self._registry.connect_to_signal('ActivityAdded', self._activity_added_cb)
|
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.
|
# Two caches fo saving some travel across dbus.
|
||||||
self._service_name_to_activity_info = {}
|
self._service_name_to_activity_info = {}
|
||||||
@ -133,6 +136,15 @@ class ActivityRegistry(gobject.GObject):
|
|||||||
self._mime_type_to_activities.clear()
|
self._mime_type_to_activities.clear()
|
||||||
self.emit('activity-added', _activity_info_from_dict(info_dict))
|
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
|
_registry = None
|
||||||
|
|
||||||
def get_registry():
|
def get_registry():
|
||||||
|
@ -252,8 +252,13 @@ class ActivityBundle(Bundle):
|
|||||||
raise RegistrationException
|
raise RegistrationException
|
||||||
|
|
||||||
def uninstall(self):
|
def uninstall(self):
|
||||||
|
if self._unpacked:
|
||||||
|
install_path = self._path
|
||||||
|
else:
|
||||||
if not self.is_installed():
|
if not self.is_installed():
|
||||||
raise NotInstalledException
|
raise NotInstalledException
|
||||||
|
install_path = os.path.join(env.get_user_activities_path(),
|
||||||
|
self._zip_root_dir)
|
||||||
|
|
||||||
xdg_data_home = os.getenv('XDG_DATA_HOME', os.path.expanduser('~/.local/share'))
|
xdg_data_home = os.getenv('XDG_DATA_HOME', os.path.expanduser('~/.local/share'))
|
||||||
|
|
||||||
@ -271,10 +276,11 @@ class ActivityBundle(Bundle):
|
|||||||
for file in os.listdir(installed_icons_dir):
|
for file in os.listdir(installed_icons_dir):
|
||||||
path = os.path.join(installed_icons_dir, file)
|
path = os.path.join(installed_icons_dir, file)
|
||||||
if os.path.islink(path) and \
|
if os.path.islink(path) and \
|
||||||
os.readlink(path).startswith(self._path):
|
os.readlink(path).startswith(install_path):
|
||||||
os.remove(path)
|
os.remove(path)
|
||||||
|
|
||||||
self._uninstall()
|
self._uninstall(install_path)
|
||||||
|
|
||||||
# FIXME: notify shell
|
if not activity.get_registry().remove_bundle(install_path):
|
||||||
|
raise RegistrationException
|
||||||
|
|
||||||
|
@ -130,19 +130,17 @@ class Bundle:
|
|||||||
zip.write(filename, os.path.join(base_dir, filename))
|
zip.write(filename, os.path.join(base_dir, filename))
|
||||||
zip.close()
|
zip.close()
|
||||||
|
|
||||||
def _uninstall(self):
|
def _uninstall(self, install_path):
|
||||||
ext = os.path.splitext(self._path)[1]
|
if not os.path.isdir(install_path):
|
||||||
if self._unpacked:
|
|
||||||
if not os.path.isdir(self._path) or ext != self._unzipped_extension:
|
|
||||||
raise InvalidPathException
|
raise InvalidPathException
|
||||||
for root, dirs, files in os.walk(self._path, topdown=False):
|
if self._unzipped_extension is not None:
|
||||||
|
ext = os.path.splitext(install_path)[1]
|
||||||
|
if ext != self._unzipped_extension:
|
||||||
|
raise InvalidPathException
|
||||||
|
|
||||||
|
for root, dirs, files in os.walk(install_path, topdown=False):
|
||||||
for name in files:
|
for name in files:
|
||||||
os.remove(os.path.join(root, name))
|
os.remove(os.path.join(root, name))
|
||||||
for name in dirs:
|
for name in dirs:
|
||||||
os.rmdir(os.path.join(root, name))
|
os.rmdir(os.path.join(root, name))
|
||||||
os.rmdir(self._path)
|
os.rmdir(install_path)
|
||||||
else:
|
|
||||||
if not os.path.isfile(self._path) or ext != self._zipped_extension:
|
|
||||||
raise InvalidPathException
|
|
||||||
os.remove(self._path)
|
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ from ConfigParser import ConfigParser
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
from sugar import env
|
from sugar import env
|
||||||
from sugar.bundle.bundle import Bundle
|
from sugar.bundle.bundle import Bundle, NotInstalledException
|
||||||
|
|
||||||
class ContentBundle(Bundle):
|
class ContentBundle(Bundle):
|
||||||
"""A Sugar content bundle
|
"""A Sugar content bundle
|
||||||
@ -178,5 +178,12 @@ class ContentBundle(Bundle):
|
|||||||
self._run_indexer()
|
self._run_indexer()
|
||||||
|
|
||||||
def uninstall(self):
|
def uninstall(self):
|
||||||
self._uninstall()
|
if self._unpacked:
|
||||||
|
if not self.is_installed():
|
||||||
|
raise NotInstalledException
|
||||||
|
install_dir = self._path
|
||||||
|
else:
|
||||||
|
install_dir = os.path.join(env.get_user_library_path(),
|
||||||
|
self._zip_root_dir)
|
||||||
|
self._uninstall(install_dir)
|
||||||
self._run_indexer()
|
self._run_indexer()
|
||||||
|
@ -106,6 +106,20 @@ def write_service(name, bin, path):
|
|||||||
service_cp.write(fileobject)
|
service_cp.write(fileobject)
|
||||||
fileobject.close()
|
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):
|
def set_proc_title(title):
|
||||||
"""Sets the process title so ps and top show more
|
"""Sets the process title so ps and top show more
|
||||||
descriptive names. This does not modify argv[0]
|
descriptive names. This does not modify argv[0]
|
||||||
|
Loading…
Reference in New Issue
Block a user