[Xfce4-commits] <design:master> Bind the two models.

Nick Schermer noreply at xfce.org
Thu Jun 2 13:24:01 CEST 2011


Updating branch refs/heads/master
         to 90c7e1988188c36b6df779f0f71076054b590208 (commit)
       from 08f85328085bf8df79c546c59cb218701c9cb5eb (commit)

commit 90c7e1988188c36b6df779f0f71076054b590208
Author: Nick Schermer <nick at xfce.org>
Date:   Thu Jun 2 13:21:31 2011 +0200

    Bind the two models.

 .../demo-code/c/appfinder-category-model.c         |  142 ++++++++++---
 .../demo-code/c/appfinder-category-model.h         |   13 +-
 .../merge-with-xfrun/demo-code/c/appfinder-model.c |  227 ++++++++++++++++++--
 .../merge-with-xfrun/demo-code/c/appfinder-model.h |   22 ++-
 .../demo-code/c/appfinder-window.c                 |  100 ++++-----
 5 files changed, 398 insertions(+), 106 deletions(-)

diff --git a/xfce4-appfinder/merge-with-xfrun/demo-code/c/appfinder-category-model.c b/xfce4-appfinder/merge-with-xfrun/demo-code/c/appfinder-category-model.c
index f3ded89..cd0abea 100644
--- a/xfce4-appfinder/merge-with-xfrun/demo-code/c/appfinder-category-model.c
+++ b/xfce4-appfinder/merge-with-xfrun/demo-code/c/appfinder-category-model.c
@@ -11,6 +11,7 @@
 #include "appfinder-category-model.h"
 
 
+
 static void               xfce_appfinder_category_model_tree_model_init       (GtkTreeModelIface        *iface);
 static void               xfce_appfinder_category_model_finalize              (GObject                  *object);
 static GtkTreeModelFlags  xfce_appfinder_category_model_get_flags             (GtkTreeModel             *tree_model);
@@ -42,6 +43,7 @@ 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);
 
 
 
@@ -55,9 +57,16 @@ struct _XfceAppfinderCategoryModel
   GObject            __parent__;
   gint               stamp;
 
-  GSList *items;
+  GSList *categories;
 };
 
