[gnome-control-center] region: make layout filtering much faster



commit 963f992452dda54ff344a924470d8bf5f7950efb
Author: Sergey V. Udaltsov <svu gnome org>
Date:   Tue Feb 8 22:21:09 2011 +0000

    region: make layout filtering much faster
    
    Using app-level filter instead of libxklavier filter

 panels/region/gnome-region-panel-layout-chooser.ui |    9 +-
 panels/region/gnome-region-panel-xkbltadd.c        |  209 +++++++++++++++++---
 2 files changed, 185 insertions(+), 33 deletions(-)
---
diff --git a/panels/region/gnome-region-panel-layout-chooser.ui b/panels/region/gnome-region-panel-layout-chooser.ui
index e020f3d..82b8e74 100644
--- a/panels/region/gnome-region-panel-layout-chooser.ui
+++ b/panels/region/gnome-region-panel-layout-chooser.ui
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <interface>
   <requires lib="gtk+" version="2.16"/>
-  <object class="GtkListStore" id="filtered_layout_list_model">
+  <object class="GtkListStore" id="layout_list_model">
     <columns>
       <!-- column-name sort_order -->
       <column type="gchararray"/>
@@ -9,10 +9,15 @@
       <column type="gchararray"/>
       <!-- column-name xkb_id -->
       <column type="gchararray"/>
-      <!-- column-name real_id -->
+      <!-- column-name country_desc -->
+      <column type="gchararray"/>
+      <!-- column-name language_desc -->
       <column type="gchararray"/>
     </columns>
   </object>
+  <object class="GtkTreeModelFilter" id="filtered_layout_list_model">
+    <property name="child_model">layout_list_model</property>
+  </object>
   <object class="GtkDialog" id="xkb_layout_chooser">
     <property name="visible">True</property>
     <property name="can_focus">False</property>
diff --git a/panels/region/gnome-region-panel-xkbltadd.c b/panels/region/gnome-region-panel-xkbltadd.c
index 3196fad..26889cc 100644
--- a/panels/region/gnome-region-panel-xkbltadd.c
+++ b/panels/region/gnome-region-panel-xkbltadd.c
@@ -33,9 +33,13 @@
 enum {
 	COMBO_BOX_MODEL_COL_SORT,
 	COMBO_BOX_MODEL_COL_VISIBLE,
-	COMBO_BOX_MODEL_COL_XKB_ID
+	COMBO_BOX_MODEL_COL_XKB_ID,
+	COMBO_BOX_MODEL_COL_COUNTRY_DESC,
+	COMBO_BOX_MODEL_COL_LANGUAGE_DESC
 };
 
+static gchar **search_pattern_list = NULL;
+
 #define RESPONSE_PREVIEW 1
 
 static void
@@ -106,15 +110,70 @@ xkb_layout_chooser_response (GtkDialog * dialog,
 	gtk_widget_destroy (GTK_WIDGET (dialog));
 }
 
+static gchar *
+xkl_create_description_from_list (const XklConfigItem * item,
+				  const XklConfigItem * subitem,
+				  const gchar * prop_name,
+				  const gchar *
+				  (*desc_getter) (const gchar * code))
+{
+	gchar *rv = NULL, *code = NULL;
+	gchar **list = NULL;
+	const gchar *desc;
+
+	if (subitem != NULL)
+		list =
+		    (gchar
+		     **) (g_object_get_data (G_OBJECT (subitem),
+					     prop_name));
+	if (list == NULL || *list == 0)
+		list =
+		    (gchar
+		     **) (g_object_get_data (G_OBJECT (item), prop_name));
+
+	/* First try the parent id as such */
+	desc = desc_getter (item->name);
+	if (desc != NULL) {
+		rv = g_utf8_strup (desc, -1);
+	} else {
+		code = g_utf8_strup (item->name, -1);
+		desc = desc_getter (code);
+		if (desc != NULL) {
+			rv = g_utf8_strup (desc, -1);
+		}
+		g_free (code);
+	}
+
+	if (list == NULL || *list == 0)
+		return rv;
+
+	while (*list != 0) {
+		code = *list++;
+		desc = desc_getter (code);
+		if (desc != NULL) {
+			gchar *udesc = g_utf8_strup (desc, -1);
+			if (rv == NULL) {
+				rv = udesc;
+			} else {
+				gchar *orv = rv;
+				rv = g_strdup_printf ("%s %s", rv, udesc);
+				g_free (orv);
+				g_free (udesc);
+			}
+		}
+	}
+	return rv;
+}
+
 static void
-xkl_layout_add_to_filtered_list (XklConfigRegistry * config,
-				 const XklConfigItem * item,
-				 const XklConfigItem * subitem,
-				 GtkBuilder * chooser_dialog)
+xkl_layout_add_to_list (XklConfigRegistry * config,
+			const XklConfigItem * item,
+			const XklConfigItem * subitem,
+			GtkBuilder * chooser_dialog)
 {
 	GtkListStore *list_store =
 	    GTK_LIST_STORE (gtk_builder_get_object (chooser_dialog,
-						    "filtered_layout_list_model"));
+						    "layout_list_model"));
 	GtkTreeIter iter;
 	gchar *utf_variant_name =
 	    subitem ?
