[Sugar-devel] [sugar PATCH] sl#2818: Modifications in "favorite" status for activities in different workflows.

Ajay Garg ajay at activitycentral.com
Fri Mar 2 14:57:07 EST 2012


==============================================================================

Following scenarios have been tested :

1. Addition of new activity, via Software-Update ==>
   It should be shown as a favorite as default.

2. Addition of new activity, via Manual-Addition in "~/Activities"
   directory ==>
   It should be shown as a favorite as default.

3. Upgrade of an existing activity, via Software-Update  ==>
   The 'favorite-status' of the new-version activity, should be the same
   as the 'favorite-status' of the old-version activity.

4. Removal of an activity, via Manual-Deletion of ".activity" directory
   in "~/Activities" folder ==>
   The activity should be removed, so should be its "favoriteness", if
   at all.

5. An activity should maintain its "favoriteness" (or none of it) upon multiple reboots.


================================================================================

Another note :: 

Before applying this patch, I saw that there were multiple entries for the same activity
(but different versions) in "~/.sugar/default/favorite_activities" (I however, did not
note down the exact workflow as to when it happened).

Anyway, AFTER the applying of this patch, there is should be a maximum of one entry per 
activity in this file (and that happens, when the activity is designated as a favorite,
obviously !!)
=================================================================================

Signed-off-by: Ajay Garg <ajay at sugarlabs.org>
---
 src/jarabe/controlpanel/gui.py         |    1 +
 src/jarabe/controlpanel/sectionview.py |    4 +
 src/jarabe/desktop/activitieslist.py   |    6 +-
 src/jarabe/desktop/favoritesview.py    |   16 ++-
 src/jarabe/model/bundleregistry.py     |  159 +++++++++++++++++++++++++++-----
 5 files changed, 156 insertions(+), 30 deletions(-)

diff --git a/src/jarabe/controlpanel/gui.py b/src/jarabe/controlpanel/gui.py
index 0b70af6..9aeafe3 100644
--- a/src/jarabe/controlpanel/gui.py
+++ b/src/jarabe/controlpanel/gui.py
@@ -285,6 +285,7 @@ class ControlPanel(gtk.Window):
         return options
 
     def __cancel_clicked_cb(self, widget):
+        self._section_view.perform_cancel_actions()
         self._section_view.undo()
         self._options[self._current_option]['alerts'] = []
         self._section_toolbar.accept_button.set_sensitive(True)
diff --git a/src/jarabe/controlpanel/sectionview.py b/src/jarabe/controlpanel/sectionview.py
index 836adf4..397784d 100644
--- a/src/jarabe/controlpanel/sectionview.py
+++ b/src/jarabe/controlpanel/sectionview.py
@@ -53,6 +53,10 @@ class SectionView(gtk.VBox):
         """Undo here the changes that have been made in this section."""
         pass
 
+    def perform_cancel_actions(self):
+        """Perform additional actions, when the "Cancel" button is clicked."""
+        pass
+
     def perform_accept_actions(self):
         """Perform additional actions, when the "Ok" button is clicked."""
         pass
diff --git a/src/jarabe/desktop/activitieslist.py b/src/jarabe/desktop/activitieslist.py
index e34abd6..5f79090 100644
--- a/src/jarabe/desktop/activitieslist.py
+++ b/src/jarabe/desktop/activitieslist.py
@@ -135,7 +135,8 @@ class ActivitiesTreeView(gtk.TreeView):
         registry = bundleregistry.get_registry()
         registry.set_bundle_favorite(row[ListModel.COLUMN_BUNDLE_ID],
                                      row[ListModel.COLUMN_VERSION],
-                                     not row[ListModel.COLUMN_FAVORITE])
+                                     not row[ListModel.COLUMN_FAVORITE],
+                                     True)
 
     def __icon_clicked_cb(self, cell, path):
         row = self.get_model()[path]
@@ -447,7 +448,8 @@ class ActivityListPalette(ActivityPalette):
         registry = bundleregistry.get_registry()
         registry.set_bundle_favorite(self._bundle_id,
                                      self._version,
-                                     not self._favorite)
+                                     not self._favorite,
+                                     True)
 
     def __activity_changed_cb(self, activity_registry, activity_info):
         if activity_info.get_bundle_id() == self._bundle_id and \
diff --git a/src/jarabe/desktop/favoritesview.py b/src/jarabe/desktop/favoritesview.py
index e9c87ea..d91610b 100644
--- a/src/jarabe/desktop/favoritesview.py
+++ b/src/jarabe/desktop/favoritesview.py
@@ -142,11 +142,17 @@ class FavoritesView(hippo.Canvas):
     def _add_activity(self, activity_info):
         if activity_info.get_bundle_id() == 'org.laptop.JournalActivity':
             return