+typedef struct
+{
+  GarconMenuDirectory *directory;
+  GdkPixbuf           *pixbuf;
+}
+Categoryitem;
+
 
 
 G_DEFINE_TYPE_WITH_CODE (XfceAppfinderCategoryModel, xfce_appfinder_category_model, G_TYPE_OBJECT,
@@ -79,20 +88,28 @@ xfce_appfinder_category_model_class_init (XfceAppfinderCategoryModelClass *klass
 static void
 xfce_appfinder_category_model_init (XfceAppfinderCategoryModel *model)
 {
-  GarconMenuDirectory *directory;
+  Categoryitem *item;
 
   /* generate a unique stamp */
   model->stamp = g_random_int ();
 
-  directory = g_object_new (GARCON_TYPE_MENU_DIRECTORY,
-                            "name", _("Commands History"),
-                            "icon-name", GTK_STOCK_EXECUTE, NULL);
-  model->items = g_slist_prepend (model->items, directory);
-
-  directory = g_object_new (GARCON_TYPE_MENU_DIRECTORY,
-                            "name", _("All Applications"),
-                            "icon-name", "applications-other", NULL);
-  model->items = g_slist_prepend (model->items, directory);
+    /* 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);
 }
 
 
@@ -119,7 +136,10 @@ xfce_appfinder_category_model_tree_model_init (GtkTreeModelIface *iface)
 static void
 xfce_appfinder_category_model_finalize (GObject *object)
 {
-  //XfceAppfinderCategoryModel *model = XFCE_APPFINDER_CATEGORY_MODEL (object);
+  XfceAppfinderCategoryModel *model = XFCE_APPFINDER_CATEGORY_MODEL (object);
+
+  g_slist_foreach (model->categories, (GFunc) xfce_appfinder_category_item_free, NULL);
+  g_slist_free (model->categories);
 
   (*G_OBJECT_CLASS (xfce_appfinder_category_model_parent_class)->finalize) (object);
 }
@@ -173,7 +193,7 @@ xfce_appfinder_category_model_get_iter (GtkTreeModel *tree_model,
   g_return_val_if_fail (gtk_tree_path_get_depth (path) > 0, FALSE);
 
   iter->stamp = model->stamp;
-  iter->user_data = g_slist_nth (model->items, gtk_tree_path_get_indices (path)[0]);
+  iter->user_data = g_slist_nth (model->categories, gtk_tree_path_get_indices (path)[0]);
 
   return (iter->user_data != NULL);
 }
@@ -191,7 +211,7 @@ xfce_appfinder_category_model_get_path (GtkTreeModel *tree_model,
   g_return_val_if_fail (iter->stamp == model->stamp, NULL);
 
   /* determine the index of the iter */
-  idx = g_slist_position (model->items, iter->user_data);
+  idx = g_slist_position (model->categories, iter->user_data);
   if (G_UNLIKELY (idx < 0))
     return NULL;
 
@@ -207,25 +227,33 @@ xfce_appfinder_category_model_get_value (GtkTreeModel *tree_model,
                                          GValue       *value)
 {
   XfceAppfinderCategoryModel *model = XFCE_APPFINDER_CATEGORY_MODEL (tree_model);
-  GarconMenuDirectory        *directory;
-  GdkPixbuf                  *icon;
+  Categoryitem               *item;
+  const gchar                *icon_name;
 
   g_return_if_fail (XFCE_IS_APPFINDER_CATEGORY_MODEL (model));
   g_return_if_fail (iter->stamp == model->stamp);
 
-  directory = ((GSList *) iter->user_data)->data;
+  item = ITER_GET_DATA (iter);
+  g_return_if_fail (item->directory == NULL || GARCON_IS_MENU_DIRECTORY (item->directory));
 
   switch (column)
     {
     case XFCE_APPFINDER_CATEGORY_MODEL_COLUMN_NAME:
       g_value_init (value, G_TYPE_STRING);
-      g_value_set_static_string (value, garcon_menu_directory_get_name (directory));
+      if (item->directory != NULL)
+        g_value_set_static_string (value, garcon_menu_directory_get_name (item->directory));
       break;
 
     case XFCE_APPFINDER_CATEGORY_MODEL_COLUMN_ICON:
+      if (item->pixbuf == NULL
+          && item->directory != NULL)
+        {
+          icon_name = garcon_menu_directory_get_icon_name (item->directory);
+          item->pixbuf = xfce_appfinder_model_load_pixbuf (icon_name, 24);
+        }
+
       g_value_init (value, GDK_TYPE_PIXBUF);
-      icon = xfce_appfinder_model_load_pixbuf (garcon_menu_directory_get_icon_name (directory), 24);
-      g_value_take_object (value, icon);
+      g_value_set_object (value, item->pixbuf);
       break;
 
     default:
@@ -258,10 +286,10 @@ xfce_appfinder_category_model_iter_children (GtkTreeModel *tree_model,
 
   g_return_val_if_fail (XFCE_IS_APPFINDER_CATEGORY_MODEL (model), FALSE);
 
-  if (G_LIKELY (parent == NULL && model->items != NULL))
+  if (G_LIKELY (parent == NULL && model->categories != NULL))
     {
       iter->stamp = model->stamp;
-      iter->user_data = model->items;
+      iter->user_data = model->categories;
       return TRUE;
     }
 
@@ -287,7 +315,7 @@ xfce_appfinder_category_model_iter_n_children (GtkTreeModel *tree_model,
 
   g_return_val_if_fail (XFCE_IS_APPFINDER_CATEGORY_MODEL (model), 0);
 
-  return (iter == NULL) ? g_slist_length (model->items) : 0;
+  return (iter == NULL) ? g_slist_length (model->categories) : 0;
 }
 
 
@@ -305,7 +333,7 @@ xfce_appfinder_category_model_iter_nth_child (GtkTreeModel *tree_model,
   if (G_LIKELY (parent != NULL))
     {
       iter->stamp = model->stamp;
-      iter->user_data = g_slist_nth (model->items, n);
+      iter->user_data = g_slist_nth (model->categories, n);
       return (iter->user_data != NULL);
     }
 
@@ -324,6 +352,20 @@ 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)
 {
@@ -332,10 +374,60 @@ xfce_appfinder_category_model_new (void)
 
 
 
+void
+xfce_appfinder_category_model_set_categories (XfceAppfinderCategoryModel *model,
+                                              GSList                     *categories)
+{
+  Categoryitem *item;
+  GSList       *li, *lnext;
+  gint          idx;
+  GtkTreePath  *path;
+  GtkTreeIter   iter;
+
+  g_message ("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++)
+    {
+      lnext = li->next;
+      item = li->data;
+
+      model->categories = g_slist_delete_link (model->categories, li);
+
+      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));
+
+      item = g_slice_new0 (Categoryitem);
+      item->directory = g_object_ref (G_OBJECT (li->data));
+      model->categories = g_slist_append (model->categories, item);
+
+      path = gtk_tree_path_new_from_indices (idx, -1);
+      gtk_tree_model_get_iter (GTK_TREE_MODEL (model), &iter, path);
+      gtk_tree_model_row_inserted (GTK_TREE_MODEL (model), path, &iter);
+      gtk_tree_path_free (path);
+    }
+}
+
+
+
 gboolean
 xfce_appfinder_category_model_row_separator_func (GtkTreeModel *tree_model,
                                                   GtkTreeIter  *iter,
                                                   gpointer      user_data)
 {
-  return ((GSList *) iter->user_data)->data == NULL;
+  Categoryitem *item = ITER_GET_DATA (iter);
+
+  g_return_val_if_fail (XFCE_IS_APPFINDER_CATEGORY_MODEL (tree_model), FALSE);
+
+  return (item->directory == NULL);
 }
diff --git a/xfce4-appfinder/merge-with-xfrun/demo-code/c/appfinder-category-model.h b/xfce4-appfinder/merge-with-xfrun/demo-code/c/appfinder-category-model.h
index 1f8d719..13951cd 100644
--- a/xfce4-appfinder/merge-with-xfrun/demo-code/c/appfinder-category-model.h
+++ b/xfce4-appfinder/merge-with-xfrun/demo-code/c/appfinder-category-model.h
@@ -26,13 +26,16 @@ enum
 
 
 
-GType                       xfce_appfinder_category_model_get_type          (void) G_GNUC_CONST;
+GType                       xfce_appfinder_category_model_get_type           (void) G_GNUC_CONST;
 
-XfceAppfinderCategoryModel *xfce_appfinder_category_model_new               (void) G_GNUC_MALLOC;
+XfceAppfinderCategoryModel *xfce_appfinder_category_model_new                (void) G_GNUC_MALLOC;
 
-gboolean                   xfce_appfinder_category_model_row_separator_func (GtkTreeModel *tree_model,
-                                                                             GtkTreeIter  *iter,
-                                                                             gpointer      user_data);
+void                        xfce_appfinder_category_model_set_categories     (XfceAppfinderCategoryModel *model,
+                                                                              GSList                     *categories);
+
+gboolean                    xfce_appfinder_category_model_row_separator_func (GtkTreeModel               *tree_model,
+                                                                              GtkTreeIter                *iter,
+                                                                              gpointer                    user_data);
 
 G_END_DECLS
 
diff --git a/xfce4-appfinder/merge-with-xfrun/demo-code/c/appfinder-model.c b/xfce4-appfinder/merge-with-xfrun/demo-code/c/appfinder-model.c
index aa3e89d..4bdc7d9 100644
--- a/xfce4-appfinder/merge-with-xfrun/demo-code/c/appfinder-model.c
+++ b/xfce4-appfinder/merge-with-xfrun/demo-code/c/appfinder-model.c
@@ -60,8 +60,13 @@ struct _XfceAppfinderModel
   GSList            *items;
   GarconMenu        *menu;
 
-  gint               collect_idle_id;
+  gchar             *filter_category;
+  gchar             *filter_string;
+  guint              filter_idle_id;
+
+  guint              collect_idle_id;
   GSList            *collect_items;
+  GSList            *collect_categories;
   GThread           *collect_thread;
   volatile gboolean  collect_cancelled;
 };
@@ -72,9 +77,21 @@ typedef struct
   GdkPixbuf      *pixbuf;
   gchar          *key;
   gchar          *abstract;
+  gchar          *category;
+  guint           visible : 1;
 }
 ModelItem;
 
+enum
+{
+  CATEGORIES_CHANGED,
+  LAST_SIGNAL
+};
+
+
+
+static guint    model_signals[LAST_SIGNAL];
+
 
 
 G_DEFINE_TYPE_WITH_CODE (XfceAppfinderModel, xfce_appfinder_model, G_TYPE_OBJECT,
@@ -89,6 +106,15 @@ xfce_appfinder_model_class_init (XfceAppfinderModelClass *klass)
 
   gobject_class = G_OBJECT_CLASS (klass);
   gobject_class->finalize = xfce_appfinder_model_finalize;
+
+  model_signals[CATEGORIES_CHANGED] =
+    g_signal_new (g_intern_static_string ("categories-changed"),
+                  G_TYPE_FROM_CLASS (gobject_class),
+                  G_SIGNAL_RUN_LAST,
+                  0, NULL, NULL,
+                  g_cclosure_marshal_VOID__POINTER,
+                  G_TYPE_NONE, 1,
+                  G_TYPE_POINTER /* GSList */);
 }
 
 
@@ -100,8 +126,7 @@ xfce_appfinder_model_init (XfceAppfinderModel *model)
   model->stamp = g_random_int ();
 
   model->menu = garcon_menu_new_applications ();
-  model->collect_thread = g_thread_create_full (xfce_appfinder_model_collect_thread, model,
-                                                0, TRUE, FALSE, G_THREAD_PRIORITY_LOW, NULL);
+  model->collect_thread = g_thread_create (xfce_appfinder_model_collect_thread, model, TRUE, NULL);
 }
 
 
@@ -130,11 +155,27 @@ xfce_appfinder_model_finalize (GObject *object)
 {
   XfceAppfinderModel *model = XFCE_APPFINDER_MODEL (object);
 
+  /* join the collector thread */
+  model->collect_cancelled = TRUE;
+  g_thread_join (model->collect_thread);
+
+  /* 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_object_unref (G_OBJECT (model->menu));
 
   g_slist_foreach (model->items, (GFunc) xfce_appfinder_model_item_free, NULL);
   g_slist_free (model->items);
 
+  if (G_UNLIKELY (model->filter_idle_id != 0))
+    g_source_remove (model->filter_idle_id);
+
+  g_free (model->filter_category);
+  g_free (model->filter_string);
+
   (*G_OBJECT_CLASS (xfce_appfinder_model_parent_class)->finalize) (object);
 }
 
@@ -170,6 +211,9 @@ xfce_appfinder_model_get_column_type (GtkTreeModel *tree_model,
     case XFCE_APPFINDER_MODEL_COLUMN_ICON:
       return GDK_TYPE_PIXBUF;
 
+    case XFCE_APPFINDER_MODEL_COLUMN_VISIBLE:
+      return G_TYPE_BOOLEAN;
+
     default:
       g_assert_not_reached ();
       return G_TYPE_INVALID;
@@ -229,7 +273,7 @@ xfce_appfinder_model_get_value (GtkTreeModel *tree_model,
   g_return_if_fail (XFCE_IS_APPFINDER_MODEL (model));
   g_return_if_fail (iter->stamp == model->stamp);
 
-  item = ((GSList *) iter->user_data)->data;
+  item = ITER_GET_DATA (iter);
   g_return_if_fail (item->item == NULL || GARCON_IS_MENU_ITEM (item->item));
 
   switch (column)
@@ -277,6 +321,11 @@ xfce_appfinder_model_get_value (GtkTreeModel *tree_model,
       g_value_set_static_string (value, garcon_menu_item_get_icon_name (item->item));
       break;
 
+    case XFCE_APPFINDER_MODEL_COLUMN_VISIBLE:
+      g_value_init (value, G_TYPE_BOOLEAN);
+      g_value_set_boolean (value, item->visible);
+      break;
+
     default:
       g_assert_not_reached ();
       break;
@@ -401,8 +450,7 @@ xfce_appfinder_model_collect_idle (gpointer user_data)
       li->next = NULL;
 
       /* generate the iterator */
-      iter.stamp = model->stamp;
-      iter.user_data = li;
+      ITER_INIT (iter, model->stamp, li);
 
       /* emit the "row-inserted" signal */
       gtk_tree_model_row_inserted (GTK_TREE_MODEL (model), path, &iter);
@@ -415,6 +463,15 @@ xfce_appfinder_model_collect_idle (gpointer user_data)
     }
   gtk_tree_path_free (path);
 
+  /* 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);
+      model->collect_categories = NULL;
+    }
+
   GDK_THREADS_LEAVE ();
 
   g_message ("insert idle end");
@@ -448,6 +505,19 @@ 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)
 {
@@ -457,18 +527,33 @@ xfce_appfinder_model_item_free (gpointer data)
     g_object_unref (G_OBJECT (item->pixbuf));
   g_free (item->abstract);
   g_free (item->key);
+  g_free (item->category);
   g_slice_free (ModelItem, item);
 }
 
 
 
-static void
-xfce_appfinder_model_collect_items (XfceAppfinderModel  *model,
-                                    GarconMenu          *menu)
+static gboolean
+xfce_appfinder_model_collect_items (XfceAppfinderModel *model,
+                                    GarconMenu         *menu,
+                                    const gchar        *category)
 {
   GList               *elements, *li;
   GarconMenuDirectory *directory;
   ModelItem           *item;
+  gboolean             has_items = FALSE;
+
+  g_return_val_if_fail (GARCON_IS_MENU (menu), FALSE);
+
+  directory = garcon_menu_get_directory (menu);
+  if (directory != NULL)
+    {
+      if (!garcon_menu_directory_get_visible (directory))
+        return FALSE;
+
+      if (category == NULL)
+        category = garcon_menu_directory_get_name (directory);
+    }
 
   /* collect all the elements in this menu and its sub menus */
   elements = garcon_menu_get_elements (menu);
@@ -480,18 +565,28 @@ xfce_appfinder_model_collect_items (XfceAppfinderModel  *model,
             continue;
 
           item = g_slice_new0 (ModelItem);
+          item->visible = TRUE;
           item->item = li->data;
+          if (category != NULL)
+            item->category = g_utf8_collate_key (category, -1);
 
           model->collect_items = g_slist_prepend (model->collect_items, item);
+
+          has_items = TRUE;
         }
       else if (GARCON_IS_MENU (li->data))
         {
-          directory = garcon_menu_get_directory (li->data);
-          if (directory != NULL && garcon_menu_directory_get_visible (directory))
-            xfce_appfinder_model_collect_items (model, li->data);
+          if (xfce_appfinder_model_collect_items (model, li->data, category))
+            has_items = TRUE;
         }
     }
   g_list_free (elements);
+
+  if (directory != NULL
+      && has_items)
+    model->collect_categories = g_slist_prepend (model->collect_categories, directory);
+
+  return has_items;
 }
 
 
@@ -500,8 +595,7 @@ static gpointer
 xfce_appfinder_model_collect_thread (gpointer user_data)
 {
   XfceAppfinderModel *model = XFCE_APPFINDER_MODEL (user_data);
-  GError *error = NULL;
-  GList *menus, *li;
+  GError             *error = NULL;
 
   g_return_val_if_fail (GARCON_IS_MENU (model->menu), NULL);
   g_return_val_if_fail (model->collect_items == NULL, NULL);
@@ -512,10 +606,7 @@ xfce_appfinder_model_collect_thread (gpointer user_data)
     {
       if (garcon_menu_load (model->menu, NULL, &error))
         {
-          menus = garcon_menu_get_menus (model->menu);
-          for (li = menus; li != NULL && !model->collect_cancelled; li = li->next)
-            xfce_appfinder_model_collect_items (model, li->data);
-          g_list_free (menus);
+          xfce_appfinder_model_collect_items (model, model->menu, NULL);
         }
       else
         {
@@ -528,6 +619,8 @@ xfce_appfinder_model_collect_thread (gpointer user_data)
       && !model->collect_cancelled)
     {
       model->collect_items = g_slist_sort (model->collect_items, xfce_appfinder_model_item_compare);
+      model->collect_categories = g_slist_sort (model->collect_categories, xfce_appfinder_model_category_compare);
+
       model->collect_idle_id = g_idle_add_full (G_PRIORITY_LOW, xfce_appfinder_model_collect_idle,
                                                 model, xfce_appfinder_model_collect_idle_destroy);
     }
@@ -539,6 +632,72 @@ xfce_appfinder_model_collect_thread (gpointer user_data)
 
 
 
+static gboolean
+xfce_appfinder_model_filter_idle (gpointer data)
+{
+  XfceAppfinderModel *model = XFCE_APPFINDER_MODEL (data);
+  GSList             *li;
+  gint                idx;
+  ModelItem          *item;
+  gboolean            visible;
+  GtkTreeIter         iter;
+  GtkTreePath        *path;
+
+  GDK_THREADS_ENTER ();
+
+  for (li = model->items, idx = 0; li != NULL; li = li->next, idx++)
+    {
+      item = li->data;
+      visible = TRUE;
+
+      if (model->filter_category != NULL
+          && g_strcmp0 (model->filter_category, item->category) != 0)
+        visible = FALSE;
+
+      /*if (visible
+          && model->filter_string != NULL)
+        visible = FALSE;*/
+
+      if (item->visible != visible)
+        {
+          item->visible = visible;
+
+          /* generate an iterator for the path */
+          ITER_INIT (iter, model->stamp, li);
+
+          /* tell the view that the volume has changed in some way */
+          path = gtk_tree_path_new_from_indices (idx, -1);
+          gtk_tree_model_row_changed (GTK_TREE_MODEL (model), path, &iter);
+          gtk_tree_path_free (path);
+        }
+    }
+
+  GDK_THREADS_LEAVE ();
+
+  return FALSE;
+}
+
+
+
+static void
+xfce_appfinder_model_filter_idle_destroyed (gpointer data)
+{
+  XFCE_APPFINDER_MODEL (data)->filter_idle_id = 0;
+}
+
+
+static void
+xfce_appfinder_model_filter (XfceAppfinderModel *model)
+{
+  if (model->filter_idle_id == 0)
+    {
+      model->filter_idle_id = g_idle_add_full (G_PRIORITY_LOW, xfce_appfinder_model_filter_idle,
+                                               model, xfce_appfinder_model_filter_idle_destroyed);
+    }
+}
+
+
+
 XfceAppfinderModel *
 xfce_appfinder_model_new (void)
 {
@@ -547,6 +706,38 @@ xfce_appfinder_model_new (void)
 
 
 
+void
+xfce_appfinder_model_filter_category (XfceAppfinderModel *model,
+                                      const gchar        *category)
+{
+  g_return_if_fail (XFCE_IS_APPFINDER_MODEL (model));
+
+  g_free (model->filter_category);
+
+  if (category != NULL)
+    model->filter_category = g_utf8_collate_key (category, -1);
+  else
+    model->filter_category = NULL;
+
+  xfce_appfinder_model_filter (model);
+}
+
+
+
+void
+xfce_appfinder_model_filter_string (XfceAppfinderModel *model,
+                                    const gchar        *seach_string)
+{
+  g_return_if_fail (XFCE_IS_APPFINDER_MODEL (model));
+
+  g_free (model->filter_string);
+  model->filter_string = g_strdup (seach_string);
+
+  xfce_appfinder_model_filter (model);
+}
+
+
+
 GdkPixbuf *
 xfce_appfinder_model_load_pixbuf (const gchar *icon_name,
                                   gint         size)
diff --git a/xfce4-appfinder/merge-with-xfrun/demo-code/c/appfinder-model.h b/xfce4-appfinder/merge-with-xfrun/demo-code/c/appfinder-model.h
index c3eeb5b..2cf37e9 100644
--- a/xfce4-appfinder/merge-with-xfrun/demo-code/c/appfinder-model.h
+++ b/xfce4-appfinder/merge-with-xfrun/demo-code/c/appfinder-model.h
@@ -15,7 +15,12 @@ typedef struct _XfceAppfinderModel      XfceAppfinderModel;
 #define XFCE_IS_APPFINDER_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XFCE_TYPE_APPFINDER_MODEL))
 #define XFCE_APPFINDER_MODEL_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), XFCE_TYPE_APPFINDER_MODEL, XfceAppfinderModelClass))
 
-
+#define ITER_GET_DATA(iter)          (((GSList *) (iter)->user_data)->data)
+#define ITER_INIT(iter, iter_stamp, iter_data) \
+G_STMT_START { \
+  (iter).stamp = iter_stamp; \
+  (iter).user_data = iter_data; \
+} G_STMT_END
 
 enum
 {
@@ -23,17 +28,24 @@ enum
   XFCE_APPFINDER_MODEL_COLUMN_ICON,
   XFCE_APPFINDER_MODEL_COLUMN_KEY,
   XFCE_APPFINDER_MODEL_COLUMN_ICON_NAME,
+  XFCE_APPFINDER_MODEL_COLUMN_VISIBLE,
   XFCE_APPFINDER_MODEL_N_COLUMNS,
 };
 
 
 
-GType               xfce_appfinder_model_get_type               (void) G_GNUC_CONST;
+GType               xfce_appfinder_model_get_type             (void) G_GNUC_CONST;
+
+XfceAppfinderModel *xfce_appfinder_model_new                  (void) G_GNUC_MALLOC;
+
+void                xfce_appfinder_model_filter_category      (XfceAppfinderModel *model,
+                                                               const gchar        *category);
 
-XfceAppfinderModel *xfce_appfinder_model_new                    (void) G_GNUC_MALLOC;
+void                xfce_appfinder_model_filter_string        (XfceAppfinderModel *model,
+                                                               const gchar        *seach_string);
 
-GdkPixbuf          *xfce_appfinder_model_load_pixbuf            (const gchar *icon_name,
-                                                                 gint         size) G_GNUC_MALLOC;
+GdkPixbuf          *xfce_appfinder_model_load_pixbuf          (const gchar        *icon_name,
+                                                               gint                size) G_GNUC_MALLOC;
 
 G_END_DECLS
 
diff --git a/xfce4-appfinder/merge-with-xfrun/demo-code/c/appfinder-window.c b/xfce4-appfinder/merge-with-xfrun/demo-code/c/appfinder-window.c
index 7c67222..397b122 100644
--- a/xfce4-appfinder/merge-with-xfrun/demo-code/c/appfinder-window.c
+++ b/xfce4-appfinder/merge-with-xfrun/demo-code/c/appfinder-window.c
@@ -11,18 +11,16 @@
 
 
 
-static void       xfce_appfinder_window_finalize            (GObject                     *object);
-static void       xfce_appfinder_window_set_padding         (GtkWidget                   *entry,
-                                                             GtkWidget                   *align);
-static GtkWidget *xfce_appfinder_window_buttonbox           (void);
-static void       xfce_appfinder_window_entry_icon_released (GtkEntry                    *entry,
-                                                             GtkEntryIconPosition         icon_pos,
-                                                             GdkEvent                    *event,
-                                                             XfceAppfinderWindow         *window);
-static gboolean   xfce_appfinder_window_match_selected      (GtkEntryCompletion          *widget,
-                                                             GtkTreeModel                *model,
-                                                             GtkTreeIter                 *iter,
-                                                             XfceAppfinderWindow         *window);
+static void       xfce_appfinder_window_finalize                 (GObject                     *object);
+static void       xfce_appfinder_window_set_padding              (GtkWidget                   *entry,
+                                                                  GtkWidget                   *align);
+static GtkWidget *xfce_appfinder_window_buttonbox                (void);
+static void       xfce_appfinder_window_entry_icon_released      (GtkEntry                    *entry,
+                                                                  GtkEntryIconPosition         icon_pos,
+                                                                  GdkEvent                    *event,
+                                                                  XfceAppfinderWindow         *window);
+static void       xfce_appfinder_window_category_changed         (GtkTreeSelection            *selection,
+                                                                  XfceAppfinderWindow         *window);
 
 struct _XfceAppfinderWindowClass
 {
@@ -76,13 +74,17 @@ xfce_appfinder_window_init (XfceAppfinderWindow *window)
   GtkWidget          *align;
   GtkTreeViewColumn  *column;
   GtkCellRenderer    *renderer;
-  GtkEntryCompletion *completion;
+  GtkTreeModel       *filter_model;
+  GtkTreeSelection   *selection;
 
   window->model = xfce_appfinder_model_new ();
   window->category_model = xfce_appfinder_category_model_new ();
+  g_signal_connect_swapped (G_OBJECT (window->model), "categories-changed",
+                            G_CALLBACK (xfce_appfinder_category_model_set_categories),
+                            window->category_model);
 
   gtk_window_set_title (GTK_WINDOW (window), _("Application Finder"));
-  gtk_window_set_default_size (GTK_WINDOW (window), 400 /* todo, remember */, -1);
+  gtk_window_set_default_size (GTK_WINDOW (window), 500 /* todo, remember */, -1);
   gtk_window_set_icon_name (GTK_WINDOW (window), GTK_STOCK_EXECUTE);
   g_signal_connect (G_OBJECT (window), "delete-event", G_CALLBACK (gtk_main_quit), NULL);
 
@@ -99,7 +101,7 @@ xfce_appfinder_window_init (XfceAppfinderWindow *window)
   gtk_box_pack_start (GTK_BOX (hbox), align, FALSE, FALSE, 0);
   gtk_widget_show (align);
 
-  window->image = image = gtk_image_new_from_icon_name ("preferences-desktop-theme", GTK_ICON_SIZE_DIALOG);
+  window->image = image = gtk_image_new_from_stock (GTK_STOCK_FIND, GTK_ICON_SIZE_DIALOG);
   gtk_container_add (GTK_CONTAINER (align), image);
   gtk_widget_show (image);
 
@@ -117,17 +119,6 @@ xfce_appfinder_window_init (XfceAppfinderWindow *window)
   g_signal_connect (G_OBJECT (entry), "realize", G_CALLBACK (xfce_appfinder_window_set_padding), align);
   gtk_widget_show (entry);
 
-  completion = gtk_entry_completion_new ();
-  gtk_entry_completion_set_model (completion, GTK_TREE_MODEL (window->model));
-  /*gtk_entry_completion_set_match_func (completion, xfce_appfinder_window_match_func, window, NULL);*/
-  gtk_entry_completion_set_text_column (completion, XFCE_APPFINDER_MODEL_COLUMN_KEY);
-  gtk_entry_completion_set_popup_completion (completion, TRUE);
-  gtk_entry_completion_set_popup_single_match (completion, FALSE);
-  gtk_entry_completion_set_inline_completion (completion, TRUE);
-  gtk_entry_set_completion (GTK_ENTRY (window->entry), completion);
-  g_signal_connect (G_OBJECT (completion), "match-selected", G_CALLBACK (xfce_appfinder_window_match_selected), window);
-  g_object_unref (G_OBJECT (completion));
-
   window->bbox1 = xfce_appfinder_window_buttonbox ();
   gtk_box_pack_start (GTK_BOX (vbox2), window->bbox1, FALSE, TRUE, 0);
 
@@ -148,9 +139,9 @@ xfce_appfinder_window_init (XfceAppfinderWindow *window)
   gtk_container_add (GTK_CONTAINER (scroll), sidepane);
   gtk_widget_show (sidepane);
 
-  /*selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (sidepane));
-  g_signal_connect_swapped (G_OBJECT (selection), "changed",
-      G_CALLBACK (xfce_appfinder_window_category_changed), window);*/
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (sidepane));
+  g_signal_connect (G_OBJECT (selection), "changed",
+      G_CALLBACK (xfce_appfinder_window_category_changed), window);
 
   column = gtk_tree_view_column_new ();
   gtk_tree_view_append_column (GTK_TREE_VIEW (sidepane), GTK_TREE_VIEW_COLUMN (column));
@@ -172,19 +163,27 @@ xfce_appfinder_window_init (XfceAppfinderWindow *window)
   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
   gtk_widget_show (scroll);
 
-  treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (window->model));
+  filter_model = gtk_tree_model_filter_new (GTK_TREE_MODEL (window->model), NULL);
+  gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), XFCE_APPFINDER_MODEL_COLUMN_VISIBLE);
+
+  treeview = gtk_tree_view_new_with_model (filter_model);
   gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
   /* gtk_tree_view_set_tooltip_column (GTK_TREE_VIEW (treeview), XFCE_RUN_MODEL_COLUMN_TOOLTIP); */
   gtk_container_add (GTK_CONTAINER (scroll), treeview);
   gtk_widget_show (treeview);
+  g_object_unref (G_OBJECT (filter_model));
 
   renderer = gtk_cell_renderer_pixbuf_new ();
-  column = gtk_tree_view_column_new_with_attributes (NULL, renderer, "pixbuf", XFCE_APPFINDER_MODEL_COLUMN_ICON, NULL);
+  column = gtk_tree_view_column_new_with_attributes (NULL, renderer,
+                                                     "pixbuf", XFCE_APPFINDER_MODEL_COLUMN_ICON,
+                                                     NULL);
   gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), GTK_TREE_VIEW_COLUMN (column));
 
   renderer = gtk_cell_renderer_text_new ();
   g_object_set (renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
-  column = gtk_tree_view_column_new_with_attributes (NULL, renderer, "markup", XFCE_APPFINDER_MODEL_COLUMN_ABSTRACT, NULL);
+  column = gtk_tree_view_column_new_with_attributes (NULL, renderer,
+                                                     "markup", XFCE_APPFINDER_MODEL_COLUMN_ABSTRACT,
+                                                     NULL);
   gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), GTK_TREE_VIEW_COLUMN (column));
 
   window->bbox2 = xfce_appfinder_window_buttonbox ();
