Merge branch 'wip/otte/for-main' into 'main'
authorBenjamin Otte <otte.benjamin@googlemail.com>
Sun, 19 Mar 2023 06:23:46 +0000 (06:23 +0000)
committerBenjamin Otte <otte.benjamin@googlemail.com>
Sun, 19 Mar 2023 06:24:01 +0000 (02:24 -0400)
Fix inspector doing weird stuff

Closes #5646

See merge request GNOME/gtk!5678

(cherry picked from commit f211a2177f6160c3678e30ee07263229c48ec3ef)

f4be5c80 cssnode: Refer the correct previous item
9048e391 treelistmodel: Cache the item
bf556850 treelistmodel: Track the item in the row
c4636852 treelistmodel: Clarify docs

gtk/gtkcssnode.c
gtk/gtktreelistmodel.c
testsuite/gtk/defaultvalue.c

index 3d86740e96104e5c7d34bdf07fe718c21d863565..483b1e7ef489a540bec5ee26232ced81b8364546 100644 (file)
@@ -713,7 +713,7 @@ gtk_css_node_reposition (GtkCssNode *node,
     {
       GTK_CSS_NODE_GET_CLASS (old_parent)->node_removed (old_parent, node, node->previous_sibling);
       if (old_parent->children_observer && old_parent != new_parent)
-        gtk_list_list_model_item_removed (old_parent->children_observer, previous);
+        gtk_list_list_model_item_removed (old_parent->children_observer, old_previous);
       if (old_parent->first_child && node->visible)
         gtk_css_node_invalidate (old_parent->first_child, GTK_CSS_CHANGE_NTH_LAST_CHILD);
     }
index 84538fd4cfb07d7fbb20b5402e9c9ba49b55b572..8a189fe2ce1d231ea4a73b20f2a09c01041c31c4 100644 (file)
@@ -45,6 +45,7 @@ typedef struct _TreeAugment TreeAugment;
 
 struct _TreeNode
 {
+  gpointer item;
   GListModel *model;
   GtkTreeListRow *row;
   GtkRbTree *children;
@@ -87,6 +88,7 @@ struct _GtkTreeListRow
   GObject parent_instance;
 
   TreeNode *node; /* NULL when the row has been destroyed */
+  gpointer item;
 };
 
 struct _GtkTreeListRowClass
@@ -159,50 +161,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 +274,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)
 {
@@ -351,6 +294,7 @@ tree_node_get_row (TreeNode *node)
     {
       node->row = g_object_new (GTK_TYPE_TREE_LIST_ROW, NULL);
       node->row->node = node;
+      node->row->item = g_object_ref (node->item);
 
       return node->row;
     }
@@ -417,6 +361,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 +387,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 +463,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 +544,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
     {
@@ -1001,7 +949,6 @@ gtk_tree_list_row_destroy (GtkTreeListRow *self)
   g_object_notify_by_pspec (G_OBJECT (self), row_properties[ROW_PROP_DEPTH]);
   g_object_notify_by_pspec (G_OBJECT (self), row_properties[ROW_PROP_EXPANDABLE]);
   g_object_notify_by_pspec (G_OBJECT (self), row_properties[ROW_PROP_EXPANDED]);
-  g_object_notify_by_pspec (G_OBJECT (self), row_properties[ROW_PROP_ITEM]);
 
   self->node = NULL;
   g_object_thaw_notify (G_OBJECT (self));
@@ -1071,6 +1018,8 @@ gtk_tree_list_row_dispose (GObject *object)
   if (self->node)
     self->node->row = NULL;
 
+  g_clear_object (&self->item);
+
   G_OBJECT_CLASS (gtk_tree_list_row_parent_class)->dispose (object);
 }
 
@@ -1171,7 +1120,8 @@ gtk_tree_list_row_get_position (GtkTreeListRow *self)
  * of zero, rows corresponding to items of models of direct children
  * of the root model have a depth of 1 and so on.
  *
- * The depth of a row never changes until the row is destroyed.
+ * The depth of a row never changes until the row is removed from its model
+ * at which point it will forever return 0.
  *
  * Returns: The depth of this row
  */
@@ -1279,7 +1229,8 @@ gtk_tree_list_row_get_expanded (GtkTreeListRow *self)
  * This does not mean that the row is actually expanded,
  * this can be checked with [method@Gtk.TreeListRow.get_expanded].
  *
- * If a row is expandable never changes until the row is destroyed.
+ * If a row is expandable never changes until the row is removed
+ * from its model at which point it will forever return %FALSE.
  *
  * Returns: %TRUE if the row is expandable
  */
@@ -1317,21 +1268,16 @@ gtk_tree_list_row_is_expandable (GtkTreeListRow *self)
  *
  * Gets the item corresponding to this row,
  *
- * The value returned by this function never changes until the
- * row is destroyed.
- *
  * Returns: (nullable) (type GObject) (transfer full): The item
- *   of this row or %NULL when the row was destroyed
+ *   of this row. This function is only marked as nullable for backwards
+ *   compatibility reasons.
  */
 gpointer
 gtk_tree_list_row_get_item (GtkTreeListRow *self)
 {
   g_return_val_if_fail (GTK_IS_TREE_LIST_ROW (self), NULL);
 
-  if (self->node == NULL)
-    return NULL;
-
-  return tree_node_get_item (self->node);
+  return g_object_ref (self->item);
 }
 
 /**
@@ -1371,7 +1317,8 @@ gtk_tree_list_row_get_children (GtkTreeListRow *self)
  * %NULL is returned.
  *
  * The value returned by this function never changes
- * until the row is destroyed.
+ * until the row is removed from its model at which point
+ * it will forever return %NULL.
  *
  * Returns: (nullable) (transfer full): The parent of @self
  */
index a1ce47c9b0c31dae53da000b4acf0539d93d7ab7..a9d7053a2db8363910b004cbdf90d5867624a576 100644 (file)
@@ -151,6 +151,12 @@ test_type (gconstpointer data)
       if ((pspec->flags & G_PARAM_READABLE) == 0)
        continue;
 
+      /* This is set by the treelistmodel, plain 
+       * g_object_new() will crash here */
+      if (g_type_is_a (type, GTK_TYPE_TREE_LIST_ROW) &&
+         (strcmp (pspec->name, "item") == 0))
+       continue;
+
       /* This is set via class_init, and we have a11y tests to verify it */
       if (g_type_is_a (type, GTK_TYPE_ACCESSIBLE) &&
           strcmp (pspec->name, "accessible-role") == 0)