[gnome-control-center] shell: Use CcShellMode to do the panels filtering



commit eb3dfe9b77a3139acda58fde048c0c7af66f7b95
Author: Giovanni Campagna <gcampagna src gnome org>
Date:   Tue Jan 15 11:37:24 2013 +0100

    shell: Use CcShellMode to do the panels filtering
    
    https://bugzilla.gnome.org/show_bug.cgi?id=690577

 shell/Makefile.am              |    2 +
 shell/cc-shell-category-view.c |    3 +-
 shell/cc-shell-item-view.c     |    9 +--
 shell/cc-shell-model.c         |  151 ++++++++++++++++++---------------------
 shell/cc-shell-model.h         |    9 ++-
 shell/cc-util.c                |  105 ++++++++++++++++++++++++++++
 shell/cc-util.h                |   28 ++++++++
 shell/gnome-control-center.c   |   58 ++-------------
 8 files changed, 225 insertions(+), 140 deletions(-)
---
diff --git a/shell/Makefile.am b/shell/Makefile.am
index 75454e3..f2eae95 100644
--- a/shell/Makefile.am
+++ b/shell/Makefile.am
@@ -33,6 +33,8 @@ gnome_control_center_SOURCES =			\
 	cc-panel.h				\
 	cc-shell.c				\
 	cc-shell.h				\
+	cc-util.c				\
+	cc-util.h				\
 	hostname-helper.c			\
 	hostname-helper.h			\
 	cc-hostname-entry.c			\
diff --git a/shell/cc-shell-category-view.c b/shell/cc-shell-category-view.c
index edf87ef..c924bd0 100644
--- a/shell/cc-shell-category-view.c
+++ b/shell/cc-shell-category-view.c
@@ -129,11 +129,12 @@ cc_shell_category_view_constructed (GObject *object)
   renderer = gtk_cell_renderer_pixbuf_new ();
   g_object_set (renderer,
                 "follow-state", TRUE,
+                "stock-size", GTK_ICON_SIZE_DIALOG,
                 NULL);
   gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (iconview),
                               renderer, FALSE);
   gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (iconview), renderer,
-                                 "pixbuf", COL_PIXBUF);
+                                 "gicon", COL_GICON);
 
   gtk_icon_view_set_text_column (GTK_ICON_VIEW (iconview), COL_NAME);
   gtk_icon_view_set_item_width (GTK_ICON_VIEW (iconview), 100);
diff --git a/shell/cc-shell-item-view.c b/shell/cc-shell-item-view.c
index 4b41d4c..cc8ae98 100644
--- a/shell/cc-shell-item-view.c
+++ b/shell/cc-shell-item-view.c
@@ -123,7 +123,7 @@ iconview_item_activated_cb (GtkIconView     *icon_view,
 {
   GtkTreeModel *model;
   GtkTreeIter iter;
-  gchar *name, *desktop_file, *id;
+  gchar *name, *id;
 
   model = gtk_icon_view_get_model (icon_view);
 
@@ -135,14 +135,12 @@ iconview_item_activated_cb (GtkIconView     *icon_view,
 
   gtk_tree_model_get (model, &iter,
                       COL_NAME, &name,
-                      COL_DESKTOP_FILE, &desktop_file,
                       COL_ID, &id,
                       -1);
 
   g_signal_emit (cc_view, signals[DESKTOP_ITEM_ACTIVATED], 0,
-                 name, id, desktop_file);
+                 name, id);
 
-  g_free (desktop_file);
   g_free (name);
   g_free (id);
 }
@@ -187,8 +185,7 @@ cc_shell_item_view_class_init (CcShellItemViewClass *klass)
                                                   NULL,
                                                   g_cclosure_marshal_generic,
                                                   G_TYPE_NONE,
-                                                  3,
-                                                  G_TYPE_STRING,
+                                                  2,
                                                   G_TYPE_STRING,
                                                   G_TYPE_STRING);
 }
diff --git a/shell/cc-shell-model.c b/shell/cc-shell-model.c
index fafd648..2add15e 100644
--- a/shell/cc-shell-model.c
+++ b/shell/cc-shell-model.c
@@ -19,11 +19,13 @@
  * Author: Thomas Wood <thos gnome org>
  */
 
