Hi,

these two patches are the continuation of the work to implement a new
favorites screen in the home view.

Thanks,

Tomeu
From 40bdb87d43d0644edf62e1e727b6e936ccf7b00d Mon Sep 17 00:00:00 2001
From: Tomeu Vizoso <[EMAIL PROTECTED](none)>
Date: Wed, 11 Jun 2008 17:38:17 +0200
Subject: [PATCH] Persist position of favorite icons

---
 service/activityregistryservice.py |   12 ++++-
 service/bundleregistry.py          |  106 ++++++++++++++++++++++++++----------
 src/view/home/activitiesring.py    |   36 ++++++++++---
 3 files changed, 117 insertions(+), 37 deletions(-)

diff --git a/service/activityregistryservice.py b/service/activityregistryservice.py
index bf98ef9..a42eae0 100644
--- a/service/activityregistryservice.py
+++ b/service/activityregistryservice.py
@@ -109,6 +109,12 @@ class ActivityRegistry(dbus.service.Object):
         registry = bundleregistry.get_registry()
         registry.set_bundle_favorite(bundle_id, version, favorite)
 
+    @dbus.service.method(_ACTIVITY_REGISTRY_IFACE,
+                         in_signature='siii', out_signature='')
+    def SetActivityPosition(self, bundle_id, version, x, y):
+        registry = bundleregistry.get_registry()
+        registry.set_bundle_position(bundle_id, version, x, y)
+
     @dbus.service.signal(_ACTIVITY_REGISTRY_IFACE, signature='a{sv}')
     def ActivityAdded(self, activity_info):
         pass
@@ -125,6 +131,8 @@ class ActivityRegistry(dbus.service.Object):
         registry = bundleregistry.get_registry()
         favorite = registry.is_bundle_favorite(bundle.get_bundle_id(),
                                                bundle.get_activity_version())
+        x, y = registry.get_bundle_position(bundle.get_bundle_id(),
+                                            bundle.get_activity_version())
         return {'name': bundle.get_name(),
                 'icon': bundle.get_icon(),
                 'bundle_id': bundle.get_bundle_id(),
@@ -133,7 +141,9 @@ class ActivityRegistry(dbus.service.Object):
                 'command': bundle.get_command(),
                 'show_launcher': bundle.get_show_launcher(),
                 'favorite': favorite,
-                'installation_time': bundle.get_installation_time()}
+                'installation_time': bundle.get_installation_time(),
+                'position_x': x,
+                'position_y': y}
 
     def _bundle_added_cb(self, bundle_registry, bundle):
         self.ActivityAdded(self._bundle_to_dict(bundle))
diff --git a/service/bundleregistry.py b/service/bundleregistry.py
index 8b7f09b..e7c30a8 100644
--- a/service/bundleregistry.py
+++ b/service/bundleregistry.py
@@ -16,6 +16,7 @@
 
 import os
 import logging
+import traceback
 
 import gobject
 import simplejson
@@ -48,7 +49,14 @@ class BundleRegistry(gobject.GObject):
             self._scan_directory(activity_dir)
 
         self._last_defaults_mtime = -1
-        self._favorite_bundles = self._load_favorites()
+        self._favorite_bundles = {}
+
+        try:
+            self._load_favorites()
+        except Exception, e:
+            logging.error('Error while loading favorite_activities\n%s.' \
+                    % traceback.format_exc())
+
         self._merge_default_favorites()
 
     def _get_activity_directories(self):
@@ -74,24 +82,34 @@ class BundleRegistry(gobject.GObject):
 
         return defaults
 
+    def _get_favorite_key(self, bundle_id, version):
+        """We use a string as a composite key for the favorites dictionary
+        because JSON doesn't support tuples and python won't accept a list
+        as a dictionary key.
+        """
+        if ' ' in bundle_id:
+            raise ValueError('bundle_id cannot contain spaces')
+        return '%s %s' % (bundle_id, version)
+
     def _load_favorites(self):
-        favorite_bundles = []
         favorites_path = env.get_profile_path('favorite_activities')
         if os.path.exists(favorites_path):
-            try:
-                favorites_data = simplejson.load(open(favorites_path))
-            except ValueError, e:
-                logging.error('Error while loading favorite_activities: %r.' %
-                              e)
-            else:
-                # Old structure used to be a list, instead of a dictionary.
-                if isinstance(favorites_data, list):
-                    favorite_bundles = favorites_data
-                else:
-                    favorite_bundles = favorites_data['favorites']
-                    self._last_defaults_mtime = favorites_data['defaults-mtime']
+            favorites_data = simplejson.load(open(favorites_path))
+
+            favorite_bundles = favorites_data['favorites']
+            if not isinstance(favorite_bundles, dict):
+                raise ValueError('Invalid format in %s.' % favorites_path)
+            if favorite_bundles:
+                first_key = favorite_bundles.keys()[0]
+                if not isinstance(first_key, basestring):
+                    raise ValueError('Invalid format in %s.' % favorites_path)
 