@@ -127,6 +186,15 @@ xkl_layout_add_to_filtered_list (XklConfigRegistry * config,
 							subitem->name) :
 	    item->name;
 
+	gchar *country_desc =
+	    xkl_create_description_from_list (item, subitem,
+					      XCI_PROP_COUNTRY_LIST,
+					      xkl_get_country_name);
+	gchar *language_desc =
+	    xkl_create_description_from_list (item, subitem,
+					      XCI_PROP_LANGUAGE_LIST,
+					      xkl_get_language_name);
+
 	if (subitem
 	    && g_object_get_data (G_OBJECT (subitem),
 				  XCI_PROP_EXTRA_ITEM)) {
@@ -138,7 +206,11 @@ xkl_layout_add_to_filtered_list (XklConfigRegistry * config,
 						   COMBO_BOX_MODEL_COL_VISIBLE,
 						   buf,
 						   COMBO_BOX_MODEL_COL_XKB_ID,
-						   xkb_id, -1);
+						   xkb_id,
+						   COMBO_BOX_MODEL_COL_COUNTRY_DESC,
+						   country_desc,
+						   COMBO_BOX_MODEL_COL_LANGUAGE_DESC,
+						   language_desc, -1);
 		g_free (buf);
 	} else
 		gtk_list_store_insert_with_values (list_store, &iter,
@@ -148,27 +220,34 @@ xkl_layout_add_to_filtered_list (XklConfigRegistry * config,
 						   COMBO_BOX_MODEL_COL_VISIBLE,
 						   utf_variant_name,
 						   COMBO_BOX_MODEL_COL_XKB_ID,
-						   xkb_id, -1);
+						   xkb_id,
+						   COMBO_BOX_MODEL_COL_COUNTRY_DESC,
+						   country_desc,
+						   COMBO_BOX_MODEL_COL_LANGUAGE_DESC,
+						   language_desc, -1);
 	g_free (utf_variant_name);
+	g_free (country_desc);
+	g_free (language_desc);
 }
 
 static void
 xkb_layout_filter_changed (GtkBuilder * chooser_dialog)
 {
+	GtkTreeModelFilter *filtered_model =
+	    GTK_TREE_MODEL_FILTER (gtk_builder_get_object (chooser_dialog,
+							   "filtered_layout_list_model"));
 	GtkWidget *xkb_layout_filter = CWID ("xkb_layout_filter");
 	const gchar *pattern =
 	    gtk_entry_get_text (GTK_ENTRY (xkb_layout_filter));
-	GtkListStore *model =
-	    GTK_LIST_STORE (gtk_builder_get_object (chooser_dialog,
-						    "filtered_layout_list_model"));
+	gchar *upattern = g_utf8_strup (pattern, -1);
 
-	gtk_list_store_clear (model);
-	xkl_config_registry_search_by_pattern (config_registry, pattern,
-					       (TwoConfigItemsProcessFunc)
-					       (xkl_layout_add_to_filtered_list), chooser_dialog);
-	gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
-					      COMBO_BOX_MODEL_COL_SORT,
-					      GTK_SORT_ASCENDING);
+	if (search_pattern_list != NULL)
+		g_strfreev (search_pattern_list);
+
+	search_pattern_list = g_strsplit (upattern, " ", -1);
+	g_free (upattern);
+
+	gtk_tree_model_filter_refilter (filtered_model);
 }
 
 static void
@@ -184,6 +263,52 @@ xkb_layout_chooser_selection_changed (GtkTreeSelection * selection,
 	gtk_widget_set_sensitive (preview_button, anything_selected);
 }
 