-#include "cc-shell-model.h"
 #include <string.h>
 
 #include <gio/gdesktopappinfo.h>
 
+#include "cc-shell-model.h"
+#include "cc-util.h"
+
 #define GNOME_SETTINGS_PANEL_ID_KEY "X-GNOME-Settings-Panel"
 #define GNOME_SETTINGS_PANEL_CATEGORY GNOME_SETTINGS_PANEL_ID_KEY
 #define GNOME_SETTINGS_PANEL_ID_KEYWORDS "Keywords"
@@ -31,73 +33,6 @@
 
 G_DEFINE_TYPE (CcShellModel, cc_shell_model, GTK_TYPE_LIST_STORE)
 
-static GdkPixbuf *
-load_pixbuf_for_gicon (GIcon *icon)
-{
-  GtkIconTheme *theme;
-  GtkIconInfo *icon_info;
-  GdkPixbuf *pixbuf = NULL;
-  GError *err = NULL;
-
-  if (icon == NULL)
-    return NULL;
-
-  theme = gtk_icon_theme_get_default ();
-
-  icon_info = gtk_icon_theme_lookup_by_gicon (theme, icon,
-                                              48, GTK_ICON_LOOKUP_FORCE_SIZE);
-  if (icon_info)
-    {
-      pixbuf = gtk_icon_info_load_icon (icon_info, &err);
-      if (err)
-        {
-          g_warning ("Could not load icon '%s': %s",
-                     gtk_icon_info_get_filename (icon_info), err->message);
-          g_error_free (err);
-        }
-
-      gtk_icon_info_free (icon_info);
-    }
-  else
-    {
-      char *name;
-
-      name = g_icon_to_string (icon);
-      g_warning ("Could not find icon '%s'", name);
-      g_free (name);
-    }
-
-  return pixbuf;
-}
-
-static void
-icon_theme_changed (GtkIconTheme *theme,
-                    CcShellModel *self)
-{
-  GtkTreeIter iter;
-  GtkTreeModel *model;
-  gboolean cont;
-
-  model = GTK_TREE_MODEL (self);
-  cont = gtk_tree_model_get_iter_first (model, &iter);
-  while (cont)
-    {
-      GdkPixbuf *pixbuf;
-      GIcon *icon;
-
-      gtk_tree_model_get (model, &iter,
-                          COL_GICON, &icon,
-                          -1);
-      pixbuf = load_pixbuf_for_gicon (icon);
-      g_object_unref (icon);
-      gtk_list_store_set (GTK_LIST_STORE (model), &iter,
-                          COL_PIXBUF, pixbuf,
-                          -1);
-
-      cont = gtk_tree_model_iter_next (model, &iter);
-    }
-}
-
 static void
 cc_shell_model_class_init (CcShellModelClass *klass)
 {
@@ -106,17 +41,14 @@ cc_shell_model_class_init (CcShellModelClass *klass)
 static void
 cc_shell_model_init (CcShellModel *self)
 {
-  GType types[] = {G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
-      GDK_TYPE_PIXBUF, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_ICON, G_TYPE_STRV};
+  GType types[] = {G_TYPE_STRING, G_TYPE_STRING, G_TYPE_APP_INFO, G_TYPE_STRING,
+                   G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_ICON, G_TYPE_STRV};
 
   gtk_list_store_set_column_types (GTK_LIST_STORE (self),
                                    N_COLS, types);
 
   gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (self), COL_NAME,
                                         GTK_SORT_ASCENDING);
-
-  g_signal_connect (G_OBJECT (gtk_icon_theme_get_default ()), "changed",
-                    G_CALLBACK (icon_theme_changed), self);
 }
 
 CcShellModel *
@@ -125,6 +57,24 @@ cc_shell_model_new (void)
   return g_object_new (CC_TYPE_SHELL_MODEL, NULL);
 }
 
