[gtk+] Correct handling of row-has-child-toggled signal



commit 733e532c59f90885a4f7bd422219826ca42b1a89
Author: Kristian Rietveld <kris gtk org>
Date:   Wed Sep 2 12:45:41 2009 +0200

    Correct handling of row-has-child-toggled signal
    
    When a filter function is used that determines the visibility property
    of a node using whether or it it has children, the state of this node
    very likely changes when the filter model receives a
    row-has-child-toggled signal.  Therefore, we need to handle state
    changes in the row-has-child-toggled handler.

 gtk/gtktreemodelfilter.c |   52 +++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 47 insertions(+), 5 deletions(-)
---
diff --git a/gtk/gtktreemodelfilter.c b/gtk/gtktreemodelfilter.c
index 49020af..69c8f70 100644
--- a/gtk/gtktreemodelfilter.c
+++ b/gtk/gtktreemodelfilter.c
@@ -1576,6 +1576,7 @@ gtk_tree_model_filter_row_has_child_toggled (GtkTreeModel *c_model,
   GtkTreeIter iter;
   FilterLevel *level;
   FilterElt *elt;
+  gboolean requested_state;
 
   g_return_if_fail (c_path != NULL && c_iter != NULL);
 
@@ -1589,8 +1590,9 @@ gtk_tree_model_filter_row_has_child_toggled (GtkTreeModel *c_model,
       return;
     }
 
-  if (!gtk_tree_model_filter_visible (filter, c_iter))
-    return;
+  /* For all other levels, there is a chance that the visibility state
+   * of the parent has changed now.
+   */
 
   path = gtk_real_tree_model_filter_convert_child_path_to_path (filter,
                                                                 c_path,
@@ -1601,12 +1603,52 @@ gtk_tree_model_filter_row_has_child_toggled (GtkTreeModel *c_model,
 
   gtk_tree_model_filter_get_iter_full (GTK_TREE_MODEL (data), &iter, path);
 
-  gtk_tree_path_free (path);
-
   level = FILTER_LEVEL (iter.user_data);
   elt = FILTER_ELT (iter.user_data2);
 
-  g_assert (elt->visible);
+  gtk_tree_path_free (path);
+
+  requested_state = gtk_tree_model_filter_visible (filter, c_iter);
+
+  if (!elt->visible && !requested_state)
+    {
+      /* The parent node currently is not visible and will not become
+       * visible, so we will not pass on the row-has-child-toggled event.
+       */
+      return;
+    }
+  else if (elt->visible && !requested_state)
+    {
+      /* The node is no longer visible, so it has to be removed.
+       * _remove_node() takes care of emitting row-has-child-toggled
+       * when required.
+       */
+      level->visible_nodes--;
+
+      gtk_tree_model_filter_remove_node (filter, &iter);
+
+      return;
+    }
+  else if (!elt->visible && requested_state)
+    {
+      elt->visible = TRUE;
+      level->visible_nodes++;
+
+      /* Only insert if the parent is visible in the target */
+      if (gtk_tree_model_filter_elt_is_visible_in_target (level, elt))
+        {
+          path = gtk_tree_model_get_path (GTK_TREE_MODEL (filter), &iter);
+          gtk_tree_model_row_inserted (GTK_TREE_MODEL (filter), path, &iter);
+          gtk_tree_path_free (path);
+
+          /* We do not update children now, because that will happen
+           * below.
+           */
+        }
+    }
+  /* For the remaining possibility, elt->visible && requested_state
+   * no action is required.
+   */
 
   /* If this node is referenced and has children, build the level so we
    * can monitor it for changes.



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]