region: make layout filtering much faster
Using app-level filter instead of libxklavier filter
This commit is contained in:
parent
99c1d959be
commit
963f992452
2 changed files with 185 additions and 33 deletions
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue