From: Masahiro Yamada <masahiroy@kernel.org>
To: linux-kbuild@vger.kernel.org
Cc: Masahiro Yamada <masahiroy@kernel.org>, linux-kernel@vger.kernel.org
Subject: [PATCH 44/66] kconfig: gconf: use GtkTreeModelFilter to control row visibility
Date: Wed, 25 Jun 2025 00:05:32 +0900 [thread overview]
Message-ID: <20250624150645.1107002-45-masahiroy@kernel.org> (raw)
In-Reply-To: <20250624150645.1107002-1-masahiroy@kernel.org>
Currently, update_tree() adds/removes entries to show/hide rows.
This approach is extremely complicated.
Use the tree model filter to control row visibility instead.
Do not toggle the MENU_CHANGED flag, as it is hard to control
this correctly.
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
---
scripts/kconfig/gconf.c | 217 +++++++++++++++-------------------------
1 file changed, 80 insertions(+), 137 deletions(-)
diff --git a/scripts/kconfig/gconf.c b/scripts/kconfig/gconf.c
index 184678dd4fa6..a0cc7cb98670 100644
--- a/scripts/kconfig/gconf.c
+++ b/scripts/kconfig/gconf.c
@@ -59,7 +59,9 @@ enum {
static void display_list(void);
static void display_tree(GtkTreeStore *store, struct menu *menu);
static void display_tree_part(void);
-static void update_tree(struct menu *src, GtkTreeIter * dst);
+static gchar **fill_row(struct menu *menu);
+static void set_node(GtkTreeStore *tree, GtkTreeIter *node,
+ struct menu *menu, gchar **row);
static void conf_changed(bool dirty)
{
@@ -110,6 +112,47 @@ static void select_menu(GtkTreeView *view, struct menu *match)
_select_menu(view, gtk_tree_view_get_model(view), NULL, match);
}
+static void _update_row_visibility(GtkTreeView *view)
+{
+ GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER(gtk_tree_view_get_model(view));
+
+ gtk_tree_model_filter_refilter(filter);
+}
+
+static void update_row_visibility(void)
+{
+ if (view_mode == SPLIT_VIEW)
+ _update_row_visibility(GTK_TREE_VIEW(tree1_w));
+ _update_row_visibility(GTK_TREE_VIEW(tree2_w));
+}
+
+static void _update_tree(GtkTreeStore *store, GtkTreeIter *parent)
+{
+ GtkTreeModel *model = GTK_TREE_MODEL(store);
+ GtkTreeIter iter;
+ gboolean valid;
+
+ valid = gtk_tree_model_iter_children(model, &iter, parent);
+ while (valid) {
+ struct menu *menu;
+
+ gtk_tree_model_get(model, &iter, COL_MENU, &menu, -1);
+
+ if (menu)
+ set_node(store, &iter, menu, fill_row(menu));
+
+ _update_tree(store, &iter);
+
+ valid = gtk_tree_model_iter_next(model, &iter);
+ }
+}
+
+static void update_tree(GtkTreeStore *store)
+{
+ _update_tree(store, NULL);
+ update_row_visibility();
+}
+
static void set_view_mode(enum view_mode mode)
{
view_mode = mode;
@@ -328,24 +371,21 @@ static void on_set_option_mode1_activate(GtkMenuItem *menuitem,
gpointer user_data)
{
opt_mode = OPT_NORMAL;
- gtk_tree_store_clear(tree2);
- display_tree(tree2, &rootmenu); /* instead of update_tree to speed-up */
+ update_row_visibility();
}
static void on_set_option_mode2_activate(GtkMenuItem *menuitem,
gpointer user_data)
{
opt_mode = OPT_ALL;
- gtk_tree_store_clear(tree2);
- display_tree(tree2, &rootmenu); /* instead of update_tree to speed-up */
+ update_row_visibility();
}
static void on_set_option_mode3_activate(GtkMenuItem *menuitem,
gpointer user_data)
{
opt_mode = OPT_PROMPT;
- gtk_tree_store_clear(tree2);
- display_tree(tree2, &rootmenu); /* instead of update_tree to speed-up */
+ update_row_visibility();
}
static void on_introduction1_activate(GtkMenuItem *menuitem, gpointer user_data)
@@ -559,7 +599,7 @@ static void renderer_edited(GtkCellRendererText * cell,
sym_set_string_value(sym, new_def);
- update_tree(&rootmenu, NULL);
+ update_tree(tree2);
free:
gtk_tree_path_free(path);
@@ -590,9 +630,9 @@ static void change_sym_value(struct menu *menu, gint col)
newval = yes;
sym_set_tristate_value(sym, newval);
if (view_mode == FULL_VIEW)
- update_tree(&rootmenu, NULL);
+ update_tree(tree2);
else if (view_mode == SPLIT_VIEW) {
- update_tree(browsed, NULL);
+ update_tree(tree2);
display_list();
}
else if (view_mode == SINGLE_VIEW)
@@ -613,9 +653,9 @@ static void toggle_sym_value(struct menu *menu)
sym_toggle_tristate_value(menu->sym);
if (view_mode == FULL_VIEW)
- update_tree(&rootmenu, NULL);
+ update_tree(tree2);
else if (view_mode == SPLIT_VIEW) {
- update_tree(browsed, NULL);
+ update_tree(tree2);
display_list();
}
else if (view_mode == SINGLE_VIEW)
@@ -842,7 +882,6 @@ static gchar **fill_row(struct menu *menu)
row[COL_NAME] = g_strdup(sym->name);
sym_calc_value(sym);
- menu->flags &= ~MENU_CHANGED;
if (sym_is_choice(sym)) { // parse childs for getting final value
struct menu *child;
@@ -947,120 +986,6 @@ static void set_node(GtkTreeStore *tree, GtkTreeIter *node,
g_object_unref(pix);
}
-/* Find a node in the GTK+ tree */
-static GtkTreeIter found;
-
-/*
- * Find a menu in the GtkTree starting at parent.
- */
-static GtkTreeIter *gtktree_iter_find_node(GtkTreeIter *parent,
- struct menu *tofind)
-{
- GtkTreeIter iter;
- GtkTreeIter *child = &iter;
- gboolean valid;
- GtkTreeIter *ret;
-
- valid = gtk_tree_model_iter_children(model2, child, parent);
- while (valid) {
- struct menu *menu;
-
- gtk_tree_model_get(model2, child, 6, &menu, -1);
-
- if (menu == tofind) {
- memcpy(&found, child, sizeof(GtkTreeIter));
- return &found;
- }
-
- ret = gtktree_iter_find_node(child, tofind);
- if (ret)
- return ret;
-
- valid = gtk_tree_model_iter_next(model2, child);
- }
-
- return NULL;
-}
-
-
-/*
- * Update the tree by adding/removing entries
- * Does not change other nodes
- */
-static void update_tree(struct menu *src, GtkTreeIter * dst)
-{
- struct menu *child1;
- GtkTreeIter iter, tmp;
- GtkTreeIter *child2 = &iter;
- gboolean valid;
- GtkTreeIter *sibling;
- struct symbol *sym;
- struct menu *menu1, *menu2;
-
- valid = gtk_tree_model_iter_children(model2, child2, dst);
- for (child1 = src->list; child1; child1 = child1->next) {
-
- sym = child1->sym;
-
- reparse:
- menu1 = child1;
- if (valid)
- gtk_tree_model_get(model2, child2, COL_MENU,
- &menu2, -1);
- else
- menu2 = NULL; // force adding of a first child
-
- if ((opt_mode == OPT_NORMAL && !menu_is_visible(child1)) ||
- (opt_mode == OPT_PROMPT && !menu_has_prompt(child1)) ||
- (opt_mode == OPT_ALL && !menu_get_prompt(child1))) {
-
- /* remove node */
- if (gtktree_iter_find_node(dst, menu1) != NULL) {
- memcpy(&tmp, child2, sizeof(GtkTreeIter));
- valid = gtk_tree_model_iter_next(model2,
- child2);
- gtk_tree_store_remove(tree2, &tmp);
- if (!valid)
- return; /* next parent */
- else
- goto reparse; /* next child */
- } else
- continue;
- }
-
- if (menu1 != menu2) {
- if (gtktree_iter_find_node(dst, menu1) == NULL) { // add node
- if (!valid && !menu2)
- sibling = NULL;
- else
- sibling = child2;
- gtk_tree_store_insert_before(tree2,
- child2,
- dst, sibling);
- set_node(tree2, child2, menu1, fill_row(menu1));
- if (menu2 == NULL)
- valid = TRUE;
- } else { // remove node
- memcpy(&tmp, child2, sizeof(GtkTreeIter));
- valid = gtk_tree_model_iter_next(model2,
- child2);
- gtk_tree_store_remove(tree2, &tmp);
- if (!valid)
- return; // next parent
- else
- goto reparse; // next child
- }
- } else if (sym && (child1->flags & MENU_CHANGED)) {
- set_node(tree2, child2, menu1, fill_row(menu1));
- }
-
- update_tree(child1, child2);
-
- valid = gtk_tree_model_iter_next(model2, child2);
- }
-}
-
-
/* Display the whole tree (single/split/full view) */
static void _display_tree(GtkTreeStore *tree, struct menu *menu,
GtkTreeIter *parent)
@@ -1083,8 +1008,6 @@ static void _display_tree(GtkTreeStore *tree, struct menu *menu,
prop = child->prompt;
ptype = prop ? prop->type : P_UNKNOWN;
- menu->flags &= ~MENU_CHANGED;
-
if ((view_mode == SPLIT_VIEW)
&& !(child->flags & MENU_ROOT) && (tree == tree1))
continue;
@@ -1093,12 +1016,8 @@ static void _display_tree(GtkTreeStore *tree, struct menu *menu,
&& (tree == tree2))
continue;
- if ((opt_mode == OPT_NORMAL && menu_is_visible(child)) ||
- (opt_mode == OPT_PROMPT && menu_has_prompt(child)) ||
- (opt_mode == OPT_ALL && menu_get_prompt(child))) {
- gtk_tree_store_append(tree, &iter, parent);
- set_node(tree, &iter, child, fill_row(child));
- }
+ gtk_tree_store_append(tree, &iter, parent);
+ set_node(tree, &iter, child, fill_row(child));
if ((view_mode != FULL_VIEW) && (ptype == P_MENU)
&& (tree == tree2))
@@ -1313,6 +1232,20 @@ static void init_main_window(const gchar *glade_file)
gtk_widget_show(main_wnd);
}
+static gboolean visible_func(GtkTreeModel *model, GtkTreeIter *iter,
+ gpointer data)
+{
+ struct menu *menu;
+
+ gtk_tree_model_get(model, iter, COL_MENU, &menu, -1);
+
+ if (!menu)
+ return FALSE;
+
+ return menu_is_visible(menu) || opt_mode == OPT_ALL ||
+ (opt_mode == OPT_PROMPT && menu_has_prompt(menu));
+}
+
static void init_tree_model(void)
{
tree2 = gtk_tree_store_new(COL_NUMBER,
@@ -1344,8 +1277,13 @@ static void init_left_tree(void)
GtkCellRenderer *renderer;
GtkTreeSelection *sel;
GtkTreeViewColumn *column;
+ GtkTreeModel *filter;
- gtk_tree_view_set_model(view, model1);
+ filter = gtk_tree_model_filter_new(model1, NULL);
+
+ gtk_tree_model_filter_set_visible_func(GTK_TREE_MODEL_FILTER(filter),
+ visible_func, NULL, NULL);
+ gtk_tree_view_set_model(view, filter);
column = gtk_tree_view_column_new();
gtk_tree_view_append_column(view, column);
@@ -1379,9 +1317,14 @@ static void init_right_tree(void)
GtkCellRenderer *renderer;
GtkTreeSelection *sel;
GtkTreeViewColumn *column;
+ GtkTreeModel *filter;
gint i;
- gtk_tree_view_set_model(view, model2);
+ filter = gtk_tree_model_filter_new(model2, NULL);
+
+ gtk_tree_model_filter_set_visible_func(GTK_TREE_MODEL_FILTER(filter),
+ visible_func, NULL, NULL);
+ gtk_tree_view_set_model(view, filter);
column = gtk_tree_view_column_new();
gtk_tree_view_append_column(view, column);
--
2.43.0
next prev parent reply other threads:[~2025-06-24 15:08 UTC|newest]
Thread overview: 104+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-06-24 15:04 [PATCH 00/66] kconfig: improve xconfig and gconfig Masahiro Yamada
2025-06-24 15:04 ` [PATCH 01/66] kconfig: set MENU_CHANGED to choice when the selected member is changed Masahiro Yamada
2025-06-30 6:34 ` Randy Dunlap
2025-07-02 13:23 ` Masahiro Yamada
2025-07-02 22:02 ` Randy Dunlap
2025-06-24 15:04 ` [PATCH 02/66] kconfig: qconf: do not show checkbox icon for choice Masahiro Yamada
2025-06-29 20:15 ` Randy Dunlap
2025-06-30 3:36 ` Masahiro Yamada
2025-06-30 0:51 ` Randy Dunlap
2025-06-30 0:54 ` Randy Dunlap
2025-06-24 15:04 ` [PATCH 03/66] kconfig: qconf: show selected choice in the Value column Masahiro Yamada
2025-06-30 0:56 ` Randy Dunlap
2025-06-24 15:04 ` [PATCH 04/66] kconfig: rename menu_get_parent_menu() to menu_get_menu_or_parent_menu() Masahiro Yamada
2025-06-30 0:58 ` Randy Dunlap
2025-06-24 15:04 ` [PATCH 05/66] kconfig: re-add menu_get_parent_menu() that returns parent menu Masahiro Yamada
2025-06-30 0:59 ` Randy Dunlap
2025-06-24 15:04 ` [PATCH 06/66] kconfig: gconf: make columns resizable Masahiro Yamada
2025-06-30 2:18 ` Randy Dunlap
2025-06-24 15:04 ` [PATCH 07/66] kconfig: gconf: fix potential memory leak in renderer_edited() Masahiro Yamada
2025-06-30 2:21 ` Randy Dunlap
2025-06-24 15:04 ` [PATCH 08/66] kconfig: gconf: always destroy dialog in on_window1_delete_event() Masahiro Yamada
2025-06-30 2:23 ` Randy Dunlap
2025-06-24 15:04 ` [PATCH 09/66] kconfig: gconf: remove old #ifdef GTK_CHECK_VERSION Masahiro Yamada
2025-06-24 15:04 ` [PATCH 10/66] kconfig: gconf: remove empty if-block Masahiro Yamada
2025-06-30 2:25 ` Randy Dunlap
2025-06-24 15:04 ` [PATCH 11/66] kconfig: gconf: remove meaningless code in init_main_window() Masahiro Yamada
2025-06-30 2:25 ` Randy Dunlap
2025-06-24 15:05 ` [PATCH 12/66] kconfig: gconf: remove unneeded gtk_tree_view_set_headers_visible() calls Masahiro Yamada
2025-06-24 15:05 ` [PATCH 13/66] kconfig: gconf: remove gtk_tree_view_column_set_visible() calls Masahiro Yamada
2025-06-24 15:05 ` [PATCH 14/66] kconfig: gconf: remove gtk_widget_realize() calls Masahiro Yamada
2025-06-24 15:05 ` [PATCH 15/66] kconfig: gconf: remove gtk_tree_view_set_rules_hint() calls Masahiro Yamada
2025-06-24 15:05 ` [PATCH 16/66] kconfig: gconf: remove unnecessary gtk_set_locale() call Masahiro Yamada
2025-06-24 15:05 ` [PATCH 17/66] kconfig: gconf: remove internal-child="image" nodes from glade Masahiro Yamada
2025-06-24 15:05 ` [PATCH 18/66] kconfig: gconf: remove parents[] array and indent variable Masahiro Yamada
2025-06-24 15:05 ` [PATCH 19/66] kconfig: gconf: remove unnecessary NULL checks for tree1 and tree2 Masahiro Yamada
2025-06-24 15:05 ` [PATCH 20/66] kconfig: gconf: remove unneeded variable in on_split_clicked() Masahiro Yamada
2025-06-24 15:05 ` [PATCH 21/66] kconfig: gconf: remove unneeded variables in on_treeview*_button_press_event() Masahiro Yamada
2025-06-30 2:40 ` Randy Dunlap
2025-06-30 4:22 ` Masahiro Yamada
2025-06-24 15:05 ` [PATCH 22/66] kconfig: gconf: remove unused 'color' variable Masahiro Yamada
2025-06-24 15:05 ` [PATCH 23/66] kconfig: gconf: add static qualifiers to variables Masahiro Yamada
2025-06-24 15:05 ` [PATCH 24/66] kconfig: gconf: move init_*() functions below Masahiro Yamada
2025-06-24 15:05 ` [PATCH 25/66] kconfig: gconf: refactor view setting code Masahiro Yamada
2025-06-30 2:51 ` Randy Dunlap
2025-06-24 15:05 ` [PATCH 26/66] kconfig: gconf: grey out button for current view Masahiro Yamada
2025-06-30 2:53 ` Randy Dunlap
2025-06-24 15:05 ` [PATCH 27/66] kconfig: gconf: move the main window event handlers below Masahiro Yamada
2025-06-24 15:05 ` [PATCH 28/66] kconfig: gconf: move button1 initialization below Masahiro Yamada
2025-06-24 15:05 ` [PATCH 29/66] kconfig: gconf: add static qualifiers to event handlers Masahiro Yamada
2025-06-30 2:55 ` Randy Dunlap
2025-06-24 15:05 ` [PATCH 30/66] kconfig: gconf: remove glade_xml_signal_autoconnect() call Masahiro Yamada
2025-06-30 2:58 ` Randy Dunlap
2025-06-30 4:14 ` Masahiro Yamada
2025-06-24 15:05 ` [PATCH 31/66] kconfig: gconf: make key_press_event work in left pane too Masahiro Yamada
2025-06-24 15:05 ` [PATCH 32/66] kconfig: gconf: avoid hardcoding model2 in on_treeview2_cursor_changed() Masahiro Yamada
2025-06-24 15:05 ` [PATCH 33/66] kconfig: gconf: avoid hardcoding model2 in renderer_edited() Masahiro Yamada
2025-06-24 15:05 ` [PATCH 34/66] kconfig: gconf: avoid hardcoding model* in on_treeview*_button_press_event() Masahiro Yamada
2025-06-24 15:05 ` [PATCH 35/66] kconfig: gconf: add on_save_clicked() event handler Masahiro Yamada
2025-06-24 15:05 ` [PATCH 36/66] kconfig: gconf: use GtkFileChooser in on_load1_activate() Masahiro Yamada
2025-06-30 3:14 ` Randy Dunlap
2025-06-24 15:05 ` [PATCH 37/66] kconfig: gconf: use GtkFileChooser in on_save_as1_activate() Masahiro Yamada
2025-06-30 3:20 ` Randy Dunlap
2025-06-24 15:05 ` [PATCH 38/66] kconfig: gconf: use GdkPixbuf in replace_button_icon() Masahiro Yamada
2025-06-24 15:05 ` [PATCH 39/66] kconfig: gconf: refactor replace_button_icon() Masahiro Yamada
2025-06-24 15:05 ` [PATCH 40/66] kconfig: gconf: make introduction, about, license dialogs modal Masahiro Yamada
2025-06-30 4:09 ` Randy Dunlap
2025-06-24 15:05 ` [PATCH 41/66] kconfig: gconf: remove global 'tree' variable Masahiro Yamada
2025-06-24 15:05 ` [PATCH 42/66] kconfig: gconf: merge 'current' and 'browsed' global variables Masahiro Yamada
2025-06-24 15:05 ` [PATCH 43/66] kconfig: gconf: preserve menu selection when switching view mode Masahiro Yamada
2025-06-30 5:42 ` Masahiro Yamada
2025-06-24 15:05 ` Masahiro Yamada [this message]
2025-06-24 15:05 ` [PATCH 45/66] kconfig: gconf: remove global 'model1' and 'model2' variables Masahiro Yamada
2025-06-30 4:10 ` Randy Dunlap
2025-06-24 15:05 ` [PATCH 46/66] kconfig: gconf: remove init_tree_model() Masahiro Yamada
2025-06-24 15:05 ` [PATCH 47/66] kconfig: gconf: inline fill_row() into set_node() Masahiro Yamada
2025-06-24 15:05 ` [PATCH 48/66] kconfig: gconf: do not reconstruct tree store when a symbol is changed Masahiro Yamada
2025-06-24 15:05 ` [PATCH 49/66] kconfig: gconf: inline display_list() into set_view_mode() Masahiro Yamada
2025-06-24 15:05 ` [PATCH 50/66] kconfig: gconf: remove dead code in display_tree_part() Masahiro Yamada
2025-06-24 15:05 ` [PATCH 51/66] kconfig: gconf: rename display_tree_part() Masahiro Yamada
2025-06-24 15:05 ` [PATCH 52/66] kconfig: gconf: remove fixup_rootmenu() Masahiro Yamada
2025-06-27 12:46 ` Masahiro Yamada
2025-06-24 15:05 ` [PATCH 53/66] kconfig: gconf: use size_allocate event handler Masahiro Yamada
2025-06-29 17:56 ` Masahiro Yamada
2025-06-30 5:23 ` Randy Dunlap
2025-06-30 5:30 ` Masahiro Yamada
2025-06-24 15:05 ` [PATCH 54/66] kconfig: gconf: replace GDK_space with GDK_KEY_space Masahiro Yamada
2025-06-24 15:05 ` [PATCH 55/66] kconfig: gconf: replace GTK_STOCK_{OK,NO,CANCEL} Masahiro Yamada
2025-06-30 5:26 ` Randy Dunlap
2025-06-24 15:05 ` [PATCH 56/66] kconfig: gconf: remove "tooltips" property from glade Masahiro Yamada
2025-06-24 15:05 ` [PATCH 57/66] kconfig: gconf: replace "tooltip" property with "tooltip-text" Masahiro Yamada
2025-06-30 5:36 ` Randy Dunlap
2025-06-24 15:05 ` [PATCH 58/66] kconfig: gconf: remove unnecessary default message in text view Masahiro Yamada
2025-06-24 15:05 ` [PATCH 59/66] kconfig: gconf: use gtk_check_menu_item_get_active() accessor Masahiro Yamada
2025-06-24 15:05 ` [PATCH 60/66] kconfig: gconf: use gtk_dialog_get_content_area() accessor Masahiro Yamada
2025-06-24 15:05 ` [PATCH 61/66] kconfig: gconf: remove GtkHandleBox from glade Masahiro Yamada
2025-06-24 15:05 ` [PATCH 62/66] kconfig: gconf: rename gconf.glade to gconf.ui Masahiro Yamada
2025-06-24 15:05 ` [PATCH 63/66] kconfig: gconf: migrate to GTK 3 Masahiro Yamada
2025-06-24 15:05 ` [PATCH 64/66] kconfig: gconf: replace GtkVbox with GtkBox Masahiro Yamada
2025-06-24 15:05 ` [PATCH 65/66] kconfig: gconf: replace GdkColor with GdkRGBA Masahiro Yamada
2025-06-24 15:05 ` [PATCH 66/66] kconfig: gconf: show GTK version in About dialog Masahiro Yamada
2025-06-30 6:06 ` Randy Dunlap
2025-06-30 6:55 ` [PATCH 00/66] kconfig: improve xconfig and gconfig Randy Dunlap
2025-06-30 15:48 ` Masahiro Yamada
2025-06-30 23:43 ` Randy Dunlap
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250624150645.1107002-45-masahiroy@kernel.org \
--to=masahiroy@kernel.org \
--cc=linux-kbuild@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®