[gnome-builder] tree: implement recursive search for tree nodes



commit aa17bff9dc2f196556ff76ea448e886bf8e6afb0
Author: Christian Hergert <chergert redhat com>
Date:   Mon Oct 12 19:49:17 2015 -0700

    tree: implement recursive search for tree nodes
    
    This will only filter items that have been loaded. If you have a tree that
    needs to dynamically load data, you are expected to have done that, or
    be doing that, in the background iteratively.
    
    This will match the filters as items are added or already existing in
    the underlying TreeStore.

 src/tree/gb-tree.c |   64 +++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 61 insertions(+), 3 deletions(-)
---
diff --git a/src/tree/gb-tree.c b/src/tree/gb-tree.c
index 7369c2b..e3ecd12 100644
--- a/src/tree/gb-tree.c
+++ b/src/tree/gb-tree.c
@@ -640,7 +640,6 @@ gb_tree_row_expanded (GtkTreeView *tree_view,
                       GtkTreePath *path)
 {
   GbTree *self = (GbTree *)tree_view;
-  GbTreePrivate *priv = gb_tree_get_instance_private (self);
   GtkTreeModel *model;
   GbTreeNode *node;
 
@@ -648,7 +647,7 @@ gb_tree_row_expanded (GtkTreeView *tree_view,
   g_assert (iter != NULL);
   g_assert (path != NULL);
 
-  model = GTK_TREE_MODEL (priv->store);
+  model = gtk_tree_view_get_model (tree_view);
 
   gtk_tree_model_get (model, iter, 0, &node, -1);
 
@@ -1618,6 +1617,36 @@ filter_func_free (gpointer user_data)
 }
 
 static gboolean
+gb_tree_model_filter_recursive (GtkTreeModel *model,
+                                GtkTreeIter  *parent,
+                                FilterFunc   *filter)
+{
+  GtkTreeIter child;
+
+  if (gtk_tree_model_iter_children (model, &child, parent))
+    {
+      do
+        {
+          g_autoptr(GbTreeNode) node = NULL;
+
+          gtk_tree_model_get (model, &child, 0, &node, -1);
+
+          if (node != NULL)
+            {
+              if (filter->filter_func (filter->self, node, filter->filter_data))
+                return TRUE;
+
+              if (gb_tree_model_filter_recursive (model, &child, filter))
+                return TRUE;
+            }
+        }
+      while (gtk_tree_model_iter_next (model, &child));
+    }
+
+  return FALSE;
+}
+
+static gboolean
 gb_tree_model_filter_visible_func (GtkTreeModel *model,
                                    GtkTreeIter  *iter,
                                    gpointer      data)
@@ -1626,11 +1655,40 @@ gb_tree_model_filter_visible_func (GtkTreeModel *model,
   FilterFunc *filter = data;
   gboolean ret;
 
+  /*
+   * This is a rather complex situation.
+   *
+   * We might not match, but one of our children nodes might match.
+   * Furthering the issue, the children might still need to be built.
+   * For some cases, this could be really expensive (think file tree)
+   * but for other things, it could be cheap. If you are going to use
+   * a filter func for your tree, you probably should avoid being
+   * too lazy and ensure the nodes are available.
+   *
+   * Therefore, we will only check available nodes, and ignore the
+   * case where the children nodes need to be built.   *
+   *
+   * TODO: Another option would be to iteratively build the items after
+   *       the initial filter.
+   */
+
   gtk_tree_model_get (model, iter, 0, &node, -1);
   ret = filter->filter_func (filter->self, node, filter->filter_data);
   g_clear_object (&node);
 
-  return ret;
+  /*
+   * Short circuit if we already matched.
+   */
+  if (ret)
+    return TRUE;
+
+  /*
+   * If any of our children match, we should match.
+   */
+  if (gb_tree_model_filter_recursive (model, iter, filter))
+    return TRUE;
+
+  return FALSE;
 }
 
 /**


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