[Xfce4-commits] <xfce4-appfinder:nick/xfrun4-merge> Share category data and use pointers for category comparison.

Nick Schermer noreply at xfce.org
Sun Jun 12 12:02:01 CEST 2011


Updating branch refs/heads/nick/xfrun4-merge
         to 6fbb17c8fbb7f7e422df13b592d404274a962a9c (commit)
       from 2564fb266685e11b5f7e0a2a47cdaeb197f5e625 (commit)

commit 6fbb17c8fbb7f7e422df13b592d404274a962a9c
Author: Nick Schermer <nick at xfce.org>
Date:   Sun Jun 12 12:01:14 2011 +0200

    Share category data and use pointers for category comparison.

 src/appfinder-category-model.c |  133 ++++++++++----------
 src/appfinder-category-model.h |    1 +
 src/appfinder-model.c          |  270 +++++++++++++++++++++++++---------------
 src/appfinder-model.h          |   52 +++++---
 src/appfinder-window.c         |   36 +++---
 5 files changed, 293 insertions(+), 199 deletions(-)

diff --git a/src/appfinder-category-model.c b/src/appfinder-category-model.c
index 06d208d..ca69485 100644
--- a/src/appfinder-category-model.c
+++ b/src/appfinder-category-model.c
@@ -25,7 +25,6 @@
 #endif
 
 #include <libxfce4util/libxfce4util.h>
-#include <garcon/garcon.h>
 
 #include <src/appfinder-model.h>
 #include <src/appfinder-category-model.h>
@@ -64,7 +63,6 @@ static gboolean           xfce_appfinder_category_model_iter_nth_child        (G
 static gboolean           xfce_appfinder_category_model_iter_parent           (GtkTreeModel             *tree_model,
                                                                                GtkTreeIter              *iter,
                                                                                GtkTreeIter              *child);
-static void               xfce_appfinder_category_item_free                   (gpointer                  data);
 
 
 
@@ -75,18 +73,13 @@ struct _XfceAppfinderCategoryModelClass
 
 struct _XfceAppfinderCategoryModel
 {
-  GObject            __parent__;
-  gint               stamp;
+  GObject              __parent__;
+  gint                 stamp;
 
-  GSList *categories;
-};
+  GSList              *categories;
 
-typedef struct
-{
-  GarconMenuDirectory *directory;
-  GdkPixbuf           *pixbuf;
-}
-Categoryitem;
+  GarconMenuDirectory *all_applications;
+};
 
 
 
