From: Benjamin Otte Date: Sun, 19 Mar 2023 04:04:51 +0000 (+0100) Subject: treelistmodel: Cache the item X-Git-Tag: archive/raspbian/4.12.3+ds-1+rpi1~1^2^2^2~22^2~1^2~527^2~2 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=9048e391b60e19ccefa0b9fe51c466d16b42dcc4;p=gtk4.git treelistmodel: Cache the item This is a good idea to avoid reentrancy problems when any child model (or potentially more than one child model) has started emitting items-changed but the emission hasn't arrived in this model yet. At tat point, we'd get_item() the wrong item from those models. We want to avoid such cases of reentrancy. Related: #5646 --- diff --git a/gtk/gtktreelistmodel.c b/gtk/gtktreelistmodel.c index 84538fd4cf..775e311214 100644 --- a/gtk/gtktreelistmodel.c +++ b/gtk/gtktreelistmodel.c @@ -45,6 +45,7 @@ typedef struct _TreeAugment TreeAugment; struct _TreeNode { + gpointer item; GListModel *model; GtkTreeListRow *row; GtkRbTree *children; @@ -159,50 +160,6 @@ tree_node_get_n_children (TreeNode *node) return child_aug->n_items; } -static guint -tree_node_get_local_position (GtkRbTree *tree, - TreeNode *node) -{ - TreeNode *left, *parent; - TreeAugment *left_aug; - guint n; - - left = gtk_rb_tree_node_get_left (node); - if (left) - { - left_aug = gtk_rb_tree_get_augment (tree, left); - n = left_aug->n_local; - } - else - { - n = 0; - } - - for (parent = gtk_rb_tree_node_get_parent (node); - parent; - parent = gtk_rb_tree_node_get_parent (node)) - { - left = gtk_rb_tree_node_get_left (parent); - if (left == node) - { - /* we are the left node, nothing changes */ - } - else - { - /* we are the right node */ - n++; - if (left) - { - left_aug = gtk_rb_tree_get_augment (tree, left); - n += left_aug->n_local; - } - } - node = parent; - } - - return n; -} - static guint tree_node_get_position (TreeNode *node) { @@ -316,30 +273,15 @@ static GListModel * tree_node_create_model (GtkTreeListModel *self, TreeNode *node) { - TreeNode *parent = node->parent; GListModel *model; - GObject *item; - item = g_list_model_get_item (parent->model, - tree_node_get_local_position (parent->children, node)); - model = self->create_func (item, self->user_data); - g_object_unref (item); + model = self->create_func (node->item, self->user_data); if (model == NULL) node->empty = TRUE; return model; } -static gpointer -tree_node_get_item (TreeNode *node) -{ - TreeNode *parent; - - parent = node->parent; - return g_list_model_get_item (parent->model, - tree_node_get_local_position (parent->children, node)); -} - static GtkTreeListRow * tree_node_get_row (TreeNode *node) { @@ -417,6 +359,7 @@ gtk_tree_list_model_items_changed_cb (GListModel *model, { child = gtk_rb_tree_insert_before (node->children, child); child->parent = node; + child->item = g_list_model_get_item (model, position + i); } if (self->autoexpand) { @@ -442,6 +385,8 @@ static void gtk_tree_list_row_destroy (GtkTreeListRow *row); static void gtk_tree_list_model_clear_node_children (TreeNode *node) { + g_clear_object (&node->item); + if (node->model) { g_signal_handlers_disconnect_by_func (node->model, @@ -516,6 +461,7 @@ gtk_tree_list_model_init_node (GtkTreeListModel *list, { node = gtk_rb_tree_insert_after (self->children, node); node->parent = self; + node->item = g_list_model_get_item (model, i); if (list->autoexpand) gtk_tree_list_model_expand_node (list, node); } @@ -596,7 +542,7 @@ gtk_tree_list_model_get_item (GListModel *list, if (self->passthrough) { - return tree_node_get_item (node); + return g_object_ref (node->item); } else { @@ -1331,7 +1277,7 @@ gtk_tree_list_row_get_item (GtkTreeListRow *self) if (self->node == NULL) return NULL; - return tree_node_get_item (self->node); + return g_object_ref (self->node->item); } /**