-        return favorite_bundles
+                first_value = favorite_bundles.values()[0]
+                if first_value is not None and not isinstance(first_value, dict):
+                    raise ValueError('Invalid format in %s.' % favorites_path)
+
+            self._last_defaults_mtime = float(favorites_data['defaults-mtime'])
+            self._favorite_bundles = favorite_bundles
 
     def _merge_default_favorites(self):
         default_activities = []
@@ -117,9 +135,9 @@ class BundleRegistry(gobject.GObject):
                         max_version < bundle.get_activity_version():
                     max_version = bundle.get_activity_version()
 
-            if max_version > -1 and \
-                    [bundle_id, max_version] not in self._favorite_bundles:
-                self._favorite_bundles.append([bundle_id, max_version])
+            key = self._get_favorite_key(bundle_id, max_version)
+            if max_version > -1 and key not in self._favorite_bundles:
+                self._favorite_bundles[key] = None
 
         logging.debug('After merging: %r' % self._favorite_bundles)
 
@@ -205,24 +223,56 @@ class BundleRegistry(gobject.GObject):
                 (bundle_id, version))
 
     def set_bundle_favorite(self, bundle_id, version, favorite):
+        key = self._get_favorite_key(bundle_id, version)
+        if favorite and not key in self._favorite_bundles:
+            self._favorite_bundles[key] = None
+        elif not favorite and key in self._favorite_bundles:
+            del self._favorite_bundles[key]
+        else:
+            return
+
+        self._write_favorites_file()
         bundle = self._find_bundle(bundle_id, version)
-        if favorite and not [bundle_id, version] in self._favorite_bundles:
-            self._favorite_bundles.append([bundle_id, version])
-            self.emit('bundle-changed', bundle)
-            self._write_favorites_file()
-        elif not favorite and [bundle_id, version] in self._favorite_bundles:
-            self._favorite_bundles.remove([bundle_id, version])
-            self.emit('bundle-changed', bundle)
-            self._write_favorites_file()
+        self.emit('bundle-changed', bundle)
 
     def is_bundle_favorite(self, bundle_id, version):
-        return [bundle_id, version] in self._favorite_bundles
+        key = self._get_favorite_key(bundle_id, version)
+        return key in self._favorite_bundles
+
+    def set_bundle_position(self, bundle_id, version, x, y):
+        key = self._get_favorite_key(bundle_id, version)
+        if key not in self._favorite_bundles:
+            raise ValueError('Bundle %s %s not favorite' % (bundle_id, version))
+
+        if self._favorite_bundles[key] is None:
+            self._favorite_bundles[key] = {}
+        if 'position' not in self._favorite_bundles[key] or \
+                [x, y] != self._favorite_bundles[key]['position']:
+            self._favorite_bundles[key]['position'] = [x, y]
+        else:
+            return
+
+        self._write_favorites_file()
+        bundle = self._find_bundle(bundle_id, version)
+        self.emit('bundle-changed', bundle)
+
+    def get_bundle_position(self, bundle_id, version):
+        """Get the coordinates where the user wants the representation of this
+        bundle to be displayed. Coordinates are relative to a 1000x1000 area.
+        """
+        key = self._get_favorite_key(bundle_id, version)
+        if key not in self._favorite_bundles or \
+                self._favorite_bundles[key] is None or \
+                'position' not in self._favorite_bundles[key]:
+            return (-1, -1)
+        else:
+            return tuple(self._favorite_bundles[key]['position'])
 
     def _write_favorites_file(self):
         path = env.get_profile_path('favorite_activities')
         favorites_data = {'defaults-mtime': self._last_defaults_mtime,
                           'favorites': self._favorite_bundles}
-        simplejson.dump(favorites_data, open(path, 'w'))
+        simplejson.dump(favorites_data, open(path, 'w'), indent=1)
 
 _instance = None
 
diff --git a/src/view/home/activitiesring.py b/src/view/home/activitiesring.py
index 5d66ec3..a250c1d 100644
--- a/src/view/home/activitiesring.py
+++ b/src/view/home/activitiesring.py
@@ -203,7 +203,9 @@ class ActivitiesRing(hippo.Canvas):
         icon_file_name = self._last_clicked_icon.props.file_name
         # TODO: we should get the pixbuf from the widget, so it has colors, etc
         pixbuf = gtk.gdk.pixbuf_new_from_file(icon_file_name)