@@ -262,30 +261,25 @@ xfce_appfinder_window_entry_icon_released (GtkEntry             *entry,
 
 
 
-static gboolean
-xfce_appfinder_window_match_selected (GtkEntryCompletion  *widget,
-                                      GtkTreeModel        *model,
-                                      GtkTreeIter         *iter,
-                                      XfceAppfinderWindow *window)
+static void
+xfce_appfinder_window_category_changed (GtkTreeSelection    *selection,
+                                        XfceAppfinderWindow *window)
 {
-  gchar     *icon_name;
-  GdkPixbuf *pixbuf;
+  GtkTreeIter   iter;
+  GtkTreeModel *model;
+  gchar        *category;
 
-  gtk_tree_model_get (model, iter, XFCE_APPFINDER_MODEL_COLUMN_ICON_NAME, &icon_name, -1);
-  pixbuf = xfce_appfinder_model_load_pixbuf (icon_name, 48);
-  g_free (icon_name);
-
-  if (G_LIKELY (pixbuf != NULL))
-    {
-      gtk_image_set_from_pixbuf (GTK_IMAGE (window->image), pixbuf);
-      g_object_unref (G_OBJECT (pixbuf));
-    }
-  else
+  if (gtk_tree_selection_get_selected (selection, &model, &iter))
     {
-      gtk_image_clear (GTK_IMAGE (window->image));
-    }
+      gtk_tree_model_get (model, &iter, XFCE_APPFINDER_CATEGORY_MODEL_COLUMN_NAME, &category, -1);
 
-  return FALSE;
+      if (g_utf8_collate (category, _("All Applications")) == 0)
+        xfce_appfinder_model_filter_category (window->model, NULL);
+      else
+        xfce_appfinder_model_filter_category (window->model, category);
+
+      g_free (category);
+    }
 }
 
 
@@ -309,7 +303,7 @@ xfce_appfinder_window_set_expanded (XfceAppfinderWindow *window,
     {
       gtk_window_set_geometry_hints (GTK_WINDOW (window), NULL, NULL, 0);
       gtk_window_get_size (GTK_WINDOW (window), &width, NULL);
-      gtk_window_resize (GTK_WINDOW (window), width, 500);
+      gtk_window_resize (GTK_WINDOW (window), width, 400);
     }
   else
     {



More information about the Xfce4-commits mailing list