-        icon = ActivityIcon(activity_info)
-        icon.props.size = style.STANDARD_ICON_SIZE
-        icon.set_resume_mode(self._resume_mode)
-        self._box.insert_sorted(icon, 0, self._layout.compare_activities)
-        self._layout.append(icon)
+
+        # Add icon, if not already present (for the same combination of
+        # activity-id and activity-version)
+        icon = self._find_activity_icon(activity_info.get_bundle_id(),
+                                        activity_info.get_activity_version())
+        if icon is None:
+            icon = ActivityIcon(activity_info)
+            icon.props.size = style.STANDARD_ICON_SIZE
+            icon.set_resume_mode(self._resume_mode)
+            self._box.insert_sorted(icon, 0, self._layout.compare_activities)
+            self._layout.append(icon)
 
     def __activity_added_cb(self, activity_registry, activity_info):
         registry = bundleregistry.get_registry()
diff --git a/src/jarabe/model/bundleregistry.py b/src/jarabe/model/bundleregistry.py
index 26e719f..7594c01 100644
--- a/src/jarabe/model/bundleregistry.py
+++ b/src/jarabe/model/bundleregistry.py
@@ -59,14 +59,17 @@ class BundleRegistry(gobject.GObject):
         self._bundles = []
         # hold a reference to the monitors so they don't get disposed
         self._gio_monitors = []
+        self._monitor = {}
+        self._handler_id = {}
+        self._allow_file_monitoring = True
 
         user_path = env.get_user_activities_path()
         for activity_dir in [user_path, config.activities_path]:
             self._scan_directory(activity_dir)
             directory = gio.File(activity_dir)
-            monitor = directory.monitor_directory()
-            monitor.connect('changed', self.__file_monitor_changed_cb)
-            self._gio_monitors.append(monitor)
+            self._monitor = directory.monitor_directory()
+            self._handler_id = self._monitor.connect('changed', self.__file_monitor_changed_cb)
+            self._gio_monitors.append(self._monitor)
 
         self._last_defaults_mtime = -1
         self._favorite_bundles = {}
@@ -88,12 +91,31 @@ class BundleRegistry(gobject.GObject):
 
     def __file_monitor_changed_cb(self, monitor, one_file, other_file,
                                   event_type):
-        if not one_file.get_path().endswith('.activity'):
-            return
-        if event_type == gio.FILE_MONITOR_EVENT_CREATED:
-            self.add_bundle(one_file.get_path(), install_mime_type=True)
-        elif event_type == gio.FILE_MONITOR_EVENT_DELETED:
-            self.remove_bundle(one_file.get_path())
+        if self._allow_file_monitoring:
+            if not one_file.get_path().endswith('.activity'):
+                return
+            if event_type == gio.FILE_MONITOR_EVENT_CREATED:
+                if self.get_bundle_by_path(one_file.get_path()) is None:
+                    self.add_bundle(one_file.get_path(),install_mime_type=True)
+            elif event_type == gio.FILE_MONITOR_EVENT_DELETED:
+                self.remove_bundle(one_file.get_path())
+
+    # I tried 2 hours, trying to make the following mechanisms for
+    # event-blocking, work ::
+    #
+    # a. disconnect
+    # b. handler_disconnect
+    # c. handler_block/handler_unblock
+    # d. handler_block_by_func/handler_unblock_by_func
+    #
+    # I could not.
+    #
+    # In the end, I had to revert to using the oldy-goldy boolean flag.
+    def disable_directory_monitoring(self):
+        self._allow_file_monitoring = False
+
+    def enable_directory_monitoring(self):
+        self._allow_file_monitoring = True
 
     def _load_mime_defaults(self):
         defaults = {}
@@ -180,6 +202,12 @@ class BundleRegistry(gobject.GObject):
                 return bundle
         return None
 
+    def get_bundle_by_path(self, bundle_path):
+        for bundle in self._bundles:
+            if bundle.get_path() == bundle_path:
+                return bundle
+        return None
+
     def __iter__(self):
         return self._bundles.__iter__()
 
@@ -207,7 +235,13 @@ class BundleRegistry(gobject.GObject):
         bundle_dirs.sort(lambda d1, d2: cmp(bundles[d1], bundles[d2]))
         for folder in bundle_dirs:
             try:
