[gnome-shell] Cache applications for a menu



commit 2f2df6109304fb4c34de0dd7c9c16bde534b52cd
Author: Colin Walters <walters verbum org>
Date:   Fri Oct 2 19:02:14 2009 -0400

    Cache applications for a menu
    
    Rather than recomputing this each time someone asks, have a
    cache of the apps for a given menu.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=597167

 src/shell-app-system.c |   49 ++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 37 insertions(+), 12 deletions(-)
---
diff --git a/src/shell-app-system.c b/src/shell-app-system.c
index 84804ba..610b24a 100644
--- a/src/shell-app-system.c
+++ b/src/shell-app-system.c
@@ -45,6 +45,7 @@ struct _ShellAppSystemPrivate {
 
   GHashTable *app_id_to_app;
 
+  GHashTable *cached_menu_contents;  /* <char *id, GSList<ShellAppInfo*>> */
   GSList *cached_app_menus; /* ShellAppMenuEntry */
 
   GSList *cached_settings; /* ShellAppInfo */
@@ -56,6 +57,7 @@ struct _ShellAppSystemPrivate {
   guint app_change_timeout_id;
 };
 
+static void free_appinfo_gslist (gpointer list);
 static void shell_app_system_finalize (GObject *object);
 static gboolean on_tree_changed (gpointer user_data);
 static void on_tree_changed_cb (GMenuTree *tree, gpointer user_data);
@@ -229,6 +231,9 @@ shell_app_system_init (ShellAppSystem *self)
   priv->app_id_to_app = g_hash_table_new_full (g_str_hash, g_str_equal,
                                                NULL, (GDestroyNotify) shell_app_info_unref);
 
+  priv->cached_menu_contents = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                                      g_free, free_appinfo_gslist);
+
   /* For now, we want to pick up Evince, Nautilus, etc.  We'll
    * handle NODISPLAY semantics at a higher level or investigate them
    * case by case.
@@ -262,6 +267,8 @@ shell_app_system_finalize (GObject *object)
   gmenu_tree_unref (priv->apps_tree);
   gmenu_tree_unref (priv->settings_tree);
 
+  g_hash_table_destroy (priv->cached_menu_contents);
+
   g_hash_table_destroy (priv->app_id_to_app);
 
   g_slist_foreach (priv->cached_app_menus, (GFunc)shell_app_menu_entry_free, NULL);
@@ -280,6 +287,14 @@ shell_app_system_finalize (GObject *object)
 }
 
 static void
+free_appinfo_gslist (gpointer listp)
+{
+  GSList *list = listp;
+  g_slist_foreach (list, (GFunc) shell_app_info_unref, NULL);
+  g_slist_free (list);
+}
+
+static void
 reread_directories (ShellAppSystem *self, GSList **cache, GMenuTree *tree)
 {
   GMenuTreeDirectory *trunk;
@@ -419,8 +434,12 @@ static gboolean
 on_tree_changed (gpointer user_data)
 {
   ShellAppSystem *self = SHELL_APP_SYSTEM (user_data);
-  g_signal_emit (self, signals[INSTALLED_CHANGED], 0);
+
   reread_menus (self);
+  g_hash_table_remove_all (self->priv->cached_menu_contents);
+
+  g_signal_emit (self, signals[INSTALLED_CHANGED], 0);
+
   self->priv->app_change_timeout_id = 0;
   return FALSE;
 }
@@ -537,26 +556,32 @@ shell_app_menu_entry_get_type (void)
  * shell_app_system_get_applications_for_menu:
  *
  * Traverses a toplevel menu, and returns all items under it.  Nested items
- * are flattened.
+ * are flattened.  This value is computed on initial call and cached thereafter
+ * until the set of installed applications changes.
  *
- * Return value: (transfer full) (element-type ShellAppInfo): List of applications
+ * Return value: (transfer none) (element-type ShellAppInfo): List of applications
  */
 GSList *
-shell_app_system_get_applications_for_menu (ShellAppSystem *monitor,
+shell_app_system_get_applications_for_menu (ShellAppSystem *self,
                                             const char *menu)
 {
-  char *path;
-  GMenuTreeDirectory *menu_entry;
   GSList *apps;
 
-  path = g_strdup_printf ("/%s", menu);
-  menu_entry = gmenu_tree_get_directory_from_path (monitor->priv->apps_tree, path);
-  g_free (path);
-  g_assert (menu_entry != NULL);
+  apps = g_hash_table_lookup (self->priv->cached_menu_contents, menu);
+  if (!apps)
+    {
+      char *path;
+      GMenuTreeDirectory *menu_entry;
+      path = g_strdup_printf ("/%s", menu);
+      menu_entry = gmenu_tree_get_directory_from_path (self->priv->apps_tree, path);
+      g_free (path);
+      g_assert (menu_entry != NULL);
 
-  apps = gather_entries_recurse (monitor, NULL, menu_entry);
+      apps = gather_entries_recurse (self, NULL, menu_entry);
+      g_hash_table_insert (self->priv->cached_menu_contents, g_strdup (menu), apps);
 
-  gmenu_tree_item_unref (menu_entry);
+      gmenu_tree_item_unref (menu_entry);
+    }
 
   return apps;
 }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]