+static gboolean
+xkb_filter_layouts (GtkTreeModel * model,
+		    GtkTreeIter * iter, gpointer data)
+{
+	gchar *desc = NULL, *country_desc = NULL, *language_desc =
+	    NULL, **pattern;
+	gboolean rv = TRUE;
+
+	if (search_pattern_list == NULL || search_pattern_list[0] == NULL)
+		return TRUE;
+
+	gtk_tree_model_get (model, iter,
+			    COMBO_BOX_MODEL_COL_SORT, &desc,
+			    COMBO_BOX_MODEL_COL_COUNTRY_DESC,
+			    &country_desc,
+			    COMBO_BOX_MODEL_COL_LANGUAGE_DESC,
+			    &language_desc, -1);
+
+	pattern = search_pattern_list;
+	do {
+		gboolean is_pattern_found = FALSE;
+		gchar *udesc = g_utf8_strup (desc, -1);
+		if (udesc != NULL && g_strstr_len (udesc, -1, *pattern)) {
+			is_pattern_found = TRUE;
+		} else if (country_desc != NULL
+			   && g_strstr_len (country_desc, -1, *pattern)) {
+			is_pattern_found = TRUE;
+		} else if (language_desc != NULL
+			   && g_strstr_len (language_desc, -1, *pattern)) {
+			is_pattern_found = TRUE;
+		}
+		g_free (udesc);
+
+		if (!is_pattern_found) {
+			rv = FALSE;
+			break;
+		}
+
+	} while (*++pattern != NULL);
+
+	g_free (desc);
+	g_free (country_desc);
+	g_free (language_desc);
+	return rv;
+}
+
 void
 xkb_layout_choose (GtkBuilder * dialog)
 {
@@ -191,6 +316,8 @@ xkb_layout_choose (GtkBuilder * dialog)
 	GtkWidget *chooser, *xkb_filtered_layouts_list, *xkb_layout_filter;
 	GtkTreeViewColumn *visible_column;
 	GtkTreeSelection *selection;
+	GtkListStore *model;
+	GtkTreeModelFilter *filtered_model;
 
 	gtk_builder_add_from_file (chooser_dialog, GNOMECC_UI_DIR
 				   "/gnome-region-panel-layout-chooser.ui",
@@ -207,16 +334,17 @@ xkb_layout_choose (GtkBuilder * dialog)
 						      NULL);
 
 	gtk_window_set_transient_for (GTK_WINDOW (chooser),
-				      GTK_WINDOW (gtk_widget_get_toplevel
-						  (WID
-						   ("region_notebook"))));
+				      GTK_WINDOW
+				      (gtk_widget_get_toplevel
+				       (WID ("region_notebook"))));
 
 	gtk_tree_view_append_column (GTK_TREE_VIEW
 				     (xkb_filtered_layouts_list),
 				     visible_column);
 	g_signal_connect_swapped (G_OBJECT (xkb_layout_filter),
 				  "notify::text",
-				  G_CALLBACK (xkb_layout_filter_changed),
+				  G_CALLBACK
+				  (xkb_layout_filter_changed),
 				  chooser_dialog);
 
 	g_signal_connect (G_OBJECT (chooser),
@@ -236,7 +364,26 @@ xkb_layout_choose (GtkBuilder * dialog)
 
 	xkb_layout_chooser_selection_changed (selection, chooser_dialog);
 
-	xkb_layout_filter_changed (chooser_dialog);
+	filtered_model =
+	    GTK_TREE_MODEL_FILTER (gtk_builder_get_object
+				   (chooser_dialog,
+				    "filtered_layout_list_model"));
+	model =
+	    GTK_LIST_STORE (gtk_builder_get_object
+			    (chooser_dialog, "layout_list_model"));
+
+	xkl_config_registry_search_by_pattern (config_registry,
+					       NULL,
+					       (TwoConfigItemsProcessFunc)
+					       (xkl_layout_add_to_list),
+					       chooser_dialog);
+	gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
+					      COMBO_BOX_MODEL_COL_SORT,
+					      GTK_SORT_ASCENDING);
+
+	gtk_tree_model_filter_set_visible_func (filtered_model,
+						xkb_filter_layouts,
+						NULL, NULL);
 
 	gtk_widget_grab_focus (xkb_layout_filter);
 
@@ -246,9 +393,7 @@ xkb_layout_choose (GtkBuilder * dialog)
 gchar *
 xkb_layout_chooser_get_selected_id (GtkBuilder * chooser_dialog)
 {
-	GtkListStore *list_store =
-	    GTK_LIST_STORE (gtk_builder_get_object (chooser_dialog,
-						    "filtered_layout_list_model"));
+	GtkTreeModel *filtered_list_model;
 	GtkWidget *xkb_filtered_layouts_list =
 	    CWID ("xkb_filtered_layouts_list");
 	GtkTreeIter viter;
@@ -257,18 +402,20 @@ xkb_layout_chooser_get_selected_id (GtkBuilder * chooser_dialog)
 	    gtk_tree_view_get_selection (GTK_TREE_VIEW
 					 (xkb_filtered_layouts_list));
 	GList *selected_layouts =
-	    gtk_tree_selection_get_selected_rows (selection, NULL);
+	    gtk_tree_selection_get_selected_rows (selection,
+						  &filtered_list_model);
 
 	if (g_list_length (selected_layouts) != 1)
 		return NULL;
 
-	gtk_tree_model_get_iter (GTK_TREE_MODEL (list_store), &viter,
+	gtk_tree_model_get_iter (filtered_list_model,
+				 &viter,
 				 (GtkTreePath *) (selected_layouts->data));
-	g_list_foreach (selected_layouts, (GFunc) gtk_tree_path_free,
-			NULL);
+	g_list_foreach (selected_layouts,
+			(GFunc) gtk_tree_path_free, NULL);
 	g_list_free (selected_layouts);
 
-	gtk_tree_model_get (GTK_TREE_MODEL (list_store), &viter,
+	gtk_tree_model_get (filtered_list_model, &viter,
 			    COMBO_BOX_MODEL_COL_XKB_ID, &v_id, -1);
 
 	return v_id;



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