]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
kconfig: gconf: use GtkTreeModelFilter to control row visibility
authorMasahiro Yamada <masahiroy@kernel.org>
Tue, 24 Jun 2025 15:05:32 +0000 (00:05 +0900)
committerMasahiro Yamada <masahiroy@kernel.org>
Wed, 2 Jul 2025 02:11:52 +0000 (11:11 +0900)
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

index eed6a10660eb49e1eabe76d482f8ebfbfd4a010a..e2b98b2205131317a9cc1aff88f52d20c561423c 100644 (file)
@@ -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)
 {
@@ -158,6 +160,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;
@@ -330,24 +373,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)
@@ -561,7 +601,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);
@@ -592,9 +632,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)
@@ -615,9 +655,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)
@@ -844,7 +884,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;
@@ -949,120 +988,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)
@@ -1085,8 +1010,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;
@@ -1095,12 +1018,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))
@@ -1322,6 +1241,20 @@ static void init_main_window(const gchar *glade_file)
        conf_set_changed_callback(conf_changed);
 }
 
+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,
@@ -1353,8 +1286,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);
@@ -1388,9 +1326,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);