-                self._add_bundle(folder)
+                # sl#2818
+                #
+                # Add meta-info, to indicate that this is a startup
+                # operation.
+                #
+                # See 'elif not startup' notes in 'self._add_bundle()'
+                self._add_bundle(folder, False, True)
             except:
                 # pylint: disable=W0702
                 logging.exception('Error while processing installed activity'
@@ -216,15 +250,13 @@ class BundleRegistry(gobject.GObject):
     def add_bundle(self, bundle_path, install_mime_type=False):
         bundle = self._add_bundle(bundle_path, install_mime_type)
         if bundle is not None:
-            self._set_bundle_favorite(bundle.get_bundle_id(),
-                                      bundle.get_activity_version(),
-                                      True)
             self.emit('bundle-added', bundle)
             return True
         else:
             return False
 
-    def _add_bundle(self, bundle_path, install_mime_type=False):
+    def _add_bundle(self, bundle_path, install_mime_type=False,
+                    startup=False):
         logging.debug('STARTUP: Adding bundle %r', bundle_path)
         try:
             bundle = ActivityBundle(bundle_path)
@@ -244,17 +276,92 @@ class BundleRegistry(gobject.GObject):
                 return None
             else:
                 logging.debug('Upgrade %s', bundle_id)
+
+                # Query if the bundle is a favorite...
+                self._is_bundle_favorite = \
+                        self.is_bundle_favorite(installed.get_bundle_id(),
+                                                installed.get_activity_version())
+
+                # ...and then, remove the old bundle (we have the new
+                #    one !!)
                 self.remove_bundle(installed.get_path())
 
-        self._bundles.append(bundle)
+                # Check, if this bundle-id is a favorite.
+                if self._is_bundle_favorite:
+
+                    # Mark the (new) bundle with this bundle-id, as
+                    # favorite.
+                    self.set_bundle_favorite(bundle.get_bundle_id(),
+                                             bundle.get_activity_version(),
+                                             True,
+                                             True)
+
+                    # This (new) bundle is new (!!), and is also a
+                    # favorite. Add this to Favorites-View.
+                    self.emit('bundle-added', bundle)
+
+        elif not startup:
+
+            # Ticket sl#2818
+
+            # Sub-case
+            # --------
+            #       The bundle is newly added; so set it as favorite as
+            #       default, so that it is promptly available to the
+            #       user.
+            #       Note that, any newly added bundles during system
+            #       startup, are not new-bundles-as-such. They were
+            #       new, when they were first added, and their
+            #       favorite-status set at that time.
+            #       However, from code point of view, control reaches
+            #       here, only if the bundle IS newly added by
+            #       user-discretion.
+            self.set_bundle_favorite(bundle.get_bundle_id(),
+                                     bundle.get_activity_version(),
+                                     True,
+                                     True)
+
+            # Emit 'bundle-added' (of course, this bundle is new !!),
+            # so that it is added in Favorites-View.
+            self.emit('bundle-added', bundle)
+
+
+        # In either case,
+        #            a. Startup
+        #            b. Upgrade of bundle
+        #            c, Addition of new bundle, by user-discretion.
+        # add the bundle to bundles-list.
+        self.add_bundle_to_bundlelist(bundle)
         return bundle
 
+    def add_bundle_to_bundlelist(self, bundle):
+        for bundle_in_list in self._bundles:
+            if bundle_in_list.get_path() == \
+               bundle.get_path():
+                return False
+
+        self._bundles.append(bundle)
+        return True
+
     def remove_bundle(self, bundle_path):
         for bundle in self._bundles:
             if bundle.get_path() == bundle_path:
+
+                # This bundle is going.
+                # Remove it from bundles list...
                 self._bundles.remove(bundle)
+
+                # ... and remove it from Favorites-List...
+                self.set_bundle_favorite(bundle.get_bundle_id(),
+                                         bundle.get_activity_version(),
+                                         False,
+                                         True)
+
+                # ...and remove its trace from Favorites-View.
                 self.emit('bundle-removed', bundle)
+
                 return True
+
         return False
 
     def get_activities_for_type(self, mime_type):
@@ -287,14 +394,22 @@ class BundleRegistry(gobject.GObject):
             if bundle.get_bundle_id() == bundle_id and \
                     bundle.get_activity_version() == version:
                 return bundle
-        raise ValueError('No bundle %r with version %r exists.' % \
-                (bundle_id, version))
+        return None
+
+    def set_bundle_favorite(self, bundle_id, version, favorite,
+                            force=False):
+        # Return if file monitoring is not allowed, and the previous
+        # bundle is not a favorite.
+        if not force:
+            if not self._allow_file_monitoring:
+                if not self._is_bundle_favorite:
+                    return
 
-    def set_bundle_favorite(self, bundle_id, version, favorite):
         changed = self._set_bundle_favorite(bundle_id, version, favorite)
         if changed:
             bundle = self._find_bundle(bundle_id, version)
-            self.emit('bundle-changed', bundle)
+            if bundle is not None:
+                self.emit('bundle-changed', bundle)
 
     def _set_bundle_favorite(self, bundle_id, version, favorite):
         key = self._get_favorite_key(bundle_id, version)
@@ -331,7 +446,8 @@ class BundleRegistry(gobject.GObject):
 
         self._write_favorites_file()
         bundle = self._find_bundle(bundle_id, version)
-        self.emit('bundle-changed', bundle)
+        if bundle is not None:
+            self.emit('bundle-changed', bundle)
 
     def get_bundle_position(self, bundle_id, version):
         """Get the coordinates where the user wants the representation of this
@@ -420,9 +536,6 @@ class BundleRegistry(gobject.GObject):
 
         bundle.uninstall(install_path, force, delete_profile)
 
-        if not self.remove_bundle(install_path):
-            raise RegistrationException
-
     def upgrade(self, bundle):
         act = self.get_bundle(bundle.get_bundle_id())
         if act is None:
-- 
1.7.4.4



More information about the Sugar-devel mailing list