@eht16 I've just tested the PR briefly but I didn't like that parents not containing any children were still displayed - when filtering for something in the last group, one would have to scroll the tree to see it for the empty groups above.
I think it's hard/impossible to achieve that with the filter function but I tried adding an extra column to the store indicating visibility and then using `gtk_tree_model_filter_set_visible_column()` and it seems to work. I also added `expand_all()` to the result because the collapsed entries weren't very nice.
The patch is below (created very quickly by reusing code from `kb_update()` for the update function, possibly needs improving).
What do you think?
```diff diff --git a/src/prefs.c b/src/prefs.c index 57e95837e..7b8129089 100644 --- a/src/prefs.c +++ b/src/prefs.c @@ -87,7 +87,6 @@ static gboolean kb_find_duplicate(GtkTreeStore *store, GtkWidget *parent, GtkTre static void kb_filter_entry_changed_cb(GtkEntry *entry, gpointer user_data); static void kb_filter_entry_icon_release_cb(GtkEntry *entry, GtkEntryIconPosition icon_pos, GdkEvent *event, gpointer user_data); -static gboolean kb_tree_filter_func(GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data); static gboolean kb_tree_key_press_cb(GtkWidget *widget, GdkEventKey *event, gpointer user_data); static void on_toolbar_show_toggled(GtkToggleButton *togglebutton, gpointer user_data); static void on_show_notebook_tabs_toggled(GtkToggleButton *togglebutton, gpointer user_data); @@ -146,6 +145,7 @@ enum KB_TREE_INDEX, KB_TREE_EDITABLE, KB_TREE_WEIGHT, + KB_TREE_VISIBLE, KB_TREE_COLUMNS };
@@ -276,10 +276,9 @@ static void kb_init_tree(KbData *kbdata, GtkWidget *kb_filter_entry) kbdata->tree = GTK_TREE_VIEW(ui_lookup_widget(ui_widgets.prefs_dialog, "treeview7"));
kbdata->store = gtk_tree_store_new(KB_TREE_COLUMNS, - G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT, G_TYPE_BOOLEAN, G_TYPE_INT); + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT, G_TYPE_BOOLEAN, G_TYPE_INT, G_TYPE_BOOLEAN); filter_model = gtk_tree_model_filter_new(GTK_TREE_MODEL(kbdata->store), NULL); - gtk_tree_model_filter_set_visible_func( - GTK_TREE_MODEL_FILTER(filter_model), kb_tree_filter_func, kb_filter_entry, NULL); + gtk_tree_model_filter_set_visible_column(GTK_TREE_MODEL_FILTER(filter_model), KB_TREE_VISIBLE); /* set model to tree view */ gtk_tree_view_set_model(GTK_TREE_VIEW(kbdata->tree), filter_model); g_object_unref(filter_model); @@ -376,14 +375,14 @@ static void kb_init(KbData *kbdata, GtkWidget *kb_filter_entry) { gtk_tree_store_append(kbdata->store, &parent, NULL); gtk_tree_store_set(kbdata->store, &parent, KB_TREE_ACTION, group->label, - KB_TREE_INDEX, g, -1); + KB_TREE_INDEX, g, KB_TREE_VISIBLE, TRUE, -1);
foreach_ptr_array(kb, i, group->key_items) { label = keybindings_get_label(kb); gtk_tree_store_append(kbdata->store, &iter, &parent); gtk_tree_store_set(kbdata->store, &iter, KB_TREE_ACTION, label, - KB_TREE_EDITABLE, TRUE, KB_TREE_INDEX, kb->id, -1); + KB_TREE_EDITABLE, TRUE, KB_TREE_INDEX, kb->id, KB_TREE_VISIBLE, TRUE, -1); kb_set_shortcut(kbdata->store, &iter, kb->key, kb->mods); g_free(label); } @@ -1413,10 +1412,62 @@ static void kb_cell_edited_cb(GtkCellRendererText *cellrenderertext, }
+static void update_visibility(GtkTreeStore *store, const gchar *entry_text) +{ + GtkTreeModel *model = GTK_TREE_MODEL(store); + GtkTreeIter child, parent; + + /* get first parent */ + if (! gtk_tree_model_iter_children(model, &parent, NULL)) + return; + + /* foreach parent */ + while (TRUE) + { + gboolean visible_children = FALSE; + + /* get first child */ + if (! gtk_tree_model_iter_children(model, &child, &parent)) + return; + + /* foreach child */ + while (TRUE) + { + gboolean visible; + gchar *action_name; + + gtk_tree_model_get(model, &child, KB_TREE_ACTION, &action_name, -1); + if (!action_name || EMPTY(entry_text)) + visible = TRUE; + else + visible = utils_utf8_substring_match(entry_text, action_name); + g_free(action_name); + + if (visible) + visible_children = TRUE; + + gtk_tree_store_set(store, &child, KB_TREE_VISIBLE, visible, -1); + + if (! gtk_tree_model_iter_next(model, &child)) + break; + } + + gtk_tree_store_set(store, &parent, KB_TREE_VISIBLE, visible_children, -1); + + if (! gtk_tree_model_iter_next(model, &parent)) + return; + } +} + + static void kb_filter_entry_changed_cb(GtkEntry *entry, gpointer user_data) { GtkTreeModel *filter_model = gtk_tree_view_get_model(GTK_TREE_VIEW(global_kb_data.tree)); + const gchar *entry_text = gtk_entry_get_text(entry); + + update_visibility(global_kb_data.store, entry_text); gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER(filter_model)); + gtk_tree_view_expand_all(global_kb_data.tree); }
@@ -1428,31 +1479,6 @@ static void kb_filter_entry_icon_release_cb(GtkEntry *entry, GtkEntryIconPositio }
-static gboolean kb_tree_filter_func(GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data) -{ - const gchar *key; - gboolean matched; - gchar *action_name; - GtkWidget *kb_filter_entry = user_data; - - // always show categories - if (gtk_tree_model_iter_has_child(model, iter)) - return TRUE; - - gtk_tree_model_get(model, iter, KB_TREE_ACTION, &action_name, -1); - if (!action_name) - return TRUE; - - key = gtk_entry_get_text(GTK_ENTRY(kb_filter_entry)); - if (EMPTY(key)) - return TRUE; - - matched = utils_utf8_substring_match(key, action_name); - g_free(action_name); - return matched; -} - - static gboolean kb_tree_key_press_cb(GtkWidget *widget, GdkEventKey *event, gpointer user_data) { if (event->keyval == GDK_KEY_f && (event->state & GEANY_PRIMARY_MOD_MASK)) ```