diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/sugar/activity/activity.py | 10 | ||||
-rw-r--r-- | lib/sugar/activity/activityfactory.py | 2 | ||||
-rw-r--r-- | lib/sugar/activity/registry.py | 10 | ||||
-rw-r--r-- | lib/sugar/bundle/activitybundle.py | 42 | ||||
-rw-r--r-- | lib/sugar/datastore/datastore.py | 6 | ||||
-rw-r--r-- | lib/sugar/graphics/icon.py | 61 |
6 files changed, 112 insertions, 19 deletions
diff --git a/lib/sugar/activity/activity.py b/lib/sugar/activity/activity.py index 7c44981..96e757a 100644 --- a/lib/sugar/activity/activity.py +++ b/lib/sugar/activity/activity.py @@ -76,6 +76,10 @@ SCOPE_PRIVATE = "private" SCOPE_INVITE_ONLY = "invite" # shouldn't be shown in UI, it's implicit when you invite somebody SCOPE_NEIGHBORHOOD = "public" +J_DBUS_SERVICE = 'org.laptop.Journal' +J_DBUS_PATH = '/org/laptop/Journal' +J_DBUS_INTERFACE = 'org.laptop.Journal' + class ActivityToolbar(gtk.Toolbar): """The Activity toolbar with the Journal entry title, sharing, Keep and Stop buttons @@ -905,3 +909,9 @@ def get_activity_root(): return os.environ['SUGAR_ACTIVITY_ROOT'] else: raise RuntimeError("No SUGAR_ACTIVITY_ROOT set.") + +def show_object_in_journal(object_id): + bus = dbus.SessionBus() + obj = bus.get_object(J_DBUS_SERVICE, J_DBUS_PATH) + journal = dbus.Interface(obj, J_DBUS_INTERFACE) + journal.ShowObject(object_id) diff --git a/lib/sugar/activity/activityfactory.py b/lib/sugar/activity/activityfactory.py index 119dcea..835ec13 100644 --- a/lib/sugar/activity/activityfactory.py +++ b/lib/sugar/activity/activityfactory.py @@ -270,7 +270,7 @@ class ActivityCreationHandler(gobject.GObject): def _activate_error_handler(self, err): logging.error("Activity activation request failed %s" % err) - def _create_reply_handler(self, xid): + def _create_reply_handler(self): logging.debug("Activity created %s (%s)." % (self._handle.activity_id, self._service_name)) diff --git a/lib/sugar/activity/registry.py b/lib/sugar/activity/registry.py index c21d4a5..ac672d5 100644 --- a/lib/sugar/activity/registry.py +++ b/lib/sugar/activity/registry.py @@ -29,15 +29,17 @@ def _activity_info_from_dict(info_dict): if not info_dict: return None return ActivityInfo(info_dict['name'], info_dict['icon'], - info_dict['bundle_id'], info_dict['path'], - info_dict['show_launcher'], info_dict['command']) + info_dict['bundle_id'], info_dict['version'], + info_dict['path'], info_dict['show_launcher'], + info_dict['command']) class ActivityInfo(object): - def __init__(self, name, icon, bundle_id, + def __init__(self, name, icon, bundle_id, version, path, show_launcher, command): self.name = name self.icon = icon self.bundle_id = bundle_id + self.version = version self.path = path self.command = command self.show_launcher = show_launcher @@ -146,6 +148,8 @@ class ActivityRegistry(gobject.GObject): self._mime_type_to_activities.clear() def remove_bundle(self, bundle_path): + self._service_name_to_activity_info.clear() + self._mime_type_to_activities.clear() return self._registry.RemoveBundle(bundle_path) def _activity_removed_cb(self, info_dict): diff --git a/lib/sugar/bundle/activitybundle.py b/lib/sugar/bundle/activitybundle.py index ce1510f..ee72f80 100644 --- a/lib/sugar/bundle/activitybundle.py +++ b/lib/sugar/bundle/activitybundle.py @@ -22,10 +22,15 @@ import locale import os import tempfile -from sugar.bundle.bundle import Bundle, MalformedBundleException +from sugar.bundle.bundle import Bundle, MalformedBundleException, \ + AlreadyInstalledException, RegistrationException, \ + NotInstalledException + from sugar import activity from sugar import env +import logging + class ActivityBundle(Bundle): """A Sugar activity bundle @@ -204,8 +209,16 @@ class ActivityBundle(Bundle): else: return False + def need_upgrade(self): + act = activity.get_registry().get_activity(self._bundle_id) + if act is None or act.version != self._activity_version: + return True + else: + return False + def install(self): - if self.is_installed(): + act = activity.get_registry().get_activity(self._bundle_id) + if act is not None and act.path.startswith(env.get_user_activities_path()): raise AlreadyInstalledException install_dir = env.get_user_activities_path() @@ -250,12 +263,21 @@ class ActivityBundle(Bundle): if not activity.get_registry().add_bundle(install_path): raise RegistrationException - def uninstall(self): + def uninstall(self, force=False): if self._unpacked: install_path = self._path else: if not self.is_installed(): raise NotInstalledException + + act = activity.get_registry().get_activity(self._bundle_id) + if not force and act.version != self._activity_version: + logging.warning('Not uninstalling because different bundle present') + return + elif not act.path.startswith(env.get_user_activities_path()): + logging.warning('Not uninstalling system activity') + return + install_path = os.path.join(env.get_user_activities_path(), self._zip_root_dir) @@ -283,3 +305,17 @@ class ActivityBundle(Bundle): if not activity.get_registry().remove_bundle(install_path): raise RegistrationException + def upgrade(self): + act = activity.get_registry().get_activity(self._bundle_id) + if act is None: + logging.warning('Activity not installed') + elif act.path.startswith(env.get_user_activities_path()): + try: + self.uninstall(force=True) + except Exception, e: + logging.warning('Uninstall failed (%s), still trying to install newer bundle', e) + else: + logging.warning('Unable to uninstall system activity, installing upgraded version in user activities') + + self.install() + diff --git a/lib/sugar/datastore/datastore.py b/lib/sugar/datastore/datastore.py index 5238d18..334c866 100644 --- a/lib/sugar/datastore/datastore.py +++ b/lib/sugar/datastore/datastore.py @@ -160,10 +160,16 @@ class DSObject(object): if bundle_id is not None: raise ValueError('Object is a bundle, cannot be resumed as an activity.') + logging.debug('Creating activity bundle') bundle = ActivityBundle(self.file_path) if not bundle.is_installed(): + logging.debug('Installing activity bundle') bundle.install() + elif bundle.need_upgrade(): + logging.debug('Upgrading activity bundle') + bundle.upgrade() + logging.debug('activityfactory.creating bundle with id %r', bundle.get_bundle_id()) activityfactory.create(bundle.get_bundle_id()) else: if not self.get_activities() and bundle_id is None: diff --git a/lib/sugar/graphics/icon.py b/lib/sugar/graphics/icon.py index 2f88f5e..a739341 100644 --- a/lib/sugar/graphics/icon.py +++ b/lib/sugar/graphics/icon.py @@ -88,9 +88,10 @@ class _IconBuffer(object): self.cache = False self.scale = 1.0 - def _get_cache_key(self): + def _get_cache_key(self, sensitive): return (self.icon_name, self.file_name, self.fill_color, - self.stroke_color, self.badge_name, self.width, self.height) + self.stroke_color, self.badge_name, self.width, self.height, + sensitive) def _load_svg(self, file_name): entities = {} @@ -139,19 +140,22 @@ class _IconBuffer(object): return icon_info - def _draw_badge(self, context, size): + def _draw_badge(self, context, size, sensitive, widget): theme = gtk.icon_theme_get_default() badge_info = theme.lookup_icon(self.badge_name, size, 0) if badge_info: badge_file_name = badge_info.get_filename() if badge_file_name.endswith('.svg'): handle = self._loader.load(badge_file_name, {}, self.cache) - handle.render_cairo(context) + pixbuf = handle.get_pixbuf() else: pixbuf = gtk.gdk.pixbuf_new_from_file(badge_file_name) - surface = hippo.cairo_surface_from_gdk_pixbuf(pixbuf) - context.set_source_surface(surface, 0, 0) - context.paint() + + if not sensitive: + pixbuf = self._get_insensitive_pixbuf(pixbuf, widget) + surface = hippo.cairo_surface_from_gdk_pixbuf(pixbuf) + context.set_source_surface(surface, 0, 0) + context.paint() def _get_size(self, icon_width, icon_height, padding): if self.width is not None and self.height is not None: @@ -196,8 +200,30 @@ class _IconBuffer(object): self.stroke_color = None self.fill_color = None - def get_surface(self): - cache_key = self._get_cache_key() + def _get_insensitive_pixbuf (self, pixbuf, widget): + if not (widget and widget.style): + return pixbuf + + icon_source = gtk.IconSource() + # Special size meaning "don't touch" + icon_source.set_size(-1) + icon_source.set_pixbuf(pixbuf) + icon_source.set_state(gtk.STATE_INSENSITIVE) + icon_source.set_direction_wildcarded(False) + icon_source.set_size_wildcarded(False) + + # Please note that the pixbuf returned by this function is leaked + # with current stable versions of pygtk. The relevant bug is + # http://bugzilla.gnome.org/show_bug.cgi?id=502871 + # -- 2007-12-14 Benjamin Berg + pixbuf = widget.style.render_icon(icon_source, widget.get_direction(), + gtk.STATE_INSENSITIVE, -1, widget, + "sugar-icon") + + return pixbuf + + def get_surface(self, sensitive=True, widget=None): + cache_key = self._get_cache_key(sensitive) if cache_key in self._surface_cache: return self._surface_cache[cache_key] @@ -230,8 +256,18 @@ class _IconBuffer(object): context.translate(padding, padding) if is_svg: - handle.render_cairo(context) + if sensitive: + handle.render_cairo(context) + else: + pixbuf = handle.get_pixbuf() + pixbuf = self._get_insensitive_pixbuf(pixbuf, widget) + + pixbuf_surface = hippo.cairo_surface_from_gdk_pixbuf(pixbuf) + context.set_source_surface(pixbuf_surface, 0, 0) + context.paint() else: + if not sensitive: + pixbuf = self._get_insensitive_pixbuf(pixbuf, widget) pixbuf_surface = hippo.cairo_surface_from_gdk_pixbuf(pixbuf) context.set_source_surface(pixbuf_surface, 0, 0) context.paint() @@ -239,7 +275,7 @@ class _IconBuffer(object): if self.badge_name: context.restore() context.translate(badge_info.attach_x, badge_info.attach_y) - self._draw_badge(context, badge_info.size) + self._draw_badge(context, badge_info.size, sensitive, widget) self._surface_cache[cache_key] = surface @@ -307,7 +343,8 @@ class Icon(gtk.Image): def do_expose_event(self, event): self._sync_image_properties() - surface = self._buffer.get_surface() + sensitive = (self.state != gtk.STATE_INSENSITIVE) + surface = self._buffer.get_surface(sensitive, self) if surface is None: return |