-        context.set_icon_pixbuf(pixbuf, 0, 0)        
+        
+        hot_spot = style.zoom(10)
+        context.set_icon_pixbuf(pixbuf, hot_spot, hot_spot)
 
     def __drag_motion_cb(self, widget, context, x, y, time):
         if self._last_clicked_icon is not None:
@@ -266,6 +268,10 @@ class ActivityIcon(CanvasIcon):
         return self._activity_info.installation_time
     installation_time = property(_get_installation_time, None)
 
+    def _get_fixed_position(self):
+        return self._activity_info.position
+    fixed_position = property(_get_fixed_position, None)
+
 class CurrentActivityIcon(CanvasIcon, hippo.CanvasItem):
     def __init__(self):
         CanvasIcon.__init__(self, cache=True)
@@ -389,18 +395,32 @@ class RingLayout(gobject.GObject, hippo.CanvasLayout):
         else:
             return 0
 
-    def append(self, child):
-        self._box.insert_sorted(child, 0, self._compare_activities)
+    def append(self, icon):
+        self._box.insert_sorted(icon, 0, self._compare_activities)
+        relative_x, relative_y = icon.fixed_position
+        if relative_x >= 0 and relative_y >= 0:
+            width = gtk.gdk.screen_width()
+            height = gtk.gdk.screen_height() - style.GRID_CELL_SIZE
+            self._fixed_positions[icon] = (relative_x * 1000 / width,
+                                           relative_y * 1000 / height)
         self._update_icon_sizes()
 
-    def remove(self, child):
-        self._box.remove(child)
+    def remove(self, icon):
+        del self._fixed_positions[icon]
+        self._box.remove(icon)
         self._update_icon_sizes()
 
-    def move_icon(self, child, x, y):
-        if child not in self._box.get_children():
+    def move_icon(self, icon, x, y):
+        if icon not in self._box.get_children():
             raise ValueError('Child not in box.')
-        self._fixed_positions[child] = (x, y)
+
+        width = gtk.gdk.screen_width()
+        height = gtk.gdk.screen_height() - style.GRID_CELL_SIZE
+        registry = activity.get_registry()
+        registry.set_activity_position(icon.get_bundle_id(), icon.get_version(),
+                                       x * width / 1000, y * height / 1000)
+
+        self._fixed_positions[icon] = (x, y)
         self._box.emit_request_changed()
 
     def do_allocate(self, x, y, width, height, req_width, req_height,
-- 
1.5.4.3

From 2d9979ce907296ce2f13bfdfb064d4d9dd1c37df Mon Sep 17 00:00:00 2001
From: Tomeu Vizoso <[EMAIL PROTECTED](none)>
Date: Wed, 11 Jun 2008 17:41:58 +0200
Subject: [PATCH] Add a position attribute to registered activity bundles.

---
 src/sugar/activity/registry.py |    9 +++++++--
 1 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/src/sugar/activity/registry.py b/src/sugar/activity/registry.py
index d5d0529..da2eb27 100644
--- a/src/sugar/activity/registry.py
+++ b/src/sugar/activity/registry.py
@@ -32,11 +32,12 @@ def _activity_info_from_dict(info_dict):
                         info_dict['bundle_id'], info_dict['version'],
                         info_dict['path'], info_dict['show_launcher'],
                         info_dict['command'], info_dict['favorite'],
-                        info_dict['installation_time'])
+                        info_dict['installation_time'],
+                        info_dict['position_x'], info_dict['position_y'])
 
 class ActivityInfo(object):
     def __init__(self, name, icon, bundle_id, version, path, show_launcher,
-                 command, favorite, installation_time):
+                 command, favorite, installation_time, position_x, position_y):
         self.name = name
         self.icon = icon
         self.bundle_id = bundle_id
@@ -46,6 +47,7 @@ class ActivityInfo(object):
         self.show_launcher = show_launcher
         self.favorite = favorite
         self.installation_time = installation_time
+        self.position = (position_x, position_y)
 
 class ActivityRegistry(gobject.GObject):
     __gsignals__ = {
@@ -175,6 +177,9 @@ class ActivityRegistry(gobject.GObject):
     def set_activity_favorite(self, bundle_id, version, favorite):
         self._registry.SetActivityFavorite(bundle_id, version, favorite)
 
+    def set_activity_position(self, bundle_id, version, x, y):
+        self._registry.SetActivityPosition(bundle_id, version, x, y)
+
 _registry = None
 
 def get_registry():
-- 
1.5.4.3

_______________________________________________
Sugar mailing list
Sugar@lists.laptop.org
http://lists.laptop.org/listinfo/sugar

Reply via email to