+static char **
+get_casefolded_keywords (GAppInfo *appinfo)
+{
+  const char * const * keywords;
+  char **casefolded_keywords;
+  int i, n;
+
+  keywords = g_desktop_app_info_get_keywords (G_DESKTOP_APP_INFO (appinfo));
+  n = keywords ? g_strv_length ((char**) keywords) : 0;
+  casefolded_keywords = g_new (char*, n+1);
+
+  for (i = 0; i < n; i++)
+    casefolded_keywords[i] = cc_util_normalize_casefold_and_unaccent (keywords[i]);
+  casefolded_keywords[n] = NULL;
+
+  return casefolded_keywords;
+}
+
 void
 cc_shell_model_add_item (CcShellModel    *model,
                          CcPanelCategory  category,
@@ -133,23 +83,62 @@ cc_shell_model_add_item (CcShellModel    *model,
 {
   GIcon       *icon = g_app_info_get_icon (appinfo);
   const gchar *name = g_app_info_get_name (appinfo);
-  const gchar *desktop = g_desktop_app_info_get_filename (G_DESKTOP_APP_INFO (appinfo));
   const gchar *comment = g_app_info_get_description (appinfo);
-  GdkPixbuf *pixbuf = NULL;
-  const char * const * keywords;
-
-  keywords = g_desktop_app_info_get_keywords (G_DESKTOP_APP_INFO (appinfo));
+  char **keywords;
+  char *casefolded_name, *casefolded_description;
 
-  pixbuf = load_pixbuf_for_gicon (icon);
+  casefolded_name = cc_util_normalize_casefold_and_unaccent (name);
+  casefolded_description = cc_util_normalize_casefold_and_unaccent (comment);
+  keywords = get_casefolded_keywords (appinfo);
 
   gtk_list_store_insert_with_values (GTK_LIST_STORE (model), NULL, 0,
                                      COL_NAME, name,
-                                     COL_DESKTOP_FILE, desktop,
+                                     COL_CASEFOLDED_NAME, casefolded_name,
+                                     COL_APP, appinfo,
                                      COL_ID, id,
-                                     COL_PIXBUF, pixbuf,
                                      COL_CATEGORY, category,
                                      COL_DESCRIPTION, comment,
+                                     COL_CASEFOLDED_DESCRIPTION, casefolded_description,
                                      COL_GICON, icon,
                                      COL_KEYWORDS, keywords,
                                      -1);
+
+  g_free (casefolded_name);
+  g_free (casefolded_description);
+  g_strfreev (keywords);
+}
+
+gboolean
+cc_shell_model_iter_matches_search (CcShellModel *model,
+                                    GtkTreeIter  *iter,
+                                    const char   *term)
+{
+  gchar *name, *description;
+  gboolean result;
+  gchar **keywords;
+
+  gtk_tree_model_get (GTK_TREE_MODEL (model), iter,
+                      COL_CASEFOLDED_NAME, &name,
+                      COL_CASEFOLDED_DESCRIPTION, &description,
+                      COL_KEYWORDS, &keywords,
+                      -1);
+
+  result = (strstr (name, term) != NULL);
+
+  if (!result && description)
+    result = (strstr (description, term) != NULL);
+
+  if (!result && keywords)
+    {
+      gint i;
+
+      for (i = 0; !result && keywords[i]; i++)
+        result = (strstr (keywords[i], term) == keywords[i]);
+    }
+
+  g_free (name);
+  g_free (description);
+  g_strfreev (keywords);
+
+  return result;
 }
diff --git a/shell/cc-shell-model.h b/shell/cc-shell-model.h
index b2e92fd..f92c25f 100644
--- a/shell/cc-shell-model.h
+++ b/shell/cc-shell-model.h
@@ -61,11 +61,12 @@ typedef enum {
 enum
 {
   COL_NAME,
-  COL_DESKTOP_FILE,
+  COL_CASEFOLDED_NAME,
+  COL_APP,
   COL_ID,
-  COL_PIXBUF,
   COL_CATEGORY,
   COL_DESCRIPTION,
+  COL_CASEFOLDED_DESCRIPTION,
   COL_GICON,
   COL_KEYWORDS,
 
@@ -91,6 +92,10 @@ void cc_shell_model_add_item (CcShellModel   *model,
                               GAppInfo       *appinfo,
                               const char     *id);
 
+gboolean cc_shell_model_iter_matches_search (CcShellModel *model,
+                                             GtkTreeIter  *iter,
+                                             const char   *term);
+
 G_END_DECLS
 
 #endif /* _CC_SHELL_MODEL_H */
diff --git a/shell/cc-util.c b/shell/cc-util.c
new file mode 100644
index 0000000..e51a9d2
--- /dev/null
+++ b/shell/cc-util.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2012 Giovanni Campagna <scampa giovanni gmail com>
+ *
+ * The Control Center is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * The Control Center is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with the Control Center; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+
+#include "cc-util.h"
+
+/* Combining diacritical mark?
+ *  Basic range: [0x0300,0x036F]
+ *  Supplement:  [0x1DC0,0x1DFF]
+ *  For Symbols: [0x20D0,0x20FF]
+ *  Half marks:  [0xFE20,0xFE2F]
+ */
+#define IS_CDM_UCS4(c) (((c) >= 0x0300 && (c) <= 0x036F)  || \
+                        ((c) >= 0x1DC0 && (c) <= 0x1DFF)  || \
+                        ((c) >= 0x20D0 && (c) <= 0x20FF)  || \
+                        ((c) >= 0xFE20 && (c) <= 0xFE2F))
+
+/* Copied from tracker/src/libtracker-fts/tracker-parser-glib.c under the GPL
+ * And then from gnome-shell/src/shell-util.c
+ *
+ * Originally written by Aleksander Morgado <aleksander gnu org>
+ */
+char *
+cc_util_normalize_casefold_and_unaccent (const char *str)
+{
+  char *normalized, *tmp;
+  int i = 0, j = 0, ilen;
+
+  if (str == NULL)
+    return NULL;
+
+  normalized = g_utf8_normalize (str, -1, G_NORMALIZE_NFKD);
+  tmp = g_utf8_casefold (normalized, -1);
+  g_free (normalized);
+
+  ilen = strlen (tmp);
+
+  while (i < ilen)
+    {
+      gunichar unichar;
+      gchar *next_utf8;
+      gint utf8_len;
+
+      /* Get next character of the word as UCS4 */
+      unichar = g_utf8_get_char_validated (&tmp[i], -1);
+
+      /* Invalid UTF-8 character or end of original string. */
+      if (unichar == (gunichar) -1 ||
+          unichar == (gunichar) -2)
+        {
+          break;
+        }
+
+      /* Find next UTF-8 character */
+      next_utf8 = g_utf8_next_char (&tmp[i]);
+      utf8_len = next_utf8 - &tmp[i];
+
+      if (IS_CDM_UCS4 ((guint32) unichar))
+        {
+          /* If the given unichar is a combining diacritical mark,
+           * just update the original index, not the output one */
+          i += utf8_len;
+          continue;
+        }
+
+      /* If already found a previous combining
+       * diacritical mark, indexes are different so
+       * need to copy characters. As output and input
+       * buffers may overlap, need to use memmove
+       * instead of memcpy */
+      if (i != j)
+        {
+          memmove (&tmp[j], &tmp[i], utf8_len);
+        }
+
+      /* Update both indexes */
+      i += utf8_len;
+      j += utf8_len;
+    }
+
+  /* Force proper string end */
+  tmp[j] = '\0';
+
+  return tmp;
+}
diff --git a/shell/cc-util.h b/shell/cc-util.h
new file mode 100644
index 0000000..42b09ff
--- /dev/null
+++ b/shell/cc-util.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2012 Giovanni Campagna <scampa giovanni gmail com>
+ *
+ * The Control Center is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * The Control Center is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with the Control Center; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+
+#ifndef _CC_UTIL_H
+#define _CC_UTIL_H
+
+#include <glib.h>
+
+char *cc_util_normalize_casefold_and_unaccent (const char *str);
+
+#endif
diff --git a/shell/gnome-control-center.c b/shell/gnome-control-center.c
index 0f1a675..145b0b9 100644
--- a/shell/gnome-control-center.c
+++ b/shell/gnome-control-center.c
@@ -40,6 +40,7 @@
 #include "cc-shell-category-view.h"
 #include "cc-shell-model.h"
 #include "cc-panel-loader.h"
+#include "cc-util.h"
 
 G_DEFINE_TYPE (GnomeControlCenter, gnome_control_center, CC_TYPE_SHELL)
 
@@ -176,7 +177,6 @@ static gboolean
 activate_panel (GnomeControlCenter *shell,
                 const gchar        *id,
 		const gchar       **argv,
-                const gchar        *desktop_file,
                 const gchar        *name,
                 GIcon              *gicon)
 {
@@ -184,8 +184,6 @@ activate_panel (GnomeControlCenter *shell,
   GtkWidget *box;
   const gchar *icon_name;
 
-  if (!desktop_file)
-    return FALSE;
   if (!id)
     return FALSE;
 
@@ -580,47 +578,12 @@ model_filter_func (GtkTreeModel              *model,
                    GtkTreeIter               *iter,
                    GnomeControlCenterPrivate *priv)
 {
-  gchar *name;
-  gchar *needle, *haystack;
-  gboolean result;
-  gchar **keywords;
-
-  gtk_tree_model_get (model, iter,
-                      COL_NAME, &name,
-                      COL_KEYWORDS, &keywords,
-                      -1);
-
-  if (!priv->filter_string || !name)
-    {
-      g_free (name);
-      g_strfreev (keywords);
-      return FALSE;
-    }
-
-  needle = g_utf8_casefold (priv->filter_string, -1);
-  haystack = g_utf8_casefold (name, -1);
-
-  result = (strstr (haystack, needle) != NULL);
-
-  if (!result && keywords)
-    {
-      gint i;
-      gchar *keyword;
-
-      for (i = 0; !result && keywords[i]; i++)
-        {
-          keyword = g_utf8_casefold (keywords[i], -1);
-          result = strstr (keyword, needle) == keyword;
-          g_free (keyword);
-        }
-    }
-
-  g_free (name);
-  g_free (haystack);
-  g_free (needle);
-  g_strfreev (keywords);
+  if (!priv->filter_string)
+    return FALSE;
 
-  return result;
+  return cc_shell_model_iter_matches_search (CC_SHELL_MODEL (model),
+                                             iter,
+                                             priv->filter_string);
 }
 
 static gboolean
@@ -647,7 +610,7 @@ search_entry_changed_cb (GtkEntry           *entry,
     return;
 
   /* Don't re-filter for added trailing or leading spaces */
-  str = g_strdup (gtk_entry_get_text (entry));
+  str = cc_util_normalize_casefold_and_unaccent (gtk_entry_get_text (entry));
   g_strstrip (str);
   if (!g_strcmp0 (str, priv->filter_string))
     {
@@ -991,7 +954,6 @@ _shell_set_active_panel_from_id (CcShell      *shell,
   GtkTreeIter iter;
   gboolean iter_valid;
   gchar *name = NULL;
-  gchar *desktop = NULL;
   GIcon *gicon = NULL;
   GnomeControlCenterPrivate *priv = GNOME_CONTROL_CENTER (shell)->priv;
   GtkWidget *old_panel;
@@ -1016,7 +978,6 @@ _shell_set_active_panel_from_id (CcShell      *shell,
 
       gtk_tree_model_get (GTK_TREE_MODEL (priv->store), &iter,
                           COL_NAME, &name,
-                          COL_DESKTOP_FILE, &desktop,
                           COL_GICON, &gicon,
                           COL_ID, &id,
                           -1);
@@ -1030,13 +991,11 @@ _shell_set_active_panel_from_id (CcShell      *shell,
         {
           g_free (id);
           g_free (name);
-          g_free (desktop);
 	  if (gicon)
 	    g_object_unref (gicon);
 
           name = NULL;
           id = NULL;
-          desktop = NULL;
           gicon = NULL;
         }
 
@@ -1050,7 +1009,7 @@ _shell_set_active_panel_from_id (CcShell      *shell,
     {
       g_warning ("Could not find settings panel \"%s\"", start_id);
     }
-  else if (activate_panel (GNOME_CONTROL_CENTER (shell), start_id, argv, desktop,
+  else if (activate_panel (GNOME_CONTROL_CENTER (shell), start_id, argv,
                            name, gicon) == FALSE)
     {
       /* Failed to activate the panel for some reason,
@@ -1067,7 +1026,6 @@ _shell_set_active_panel_from_id (CcShell      *shell,
     }
 
   g_free (name);
-  g_free (desktop);
   if (gicon)
     g_object_unref (gicon);
 



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