Merge branch 'wip/otte/treelistmodel-madness' into 'main'
authorBenjamin Otte <otte.benjamin@googlemail.com>
Wed, 26 Apr 2023 22:06:40 +0000 (22:06 +0000)
committerBenjamin Otte <otte.benjamin@googlemail.com>
Fri, 5 May 2023 01:45:06 +0000 (21:45 -0400)
treelistmodel: Be safer during collapsing

See merge request GNOME/gtk!5875

(cherry picked from commit 29e71868298448eb7fa570ed0a75935c235262de)

8766a6fa treelistmodel: Be safer during collapsing
3c76f3fb treelistmodel: Delay notifies from TreeListRow

gtk/gtktreelistmodel.c

index 1e55323c0a4e548bcde5389e72928eee1438c0c9..a4f0fa1d4b9ffe870e0bc9e7420945da946bc253 100644 (file)
@@ -101,8 +101,15 @@ static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
 static GtkTreeListModel *
 tree_node_get_tree_list_model (TreeNode *node)
 {
-  for (; !node->is_root; node = node->parent)
-    { }
+  if (node->is_root)
+    return node->list;
+
+  for (node = node->parent; !node->is_root; node = node->parent)
+    {
+      /* This can happen during collapsing of a parent node */
+      if (node->children == NULL)
+        return NULL;
+    }
 
   return node->list;
 }
@@ -316,6 +323,9 @@ gtk_tree_list_model_items_changed_cb (GListModel *model,
   guint i, tree_position, tree_removed, tree_added, n_local;
 
   self = tree_node_get_tree_list_model (node);
+  if (self == NULL)
+    return;
+
   n_local = g_list_model_get_n_items (model) - added + removed;
 
   if (position < n_local)
@@ -405,10 +415,16 @@ gtk_tree_list_model_clear_node (gpointer data)
   TreeNode *node = data;
 
   if (node->row)
-    gtk_tree_list_row_destroy (node->row);
+    {
+      g_object_freeze_notify (G_OBJECT (node->row));
+      gtk_tree_list_row_destroy (node->row);
+    }
 
   gtk_tree_list_model_clear_node_children (node);
 
+  if (node->row)
+    g_object_thaw_notify (G_OBJECT (node->row));
+
   g_clear_object (&node->item);
 }
 
@@ -945,16 +961,12 @@ G_DEFINE_TYPE (GtkTreeListRow, gtk_tree_list_row, G_TYPE_OBJECT)
 static void
 gtk_tree_list_row_destroy (GtkTreeListRow *self)
 {
-  g_object_freeze_notify (G_OBJECT (self));
-
   self->node = NULL;
 
   /* FIXME: We could check some properties to avoid excess notifies */
   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_thaw_notify (G_OBJECT (self));
 }
 
 static void
@@ -1180,6 +1192,8 @@ gtk_tree_list_row_set_expanded (GtkTreeListRow *self,
     return;
 
   list = tree_node_get_tree_list_model (self->node);
+  if (list == NULL)
+    return;
 
   if (expanded)
     {
@@ -1255,6 +1269,9 @@ gtk_tree_list_row_is_expandable (GtkTreeListRow *self)
     return TRUE;
 
   list = tree_node_get_tree_list_model (self->node);
+  if (list == NULL)
+    return FALSE;
+
   model = tree_node_create_model (list, self->node);
   if (model)
     {