@@ -109,28 +102,11 @@ xfce_appfinder_category_model_class_init (XfceAppfinderCategoryModelClass *klass
 static void
 xfce_appfinder_category_model_init (XfceAppfinderCategoryModel *model)
 {
-  Categoryitem *item;
-
   /* generate a unique stamp */
   model->stamp = g_random_int ();
-
-    /* separator */
-  item = g_slice_new0 (Categoryitem);
-  model->categories = g_slist_prepend (model->categories, item);
-
-  item = g_slice_new0 (Categoryitem);
-  item->directory = g_object_new (GARCON_TYPE_MENU_DIRECTORY,
-                                  "name", _("Commands History"),
-                                  "icon-name", GTK_STOCK_EXECUTE,
-                                  NULL);
-  model->categories = g_slist_prepend (model->categories, item);
-
-  item = g_slice_new0 (Categoryitem);
-  item->directory = g_object_new (GARCON_TYPE_MENU_DIRECTORY,
-                                  "name", _("All Applications"),
-                                  "icon-name", "applications-other",
-                                  NULL);
-  model->categories = g_slist_prepend (model->categories, item);
+  model->all_applications = g_object_new (GARCON_TYPE_MENU_DIRECTORY,
+                                          "name", _("All Applications"),
+                                          "icon-name", "applications-other", NULL);
 }
 
 
@@ -158,10 +134,16 @@ static void
 xfce_appfinder_category_model_finalize (GObject *object)
 {
   XfceAppfinderCategoryModel *model = XFCE_APPFINDER_CATEGORY_MODEL (object);
+  GSList                     *li;
+  guint                       n;
 
-  g_slist_foreach (model->categories, (GFunc) xfce_appfinder_category_item_free, NULL);
+  /* clear the first three items */
+  for (li = model->categories, n = 0; li != NULL && n < 3; li = li->next, n++)
+    xfce_appfinder_model_category_free (li->data);
   g_slist_free (model->categories);
 
+  g_object_unref (G_OBJECT (model->all_applications));
+
   (*G_OBJECT_CLASS (xfce_appfinder_category_model_parent_class)->finalize) (object);
 }
 
@@ -195,6 +177,9 @@ xfce_appfinder_category_model_get_column_type (GtkTreeModel *tree_model,
     case XFCE_APPFINDER_CATEGORY_MODEL_COLUMN_ICON:
       return GDK_TYPE_PIXBUF;
 
+    case XFCE_APPFINDER_CATEGORY_MODEL_COLUMN_DIRECTORY:
+      return GARCON_TYPE_MENU_DIRECTORY;
+
     default:
       g_assert_not_reached ();
       return G_TYPE_INVALID;
@@ -248,7 +233,7 @@ xfce_appfinder_category_model_get_value (GtkTreeModel *tree_model,
                                          GValue       *value)
 {
   XfceAppfinderCategoryModel *model = XFCE_APPFINDER_CATEGORY_MODEL (tree_model);
-  Categoryitem               *item;
+  CategoryItem               *item;
   const gchar                *icon_name;
 
   g_return_if_fail (XFCE_IS_APPFINDER_CATEGORY_MODEL (model));
@@ -277,6 +262,13 @@ xfce_appfinder_category_model_get_value (GtkTreeModel *tree_model,
       g_value_set_object (value, item->pixbuf);
       break;
 
+    case XFCE_APPFINDER_CATEGORY_MODEL_COLUMN_DIRECTORY:
+      g_value_init (value, G_TYPE_OBJECT);
+      /* return null for all applications */
+      if (item->directory != model->all_applications)
+        g_value_set_object (value, item->directory);
+      break;
+
     default:
       g_assert_not_reached ();
       break;
@@ -373,20 +365,6 @@ xfce_appfinder_category_model_iter_parent (GtkTreeModel *tree_model,
 
 
 
-static void
-xfce_appfinder_category_item_free (gpointer data)
-{
-  Categoryitem *item = data;
-
-  if (item->directory != NULL)
-    g_object_unref (G_OBJECT (item->directory));
-  if (item->pixbuf != NULL)
-    g_object_unref (G_OBJECT (item->pixbuf));
-  g_slice_free (Categoryitem, item);
-}
-
-
-
 XfceAppfinderCategoryModel *
 xfce_appfinder_category_model_new (void)
 {
@@ -399,7 +377,7 @@ void
 xfce_appfinder_category_model_set_categories (XfceAppfinderCategoryModel *model,
                                               GSList                     *categories)
 {
-  Categoryitem *item;
+  CategoryItem *item;
   GSList       *li, *lnext;
   gint          idx;
   GtkTreePath  *path;
@@ -407,36 +385,57 @@ xfce_appfinder_category_model_set_categories (XfceAppfinderCategoryModel *model,
 
   APPFINDER_DEBUG ("insert %d categories", g_slist_length (categories));
 
-  /* remove shortcuts after hard-coded before inserting */
-  li = g_slist_nth (model->categories, 3);
-  for (idx = 3; li != NULL; li = lnext, idx++)
+  /* remove items from the model */
+  for (li = model->categories, idx = 0; li != NULL; li = lnext, idx++)
     {
       lnext = li->next;
-      item = li->data;
 
       model->categories = g_slist_delete_link (model->categories, li);
 
+      /* remove the items we own */
+      if (idx < 3)
+        xfce_appfinder_model_category_free (li->data);
+
       path = gtk_tree_path_new_from_indices (idx, -1);
       gtk_tree_model_row_deleted (GTK_TREE_MODEL (model), path);
       gtk_tree_path_free (path);
-
-      xfce_appfinder_category_item_free (item);
     }
 
-  /* insert after the hard-coded items */
-  for (li = categories, idx = 3; li != NULL; li = li->next, idx++)
-    {
-      g_return_if_fail (GARCON_IS_MENU_DIRECTORY (li->data));
+  g_assert (model->categories == NULL);
 
-      item = g_slice_new0 (Categoryitem);
-      item->directory = g_object_ref (G_OBJECT (li->data));
-      model->categories = g_slist_append (model->categories, item);
+  /* separator and the main categories */
+  item = g_slice_new0 (CategoryItem);
+  model->categories = g_slist_prepend (model->categories, item);
 
-      path = gtk_tree_path_new_from_indices (idx, -1);
-      gtk_tree_model_get_iter (GTK_TREE_MODEL (model), &iter, path);
+  item = g_slice_new0 (CategoryItem);
+  item->directory = xfce_appfinder_model_get_command_category ();
+  model->categories = g_slist_prepend (model->categories, item);
+
+  item = g_slice_new0 (CategoryItem);
+  item->directory = g_object_ref (G_OBJECT (model->all_applications));
+  model->categories = g_slist_prepend (model->categories, item);
+
+  /* move the categories online */
+  model->categories = g_slist_concat (model->categories, g_slist_copy (categories));
+
+  path = gtk_tree_path_new_first ();
+  for (li = model->categories; li != NULL; li = li->next)
+    {
+      /* remember the next item */
+      lnext = li->next;
+      li->next = NULL;
+
+      /* emit the "row-inserted" signal */
+      ITER_INIT (iter, model->stamp, li);
       gtk_tree_model_row_inserted (GTK_TREE_MODEL (model), path, &iter);
-      gtk_tree_path_free (path);
+
+      /* advance the path */
+      gtk_tree_path_next (path);
+
+      /* reset the next item */
+      li->next = lnext;
     }
+  gtk_tree_path_free (path);
 }
 
 
@@ -446,7 +445,7 @@ xfce_appfinder_category_model_row_separator_func (GtkTreeModel *tree_model,
                                                   GtkTreeIter  *iter,
                                                   gpointer      user_data)
 {
-  Categoryitem *item = ITER_GET_DATA (iter);
+  CategoryItem *item = ITER_GET_DATA (iter);
 
   g_return_val_if_fail (XFCE_IS_APPFINDER_CATEGORY_MODEL (tree_model), FALSE);
 
@@ -458,7 +457,7 @@ xfce_appfinder_category_model_row_separator_func (GtkTreeModel *tree_model,
 void
 xfce_appfinder_category_model_icon_theme_changed (XfceAppfinderCategoryModel *model)
 {
-  Categoryitem *item;
+  CategoryItem *item;
   GSList       *li;
   gint          idx;
   GtkTreeIter   iter;
diff --git a/src/appfinder-category-model.h b/src/appfinder-category-model.h
index 31e6c8a..1c28a1c 100644
--- a/src/appfinder-category-model.h
+++ b/src/appfinder-category-model.h
@@ -39,6 +39,7 @@ enum
 {
   XFCE_APPFINDER_CATEGORY_MODEL_COLUMN_NAME,
   XFCE_APPFINDER_CATEGORY_MODEL_COLUMN_ICON,
+  XFCE_APPFINDER_CATEGORY_MODEL_COLUMN_DIRECTORY,
   XFCE_APPFINDER_CATEGORY_MODEL_N_COLUMNS,
 };
 
diff --git a/src/appfinder-model.c b/src/appfinder-model.c
index 470eec0..6d038f3 100644
--- a/src/appfinder-model.c
+++ b/src/appfinder-model.c
@@ -26,7 +26,6 @@
 
 #include <libxfce4util/libxfce4util.h>
 #include <libxfce4ui/libxfce4ui.h>
-#include <garcon/garcon.h>
 
 #include <src/appfinder-model.h>
 #include <src/appfinder-private.h>
@@ -68,8 +67,11 @@ static gboolean           xfce_appfinder_model_iter_nth_child        (GtkTreeMod
 static gboolean           xfce_appfinder_model_iter_parent           (GtkTreeModel             *tree_model,
                                                                       GtkTreeIter              *iter,
                                                                       GtkTreeIter              *child);
+static void               xfce_appfinder_model_menu_changed          (GarconMenu               *menu,
+                                                                      XfceAppfinderModel       *model);
 static gpointer           xfce_appfinder_model_collect_thread        (gpointer                  user_data);
-static void               xfce_appfinder_model_item_free             (gpointer                  data);
+static void               xfce_appfinder_model_item_free             (gpointer                  data,
+                                                                      XfceAppfinderModel       *model);
 
 
 
@@ -80,22 +82,26 @@ struct _XfceAppfinderModelClass
 
 struct _XfceAppfinderModel
 {
-  GObject            __parent__;
-  gint               stamp;
-
-  GSList            *items;
-  GHashTable        *items_hash;
-  GarconMenu        *menu;
-
-  GdkPixbuf         *command_icon_small;
-  GdkPixbuf         *command_icon_large;
-
-  guint              collect_idle_id;
-  GSList            *collect_items;
-  GSList            *collect_categories;
-  GThread           *collect_thread;
-  volatile gboolean  collect_cancelled;
-  GHashTable        *collect_desktop_ids;
+  GObject              __parent__;
+  gint                 stamp;
+
+  GSList              *items;
+  GHashTable          *items_hash;
+
+  GarconMenu          *menu;
+
+  GdkPixbuf           *command_icon_small;
+  GdkPixbuf           *command_icon_large;
+  GarconMenuDirectory *command_category;
+
+  GSList              *categories;
+
+  guint                collect_idle_id;
+  GSList              *collect_items;
+  GSList              *collect_categories;
+  GThread             *collect_thread;
+  volatile gboolean    collect_cancelled;
+  GHashTable          *collect_desktop_ids;
 };
 
 typedef struct
@@ -157,6 +163,7 @@ xfce_appfinder_model_init (XfceAppfinderModel *model)
   model->items_hash = g_hash_table_new (g_str_hash, g_str_equal);
   model->command_icon_small = xfce_appfinder_model_load_pixbuf (GTK_STOCK_EXECUTE, ICON_SMALL);
   model->command_icon_large = xfce_appfinder_model_load_pixbuf (GTK_STOCK_EXECUTE, ICON_LARGE);
+  model->command_category = xfce_appfinder_model_get_command_category ();
 
   model->menu = garcon_menu_new_applications ();
   model->collect_thread = g_thread_create (xfce_appfinder_model_collect_thread, model, TRUE, NULL);
@@ -195,20 +202,29 @@ xfce_appfinder_model_finalize (GObject *object)
   /* cancel any pending collect idle source */
   if (G_UNLIKELY (model->collect_idle_id != 0))
     g_source_remove (model->collect_idle_id);
-  g_slist_free (model->collect_items);
   g_slist_free (model->collect_categories);
 
+  g_signal_handlers_disconnect_by_func (G_OBJECT (model->menu),
+      G_CALLBACK (xfce_appfinder_model_menu_changed), model);
   g_object_unref (G_OBJECT (model->menu));
 
-  g_slist_foreach (model->items, (GFunc) xfce_appfinder_model_item_free, NULL);
+  g_slist_foreach (model->collect_items, (GFunc) xfce_appfinder_model_item_free, model);
+  g_slist_free (model->collect_items);
+  g_slist_foreach (model->items, (GFunc) xfce_appfinder_model_item_free, model);
   g_slist_free (model->items);
 
+  g_slist_foreach (model->collect_categories, (GFunc) xfce_appfinder_model_category_free, NULL);
+  g_slist_free (model->collect_categories);
+  g_slist_foreach (model->categories, (GFunc) xfce_appfinder_model_category_free, NULL);
+  g_slist_free (model->categories);
+
   if (model->collect_desktop_ids != NULL)
     g_hash_table_destroy (model->collect_desktop_ids);
   g_hash_table_destroy (model->items_hash);
 
   g_object_unref (G_OBJECT (model->command_icon_large));
   g_object_unref (G_OBJECT (model->command_icon_small));
+  g_object_unref (G_OBJECT (model->command_category));
 
   APPFINDER_DEBUG ("model cleared");
 
@@ -516,6 +532,7 @@ xfce_appfinder_model_collect_idle (gpointer user_data)
   GtkTreePath        *path;
   GtkTreeIter         iter;
   GSList             *li, *lnext;
+  GSList             *tmp;
 
   g_return_val_if_fail (XFCE_IS_APPFINDER_MODEL (model), FALSE);
   g_return_val_if_fail (model->items == NULL, FALSE);
@@ -553,10 +570,14 @@ xfce_appfinder_model_collect_idle (gpointer user_data)
   /* signal new categories */
   if (model->collect_categories != NULL)
     {
-      g_signal_emit (G_OBJECT (model), model_signals[CATEGORIES_CHANGED], 0,
-                     model->collect_categories);
-      g_slist_free (model->collect_categories);
+      tmp = model->categories;
+      model->categories = model->collect_categories;
       model->collect_categories = NULL;
+
+      g_signal_emit (G_OBJECT (model), model_signals[CATEGORIES_CHANGED], 0, model->categories);
+
+      g_slist_foreach (tmp, (GFunc) xfce_appfinder_model_category_free, NULL);
+      g_slist_free (tmp);
     }
 
   GDK_THREADS_LEAVE ();
@@ -601,41 +622,6 @@ xfce_appfinder_model_item_compare (gconstpointer a,
 
 
 
-static gint
-xfce_appfinder_model_category_compare (gconstpointer a,
-                                       gconstpointer b)
-{
-  g_return_val_if_fail (GARCON_IS_MENU_DIRECTORY (a), 0);
-  g_return_val_if_fail (GARCON_IS_MENU_DIRECTORY (b), 0);
-
-  return g_utf8_collate (garcon_menu_directory_get_name (GARCON_MENU_DIRECTORY (a)),
-                         garcon_menu_directory_get_name (GARCON_MENU_DIRECTORY (b)));
-}
-
-
-
-static void
-xfce_appfinder_model_item_free (gpointer data)
-{
-  ModelItem *item = data;
-
-  if (item->item != NULL)
-    g_object_unref (G_OBJECT (item->item));
-  if (item->icon_small != NULL)
-    g_object_unref (G_OBJECT (item->icon_small));
-  if (item->icon_large != NULL)
-    g_object_unref (G_OBJECT (item->icon_large));
-  if (item->categories != NULL)
-    g_ptr_array_unref (item->categories);
-  g_free (item->abstract);
-  g_free (item->key);
-  g_free (item->command);
-  g_free (item->tooltip);
-  g_slice_free (ModelItem, item);
-}
-
-
-
 static gchar *
 xfce_appfinder_model_item_key (GarconMenuItem *item)
 {
@@ -697,6 +683,8 @@ xfce_appfinder_model_item_new (GarconMenuItem *menu_item)
         item->command = g_strdup (command);
     }
 
+  item->key = xfce_appfinder_model_item_key (menu_item);
+
   return item;
 }
 
@@ -725,7 +713,7 @@ xfce_appfinder_model_item_changed (GarconMenuItem     *menu_item,
           APPFINDER_DEBUG ("update item %s", garcon_menu_item_get_desktop_id (menu_item));
 
           g_hash_table_remove (model->items_hash, item->command);
-          xfce_appfinder_model_item_free (item);
+          xfce_appfinder_model_item_free (item, model);
 
           item = xfce_appfinder_model_item_new (menu_item);
           item->categories = categories;
@@ -748,22 +736,72 @@ xfce_appfinder_model_item_changed (GarconMenuItem     *menu_item,
 
 
 
-static gboolean
-xfce_appfinder_model_ptr_array_strcmp (GPtrArray   *array,
-                                       const gchar *str1)
+static void
+xfce_appfinder_model_item_free (gpointer            data,
+                                XfceAppfinderModel *model)
 {
-  guint        i;
-  const gchar *str2;
+  ModelItem *item = data;
 
-  if (array != NULL && str1 != NULL)
+  if (item->item != NULL)
     {
-      for (i = 0; i < array->len; i++)
-        {
-          str2 = g_ptr_array_index (array, i);
-          if (str2 != NULL && strcmp (str1, str2) == 0)
-            return TRUE;
-        }
+      g_signal_handlers_disconnect_by_func (G_OBJECT (item->item),
+          G_CALLBACK (xfce_appfinder_model_item_changed), model);
+      g_object_unref (G_OBJECT (item->item));
     }
+  if (item->icon_small != NULL)
+    g_object_unref (G_OBJECT (item->icon_small));
+  if (item->icon_large != NULL)
+    g_object_unref (G_OBJECT (item->icon_large));
+  if (item->categories != NULL)
+    g_ptr_array_unref (item->categories);
+  g_free (item->abstract);
+  g_free (item->key);
+  g_free (item->command);
+  g_free (item->tooltip);
+  g_slice_free (ModelItem, item);
+}
+
+
+
+
+static gint
+xfce_appfinder_model_category_compare (gconstpointer a,
+                                       gconstpointer b)
+{
+  const CategoryItem *cat_a = a;
+  const CategoryItem *cat_b = b;
+
+  g_return_val_if_fail (GARCON_IS_MENU_DIRECTORY (cat_a->directory), 0);
+  g_return_val_if_fail (GARCON_IS_MENU_DIRECTORY (cat_b->directory), 0);
+
+  return g_utf8_collate (garcon_menu_directory_get_name (cat_a->directory),
+                         garcon_menu_directory_get_name (cat_b->directory));
+}
+
+
+
+void
+xfce_appfinder_model_category_free (CategoryItem *item)
+{
+  if (item->directory != NULL)
+    g_object_unref (G_OBJECT (item->directory));
+  if (item->pixbuf != NULL)
+    g_object_unref (G_OBJECT (item->pixbuf));
+  g_slice_free (CategoryItem, item);
+}
+
+
+
+static gboolean
+xfce_appfinder_model_ptr_array_find (GPtrArray     *array,
+                                     gconstpointer  data)
+{
+  guint i;
+
+  if (array != NULL && data != NULL)
+    for (i = 0; i < array->len; i++)
+      if (g_ptr_array_index (array, i) == data)
+        return TRUE;
 
   return FALSE;
 }
@@ -771,17 +809,19 @@ xfce_appfinder_model_ptr_array_strcmp (GPtrArray   *array,
 
 
 static gboolean
-xfce_appfinder_model_collect_items (XfceAppfinderModel *model,
-                                    GarconMenu         *menu,
-                                    const gchar        *category)
+xfce_appfinder_model_collect_items (XfceAppfinderModel  *model,
+                                    GarconMenu          *menu,
+                                    GarconMenuDirectory *category)
 {
   GList               *elements, *li;
   GarconMenuDirectory *directory;
   ModelItem           *item;
   gboolean             has_items = FALSE;
   const gchar         *desktop_id;
+  CategoryItem        *citem;
 
   g_return_val_if_fail (GARCON_IS_MENU (menu), FALSE);
+  g_return_val_if_fail (category == NULL || GARCON_IS_MENU_DIRECTORY (category), FALSE);
 
   directory = garcon_menu_get_directory (menu);
   if (directory != NULL)
@@ -789,8 +829,9 @@ xfce_appfinder_model_collect_items (XfceAppfinderModel *model,
       if (!garcon_menu_directory_get_visible (directory))
         return FALSE;
 
+      /* this way we only have two levels */
       if (category == NULL)
-        category = garcon_menu_directory_get_name (directory);
+        category = directory;
     }
 
   /* collect all the elements in this menu and its sub menus */
@@ -808,8 +849,9 @@ xfce_appfinder_model_collect_items (XfceAppfinderModel *model,
             {
               item = xfce_appfinder_model_item_new (li->data);
 
-              item->categories = g_ptr_array_new_with_free_func (g_free);
-              g_ptr_array_add (item->categories, g_strdup (category));
+              item->categories = g_ptr_array_new_with_free_func (g_object_unref);
+              if (category != NULL)
+                g_ptr_array_add (item->categories, g_object_ref (G_OBJECT (category)));
 
               model->collect_items = g_slist_prepend (model->collect_items, item);
               g_hash_table_insert (model->collect_desktop_ids, (gchar *) desktop_id, item);
@@ -819,10 +861,11 @@ xfce_appfinder_model_collect_items (XfceAppfinderModel *model,
               g_signal_connect (G_OBJECT (item->item), "changed",
                   G_CALLBACK (xfce_appfinder_model_item_changed), model);
             }
-          else if (!xfce_appfinder_model_ptr_array_strcmp (item->categories, category))
+          else if (category != NULL
+                   && !xfce_appfinder_model_ptr_array_find (item->categories, category))
             {
               /* add category to existing item */
-              g_ptr_array_add (item->categories, g_strdup (category));
+              g_ptr_array_add (item->categories, g_object_ref (G_OBJECT (category)));
               APPFINDER_DEBUG ("%s is in %d categories", desktop_id, item->categories->len);
             }
 
@@ -836,9 +879,12 @@ xfce_appfinder_model_collect_items (XfceAppfinderModel *model,
     }
   g_list_free (elements);
 
-  if (directory != NULL
-      && has_items)
-    model->collect_categories = g_slist_prepend (model->collect_categories, directory);
+  if (directory != NULL && has_items)
+    {
+      citem = g_slice_new0 (CategoryItem);
+      citem->directory = g_object_ref (G_OBJECT (directory));
+      model->collect_categories = g_slist_prepend (model->collect_categories, citem);
+    }
 
   return has_items;
 }
@@ -976,8 +1022,8 @@ xfce_appfinder_model_get (void)
   else
     {
       model = g_object_new (XFCE_TYPE_APPFINDER_MODEL, NULL);
-      g_message ("new model");
       g_object_add_weak_pointer (G_OBJECT (model), (gpointer) &model);
+      APPFINDER_DEBUG ("allocate new model");
     }
 
   return model;
@@ -985,16 +1031,27 @@ xfce_appfinder_model_get (void)
 
 
 
+GSList *
+xfce_appfinder_model_get_categories (XfceAppfinderModel *model)
+{
+  g_return_val_if_fail (XFCE_IS_APPFINDER_MODEL (model), NULL);
+  return model->categories;
+}
+
+
+
 gboolean
-xfce_appfinder_model_get_visible (XfceAppfinderModel *model,
-                                  const GtkTreeIter  *iter,
-                                  const gchar        *category,
-                                  const gchar        *string)
+xfce_appfinder_model_get_visible (XfceAppfinderModel        *model,
+                                  const GtkTreeIter         *iter,
+                                  const GarconMenuDirectory *category,
+                                  const gchar               *string)
 {
   ModelItem *item;
 
   g_return_val_if_fail (XFCE_IS_APPFINDER_MODEL (model), FALSE);
   g_return_val_if_fail (iter->stamp == model->stamp, FALSE);
+  g_return_val_if_fail (category == NULL || GARCON_IS_MENU_DIRECTORY (category), FALSE);
+  g_return_val_if_fail (GARCON_IS_MENU_DIRECTORY (model->command_category), FALSE);
 
   item = ITER_GET_DATA (iter);
 
@@ -1003,24 +1060,18 @@ xfce_appfinder_model_get_visible (XfceAppfinderModel *model,
       g_return_val_if_fail (GARCON_IS_MENU_ITEM (item->item), FALSE);
 
       if (category != NULL
-          && (*category == '\0'
-              || !xfce_appfinder_model_ptr_array_strcmp (item->categories, category)))
+          && !xfce_appfinder_model_ptr_array_find (item->categories, category))
         return FALSE;
 
-      if (string != NULL)
-        {
-          if (item->key == NULL)
-            item->key = xfce_appfinder_model_item_key (item->item);
-
-          return strstr (item->key, string) != NULL;
-        }
+      if (string != NULL
+          && item->key != NULL)
+        return strstr (item->key, string) != NULL;
     }
   else /* command item */
     {
       g_return_val_if_fail (item->command != NULL, FALSE);
 
-      /* nul string will filter out the commands */
-      if (category == NULL || *category != '\0')
+      if (category != model->command_category)
         return FALSE;
 
       if (string != NULL)
@@ -1299,3 +1350,26 @@ xfce_appfinder_model_icon_theme_changed (XfceAppfinderModel *model)
         }
     }
 }
+
+
+
+GarconMenuDirectory *
+xfce_appfinder_model_get_command_category (void)
+{
+  static GarconMenuDirectory *category = NULL;
+
+  if (G_LIKELY (category != NULL))
+    {
+      g_object_ref (G_OBJECT (category));
+    }
+  else
+    {
+      category = g_object_new (GARCON_TYPE_MENU_DIRECTORY,
+                               "name", _("Commands History"),
+                               "icon-name", GTK_STOCK_EXECUTE,
+                               NULL);
+      g_object_add_weak_pointer (G_OBJECT (category), (gpointer) &category);
+    }
+
+  return category;
+}
diff --git a/src/appfinder-model.h b/src/appfinder-model.h
index e192d0e..c75be78 100644
--- a/src/appfinder-model.h
+++ b/src/appfinder-model.h
@@ -20,6 +20,7 @@
 #define __XFCE_APPFINDER_MODEL_H__
 
 #include <gtk/gtk.h>
+#include <garcon/garcon.h>
 
 G_BEGIN_DECLS
 
@@ -44,34 +45,47 @@ enum
   XFCE_APPFINDER_MODEL_N_COLUMNS,
 };
 
+typedef struct
+{
+  GarconMenuDirectory *directory;
+  GdkPixbuf           *pixbuf;
+}
+CategoryItem;
+
+
+
+GType                xfce_appfinder_model_get_type             (void) G_GNUC_CONST;
+
+XfceAppfinderModel  *xfce_appfinder_model_get                  (void) G_GNUC_MALLOC;
 
+GSList              *xfce_appfinder_model_get_categories       (XfceAppfinderModel        *model);
 
-GType               xfce_appfinder_model_get_type             (void) G_GNUC_CONST;
+gboolean             xfce_appfinder_model_get_visible          (XfceAppfinderModel        *model,
+                                                                const GtkTreeIter         *iter,
+                                                                const GarconMenuDirectory *category,
+                                                                const gchar               *string);
 
-XfceAppfinderModel *xfce_appfinder_model_get                  (void) G_GNUC_MALLOC;
+gboolean             xfce_appfinder_model_execute              (XfceAppfinderModel        *model,
+                                                                const GtkTreeIter         *iter,
+                                                                GdkScreen                 *screen,
+                                                                gboolean                  *is_regular_command,
+                                                                GError                   **error);
 
-gboolean            xfce_appfinder_model_get_visible          (XfceAppfinderModel  *model,
-                                                               const GtkTreeIter   *iter,
-                                                               const gchar         *category,
-                                                               const gchar         *string);
+GdkPixbuf           *xfce_appfinder_model_load_pixbuf          (const gchar               *icon_name,
+                                                                gint                       size) G_GNUC_MALLOC;
 
-gboolean            xfce_appfinder_model_execute              (XfceAppfinderModel  *model,
-                                                               const GtkTreeIter   *iter,
-                                                               GdkScreen           *screen,
-                                                               gboolean            *is_regular_command,
-                                                               GError             **error);
+gboolean             xfce_appfinder_model_save_command         (XfceAppfinderModel        *model,
+                                                                const gchar               *command,
+                                                                GError                   **error);
 
-GdkPixbuf          *xfce_appfinder_model_load_pixbuf          (const gchar         *icon_name,
-                                                               gint                 size) G_GNUC_MALLOC;
+GdkPixbuf           *xfce_appfinder_model_get_icon_for_command (XfceAppfinderModel        *model,
+                                                                const gchar               *command);
 
-gboolean            xfce_appfinder_model_save_command         (XfceAppfinderModel  *model,
-                                                               const gchar         *command,
-                                                               GError             **error);
+void                 xfce_appfinder_model_icon_theme_changed   (XfceAppfinderModel        *model);
 
-GdkPixbuf          *xfce_appfinder_model_get_icon_for_command (XfceAppfinderModel  *model,
-                                                               const gchar         *command);
+GarconMenuDirectory *xfce_appfinder_model_get_command_category (void);
 
-void                xfce_appfinder_model_icon_theme_changed   (XfceAppfinderModel  *model);
+void                 xfce_appfinder_model_category_free        (CategoryItem              *category);
 
 G_END_DECLS
 
diff --git a/src/appfinder-window.c b/src/appfinder-window.c
index eec8863..e62fdac 100644
--- a/src/appfinder-window.c
+++ b/src/appfinder-window.c
@@ -106,7 +106,7 @@ struct _XfceAppfinderWindow
   GtkWidget                  *bin_collapsed;
   GtkWidget                  *bin_expanded;
 
-  gchar                      *filter_category;
+  GarconMenuDirectory        *filter_category;
   gchar                      *filter_text;
 
   gint                        last_window_height;
@@ -162,12 +162,18 @@ xfce_appfinder_window_init (XfceAppfinderWindow *window)
   GtkIconTheme       *icon_theme;
   XfconfChannel      *channel;
   gint                integer;
+  GSList             *categories;
 
   channel = xfconf_channel_get ("xfce4-appfinder");
   window->last_window_height = xfconf_channel_get_int (channel, "/LastWindowHeight", DEFAULT_WINDOW_HEIGHT);
 
-  window->model = xfce_appfinder_model_get ();
   window->category_model = xfce_appfinder_category_model_new ();
+  window->model = xfce_appfinder_model_get ();
+
+  /* load categories in the model */
+  categories = xfce_appfinder_model_get_categories (window->model);
+  if (categories != NULL)
+    xfce_appfinder_category_model_set_categories (window->category_model, categories);
   g_signal_connect_swapped (G_OBJECT (window->model), "categories-changed",
                             G_CALLBACK (xfce_appfinder_category_model_set_categories),
                             window->category_model);
@@ -354,7 +360,8 @@ xfce_appfinder_window_finalize (GObject *object)
   g_object_unref (G_OBJECT (window->completion));
   g_object_unref (G_OBJECT (window->icon_find));
 
-  g_free (window->filter_category);
+  if (window->filter_category != NULL)
+    g_object_unref (G_OBJECT (window->filter_category));
   g_free (window->filter_text);
 
   (*G_OBJECT_CLASS (xfce_appfinder_window_parent_class)->finalize) (object);
@@ -453,6 +460,7 @@ xfce_appfinder_window_entry_changed (XfceAppfinderWindow *window)
         }
 
       model = gtk_tree_view_get_model (GTK_TREE_VIEW (window->treeview));
+      APPFINDER_DEBUG ("refilter entry");
       gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (model));
     }
   else
@@ -589,26 +597,24 @@ static void
 xfce_appfinder_window_category_changed (GtkTreeSelection    *selection,
                                         XfceAppfinderWindow *window)
 {
-  GtkTreeIter   iter;
-  GtkTreeModel *model;
-  gchar        *category;
+  GtkTreeIter          iter;
+  GtkTreeModel        *model;
+  GarconMenuDirectory *category;
 
   if (gtk_tree_selection_get_selected (selection, &model, &iter))
     {
-      gtk_tree_model_get (model, &iter, XFCE_APPFINDER_CATEGORY_MODEL_COLUMN_NAME, &category, -1);
+      gtk_tree_model_get (model, &iter, XFCE_APPFINDER_CATEGORY_MODEL_COLUMN_DIRECTORY, &category, -1);
 
-      g_free (window->filter_category);
+      if (window->filter_category != NULL)
+        g_object_unref (G_OBJECT (window->filter_category));
 
-      if (g_strcmp0 (category, _("All Applications")) == 0)
+      if (category == NULL)
         window->filter_category = NULL;
-      else if (g_strcmp0 (category, _("Commands History")) == 0)
-        window->filter_category = g_strdup ("\0");
       else
-        window->filter_category = g_strdup (category);
-
-      g_free (category);
+        window->filter_category = category;
 
       model = gtk_tree_view_get_model (GTK_TREE_VIEW (window->treeview));
+      APPFINDER_DEBUG ("refilter category");
       gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (model));
     }
 }
@@ -853,7 +859,7 @@ xfce_appfinder_window_set_expanded (XfceAppfinderWindow *window,
   if (completion != NULL)
     gtk_editable_delete_selection (GTK_EDITABLE (window->entry));
   gtk_entry_set_completion (GTK_ENTRY (window->entry), expanded ? NULL : window->completion);
-  if (!expanded)
+  if (!expanded && gtk_entry_get_text_length (GTK_ENTRY (window->entry)) > 0)
     gtk_entry_completion_insert_prefix (window->completion);
 
   /* update state */



More information about the Xfce4-commits mailing list