1 /* gtktreemodelfilter.c
2 * Copyright (C) 2000,2001 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
3 * Copyright (C) 2001-2003 Kristian Rietveld <kris@gtk.org>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
22 #include "gtktreemodelfilter.h"
24 #include "gtktreednd.h"
25 #include "gtkprivate.h"
30 * SECTION:gtktreemodelfilter
31 * @Short_description: A GtkTreeModel which hides parts of an underlying tree model
32 * @Title: GtkTreeModelFilter
33 * @See_also:#GtkTreeModelSort
35 * A #GtkTreeModelFilter is a tree model which wraps another tree model,
36 * and can do the following things:
39 * Filter specific rows, based on data from a "visible column", a column
40 * storing booleans indicating whether the row should be filtered or not,
41 * or based on the return value of a "visible function", which gets a
42 * model, iter and user_data and returns a boolean indicating whether the
43 * row should be filtered or not.
46 * Modify the "appearance" of the model, using a modify function.
47 * This is extremely powerful and allows for just changing
48 * some values and also for creating a completely different model based on
49 * the given child model.
52 * Set a different root node, also known as a "virtual root". You can pass in
53 * a #GtkTreePath indicating the root node for the filter at construction time.
57 * The basic API is similar to #GtkTreeModelSort. For an example on its usage,
58 * see the section on #GtkTreeModelSort.
60 * When using #GtkTreeModelFilter, it is important to realize that
61 * #GtkTreeModelFilter maintains an internal cache of all nodes which are
62 * visible in its clients. The cache is likely to be a subtree of the tree
63 * exposed by the child model. #GtkTreeModelFilter will not cache the entire
64 * child model when unnecessary to not compromise the caching mechanism
65 * that is exposed by the reference counting scheme. If the child model
66 * implements reference counting, unnecessary signals may not be emitted
67 * because of reference counting rule 3, see the #GtkTreeModel
68 * documentation. (Note that e.g. #GtkTreeStore does not implement
69 * reference counting and will always emit all signals, even when
70 * the receiving node is not visible).
72 * Because of this, limitations for possible visible functions do apply.
73 * In general, visible functions should only use data or properties from
74 * the node for which the visibility state must be determined, its siblings
75 * or its parents. Usually, having a dependency on the state of any child
76 * node is not possible, unless references are taken on these explicitly.
77 * When no such reference exists, no signals may be received for these child
78 * nodes (see reference couting rule number 3 in the #GtkTreeModel section).
80 * Determining the visibility state of a given node based on the state
81 * of its child nodes is a frequently occurring use case. Therefore,
82 * #GtkTreeModelFilter explicitly supports this. For example, when a node
83 * does not have any children, you might not want the node to be visible.
84 * As soon as the first row is added to the node's child level (or the
85 * last row removed), the node's visibility should be updated.
87 * This introduces a dependency from the node on its child nodes. In order
88 * to accommodate this, #GtkTreeModelFilter must make sure the necesary
89 * signals are received from the child model. This is achieved by building,
90 * for all nodes which are exposed as visible nodes to #GtkTreeModelFilter's
91 * clients, the child level (if any) and take a reference on the first node
92 * in this level. Furthermore, for every row-inserted, row-changed or
93 * row-deleted signal (also these which were not handled because the node
94 * was not cached), #GtkTreeModelFilter will check if the visibility state
95 * of any parent node has changed.
97 * Beware, however, that this explicit support is limited to these two
98 * cases. For example, if you want a node to be visible only if two nodes
99 * in a child's child level (2 levels deeper) are visible, you are on your
100 * own. In this case, either rely on #GtkTreeStore to emit all signals
101 * because it does not implement reference counting, or for models that
102 * do implement reference counting, obtain references on these child levels
106 /* Notes on this implementation of GtkTreeModelFilter
107 * ==================================================
112 * In this code there is a potential for confusion as to whether an iter,
113 * path or value refers to the GtkTreeModelFilter model, or to the child
114 * model that has been set. As a convention, variables referencing the
115 * child model will have a c_ prefix before them (ie. c_iter, c_value,
116 * c_path). In case the c_ prefixed names are already in use, an f_
117 * prefix is used. Conversion of iterators and paths between
118 * GtkTreeModelFilter and the child model is done through the various
119 * gtk_tree_model_filter_convert_* functions.
121 * Even though the GtkTreeModelSort and GtkTreeModelFilter have very
122 * similar data structures, many assumptions made in the GtkTreeModelSort
123 * code do *not* apply in the GtkTreeModelFilter case. Reference counting
124 * in particular is more complicated in GtkTreeModelFilter, because
125 * we explicitly support reliance on the state of a node's children as
126 * outlined in the public API documentation. Because of these differences,
127 * you are strongly recommended to first read through these notes before
128 * making any modification to the code.
133 * The iterator format of iterators handed out by GtkTreeModelFilter is
136 * iter->stamp = filter->priv->stamp
137 * iter->user_data = FilterLevel
138 * iter->user_data2 = FilterElt
140 * Internal data structure
141 * -----------------------
143 * Using FilterLevel and FilterElt, GtkTreeModelFilter maintains a "cache"
144 * of the mapping from GtkTreeModelFilter nodes to nodes in the child model.
145 * This is to avoid re-creating a level each time (which involves computing
146 * visibility for each node in that level) an operation is requested on
147 * GtkTreeModelFilter, such as get iter, get path and get value.
149 * A FilterElt corresponds to a single node. The FilterElt can either be
150 * visible or invisible in the model that is exposed to the clients of this
151 * GtkTreeModelFilter. The visibility state is stored in the "visible_siter"
152 * field, which is NULL when the node is not visible. The FilterLevel keeps
153 * a reference to the parent FilterElt and its FilterLevel (if any). The
154 * FilterElt can have a "children" pointer set, which points at a child
155 * level (a sub level).
157 * In a FilterLevel, two separate GSequences are maintained. One contains
158 * all nodes of this FilterLevel, regardless of the visibility state of
159 * the node. Another contains only visible nodes. A visible FilterElt
160 * is thus present in both the full and the visible GSequence. The
161 * GSequence allows for fast access, addition and removal of nodes.
163 * It is important to recognize the two different mappings that play
164 * a part in this code:
165 * I. The mapping from the client to this model. The order in which
166 * nodes are stored in the *visible* GSequence is the order in
167 * which the nodes are exposed to clients of the GtkTreeModelFilter.
168 * II. The mapping from this model to its child model. Each FilterElt
169 * contains an "offset" field which is the offset of the
170 * corresponding node in the child model.
172 * Throughout the code, two kinds of paths relative to the GtkTreeModelFilter
173 * (those generated from the sequence positions) are used. There are paths
174 * which take non-visible nodes into account (generated from the full
175 * sequences) and paths which don't (generated from the visible sequences).
176 * Paths which have been generated from the full sequences should only be
177 * used internally and NEVER be passed along with a signal emisson.
182 * GtkTreeModelFilter forwards all reference and unreference operations
183 * to the corresponding node in the child model. In addition,
184 * GtkTreeModelFilter will also add references of its own. The full reference
185 * count of each node (i.e. all forwarded references and these by the
186 * filter model) is maintained internally in the "ref_count" fields in
187 * FilterElt and FilterLevel. Because there is a need to determine whether
188 * a node should be visible for the client, the reference count of only
189 * the forwarded references is maintained as well, in the "ext_ref_count"
192 * In a few cases, GtkTreeModelFilter takes additional references on
193 * nodes. The first case is that a reference is taken on the parent
194 * (if any) of each level. This happens in gtk_tree_model_filter_build_level()
195 * and the reference is released again in gtk_tree_model_filter_free_level().
196 * This ensures that for all references which are taken by the filter
197 * model, all parent nodes are referenced according to reference counting
198 * rule 1 in the GtkTreeModel documentation.
200 * A second case is required to support visible functions which depend on
201 * the state of a node's children (see the public API documentation for
202 * GtkTreeModelFilter above). We build the child level of each node that
203 * could be visible in the client (i.e. the level has an ext_ref_count > 0;
204 * not the elt, because the elt might be invisible and thus unreferenced
205 * by the client). For each node that becomes visible, due to insertion or
206 * changes in visibility state, it is checked whether node has children, if
207 * so the child level is built.
209 * A reference is taken on the first node of each level so that the child
210 * model will emit all signals for this level, due to reference counting
211 * rule 3 in the GtkTreeModel documentation. If due to changes in the level,
212 * another node becomes the first node (e.g. due to insertion or reordering),
213 * this reference is transferred from the old to the new first node.
215 * When a level has an *external* reference count of zero (which means that
216 * none of the nodes in the level is referenced by the clients), the level
217 * has a "zero ref count" on all its parents. As soon as the level reaches
218 * an *external* reference count of zero, the zero ref count value is
219 * incremented by one for all parents of this level. Due to the additional
220 * references taken by the filter model, it is important to base the
221 * zero ref count on the external reference count instead of on the full
222 * reference count of the node.
224 * The zero ref count value aids in determining which portions of the
225 * cache are possibly unused and could be removed. If a FilterElt has
226 * a zero ref count of one, then its child level is unused. However, the
227 * child level can only be removed from the cache if the FilterElt's
228 * parent level has an external ref count of zero. (Not the parent elt,
229 * because an invisible parent elt with external ref count == 0 might still
230 * become visible because of a state change in its child level!). Otherwise,
231 * monitoring this level is necessary to possibly update the visibility state
232 * of the parent. This is an important difference from GtkTreeModelSort!
234 * Signals are only required for levels with an external ref count > 0.
235 * This due to reference counting rule 3, see the GtkTreeModel
236 * documentation. In the GtkTreeModelFilter we try hard to stick to this
237 * rule and not emit redundant signals (though redundant emissions of
238 * row-has-child-toggled could appear frequently; it does happen that
239 * we simply forward the signal emitted by e.g. GtkTreeStore but also
240 * emit our own copy).
244 typedef struct _FilterElt FilterElt;
245 typedef struct _FilterLevel FilterLevel;
250 FilterLevel *children;
255 GSequenceIter *visible_siter; /* iter into visible_seq */
261 GSequence *visible_seq;
265 FilterElt *parent_elt;
266 FilterLevel *parent_level;
270 struct _GtkTreeModelFilterPrivate
272 GtkTreeModel *child_model;
274 GtkTreePath *virtual_root;
281 GtkTreeModelFilterVisibleFunc visible_func;
282 gpointer visible_data;
283 GDestroyNotify visible_destroy;
286 GtkTreeModelFilterModifyFunc modify_func;
287 gpointer modify_data;
288 GDestroyNotify modify_destroy;
289 gint modify_n_columns;
291 guint visible_method_set : 1;
292 guint modify_func_set : 1;
294 guint in_row_deleted : 1;
295 guint virtual_root_deleted : 1;
300 gulong has_child_toggled_id;
313 /* Set this to 0 to disable caching of child iterators. This
314 * allows for more stringent testing. It is recommended to set this
315 * to one when refactoring this code and running the unit tests to
319 # define GTK_TREE_MODEL_FILTER_CACHE_CHILD_ITERS(filter) \
320 (((GtkTreeModelFilter *)filter)->priv->child_flags & GTK_TREE_MODEL_ITERS_PERSIST)
322 # define GTK_TREE_MODEL_FILTER_CACHE_CHILD_ITERS(filter) (FALSE)
325 /* Defining this constant enables more assertions, which will be
326 * helpful when debugging the code.
328 #undef MODEL_FILTER_DEBUG
330 #define FILTER_ELT(filter_elt) ((FilterElt *)filter_elt)
331 #define FILTER_LEVEL(filter_level) ((FilterLevel *)filter_level)
332 #define GET_ELT(siter) ((FilterElt*) (siter ? g_sequence_get (siter) : NULL))
334 /* general code (object/interface init, properties, etc) */
335 static void gtk_tree_model_filter_tree_model_init (GtkTreeModelIface *iface);
336 static void gtk_tree_model_filter_drag_source_init (GtkTreeDragSourceIface *iface);
337 static void gtk_tree_model_filter_finalize (GObject *object);
338 static void gtk_tree_model_filter_set_property (GObject *object,
342 static void gtk_tree_model_filter_get_property (GObject *object,
347 /* signal handlers */
348 static void gtk_tree_model_filter_row_changed (GtkTreeModel *c_model,
352 static void gtk_tree_model_filter_row_inserted (GtkTreeModel *c_model,
356 static void gtk_tree_model_filter_row_has_child_toggled (GtkTreeModel *c_model,
360 static void gtk_tree_model_filter_row_deleted (GtkTreeModel *c_model,
363 static void gtk_tree_model_filter_rows_reordered (GtkTreeModel *c_model,
369 /* GtkTreeModel interface */
370 static GtkTreeModelFlags gtk_tree_model_filter_get_flags (GtkTreeModel *model);
371 static gint gtk_tree_model_filter_get_n_columns (GtkTreeModel *model);
372 static GType gtk_tree_model_filter_get_column_type (GtkTreeModel *model,
374 static gboolean gtk_tree_model_filter_get_iter_full (GtkTreeModel *model,
377 static gboolean gtk_tree_model_filter_get_iter (GtkTreeModel *model,
380 static GtkTreePath *gtk_tree_model_filter_get_path (GtkTreeModel *model,
382 static void gtk_tree_model_filter_get_value (GtkTreeModel *model,
386 static gboolean gtk_tree_model_filter_iter_next (GtkTreeModel *model,
388 static gboolean gtk_tree_model_filter_iter_previous (GtkTreeModel *model,
390 static gboolean gtk_tree_model_filter_iter_children (GtkTreeModel *model,
392 GtkTreeIter *parent);
393 static gboolean gtk_tree_model_filter_iter_has_child (GtkTreeModel *model,
395 static gint gtk_tree_model_filter_iter_n_children (GtkTreeModel *model,
397 static gboolean gtk_tree_model_filter_iter_nth_child (GtkTreeModel *model,
401 static gboolean gtk_tree_model_filter_iter_parent (GtkTreeModel *model,
404 static void gtk_tree_model_filter_ref_node (GtkTreeModel *model,
406 static void gtk_tree_model_filter_unref_node (GtkTreeModel *model,
409 /* TreeDragSource interface */
410 static gboolean gtk_tree_model_filter_row_draggable (GtkTreeDragSource *drag_source,
412 static gboolean gtk_tree_model_filter_drag_data_get (GtkTreeDragSource *drag_source,
414 GtkSelectionData *selection_data);
415 static gboolean gtk_tree_model_filter_drag_data_delete (GtkTreeDragSource *drag_source,
418 /* private functions */
419 static void gtk_tree_model_filter_build_level (GtkTreeModelFilter *filter,
420 FilterLevel *parent_level,
421 FilterElt *parent_elt,
422 gboolean emit_inserted);
424 static void gtk_tree_model_filter_free_level (GtkTreeModelFilter *filter,
425 FilterLevel *filter_level,
427 gboolean unref_parent,
428 gboolean unref_external);
430 static GtkTreePath *gtk_tree_model_filter_elt_get_path (FilterLevel *level,
434 static GtkTreePath *gtk_tree_model_filter_add_root (GtkTreePath *src,
436 static GtkTreePath *gtk_tree_model_filter_remove_root (GtkTreePath *src,
439 static void gtk_tree_model_filter_increment_stamp (GtkTreeModelFilter *filter);
441 static void gtk_tree_model_filter_real_modify (GtkTreeModelFilter *self,
442 GtkTreeModel *child_model,
446 static gboolean gtk_tree_model_filter_real_visible (GtkTreeModelFilter *filter,
447 GtkTreeModel *child_model,
448 GtkTreeIter *child_iter);
449 static gboolean gtk_tree_model_filter_visible (GtkTreeModelFilter *filter,
450 GtkTreeIter *child_iter);
451 static void gtk_tree_model_filter_clear_cache_helper (GtkTreeModelFilter *filter,
454 static void gtk_tree_model_filter_real_ref_node (GtkTreeModel *model,
457 static void gtk_tree_model_filter_real_unref_node (GtkTreeModel *model,
460 gboolean propagate_unref);
462 static void gtk_tree_model_filter_set_model (GtkTreeModelFilter *filter,
463 GtkTreeModel *child_model);
464 static void gtk_tree_model_filter_ref_path (GtkTreeModelFilter *filter,
466 static void gtk_tree_model_filter_unref_path (GtkTreeModelFilter *filter,
469 static void gtk_tree_model_filter_set_root (GtkTreeModelFilter *filter,
472 static GtkTreePath *gtk_real_tree_model_filter_convert_child_path_to_path (GtkTreeModelFilter *filter,
473 GtkTreePath *child_path,
474 gboolean build_levels,
475 gboolean fetch_children);
477 static gboolean gtk_tree_model_filter_elt_is_visible_in_target (FilterLevel *level,
480 static FilterElt *gtk_tree_model_filter_insert_elt_in_level (GtkTreeModelFilter *filter,
485 static FilterElt *gtk_tree_model_filter_fetch_child (GtkTreeModelFilter *filter,
489 static void gtk_tree_model_filter_remove_elt_from_level (GtkTreeModelFilter *filter,
492 static void gtk_tree_model_filter_update_children (GtkTreeModelFilter *filter,
495 static void gtk_tree_model_filter_emit_row_inserted_for_path (GtkTreeModelFilter *filter,
496 GtkTreeModel *c_model,
498 GtkTreeIter *c_iter);
501 G_DEFINE_TYPE_WITH_CODE (GtkTreeModelFilter, gtk_tree_model_filter, G_TYPE_OBJECT,
502 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL,
503 gtk_tree_model_filter_tree_model_init)
504 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_SOURCE,
505 gtk_tree_model_filter_drag_source_init))
508 gtk_tree_model_filter_init (GtkTreeModelFilter *filter)
510 filter->priv = G_TYPE_INSTANCE_GET_PRIVATE (filter,
511 GTK_TYPE_TREE_MODEL_FILTER,
512 GtkTreeModelFilterPrivate);
514 filter->priv->visible_column = -1;
515 filter->priv->zero_ref_count = 0;
516 filter->priv->visible_method_set = FALSE;
517 filter->priv->modify_func_set = FALSE;
518 filter->priv->in_row_deleted = FALSE;
519 filter->priv->virtual_root_deleted = FALSE;
523 gtk_tree_model_filter_class_init (GtkTreeModelFilterClass *filter_class)
525 GObjectClass *object_class;
527 object_class = (GObjectClass *) filter_class;
529 object_class->set_property = gtk_tree_model_filter_set_property;
530 object_class->get_property = gtk_tree_model_filter_get_property;
532 object_class->finalize = gtk_tree_model_filter_finalize;
534 filter_class->visible = gtk_tree_model_filter_real_visible;
535 filter_class->modify = gtk_tree_model_filter_real_modify;
537 /* Properties -- FIXME: disabled translations for now, until I can come up with a
540 g_object_class_install_property (object_class,
542 g_param_spec_object ("child-model",
544 ("The model for the filtermodel to filter"),
546 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
548 g_object_class_install_property (object_class,
550 g_param_spec_boxed ("virtual-root",
551 ("The virtual root"),
552 ("The virtual root (relative to the child model) for this filtermodel"),
554 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
556 g_type_class_add_private (object_class, sizeof (GtkTreeModelFilterPrivate));
560 gtk_tree_model_filter_tree_model_init (GtkTreeModelIface *iface)
562 iface->get_flags = gtk_tree_model_filter_get_flags;
563 iface->get_n_columns = gtk_tree_model_filter_get_n_columns;
564 iface->get_column_type = gtk_tree_model_filter_get_column_type;
565 iface->get_iter = gtk_tree_model_filter_get_iter;
566 iface->get_path = gtk_tree_model_filter_get_path;
567 iface->get_value = gtk_tree_model_filter_get_value;
568 iface->iter_next = gtk_tree_model_filter_iter_next;
569 iface->iter_previous = gtk_tree_model_filter_iter_previous;
570 iface->iter_children = gtk_tree_model_filter_iter_children;
571 iface->iter_has_child = gtk_tree_model_filter_iter_has_child;
572 iface->iter_n_children = gtk_tree_model_filter_iter_n_children;
573 iface->iter_nth_child = gtk_tree_model_filter_iter_nth_child;
574 iface->iter_parent = gtk_tree_model_filter_iter_parent;
575 iface->ref_node = gtk_tree_model_filter_ref_node;
576 iface->unref_node = gtk_tree_model_filter_unref_node;
580 gtk_tree_model_filter_drag_source_init (GtkTreeDragSourceIface *iface)
582 iface->row_draggable = gtk_tree_model_filter_row_draggable;
583 iface->drag_data_delete = gtk_tree_model_filter_drag_data_delete;
584 iface->drag_data_get = gtk_tree_model_filter_drag_data_get;
589 gtk_tree_model_filter_finalize (GObject *object)
591 GtkTreeModelFilter *filter = (GtkTreeModelFilter *) object;
593 if (filter->priv->virtual_root && !filter->priv->virtual_root_deleted)
595 gtk_tree_model_filter_unref_path (filter, filter->priv->virtual_root,
597 filter->priv->virtual_root_deleted = TRUE;
600 gtk_tree_model_filter_set_model (filter, NULL);
602 if (filter->priv->virtual_root)
603 gtk_tree_path_free (filter->priv->virtual_root);
605 if (filter->priv->root)
606 gtk_tree_model_filter_free_level (filter, filter->priv->root, TRUE, TRUE, FALSE);
608 g_free (filter->priv->modify_types);
610 if (filter->priv->modify_destroy)
611 filter->priv->modify_destroy (filter->priv->modify_data);
613 if (filter->priv->visible_destroy)
614 filter->priv->visible_destroy (filter->priv->visible_data);
617 G_OBJECT_CLASS (gtk_tree_model_filter_parent_class)->finalize (object);
621 gtk_tree_model_filter_set_property (GObject *object,
626 GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (object);
630 case PROP_CHILD_MODEL:
631 gtk_tree_model_filter_set_model (filter, g_value_get_object (value));
633 case PROP_VIRTUAL_ROOT:
634 gtk_tree_model_filter_set_root (filter, g_value_get_boxed (value));
637 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
643 gtk_tree_model_filter_get_property (GObject *object,
648 GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (object);
652 case PROP_CHILD_MODEL:
653 g_value_set_object (value, filter->priv->child_model);
655 case PROP_VIRTUAL_ROOT:
656 g_value_set_boxed (value, filter->priv->virtual_root);
659 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
667 filter_elt_new (void)
669 return g_slice_new (FilterElt);
673 filter_elt_free (gpointer elt)
675 g_slice_free (FilterElt, elt);
679 filter_elt_cmp (gconstpointer a,
683 const FilterElt *elt_a = a;
684 const FilterElt *elt_b = b;
686 if (elt_a->offset > elt_b->offset)
688 else if (elt_a->offset < elt_b->offset)
695 lookup_elt_with_offset (GSequence *seq,
697 GSequenceIter **ret_siter)
699 GSequenceIter *siter;
702 dummy.offset = offset;
703 siter = g_sequence_lookup (seq, &dummy, filter_elt_cmp, NULL);
708 return GET_ELT (siter);
712 increase_offset_iter (gpointer data,
715 FilterElt *elt = data;
716 gint offset = GPOINTER_TO_INT (user_data);
718 if (elt->offset >= offset)
723 decrease_offset_iter (gpointer data,
726 FilterElt *elt = data;
727 gint offset = GPOINTER_TO_INT (user_data);
729 if (elt->offset > offset)
734 gtk_tree_model_filter_build_level (GtkTreeModelFilter *filter,
735 FilterLevel *parent_level,
736 FilterElt *parent_elt,
737 gboolean emit_inserted)
740 GtkTreeIter first_node;
742 FilterLevel *new_level;
743 FilterLevel *tmp_level;
748 gboolean empty = TRUE;
750 g_assert (filter->priv->child_model != NULL);
752 /* Avoid building a level that already exists */
754 g_assert (parent_elt->children == NULL);
756 g_assert (filter->priv->root == NULL);
758 if (filter->priv->in_row_deleted)
763 if (filter->priv->virtual_root)
765 if (gtk_tree_model_get_iter (filter->priv->child_model, &root, filter->priv->virtual_root) == FALSE)
767 length = gtk_tree_model_iter_n_children (filter->priv->child_model, &root);
769 if (gtk_tree_model_iter_children (filter->priv->child_model, &iter, &root) == FALSE)
774 if (!gtk_tree_model_get_iter_first (filter->priv->child_model, &iter))
776 length = gtk_tree_model_iter_n_children (filter->priv->child_model, NULL);
781 GtkTreeIter parent_iter;
782 GtkTreeIter child_parent_iter;
784 parent_iter.stamp = filter->priv->stamp;
785 parent_iter.user_data = parent_level;
786 parent_iter.user_data2 = parent_elt;
788 gtk_tree_model_filter_convert_iter_to_child_iter (filter,
791 if (gtk_tree_model_iter_children (filter->priv->child_model, &iter, &child_parent_iter) == FALSE)
794 /* stamp may have changed */
795 gtk_tree_model_filter_convert_iter_to_child_iter (filter,
798 length = gtk_tree_model_iter_n_children (filter->priv->child_model, &child_parent_iter);
800 /* Take a reference on the parent */
801 gtk_tree_model_filter_real_ref_node (GTK_TREE_MODEL (filter),
802 &parent_iter, FALSE);
805 g_return_if_fail (length > 0);
807 new_level = g_new (FilterLevel, 1);
808 new_level->seq = g_sequence_new (filter_elt_free);
809 new_level->visible_seq = g_sequence_new (NULL);
810 new_level->ref_count = 0;
811 new_level->ext_ref_count = 0;
812 new_level->parent_elt = parent_elt;
813 new_level->parent_level = parent_level;
816 parent_elt->children = new_level;
818 filter->priv->root = new_level;
820 /* increase the count of zero ref_counts */
821 tmp_level = parent_level;
822 tmp_elt = parent_elt;
826 tmp_elt->zero_ref_count++;
828 tmp_elt = tmp_level->parent_elt;
829 tmp_level = tmp_level->parent_level;
831 if (new_level != filter->priv->root)
832 filter->priv->zero_ref_count++;
840 if (gtk_tree_model_filter_visible (filter, &iter))
842 FilterElt *filter_elt;
844 filter_elt = filter_elt_new ();
845 filter_elt->offset = i;
846 filter_elt->zero_ref_count = 0;
847 filter_elt->ref_count = 0;
848 filter_elt->ext_ref_count = 0;
849 filter_elt->children = NULL;
850 filter_elt->visible_siter = NULL;
852 if (GTK_TREE_MODEL_FILTER_CACHE_CHILD_ITERS (filter))
853 filter_elt->iter = iter;
855 g_sequence_append (new_level->seq, filter_elt);
856 filter_elt->visible_siter = g_sequence_append (new_level->visible_seq, filter_elt);
863 GtkTreeIter children;
865 f_iter.stamp = filter->priv->stamp;
866 f_iter.user_data = new_level;
867 f_iter.user_data2 = filter_elt;
869 f_path = gtk_tree_model_get_path (GTK_TREE_MODEL (filter),
871 gtk_tree_model_row_inserted (GTK_TREE_MODEL (filter),
873 gtk_tree_path_free (f_path);
875 if (gtk_tree_model_iter_children (filter->priv->child_model,
877 gtk_tree_model_filter_update_children (filter,
879 FILTER_ELT (f_iter.user_data2));
884 while (gtk_tree_model_iter_next (filter->priv->child_model, &iter));
886 /* The level does not contain any visible nodes. However, changes in
887 * this level might affect the parent node, which can either be visible
888 * or invisible. Therefore, this level can only be removed again,
889 * if the parent level has an external reference count of zero. That is,
890 * if this level changes state, no signals are required in the parent
894 (parent_level && parent_level->ext_ref_count == 0))
896 gtk_tree_model_filter_free_level (filter, new_level, FALSE, TRUE, FALSE);
900 /* If none of the nodes are visible, we will just pull in the
901 * first node of the level.
905 FilterElt *filter_elt;
907 filter_elt = filter_elt_new ();
908 filter_elt->offset = 0;
909 filter_elt->zero_ref_count = 0;
910 filter_elt->ref_count = 0;
911 filter_elt->ext_ref_count = 0;
912 filter_elt->children = NULL;
913 filter_elt->visible_siter = NULL;
915 if (GTK_TREE_MODEL_FILTER_CACHE_CHILD_ITERS (filter))
916 filter_elt->iter = first_node;
918 g_sequence_append (new_level->seq, filter_elt);
921 /* Keep a reference on the first node of this level. We need this
922 * to make sure that we get all signals for this level.
924 f_iter.stamp = filter->priv->stamp;
925 f_iter.user_data = new_level;
926 f_iter.user_data2 = g_sequence_get (g_sequence_get_begin_iter (new_level->seq));
928 gtk_tree_model_filter_real_ref_node (GTK_TREE_MODEL (filter), &f_iter,
933 gtk_tree_model_filter_free_level (GtkTreeModelFilter *filter,
934 FilterLevel *filter_level,
936 gboolean unref_parent,
937 gboolean unref_external)
939 GSequenceIter *siter;
940 GSequenceIter *end_siter;
942 g_assert (filter_level);
944 end_siter = g_sequence_get_end_iter (filter_level->seq);
945 for (siter = g_sequence_get_begin_iter (filter_level->seq);
947 siter = g_sequence_iter_next (siter))
949 FilterElt *elt = g_sequence_get (siter);
953 /* If we recurse and unref_self == FALSE, then unref_parent
954 * must also be FALSE (otherwise a still unref a node in this
957 gtk_tree_model_filter_free_level (filter,
958 FILTER_LEVEL (elt->children),
960 unref_self == FALSE ? FALSE : unref_parent,
968 f_iter.stamp = filter->priv->stamp;
969 f_iter.user_data = filter_level;
970 f_iter.user_data2 = elt;
972 while (elt->ext_ref_count > 0)
973 gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter),
979 /* Release the reference on the first item.
985 f_iter.stamp = filter->priv->stamp;
986 f_iter.user_data = filter_level;
987 f_iter.user_data2 = g_sequence_get (g_sequence_get_begin_iter (filter_level->seq));
989 gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter),
990 &f_iter, FALSE, TRUE);
993 if (filter_level->ext_ref_count == 0)
995 FilterLevel *parent_level = filter_level->parent_level;
996 FilterElt *parent_elt = filter_level->parent_elt;
1000 parent_elt->zero_ref_count--;
1002 parent_elt = parent_level->parent_elt;
1003 parent_level = parent_level->parent_level;
1006 if (filter_level != filter->priv->root)
1007 filter->priv->zero_ref_count--;
1010 #ifdef MODEL_FILTER_DEBUG
1011 if (filter_level == filter->priv->root)
1012 g_assert (filter->priv->zero_ref_count == 0);
1015 if (filter_level->parent_elt)
1017 /* Release reference on parent */
1018 GtkTreeIter parent_iter;
1020 parent_iter.stamp = filter->priv->stamp;
1021 parent_iter.user_data = filter_level->parent_level;
1022 parent_iter.user_data2 = filter_level->parent_elt;
1024 gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter),
1025 &parent_iter, FALSE, unref_parent);
1027 filter_level->parent_elt->children = NULL;
1030 filter->priv->root = NULL;
1032 g_sequence_free (filter_level->seq);
1033 g_sequence_free (filter_level->visible_seq);
1034 g_free (filter_level);
1037 /* prune_level() is like free_level(), however instead of being fully
1038 * freed, the level is pruned to a level with only the first node used
1039 * for monitoring. For now it is only being called from
1040 * gtk_tree_model_filter_remove_elt_from_level(), which is the reason
1041 * this function is lacking a "gboolean unref" argument.
1044 gtk_tree_model_filter_prune_level (GtkTreeModelFilter *filter,
1047 GSequenceIter *siter;
1048 GSequenceIter *end_siter;
1052 /* This function is called when the parent of level became invisible.
1053 * All external ref counts of the children need to be dropped.
1054 * All children except the first one can be removed.
1057 /* Any child levels can be freed */
1058 end_siter = g_sequence_get_end_iter (level->seq);
1059 for (siter = g_sequence_get_begin_iter (level->seq);
1061 siter = g_sequence_iter_next (siter))
1063 FilterElt *elt = g_sequence_get (siter);
1066 gtk_tree_model_filter_free_level (filter,
1067 FILTER_LEVEL (elt->children),
1071 /* For the first item, only drop the external references */
1072 elt = g_sequence_get (g_sequence_get_begin_iter (level->seq));
1074 f_iter.stamp = filter->priv->stamp;
1075 f_iter.user_data = level;
1076 f_iter.user_data2 = elt;
1078 while (elt->ext_ref_count > 0)
1079 gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter),
1080 &f_iter, TRUE, TRUE);
1082 if (elt->visible_siter)
1084 g_sequence_remove (elt->visible_siter);
1085 elt->visible_siter = NULL;
1088 /* Remove the other elts */
1089 end_siter = g_sequence_get_end_iter (level->seq);
1090 siter = g_sequence_get_begin_iter (level->seq);
1091 siter = g_sequence_iter_next (siter);
1092 for (; siter != end_siter; siter = g_sequence_iter_next (siter))
1094 elt = g_sequence_get (siter);
1096 f_iter.stamp = filter->priv->stamp;
1097 f_iter.user_data = level;
1098 f_iter.user_data2 = elt;
1100 while (elt->ext_ref_count > 0)
1101 gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter),
1102 &f_iter, TRUE, TRUE);
1103 /* In this case, we do remove reference counts we've added ourselves,
1104 * since the node will be removed from the data structures.
1106 while (elt->ref_count > 0)
1107 gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter),
1108 &f_iter, FALSE, TRUE);
1110 if (elt->visible_siter)
1112 g_sequence_remove (elt->visible_siter);
1113 elt->visible_siter = NULL;
1117 /* Remove [begin + 1, end] */
1118 siter = g_sequence_get_begin_iter (level->seq);
1119 siter = g_sequence_iter_next (siter);
1121 g_sequence_remove_range (siter, end_siter);
1123 /* The level must have reached an ext ref count of zero by now, though
1124 * we only assert on this in debugging mode.
1126 #ifdef MODEL_FILTER_DEBUG
1127 g_assert (level->ext_ref_count == 0);
1132 gtk_tree_model_filter_level_transfer_first_ref (GtkTreeModelFilter *filter,
1134 GSequenceIter *from_iter,
1135 GSequenceIter *to_iter)
1139 f_iter.stamp = filter->priv->stamp;
1140 f_iter.user_data = level;
1141 f_iter.user_data2 = g_sequence_get (to_iter);
1143 gtk_tree_model_filter_real_ref_node (GTK_TREE_MODEL (filter),
1146 f_iter.stamp = filter->priv->stamp;
1147 f_iter.user_data = level;
1148 f_iter.user_data2 = g_sequence_get (from_iter);
1150 gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter),
1151 &f_iter, FALSE, TRUE);
1155 gtk_tree_model_filter_level_transfer_first_ref_with_index (GtkTreeModelFilter *filter,
1160 gtk_tree_model_filter_level_transfer_first_ref (filter, level,
1161 g_sequence_get_iter_at_pos (level->seq, from_index),
1162 g_sequence_get_iter_at_pos (level->seq, to_index));
1165 /* Creates paths suitable for accessing the child model. */
1166 static GtkTreePath *
1167 gtk_tree_model_filter_elt_get_path (FilterLevel *level,
1171 FilterLevel *walker = level;
1172 FilterElt *walker2 = elt;
1174 GtkTreePath *real_path;
1176 g_return_val_if_fail (level != NULL, NULL);
1177 g_return_val_if_fail (elt != NULL, NULL);
1179 path = gtk_tree_path_new ();
1183 gtk_tree_path_prepend_index (path, walker2->offset);
1185 walker2 = walker->parent_elt;
1186 walker = walker->parent_level;
1191 real_path = gtk_tree_model_filter_add_root (path, root);
1192 gtk_tree_path_free (path);
1199 static GtkTreePath *
1200 gtk_tree_model_filter_add_root (GtkTreePath *src,
1203 GtkTreePath *retval;
1206 retval = gtk_tree_path_copy (root);
1208 for (i = 0; i < gtk_tree_path_get_depth (src); i++)
1209 gtk_tree_path_append_index (retval, gtk_tree_path_get_indices (src)[i]);
1214 static GtkTreePath *
1215 gtk_tree_model_filter_remove_root (GtkTreePath *src,
1218 GtkTreePath *retval;
1223 if (gtk_tree_path_get_depth (src) <= gtk_tree_path_get_depth (root))
1226 depth = gtk_tree_path_get_depth (src);
1227 indices = gtk_tree_path_get_indices (src);
1229 for (i = 0; i < gtk_tree_path_get_depth (root); i++)
1230 if (indices[i] != gtk_tree_path_get_indices (root)[i])
1233 retval = gtk_tree_path_new ();
1235 for (; i < depth; i++)
1236 gtk_tree_path_append_index (retval, indices[i]);
1242 gtk_tree_model_filter_increment_stamp (GtkTreeModelFilter *filter)
1246 filter->priv->stamp++;
1248 while (filter->priv->stamp == 0);
1250 gtk_tree_model_filter_clear_cache (filter);
1254 gtk_tree_model_filter_real_visible (GtkTreeModelFilter *filter,
1255 GtkTreeModel *child_model,
1256 GtkTreeIter *child_iter)
1258 if (filter->priv->visible_func)
1260 return filter->priv->visible_func (child_model,
1262 filter->priv->visible_data)
1265 else if (filter->priv->visible_column >= 0)
1269 gtk_tree_model_get_value (child_model, child_iter,
1270 filter->priv->visible_column, &val);
1272 if (g_value_get_boolean (&val))
1274 g_value_unset (&val);
1278 g_value_unset (&val);
1282 /* no visible function set, so always visible */
1287 gtk_tree_model_filter_visible (GtkTreeModelFilter *self,
1288 GtkTreeIter *child_iter)
1290 return GTK_TREE_MODEL_FILTER_GET_CLASS (self)->visible (self,
1291 self->priv->child_model, child_iter);
1295 gtk_tree_model_filter_clear_cache_helper_iter (gpointer data,
1298 GtkTreeModelFilter *filter = user_data;
1299 FilterElt *elt = data;
1301 #ifdef MODEL_FILTER_DEBUG
1302 g_assert (elt->zero_ref_count >= 0);
1305 if (elt->zero_ref_count > 0)
1306 gtk_tree_model_filter_clear_cache_helper (filter, elt->children);
1310 gtk_tree_model_filter_clear_cache_helper (GtkTreeModelFilter *filter,
1315 g_sequence_foreach (level->seq, gtk_tree_model_filter_clear_cache_helper_iter, filter);
1317 /* If the level's ext_ref_count is zero, it means the level is not visible
1318 * and can be removed. But, since we support monitoring a child level
1319 * of a parent for changes (these might affect the parent), we will only
1320 * free the level if the parent level also has an external ref
1321 * count of zero. In that case, changes concerning our parent are
1324 * The root level is always visible, so an exception holds for levels
1325 * with the root level as parent level: these have to remain cached.
1327 if (level->ext_ref_count == 0 && level != filter->priv->root &&
1328 level->parent_level && level->parent_level != filter->priv->root &&
1329 level->parent_level->ext_ref_count == 0)
1331 gtk_tree_model_filter_free_level (filter, level, TRUE, TRUE, FALSE);
1337 gtk_tree_model_filter_elt_is_visible_in_target (FilterLevel *level,
1340 if (!elt->visible_siter)
1343 if (!level->parent_elt)
1348 elt = level->parent_elt;
1349 level = level->parent_level;
1351 if (elt && !elt->visible_siter)
1359 /* If a change has occurred in path (inserted, changed or deleted),
1360 * then this function is used to check all its ancestors. An ancestor
1361 * could have changed state as a result and this needs to be propagated
1362 * to the objects monitoring the filter model.
1365 gtk_tree_model_filter_check_ancestors (GtkTreeModelFilter *filter,
1369 int *indices = gtk_tree_path_get_indices (path);
1372 GtkTreeIter c_iter, tmp_iter;
1374 level = FILTER_LEVEL (filter->priv->root);
1379 if (filter->priv->virtual_root)
1380 gtk_tree_model_get_iter (filter->priv->child_model, &c_iter,
1381 filter->priv->virtual_root);
1384 gtk_tree_model_iter_nth_child (filter->priv->child_model, &c_iter,
1385 filter->priv->virtual_root ? &tmp_iter : NULL,
1388 while (i < gtk_tree_path_get_depth (path) - 1)
1390 gboolean requested_state;
1392 elt = lookup_elt_with_offset (level->seq,
1393 gtk_tree_path_get_indices (path)[i], NULL);
1395 requested_state = gtk_tree_model_filter_visible (filter, &c_iter);
1400 GtkTreePath *c_path;
1402 if (requested_state == FALSE)
1405 /* The elt does not exist in this level (so it is not
1406 * visible), but should now be visible. We emit the
1407 * row-inserted and row-has-child-toggled signals.
1409 elt = gtk_tree_model_filter_insert_elt_in_level (filter,
1415 /* insert_elt_in_level defaults to FALSE */
1416 elt->visible_siter = g_sequence_insert_sorted (level->visible_seq,
1418 filter_elt_cmp, NULL);
1420 c_path = gtk_tree_model_get_path (filter->priv->child_model,
1423 gtk_tree_model_filter_emit_row_inserted_for_path (filter,
1424 filter->priv->child_model,
1428 gtk_tree_path_free (c_path);
1430 /* We can immediately return, because this node was not visible
1431 * before and its children will be checked for in response to
1432 * the emitted row-has-child-toggled signal.
1436 else if (elt->visible_siter)
1438 if (!requested_state)
1440 /* A node has turned invisible. Remove it from the level
1441 * and emit row-deleted. Since this node is being
1442 * deleted. it makes no sense to look further up the
1445 gtk_tree_model_filter_remove_elt_from_level (filter,
1450 /* Otherwise continue up the chain */
1452 else if (!elt->visible_siter)
1454 if (requested_state)
1456 /* A node is already in the cache, but invisible. This
1457 * is usually a node on which a reference is kept by
1458 * the filter model, or a node fetched on the filter's
1459 * request, and thus not shown. Therefore, we will
1460 * not emit row-inserted for this node. Instead,
1461 * we signal to its parent that a change has occurred.
1463 * Exception: root level, in this case, we must emit
1466 if (level->parent_level)
1469 GtkTreePath *f_path;
1471 elt->visible_siter = g_sequence_insert_sorted (level->visible_seq, elt,
1472 filter_elt_cmp, NULL);
1474 f_iter.stamp = filter->priv->stamp;
1475 f_iter.user_data = level->parent_level;
1476 f_iter.user_data2 = level->parent_elt;
1478 f_path = gtk_tree_model_get_path (GTK_TREE_MODEL (filter),
1480 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (filter),
1482 gtk_tree_path_free (f_path);
1486 GtkTreePath *c_path;
1488 elt->visible_siter = g_sequence_insert_sorted (level->visible_seq, elt,
1489 filter_elt_cmp, NULL);
1491 c_path = gtk_tree_model_get_path (filter->priv->child_model,
1494 gtk_tree_model_filter_emit_row_inserted_for_path (filter,
1495 filter->priv->child_model,
1499 gtk_tree_path_free (c_path);
1502 /* We can immediately return, because this node was not visible
1503 * before and the parent will check its children, including
1504 * this node, in response to the emitted row-has-child-toggled
1510 /* Not visible, so no need to continue. */
1516 /* If an elt does not have children, these are not visible.
1517 * Therefore, any signals emitted for these children will
1518 * be ignored, so we do not have to emit them.
1523 level = elt->children;
1527 gtk_tree_model_iter_nth_child (filter->priv->child_model, &c_iter,
1528 &tmp_iter, indices[i]);
1533 gtk_tree_model_filter_insert_elt_in_level (GtkTreeModelFilter *filter,
1534 GtkTreeIter *c_iter,
1540 GSequenceIter *siter;
1542 elt = filter_elt_new ();
1544 if (GTK_TREE_MODEL_FILTER_CACHE_CHILD_ITERS (filter))
1545 elt->iter = *c_iter;
1547 elt->offset = offset;
1548 elt->zero_ref_count = 0;
1550 elt->ext_ref_count = 0;
1551 elt->children = NULL;
1553 /* Because we don't emit row_inserted, the node is invisible and thus
1554 * not inserted in visible_seq
1556 elt->visible_siter = NULL;
1558 siter = g_sequence_insert_sorted (level->seq, elt, filter_elt_cmp, NULL);
1559 *index = g_sequence_iter_get_position (siter);
1561 /* If the insert location is zero, we need to move our reference
1562 * on the old first node to the new first node.
1565 gtk_tree_model_filter_level_transfer_first_ref_with_index (filter, level,
1572 gtk_tree_model_filter_fetch_child (GtkTreeModelFilter *filter,
1578 GtkTreePath *c_path = NULL;
1580 GtkTreePath *c_parent_path = NULL;
1581 GtkTreeIter c_parent_iter;
1583 /* check if child exists and is visible */
1584 if (level->parent_elt)
1587 gtk_tree_model_filter_elt_get_path (level->parent_level,
1589 filter->priv->virtual_root);
1595 if (filter->priv->virtual_root)
1596 c_parent_path = gtk_tree_path_copy (filter->priv->virtual_root);
1598 c_parent_path = NULL;
1603 gtk_tree_model_get_iter (filter->priv->child_model,
1606 len = gtk_tree_model_iter_n_children (filter->priv->child_model,
1609 c_path = gtk_tree_path_copy (c_parent_path);
1610 gtk_tree_path_free (c_parent_path);
1614 len = gtk_tree_model_iter_n_children (filter->priv->child_model, NULL);
1615 c_path = gtk_tree_path_new ();
1618 gtk_tree_path_append_index (c_path, offset);
1619 gtk_tree_model_get_iter (filter->priv->child_model, &c_iter, c_path);
1620 gtk_tree_path_free (c_path);
1622 if (offset >= len || !gtk_tree_model_filter_visible (filter, &c_iter))
1625 return gtk_tree_model_filter_insert_elt_in_level (filter, &c_iter,
1630 /* Note that this function is never called from the row-deleted handler.
1631 * This means that this function is only used for removing elements
1632 * which are still present in the child model. As a result, we must
1633 * take care to properly release the references the filter model has
1634 * on the child model nodes.
1637 gtk_tree_model_filter_remove_elt_from_level (GtkTreeModelFilter *filter,
1642 FilterLevel *parent_level;
1643 gint length, orig_level_ext_ref_count;
1645 GtkTreePath *path = NULL;
1647 gboolean emit_child_toggled = FALSE;
1649 /* We need to know about the level's ext ref count before removal
1652 orig_level_ext_ref_count = level->ext_ref_count;
1654 iter.stamp = filter->priv->stamp;
1655 iter.user_data = level;
1656 iter.user_data2 = elt;
1658 if (!parent || orig_level_ext_ref_count > 0)
1659 path = gtk_tree_model_get_path (GTK_TREE_MODEL (filter), &iter);
1661 /* If the level is not visible, the parent is potentially invisible
1662 * too. Either way, as no signal will be emitted, there is no use
1667 parent = level->parent_elt;
1668 parent_level = level->parent_level;
1670 length = g_sequence_get_length (level->seq);
1672 /* first register the node to be invisible */
1673 g_sequence_remove (elt->visible_siter);
1674 elt->visible_siter = NULL;
1677 * If level != root level and the number of visible nodes is 0 (ie. this
1678 * is the last node to be removed from the level), emit
1679 * row-has-child-toggled.
1682 if (level != filter->priv->root
1683 && g_sequence_get_length (level->visible_seq) == 0
1685 && parent->visible_siter)
1686 emit_child_toggled = TRUE;
1689 * - length > 1: in this case, the node is removed from the level
1690 * and row-deleted is emitted.
1691 * - length == 1: in this case, we need to decide whether to keep
1692 * the level or to free it.
1696 GSequenceIter *siter;
1698 /* We emit row-deleted, and remove the node from the cache.
1699 * If it has any children, these will be removed here as well.
1702 /* FIXME: I am not 100% sure it is always save to fully free the
1703 * level here. Perhaps the state of the parent level, etc. has to
1704 * be checked to make the right decision, like is done below for
1705 * the case length == 1.
1708 gtk_tree_model_filter_free_level (filter, elt->children, TRUE, TRUE, TRUE);
1710 /* If the first node is being removed, transfer, the reference */
1711 if (elt == g_sequence_get (g_sequence_get_begin_iter (level->seq)))
1713 gtk_tree_model_filter_level_transfer_first_ref_with_index (filter, level,
1717 while (elt->ext_ref_count > 0)
1718 gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter),
1720 /* In this case, we do remove reference counts we've added ourselves,
1721 * since the node will be removed from the data structures.
1723 while (elt->ref_count > 0)
1724 gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter),
1725 &iter, FALSE, TRUE);
1727 /* remove the node */
1728 lookup_elt_with_offset (level->seq, elt->offset, &siter);
1729 g_sequence_remove (siter);
1731 gtk_tree_model_filter_increment_stamp (filter);
1733 /* Only if the node is in the root level (parent == NULL) or
1734 * the level is visible, a row-deleted signal is necessary.
1736 if (!parent || orig_level_ext_ref_count > 0)
1737 gtk_tree_model_row_deleted (GTK_TREE_MODEL (filter), path);
1741 /* There is only one node left in this level */
1742 #ifdef MODEL_FILTER_DEBUG
1743 g_assert (length == 1);
1746 /* The row is signalled as deleted to the client. We have to
1747 * drop the remaining external reference count here, the client
1750 * We keep the reference counts we've obtained ourselves.
1752 while (elt->ext_ref_count > 0)
1753 gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter),
1756 /* This level is still required if:
1757 * - it is the root level
1758 * - its parent level is the root level
1759 * - its parent level has an external ref count > 0
1761 if (! (level == filter->priv->root ||
1762 level->parent_level == filter->priv->root ||
1763 level->parent_level->ext_ref_count > 0))
1765 /* Otherwise, the level can be removed */
1766 gtk_tree_model_filter_free_level (filter, level, TRUE, TRUE, TRUE);
1770 /* Level is kept, but we turn our attention to a child level.
1772 * If level is not the root level, it is a child level with
1773 * an ext ref count that is now 0. That means that any child level
1774 * of elt can be removed.
1776 if (level != filter->priv->root)
1778 #ifdef MODEL_FILTER_DEBUG
1779 g_assert (level->ext_ref_count == 0);
1782 gtk_tree_model_filter_free_level (filter, elt->children,
1787 /* In this case, we want to keep the level with the first
1788 * node pulled in to monitor for signals.
1791 gtk_tree_model_filter_prune_level (filter, elt->children);
1795 if (!parent || orig_level_ext_ref_count > 0)
1796 gtk_tree_model_row_deleted (GTK_TREE_MODEL (filter), path);
1799 gtk_tree_path_free (path);
1801 if (emit_child_toggled && parent->ext_ref_count > 0)
1806 piter.stamp = filter->priv->stamp;
1807 piter.user_data = parent_level;
1808 piter.user_data2 = parent;
1810 ppath = gtk_tree_model_get_path (GTK_TREE_MODEL (filter), &piter);
1812 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (filter),
1814 gtk_tree_path_free (ppath);
1818 /* This function is called after the given node has become visible.
1819 * When the node has children, we should build the level and
1820 * take a reference on the first child.
1823 gtk_tree_model_filter_update_children (GtkTreeModelFilter *filter,
1830 if (!elt->visible_siter)
1833 iter.stamp = filter->priv->stamp;
1834 iter.user_data = level;
1835 iter.user_data2 = elt;
1837 gtk_tree_model_filter_convert_iter_to_child_iter (filter, &c_iter, &iter);
1839 if ((!level->parent_level || level->parent_level->ext_ref_count > 0) &&
1840 gtk_tree_model_iter_has_child (filter->priv->child_model, &c_iter))
1843 gtk_tree_model_filter_build_level (filter, level, elt, FALSE);
1845 if (elt->ext_ref_count > 0 && elt->children &&
1846 g_sequence_get_length (elt->children->seq))
1849 path = gtk_tree_model_get_path (GTK_TREE_MODEL (filter), &iter);
1850 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (filter),
1854 gtk_tree_path_free (path);
1859 /* Path is relative to the child model (this is on search on elt offset)
1860 * but with the virtual root already removed if necesssary.
1863 find_elt_with_offset (GtkTreeModelFilter *filter,
1865 FilterLevel **level_,
1870 FilterLevel *parent_level = NULL;
1871 FilterElt *elt = NULL;
1873 level = FILTER_LEVEL (filter->priv->root);
1875 while (i < gtk_tree_path_get_depth (path))
1880 elt = lookup_elt_with_offset (level->seq,
1881 gtk_tree_path_get_indices (path)[i],
1887 parent_level = level;
1888 level = elt->children;
1893 *level_ = parent_level;
1901 /* TreeModel signals */
1903 gtk_tree_model_filter_emit_row_inserted_for_path (GtkTreeModelFilter *filter,
1904 GtkTreeModel *c_model,
1905 GtkTreePath *c_path,
1906 GtkTreeIter *c_iter)
1911 GtkTreeIter iter, children;
1912 gboolean signals_emitted = FALSE;
1914 if (!filter->priv->root)
1916 /* The root level has not been exposed to the view yet, so we
1917 * need to emit signals for any node that is being inserted.
1919 gtk_tree_model_filter_build_level (filter, NULL, NULL, TRUE);
1921 /* Check if the root level was built. Then child levels
1922 * that matter have also been built (due to update_children,
1923 * which triggers iter_n_children).
1925 if (filter->priv->root &&
1926 g_sequence_get_length (FILTER_LEVEL (filter->priv->root)->visible_seq) > 0)
1927 signals_emitted = TRUE;
1930 gtk_tree_model_filter_increment_stamp (filter);
1932 /* We need to disallow to build new levels, because we are then pulling
1933 * in a child in an invisible level. We only want to find path if it
1934 * is in a visible level (and thus has a parent that is visible).
1936 path = gtk_real_tree_model_filter_convert_child_path_to_path (filter,
1942 /* parent is probably being filtered out */
1945 gtk_tree_model_filter_get_iter_full (GTK_TREE_MODEL (filter), &iter, path);
1947 level = FILTER_LEVEL (iter.user_data);
1948 elt = FILTER_ELT (iter.user_data2);
1950 /* Make sure elt is visible. elt can already be visible in case
1951 * it was pulled in above, so avoid inserted it into visible_seq twice.
1953 if (!elt->visible_siter)
1955 elt->visible_siter = g_sequence_insert_sorted (level->visible_seq,
1956 elt, filter_elt_cmp,
1960 /* Check whether the node and all of its parents are visible */
1961 if (gtk_tree_model_filter_elt_is_visible_in_target (level, elt))
1963 /* visibility changed -- reget path */
1964 gtk_tree_path_free (path);
1965 path = gtk_tree_model_get_path (GTK_TREE_MODEL (filter), &iter);
1967 if (!signals_emitted &&
1968 (!level->parent_level || level->ext_ref_count > 0))
1969 gtk_tree_model_row_inserted (GTK_TREE_MODEL (filter), path, &iter);
1971 if (level->parent_level && level->parent_elt->ext_ref_count > 0 &&
1972 g_sequence_get_length (level->visible_seq) == 1)
1974 /* We know that this is the first visible node in this level, so
1975 * we need to emit row-has-child-toggled on the parent. This
1976 * does not apply to the root level.
1979 gtk_tree_path_up (path);
1980 gtk_tree_model_get_iter (GTK_TREE_MODEL (filter), &iter, path);
1982 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (filter),
1987 if (!signals_emitted
1988 && gtk_tree_model_iter_children (c_model, &children, c_iter))
1989 gtk_tree_model_filter_update_children (filter, level, elt);
1992 gtk_tree_path_free (path);
1996 gtk_tree_model_filter_row_changed (GtkTreeModel *c_model,
1997 GtkTreePath *c_path,
1998 GtkTreeIter *c_iter,
2001 GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (data);
2003 GtkTreeIter children;
2004 GtkTreeIter real_c_iter;
2005 GtkTreePath *path = NULL;
2006 GtkTreePath *real_path = NULL;
2011 gboolean requested_state;
2012 gboolean current_state;
2013 gboolean free_c_path = FALSE;
2015 g_return_if_fail (c_path != NULL || c_iter != NULL);
2019 c_path = gtk_tree_model_get_path (c_model, c_iter);
2023 if (filter->priv->virtual_root)
2024 real_path = gtk_tree_model_filter_remove_root (c_path,
2025 filter->priv->virtual_root);
2027 real_path = gtk_tree_path_copy (c_path);
2030 real_c_iter = *c_iter;
2032 gtk_tree_model_get_iter (c_model, &real_c_iter, c_path);
2034 /* is this node above the virtual root? */
2035 if (filter->priv->virtual_root &&
2036 (gtk_tree_path_get_depth (filter->priv->virtual_root)
2037 >= gtk_tree_path_get_depth (c_path)))
2040 /* what's the requested state? */
2041 requested_state = gtk_tree_model_filter_visible (filter, &real_c_iter);
2043 /* now, let's see whether the item is there */
2044 path = gtk_real_tree_model_filter_convert_child_path_to_path (filter,
2051 gtk_tree_model_filter_get_iter_full (GTK_TREE_MODEL (filter),
2053 current_state = FILTER_ELT (iter.user_data2)->visible_siter != NULL;
2056 current_state = FALSE;
2058 if (current_state == FALSE && requested_state == FALSE)
2059 /* no changes required */
2062 if (current_state == TRUE && requested_state == FALSE)
2064 gtk_tree_model_filter_remove_elt_from_level (filter,
2065 FILTER_LEVEL (iter.user_data),
2066 FILTER_ELT (iter.user_data2));
2069 gtk_tree_model_filter_check_ancestors (filter, real_path);
2074 if (current_state == TRUE && requested_state == TRUE)
2076 /* propagate the signal; also get a path taking only visible
2077 * nodes into account.
2079 gtk_tree_path_free (path);
2080 path = gtk_tree_model_get_path (GTK_TREE_MODEL (filter), &iter);
2082 level = FILTER_LEVEL (iter.user_data);
2083 elt = FILTER_ELT (iter.user_data2);
2085 if (gtk_tree_model_filter_elt_is_visible_in_target (level, elt))
2087 if (level->ext_ref_count > 0)
2088 gtk_tree_model_row_changed (GTK_TREE_MODEL (filter), path, &iter);
2090 /* and update the children */
2091 if (gtk_tree_model_iter_children (c_model, &children, &real_c_iter))
2092 gtk_tree_model_filter_update_children (filter, level, elt);
2096 gtk_tree_model_filter_check_ancestors (filter, real_path);
2101 /* only current == FALSE and requested == TRUE is left,
2104 g_return_if_fail (current_state == FALSE && requested_state == TRUE);
2107 gtk_tree_model_filter_check_ancestors (filter, real_path);
2109 gtk_tree_model_filter_emit_row_inserted_for_path (filter, c_model,
2114 gtk_tree_path_free (path);
2117 gtk_tree_path_free (real_path);
2120 gtk_tree_path_free (c_path);
2124 gtk_tree_model_filter_row_inserted (GtkTreeModel *c_model,
2125 GtkTreePath *c_path,
2126 GtkTreeIter *c_iter,
2129 GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (data);
2130 GtkTreePath *real_path = NULL;
2132 GtkTreeIter real_c_iter;
2134 FilterElt *elt = NULL;
2135 FilterLevel *level = NULL;
2136 FilterLevel *parent_level = NULL;
2137 GSequenceIter *siter;
2142 gboolean free_c_path = FALSE;
2143 gboolean emit_row_inserted = FALSE;
2145 g_return_if_fail (c_path != NULL || c_iter != NULL);
2149 c_path = gtk_tree_model_get_path (c_model, c_iter);
2154 real_c_iter = *c_iter;
2156 gtk_tree_model_get_iter (c_model, &real_c_iter, c_path);
2158 /* the row has already been inserted. so we need to fixup the
2159 * virtual root here first
2161 if (filter->priv->virtual_root)
2163 if (gtk_tree_path_get_depth (filter->priv->virtual_root) >=
2164 gtk_tree_path_get_depth (c_path))
2167 gint *v_indices, *c_indices;
2168 gboolean common_prefix = TRUE;
2170 level = gtk_tree_path_get_depth (c_path) - 1;
2171 v_indices = gtk_tree_path_get_indices (filter->priv->virtual_root);
2172 c_indices = gtk_tree_path_get_indices (c_path);
2174 for (i = 0; i < level; i++)
2175 if (v_indices[i] != c_indices[i])
2177 common_prefix = FALSE;
2181 if (common_prefix && v_indices[level] >= c_indices[level])
2182 (v_indices[level])++;
2186 /* subtract virtual root if necessary */
2187 if (filter->priv->virtual_root)
2189 real_path = gtk_tree_model_filter_remove_root (c_path,
2190 filter->priv->virtual_root);
2196 real_path = gtk_tree_path_copy (c_path);
2198 if (!filter->priv->root)
2200 /* The root level has not been exposed to the view yet, so we
2201 * need to emit signals for any node that is being inserted.
2203 gtk_tree_model_filter_build_level (filter, NULL, NULL, TRUE);
2205 /* Check if the root level was built. Then child levels
2206 * that matter have also been built (due to update_children,
2207 * which triggers iter_n_children).
2209 if (filter->priv->root)
2211 emit_row_inserted = FALSE;
2216 if (gtk_tree_path_get_depth (real_path) - 1 >= 1)
2218 gboolean found = FALSE;
2219 GtkTreePath *parent = gtk_tree_path_copy (real_path);
2220 gtk_tree_path_up (parent);
2222 found = find_elt_with_offset (filter, parent, &parent_level, &elt);
2224 gtk_tree_path_free (parent);
2227 /* Parent is not in the cache and probably being filtered out */
2230 level = elt->children;
2233 level = FILTER_LEVEL (filter->priv->root);
2237 if (elt && elt->visible_siter)
2239 /* The level in which the new node should be inserted does not
2240 * exist, but the parent, elt, does. If elt is visible, emit
2241 * row-has-child-toggled.
2243 GtkTreePath *tmppath;
2244 GtkTreeIter tmpiter;
2246 tmpiter.stamp = filter->priv->stamp;
2247 tmpiter.user_data = parent_level;
2248 tmpiter.user_data2 = elt;
2250 tmppath = gtk_tree_model_get_path (GTK_TREE_MODEL (filter),
2255 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (filter),
2257 gtk_tree_path_free (tmppath);
2263 /* let's try to insert the value */
2264 offset = gtk_tree_path_get_indices (real_path)[gtk_tree_path_get_depth (real_path) - 1];
2266 /* update the offsets, yes if we didn't insert the node above, there will
2267 * be a gap here. This will be filled with the node (via fetch_child) when
2268 * it becomes visible
2270 dummy.offset = offset;
2271 siter = g_sequence_search (level->seq, &dummy, filter_elt_cmp, NULL);
2272 siter = g_sequence_iter_prev (siter);
2273 g_sequence_foreach_range (siter, g_sequence_get_end_iter (level->seq),
2274 increase_offset_iter, GINT_TO_POINTER (offset));
2276 /* only insert when visible */
2277 if (gtk_tree_model_filter_visible (filter, &real_c_iter))
2281 felt = gtk_tree_model_filter_insert_elt_in_level (filter,
2286 /* insert_elt_in_level defaults to FALSE */
2287 felt->visible_siter = g_sequence_insert_sorted (level->visible_seq,
2289 filter_elt_cmp, NULL);
2290 emit_row_inserted = TRUE;
2295 gtk_tree_model_filter_check_ancestors (filter, real_path);
2297 if (emit_row_inserted)
2298 gtk_tree_model_filter_emit_row_inserted_for_path (filter, c_model,
2302 gtk_tree_path_free (real_path);
2305 gtk_tree_path_free (c_path);
2309 gtk_tree_model_filter_row_has_child_toggled (GtkTreeModel *c_model,
2310 GtkTreePath *c_path,
2311 GtkTreeIter *c_iter,
2314 GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (data);
2319 gboolean requested_state;
2321 g_return_if_fail (c_path != NULL && c_iter != NULL);
2323 /* If we get row-has-child-toggled on the virtual root, and there is
2324 * no root level; try to build it now.
2326 if (filter->priv->virtual_root && !filter->priv->root
2327 && !gtk_tree_path_compare (c_path, filter->priv->virtual_root))
2329 gtk_tree_model_filter_build_level (filter, NULL, NULL, TRUE);
2333 /* For all other levels, there is a chance that the visibility state
2334 * of the parent has changed now.
2337 path = gtk_real_tree_model_filter_convert_child_path_to_path (filter,
2344 gtk_tree_model_filter_get_iter_full (GTK_TREE_MODEL (data), &iter, path);
2346 level = FILTER_LEVEL (iter.user_data);
2347 elt = FILTER_ELT (iter.user_data2);
2349 gtk_tree_path_free (path);
2351 requested_state = gtk_tree_model_filter_visible (filter, c_iter);
2353 if (!elt->visible_siter && !requested_state)
2355 /* The parent node currently is not visible and will not become
2356 * visible, so we will not pass on the row-has-child-toggled event.
2360 else if (elt->visible_siter && !requested_state)
2362 /* The node is no longer visible, so it has to be removed.
2363 * _remove_elt_from_level() takes care of emitting row-has-child-toggled
2366 gtk_tree_model_filter_remove_elt_from_level (filter, level, elt);
2370 else if (!elt->visible_siter && requested_state)
2372 elt->visible_siter = g_sequence_insert_sorted (level->visible_seq,
2373 elt, filter_elt_cmp,
2376 /* Only insert if the parent is visible in the target */
2377 if (gtk_tree_model_filter_elt_is_visible_in_target (level, elt))
2379 path = gtk_tree_model_get_path (GTK_TREE_MODEL (filter), &iter);
2380 gtk_tree_model_row_inserted (GTK_TREE_MODEL (filter), path, &iter);
2381 gtk_tree_path_free (path);
2383 /* We do not update children now, because that will happen
2388 /* For the remaining possibility, elt->visible && requested_state
2389 * no action is required.
2392 /* If this node is referenced and has children, build the level so we
2393 * can monitor it for changes.
2395 if (elt->ref_count > 1 && !elt->children &&
2396 gtk_tree_model_iter_has_child (c_model, c_iter))
2397 gtk_tree_model_filter_build_level (filter, level, elt, FALSE);
2399 /* get a path taking only visible nodes into account */
2400 path = gtk_tree_model_get_path (GTK_TREE_MODEL (data), &iter);
2401 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (data), path, &iter);
2402 gtk_tree_path_free (path);
2406 gtk_tree_model_filter_virtual_root_deleted (GtkTreeModelFilter *filter,
2407 GtkTreePath *c_path)
2411 FilterLevel *level = FILTER_LEVEL (filter->priv->root);
2413 /* The virtual root (or one of its ancestors) has been deleted. This
2414 * means that all content for our model is now gone. We deal with
2415 * this by removing everything in the filter model: we just iterate
2416 * over the root level and emit a row-deleted for each FilterElt.
2417 * (FIXME: Should we emit row-deleted for child nodes as well? This
2418 * has never been fully clear in TreeModel).
2421 /* We unref the path of the virtual root, up to and not including the
2422 * deleted node which can no longer be unreffed.
2424 gtk_tree_model_filter_unref_path (filter, filter->priv->virtual_root,
2425 gtk_tree_path_get_depth (c_path) - 1);
2426 filter->priv->virtual_root_deleted = TRUE;
2431 nodes = g_sequence_get_length (level->visible_seq);
2433 /* We should not propagate the unref here. An unref for any of these
2434 * nodes will fail, since the respective nodes in the child model are
2437 gtk_tree_model_filter_free_level (filter, filter->priv->root, FALSE, TRUE, FALSE);
2439 gtk_tree_model_filter_increment_stamp (filter);
2441 path = gtk_tree_path_new ();
2442 gtk_tree_path_append_index (path, 0);
2444 for (i = 0; i < nodes; i++)
2445 gtk_tree_model_row_deleted (GTK_TREE_MODEL (filter), path);
2447 gtk_tree_path_free (path);
2451 gtk_tree_model_filter_adjust_virtual_root (GtkTreeModelFilter *filter,
2452 GtkTreePath *c_path)
2456 gint *v_indices, *c_indices;
2457 gboolean common_prefix = TRUE;
2459 level = gtk_tree_path_get_depth (c_path) - 1;
2460 v_indices = gtk_tree_path_get_indices (filter->priv->virtual_root);
2461 c_indices = gtk_tree_path_get_indices (c_path);
2463 for (i = 0; i < level; i++)
2464 if (v_indices[i] != c_indices[i])
2466 common_prefix = FALSE;
2470 if (common_prefix && v_indices[level] > c_indices[level])
2471 (v_indices[level])--;
2475 gtk_tree_model_filter_row_deleted_invisible_node (GtkTreeModelFilter *filter,
2476 GtkTreePath *c_path)
2479 GtkTreePath *real_path;
2483 GSequenceIter *siter;
2485 /* The node deleted in the child model is not visible in the
2486 * filter model. We will not emit a signal, just fixup the offsets
2487 * of the other nodes.
2490 if (!filter->priv->root)
2493 level = FILTER_LEVEL (filter->priv->root);
2495 /* subtract vroot if necessary */
2496 if (filter->priv->virtual_root)
2498 real_path = gtk_tree_model_filter_remove_root (c_path,
2499 filter->priv->virtual_root);
2500 /* we don't handle this */
2505 real_path = gtk_tree_path_copy (c_path);
2507 if (gtk_tree_path_get_depth (real_path) - 1 >= 1)
2509 gboolean found = FALSE;
2510 GtkTreePath *parent = gtk_tree_path_copy (real_path);
2511 gtk_tree_path_up (parent);
2513 found = find_elt_with_offset (filter, parent, &level, &elt);
2515 gtk_tree_path_free (parent);
2519 /* parent is filtered out, so no level */
2520 gtk_tree_path_free (real_path);
2524 level = elt->children;
2527 offset = gtk_tree_path_get_indices (real_path)[gtk_tree_path_get_depth (real_path) - 1];
2528 gtk_tree_path_free (real_path);
2533 /* decrease offset of all nodes following the deleted node */
2534 dummy.offset = offset;
2535 siter = g_sequence_search (level->seq, &dummy, filter_elt_cmp, NULL);
2536 g_sequence_foreach_range (siter, g_sequence_get_end_iter (level->seq),
2537 decrease_offset_iter, GINT_TO_POINTER (offset));
2541 gtk_tree_model_filter_row_deleted (GtkTreeModel *c_model,
2542 GtkTreePath *c_path,
2545 GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (data);
2548 FilterElt *elt, *parent_elt = NULL;
2549 FilterLevel *level, *parent_level = NULL;
2550 GSequenceIter *siter;
2551 gboolean emit_child_toggled = FALSE;
2552 gboolean emit_row_deleted = FALSE;
2554 gint orig_level_ext_ref_count;
2556 g_return_if_fail (c_path != NULL);
2558 /* special case the deletion of an ancestor of the virtual root */
2559 if (filter->priv->virtual_root &&
2560 (gtk_tree_path_is_ancestor (c_path, filter->priv->virtual_root) ||
2561 !gtk_tree_path_compare (c_path, filter->priv->virtual_root)))
2563 gtk_tree_model_filter_virtual_root_deleted (filter, c_path);
2567 /* adjust the virtual root for the deleted row */
2568 if (filter->priv->virtual_root &&
2569 gtk_tree_path_get_depth (filter->priv->virtual_root) >=
2570 gtk_tree_path_get_depth (c_path))
2571 gtk_tree_model_filter_adjust_virtual_root (filter, c_path);
2573 path = gtk_real_tree_model_filter_convert_child_path_to_path (filter,
2580 gtk_tree_model_filter_row_deleted_invisible_node (filter, c_path);
2584 /* a node was deleted, which was in our cache */
2585 gtk_tree_model_filter_get_iter_full (GTK_TREE_MODEL (data), &iter, path);
2587 level = FILTER_LEVEL (iter.user_data);
2588 elt = FILTER_ELT (iter.user_data2);
2589 offset = elt->offset;
2590 orig_level_ext_ref_count = level->ext_ref_count;
2592 if (elt->visible_siter)
2594 /* get a path taking only visible nodes into account */
2595 gtk_tree_path_free (path);
2596 path = gtk_tree_model_get_path (GTK_TREE_MODEL (filter), &iter);
2598 if (g_sequence_get_length (level->visible_seq) == 1)
2600 emit_child_toggled = TRUE;
2601 parent_level = level->parent_level;
2602 parent_elt = level->parent_elt;
2605 emit_row_deleted = TRUE;
2608 /* Release the references on this node, without propagation because
2609 * the node does not exist anymore in the child model. The filter
2610 * model's references on the node in case of level->parent or use
2611 * of a virtual root are automatically destroyed by the child model.
2613 while (elt->ext_ref_count > 0)
2614 gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (data), &iter,
2617 if (g_sequence_get_length (level->seq) == 1)
2620 /* If this last node has children, then the recursion in free_level
2621 * will release this reference.
2623 while (elt->ref_count > 1)
2624 gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (data), &iter,
2627 while (elt->ref_count > 0)
2628 gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (data), &iter,
2632 gtk_tree_model_filter_free_level (filter, level, FALSE, TRUE, FALSE);
2639 /* Release last references, if needed */
2640 while (elt->ref_count > 0)
2641 gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (data), &iter,
2644 lookup_elt_with_offset (level->seq, elt->offset, &siter);
2645 is_first = g_sequence_get_begin_iter (level->seq) == siter;
2647 /* remove the row */
2648 g_sequence_remove (elt->visible_siter);
2649 tmp = g_sequence_iter_next (siter);
2650 g_sequence_remove (siter);
2651 g_sequence_foreach_range (tmp, g_sequence_get_end_iter (level->seq),
2652 decrease_offset_iter, GINT_TO_POINTER (offset));
2654 /* Take a reference on the new first node. The first node previously
2655 * keeping this reference has been removed above.
2661 f_iter.stamp = filter->priv->stamp;
2662 f_iter.user_data = level;
2663 f_iter.user_data2 = g_sequence_get (g_sequence_get_begin_iter (level->seq));
2665 gtk_tree_model_filter_real_ref_node (GTK_TREE_MODEL (filter),
2670 if (emit_row_deleted)
2672 /* emit row_deleted */
2673 gtk_tree_model_filter_increment_stamp (filter);
2675 if (!parent_elt || orig_level_ext_ref_count > 0)
2676 gtk_tree_model_row_deleted (GTK_TREE_MODEL (data), path);
2679 if (emit_child_toggled && parent_level)
2684 iter2.stamp = filter->priv->stamp;
2685 iter2.user_data = parent_level;
2686 iter2.user_data2 = parent_elt;
2688 /* We set in_row_deleted to TRUE to avoid a level build triggered
2689 * by row-has-child-toggled (parent model could call iter_has_child
2692 filter->priv->in_row_deleted = TRUE;
2693 path2 = gtk_tree_model_get_path (GTK_TREE_MODEL (filter), &iter2);
2694 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (filter),
2696 gtk_tree_path_free (path2);
2697 filter->priv->in_row_deleted = FALSE;
2700 if (filter->priv->virtual_root)
2702 GtkTreePath *real_path;
2704 real_path = gtk_tree_model_filter_remove_root (c_path,
2705 filter->priv->root);
2708 gtk_tree_model_filter_check_ancestors (filter, real_path);
2709 gtk_tree_path_free (real_path);
2713 gtk_tree_model_filter_check_ancestors (filter, c_path);
2715 gtk_tree_path_free (path);
2719 gtk_tree_model_filter_rows_reordered (GtkTreeModel *c_model,
2720 GtkTreePath *c_path,
2721 GtkTreeIter *c_iter,
2727 GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (data);
2733 GSequenceIter *tmp_end_iter;
2734 GSequenceIter *old_first_siter = NULL;
2739 g_return_if_fail (new_order != NULL);
2741 if (c_path == NULL || gtk_tree_path_get_depth (c_path) == 0)
2743 length = gtk_tree_model_iter_n_children (c_model, NULL);
2745 if (filter->priv->virtual_root)
2749 /* reorder root level of path */
2750 for (i = 0; i < length; i++)
2751 if (new_order[i] == gtk_tree_path_get_indices (filter->priv->virtual_root)[0])
2757 gtk_tree_path_get_indices (filter->priv->virtual_root)[0] = new_pos;
2761 path = gtk_tree_path_new ();
2762 level = FILTER_LEVEL (filter->priv->root);
2766 GtkTreeIter child_iter;
2768 /* virtual root anchor reordering */
2769 if (filter->priv->virtual_root &&
2770 gtk_tree_path_is_ancestor (c_path, filter->priv->virtual_root))
2775 GtkTreeIter real_c_iter;
2777 level = gtk_tree_path_get_depth (c_path);
2780 real_c_iter = *c_iter;
2782 gtk_tree_model_get_iter (c_model, &real_c_iter, c_path);
2784 length = gtk_tree_model_iter_n_children (c_model, &real_c_iter);
2786 for (i = 0; i < length; i++)
2787 if (new_order[i] == gtk_tree_path_get_indices (filter->priv->virtual_root)[level])
2793 gtk_tree_path_get_indices (filter->priv->virtual_root)[level] = new_pos;
2797 path = gtk_real_tree_model_filter_convert_child_path_to_path (filter,
2802 if (!path && filter->priv->virtual_root &&
2803 gtk_tree_path_compare (c_path, filter->priv->virtual_root))
2806 if (!path && !filter->priv->virtual_root)
2811 /* root level mode */
2813 gtk_tree_model_get_iter (c_model, c_iter, c_path);
2814 length = gtk_tree_model_iter_n_children (c_model, c_iter);
2815 path = gtk_tree_path_new ();
2816 level = FILTER_LEVEL (filter->priv->root);
2820 gtk_tree_model_filter_get_iter_full (GTK_TREE_MODEL (data),
2823 elt = FILTER_ELT (iter.user_data2);
2827 gtk_tree_path_free (path);
2831 level = elt->children;
2833 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (filter), &child_iter, &iter);
2834 length = gtk_tree_model_iter_n_children (c_model, &child_iter);
2838 if (!level || g_sequence_get_length (level->seq) < 1)
2840 gtk_tree_path_free (path);
2844 /* NOTE: we do not bail out here if level->seq->len < 2 like
2845 * GtkTreeModelSort does. This because we do some special tricky
2849 tmp_seq = g_sequence_new (filter_elt_free);
2850 tmp_end_iter = g_sequence_get_end_iter (tmp_seq);
2851 tmp_array = g_new (gint, g_sequence_get_length (level->visible_seq));
2854 old_first_siter = g_sequence_get_iter_at_pos (level->seq, 0);
2856 for (i = 0; i < length; i++)
2859 GSequenceIter *siter;
2861 elt = lookup_elt_with_offset (level->seq, new_order[i], &siter);
2865 /* Only for visible items an entry should be present in the order array
2868 if (elt->visible_siter)
2869 tmp_array[elt_count++] = g_sequence_iter_get_position (elt->visible_siter);
2871 /* Steal elt from level->seq and append it to tmp_seq */
2872 g_sequence_move (siter, tmp_end_iter);
2876 g_warn_if_fail (g_sequence_get_length (level->seq) == 0);
2877 g_sequence_free (level->seq);
2878 level->seq = tmp_seq;
2879 g_sequence_sort (level->visible_seq, filter_elt_cmp, NULL);
2881 /* Transfer the reference from the old item at position 0 to the
2882 * new item at position 0, unless the old item at position 0 is also
2883 * at position 0 in the new sequence.
2885 if (g_sequence_iter_get_position (old_first_siter) != 0)
2886 gtk_tree_model_filter_level_transfer_first_ref (filter,
2889 g_sequence_get_iter_at_pos (level->seq, 0));
2891 /* emit rows_reordered */
2892 if (g_sequence_get_length (level->visible_seq) > 0)
2894 if (!gtk_tree_path_get_indices (path))
2895 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (data), path, NULL,
2899 /* get a path taking only visible nodes into account */
2900 gtk_tree_path_free (path);
2901 path = gtk_tree_model_get_path (GTK_TREE_MODEL (data), &iter);
2903 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (data), path, &iter,
2910 gtk_tree_path_free (path);
2913 /* TreeModelIface implementation */
2914 static GtkTreeModelFlags
2915 gtk_tree_model_filter_get_flags (GtkTreeModel *model)
2917 GtkTreeModelFlags flags;
2919 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), 0);
2920 g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL, 0);
2922 flags = gtk_tree_model_get_flags (GTK_TREE_MODEL_FILTER (model)->priv->child_model);
2924 if ((flags & GTK_TREE_MODEL_LIST_ONLY) == GTK_TREE_MODEL_LIST_ONLY)
2925 return GTK_TREE_MODEL_LIST_ONLY;
2931 gtk_tree_model_filter_get_n_columns (GtkTreeModel *model)
2933 GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
2935 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), 0);
2936 g_return_val_if_fail (filter->priv->child_model != NULL, 0);
2938 if (filter->priv->child_model == NULL)
2941 /* so we can't modify the modify func after this ... */
2942 filter->priv->modify_func_set = TRUE;
2944 if (filter->priv->modify_n_columns > 0)
2945 return filter->priv->modify_n_columns;
2947 return gtk_tree_model_get_n_columns (filter->priv->child_model);
2951 gtk_tree_model_filter_get_column_type (GtkTreeModel *model,
2954 GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
2956 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), G_TYPE_INVALID);
2957 g_return_val_if_fail (filter->priv->child_model != NULL, G_TYPE_INVALID);
2959 /* so we can't modify the modify func after this ... */
2960 filter->priv->modify_func_set = TRUE;
2962 if (filter->priv->modify_types)
2964 g_return_val_if_fail (index < filter->priv->modify_n_columns, G_TYPE_INVALID);
2966 return filter->priv->modify_types[index];
2969 return gtk_tree_model_get_column_type (filter->priv->child_model, index);
2972 /* A special case of _get_iter; this function can also get iters which
2973 * are not visible. These iters should ONLY be passed internally, never
2974 * pass those along with a signal emission.
2977 gtk_tree_model_filter_get_iter_full (GtkTreeModel *model,
2981 GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
2986 GSequenceIter *siter;
2988 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
2989 g_return_val_if_fail (filter->priv->child_model != NULL, FALSE);
2991 indices = gtk_tree_path_get_indices (path);
2993 if (filter->priv->root == NULL)
2994 gtk_tree_model_filter_build_level (filter, NULL, NULL, FALSE);
2995 level = FILTER_LEVEL (filter->priv->root);
2997 depth = gtk_tree_path_get_depth (path);
3004 for (i = 0; i < depth - 1; i++)
3006 if (!level || indices[i] >= g_sequence_get_length (level->seq))
3012 siter = g_sequence_get_iter_at_pos (level->seq, indices[i]);
3013 if (g_sequence_iter_is_end (siter))
3019 elt = GET_ELT (siter);
3022 gtk_tree_model_filter_build_level (filter, level, elt, FALSE);
3023 level = elt->children;
3026 if (!level || indices[i] >= g_sequence_get_length (level->seq))
3032 iter->stamp = filter->priv->stamp;
3033 iter->user_data = level;
3035 siter = g_sequence_get_iter_at_pos (level->seq, indices[depth - 1]);
3036 if (g_sequence_iter_is_end (siter))
3041 iter->user_data2 = GET_ELT (siter);
3047 gtk_tree_model_filter_get_iter (GtkTreeModel *model,
3051 GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
3055 GSequenceIter *siter;
3058 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
3059 g_return_val_if_fail (filter->priv->child_model != NULL, FALSE);
3061 indices = gtk_tree_path_get_indices (path);
3063 if (filter->priv->root == NULL)
3064 gtk_tree_model_filter_build_level (filter, NULL, NULL, FALSE);
3065 level = FILTER_LEVEL (filter->priv->root);
3067 depth = gtk_tree_path_get_depth (path);
3074 for (i = 0; i < depth - 1; i++)
3076 if (!level || indices[i] >= g_sequence_get_length (level->visible_seq))
3082 siter = g_sequence_get_iter_at_pos (level->visible_seq, indices[i]);
3083 if (g_sequence_iter_is_end (siter))
3089 elt = GET_ELT (siter);
3091 gtk_tree_model_filter_build_level (filter, level, elt, FALSE);
3092 level = elt->children;
3095 if (!level || indices[i] >= g_sequence_get_length (level->visible_seq))
3101 iter->stamp = filter->priv->stamp;
3102 iter->user_data = level;
3104 siter = g_sequence_get_iter_at_pos (level->visible_seq, indices[depth - 1]);
3105 if (g_sequence_iter_is_end (siter))
3110 iter->user_data2 = GET_ELT (siter);
3115 static GtkTreePath *
3116 gtk_tree_model_filter_get_path (GtkTreeModel *model,
3119 GtkTreePath *retval;
3123 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), NULL);
3124 g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL, NULL);
3125 g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->stamp == iter->stamp, NULL);
3127 level = iter->user_data;
3128 elt = iter->user_data2;
3130 if (!elt->visible_siter)
3133 retval = gtk_tree_path_new ();
3139 index = g_sequence_iter_get_position (elt->visible_siter);
3140 gtk_tree_path_prepend_index (retval, index);
3142 elt = level->parent_elt;
3143 level = level->parent_level;
3150 gtk_tree_model_filter_real_modify (GtkTreeModelFilter *self,
3151 GtkTreeModel *child_model,
3156 if (self->priv->modify_func)
3158 g_return_if_fail (column < self->priv->modify_n_columns);
3160 g_value_init (value, self->priv->modify_types[column]);
3161 self->priv->modify_func (GTK_TREE_MODEL (self),
3165 self->priv->modify_data);
3169 GtkTreeIter child_iter;
3171 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (self),
3173 gtk_tree_model_get_value (child_model, &child_iter, column, value);
3178 gtk_tree_model_filter_get_value (GtkTreeModel *model,
3183 GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (model);
3185 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (model));
3186 g_return_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL);
3187 g_return_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->stamp == iter->stamp);
3189 GTK_TREE_MODEL_FILTER_GET_CLASS (model)->modify (filter,
3190 filter->priv->child_model, iter, value, column);
3194 gtk_tree_model_filter_iter_next (GtkTreeModel *model,
3199 GSequenceIter *siter;
3201 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
3202 g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL, FALSE);
3203 g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->stamp == iter->stamp, FALSE);
3205 level = iter->user_data;
3206 elt = iter->user_data2;
3208 siter = g_sequence_iter_next (elt->visible_siter);
3209 if (g_sequence_iter_is_end (siter))
3215 iter->user_data2 = GET_ELT (siter);
3221 gtk_tree_model_filter_iter_previous (GtkTreeModel *model,
3225 GSequenceIter *siter;
3227 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
3228 g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL, FALSE);
3229 g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->stamp == iter->stamp, FALSE);
3231 elt = iter->user_data2;
3233 siter = g_sequence_iter_prev (elt->visible_siter);
3234 if (g_sequence_iter_is_begin (siter))
3240 iter->user_data2 = GET_ELT (siter);
3246 gtk_tree_model_filter_iter_children (GtkTreeModel *model,
3248 GtkTreeIter *parent)
3250 GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
3252 GSequenceIter *siter;
3255 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
3256 g_return_val_if_fail (filter->priv->child_model != NULL, FALSE);
3258 g_return_val_if_fail (filter->priv->stamp == parent->stamp, FALSE);
3262 if (!filter->priv->root)
3263 gtk_tree_model_filter_build_level (filter, NULL, NULL, FALSE);
3264 if (!filter->priv->root)
3267 level = filter->priv->root;
3268 siter = g_sequence_get_begin_iter (level->visible_seq);
3269 if (g_sequence_iter_is_end (siter))
3275 iter->stamp = filter->priv->stamp;
3276 iter->user_data = level;
3277 iter->user_data2 = GET_ELT (siter);
3283 if (FILTER_ELT (parent->user_data2)->children == NULL)
3284 gtk_tree_model_filter_build_level (filter,
3285 FILTER_LEVEL (parent->user_data),
3286 FILTER_ELT (parent->user_data2),
3288 if (FILTER_ELT (parent->user_data2)->children == NULL)
3291 level = FILTER_ELT (parent->user_data2)->children;
3292 siter = g_sequence_get_begin_iter (level->visible_seq);
3293 if (g_sequence_iter_is_end (siter))
3299 iter->stamp = filter->priv->stamp;
3300 iter->user_data = level;
3301 iter->user_data2 = GET_ELT (siter);
3311 gtk_tree_model_filter_iter_has_child (GtkTreeModel *model,
3314 GtkTreeIter child_iter;
3315 GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
3318 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
3319 g_return_val_if_fail (filter->priv->child_model != NULL, FALSE);
3320 g_return_val_if_fail (filter->priv->stamp == iter->stamp, FALSE);
3322 filter = GTK_TREE_MODEL_FILTER (model);
3324 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_iter, iter);
3325 elt = FILTER_ELT (iter->user_data2);
3327 if (!elt->visible_siter)
3330 /* we need to build the level to check if not all children are filtered
3334 && gtk_tree_model_iter_has_child (filter->priv->child_model, &child_iter))
3335 gtk_tree_model_filter_build_level (filter, FILTER_LEVEL (iter->user_data),
3338 if (elt->children && g_sequence_get_length (elt->children->visible_seq) > 0)
3345 gtk_tree_model_filter_iter_n_children (GtkTreeModel *model,
3348 GtkTreeIter child_iter;
3349 GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
3352 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), 0);
3353 g_return_val_if_fail (filter->priv->child_model != NULL, 0);
3355 g_return_val_if_fail (filter->priv->stamp == iter->stamp, 0);
3359 if (!filter->priv->root)
3360 gtk_tree_model_filter_build_level (filter, NULL, NULL, FALSE);
3362 if (filter->priv->root)
3363 return g_sequence_get_length (FILTER_LEVEL (filter->priv->root)->visible_seq);
3368 elt = FILTER_ELT (iter->user_data2);
3370 if (!elt->visible_siter)
3373 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_iter, iter);
3375 if (!elt->children &&
3376 gtk_tree_model_iter_has_child (filter->priv->child_model, &child_iter))
3377 gtk_tree_model_filter_build_level (filter,
3378 FILTER_LEVEL (iter->user_data),
3382 return g_sequence_get_length (elt->children->visible_seq);
3388 gtk_tree_model_filter_iter_nth_child (GtkTreeModel *model,
3390 GtkTreeIter *parent,
3394 GtkTreeIter children;
3395 GSequenceIter *siter;
3397 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
3399 g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->stamp == parent->stamp, FALSE);
3401 /* use this instead of has_child to force us to build the level, if needed */
3402 if (gtk_tree_model_filter_iter_children (model, &children, parent) == FALSE)
3408 level = children.user_data;
3409 siter = g_sequence_get_iter_at_pos (level->visible_seq, n);
3410 if (g_sequence_iter_is_end (siter))
3413 iter->stamp = GTK_TREE_MODEL_FILTER (model)->priv->stamp;
3414 iter->user_data = level;
3415 iter->user_data2 = GET_ELT (siter);
3421 gtk_tree_model_filter_iter_parent (GtkTreeModel *model,
3428 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
3429 g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL, FALSE);
3430 g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->stamp == child->stamp, FALSE);
3432 level = child->user_data;
3434 if (level->parent_level)
3436 iter->stamp = GTK_TREE_MODEL_FILTER (model)->priv->stamp;
3437 iter->user_data = level->parent_level;
3438 iter->user_data2 = level->parent_elt;
3447 gtk_tree_model_filter_ref_node (GtkTreeModel *model,
3450 gtk_tree_model_filter_real_ref_node (model, iter, TRUE);
3454 gtk_tree_model_filter_real_ref_node (GtkTreeModel *model,
3458 GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
3459 GtkTreeIter child_iter;
3463 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (model));
3464 g_return_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL);
3465 g_return_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->stamp == iter->stamp);
3467 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_iter, iter);
3469 gtk_tree_model_ref_node (filter->priv->child_model, &child_iter);
3471 level = iter->user_data;
3472 elt = iter->user_data2;
3479 elt->ext_ref_count++;
3480 level->ext_ref_count++;
3482 if (level->ext_ref_count == 1)
3484 FilterLevel *parent_level = level->parent_level;
3485 FilterElt *parent_elt = level->parent_elt;
3487 /* we were at zero -- time to decrease the zero_ref_count val */
3488 while (parent_level)
3490 parent_elt->zero_ref_count--;
3492 parent_elt = parent_level->parent_elt;
3493 parent_level = parent_level->parent_level;
3496 if (filter->priv->root != level)
3497 filter->priv->zero_ref_count--;
3499 #ifdef MODEL_FILTER_DEBUG
3500 g_assert (filter->priv->zero_ref_count >= 0);
3501 if (filter->priv->zero_ref_count > 0)
3502 g_assert (filter->priv->root != NULL);
3507 #ifdef MODEL_FILTER_DEBUG
3508 g_assert (elt->ref_count >= elt->ext_ref_count);
3509 g_assert (elt->ref_count >= 0);
3510 g_assert (elt->ext_ref_count >= 0);
3515 gtk_tree_model_filter_unref_node (GtkTreeModel *model,
3518 gtk_tree_model_filter_real_unref_node (model, iter, TRUE, TRUE);
3522 gtk_tree_model_filter_real_unref_node (GtkTreeModel *model,
3525 gboolean propagate_unref)
3527 GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
3531 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (model));
3532 g_return_if_fail (filter->priv->child_model != NULL);
3533 g_return_if_fail (filter->priv->stamp == iter->stamp);
3535 if (propagate_unref)
3537 GtkTreeIter child_iter;
3538 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_iter, iter);
3539 gtk_tree_model_unref_node (filter->priv->child_model, &child_iter);
3542 level = iter->user_data;
3543 elt = iter->user_data2;
3545 g_return_if_fail (elt->ref_count > 0);
3546 #ifdef MODEL_FILTER_DEBUG
3547 g_assert (elt->ref_count >= elt->ext_ref_count);
3548 g_assert (elt->ref_count >= 0);
3549 g_assert (elt->ext_ref_count >= 0);
3557 elt->ext_ref_count--;
3558 level->ext_ref_count--;
3560 if (level->ext_ref_count == 0)
3562 FilterLevel *parent_level = level->parent_level;
3563 FilterElt *parent_elt = level->parent_elt;
3565 /* we are at zero -- time to increase the zero_ref_count val */
3566 while (parent_level)
3568 parent_elt->zero_ref_count++;
3570 parent_elt = parent_level->parent_elt;
3571 parent_level = parent_level->parent_level;
3574 if (filter->priv->root != level)
3575 filter->priv->zero_ref_count++;
3577 #ifdef MODEL_FILTER_DEBUG
3578 g_assert (filter->priv->zero_ref_count >= 0);
3579 if (filter->priv->zero_ref_count > 0)
3580 g_assert (filter->priv->root != NULL);
3585 #ifdef MODEL_FILTER_DEBUG
3586 g_assert (elt->ref_count >= elt->ext_ref_count);
3587 g_assert (elt->ref_count >= 0);
3588 g_assert (elt->ext_ref_count >= 0);
3592 /* TreeDragSource interface implementation */
3594 gtk_tree_model_filter_row_draggable (GtkTreeDragSource *drag_source,
3597 GtkTreeModelFilter *tree_model_filter = (GtkTreeModelFilter *)drag_source;
3598 GtkTreePath *child_path;
3601 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (drag_source), FALSE);
3602 g_return_val_if_fail (path != NULL, FALSE);
3604 child_path = gtk_tree_model_filter_convert_path_to_child_path (tree_model_filter, path);
3605 draggable = gtk_tree_drag_source_row_draggable (GTK_TREE_DRAG_SOURCE (tree_model_filter->priv->child_model), child_path);
3606 gtk_tree_path_free (child_path);
3612 gtk_tree_model_filter_drag_data_get (GtkTreeDragSource *drag_source,
3614 GtkSelectionData *selection_data)
3616 GtkTreeModelFilter *tree_model_filter = (GtkTreeModelFilter *)drag_source;
3617 GtkTreePath *child_path;
3620 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (drag_source), FALSE);
3621 g_return_val_if_fail (path != NULL, FALSE);
3623 child_path = gtk_tree_model_filter_convert_path_to_child_path (tree_model_filter, path);
3624 gotten = gtk_tree_drag_source_drag_data_get (GTK_TREE_DRAG_SOURCE (tree_model_filter->priv->child_model), child_path, selection_data);
3625 gtk_tree_path_free (child_path);
3631 gtk_tree_model_filter_drag_data_delete (GtkTreeDragSource *drag_source,
3634 GtkTreeModelFilter *tree_model_filter = (GtkTreeModelFilter *)drag_source;
3635 GtkTreePath *child_path;
3638 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (drag_source), FALSE);
3639 g_return_val_if_fail (path != NULL, FALSE);
3641 child_path = gtk_tree_model_filter_convert_path_to_child_path (tree_model_filter, path);
3642 deleted = gtk_tree_drag_source_drag_data_delete (GTK_TREE_DRAG_SOURCE (tree_model_filter->priv->child_model), child_path);
3643 gtk_tree_path_free (child_path);
3648 /* bits and pieces */
3650 gtk_tree_model_filter_set_model (GtkTreeModelFilter *filter,
3651 GtkTreeModel *child_model)
3653 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
3655 if (filter->priv->child_model)
3657 g_signal_handler_disconnect (filter->priv->child_model,
3658 filter->priv->changed_id);
3659 g_signal_handler_disconnect (filter->priv->child_model,
3660 filter->priv->inserted_id);
3661 g_signal_handler_disconnect (filter->priv->child_model,
3662 filter->priv->has_child_toggled_id);
3663 g_signal_handler_disconnect (filter->priv->child_model,
3664 filter->priv->deleted_id);
3665 g_signal_handler_disconnect (filter->priv->child_model,
3666 filter->priv->reordered_id);
3668 /* reset our state */
3669 if (filter->priv->root)
3670 gtk_tree_model_filter_free_level (filter, filter->priv->root,
3673 filter->priv->root = NULL;
3674 g_object_unref (filter->priv->child_model);
3675 filter->priv->visible_column = -1;
3677 /* FIXME: do we need to destroy more here? */
3680 filter->priv->child_model = child_model;
3684 g_object_ref (filter->priv->child_model);
3685 filter->priv->changed_id =
3686 g_signal_connect (child_model, "row-changed",
3687 G_CALLBACK (gtk_tree_model_filter_row_changed),
3689 filter->priv->inserted_id =
3690 g_signal_connect (child_model, "row-inserted",
3691 G_CALLBACK (gtk_tree_model_filter_row_inserted),
3693 filter->priv->has_child_toggled_id =
3694 g_signal_connect (child_model, "row-has-child-toggled",
3695 G_CALLBACK (gtk_tree_model_filter_row_has_child_toggled),
3697 filter->priv->deleted_id =
3698 g_signal_connect (child_model, "row-deleted",
3699 G_CALLBACK (gtk_tree_model_filter_row_deleted),
3701 filter->priv->reordered_id =
3702 g_signal_connect (child_model, "rows-reordered",
3703 G_CALLBACK (gtk_tree_model_filter_rows_reordered),
3706 filter->priv->child_flags = gtk_tree_model_get_flags (child_model);
3707 filter->priv->stamp = g_random_int ();
3712 gtk_tree_model_filter_ref_path (GtkTreeModelFilter *filter,
3718 len = gtk_tree_path_get_depth (path);
3719 p = gtk_tree_path_copy (path);
3724 gtk_tree_model_get_iter (GTK_TREE_MODEL (filter->priv->child_model), &iter, p);
3725 gtk_tree_model_ref_node (GTK_TREE_MODEL (filter->priv->child_model), &iter);
3726 gtk_tree_path_up (p);
3729 gtk_tree_path_free (p);
3733 gtk_tree_model_filter_unref_path (GtkTreeModelFilter *filter,
3743 len = gtk_tree_path_get_depth (path);
3745 p = gtk_tree_path_copy (path);
3750 gtk_tree_model_get_iter (GTK_TREE_MODEL (filter->priv->child_model), &iter, p);
3751 gtk_tree_model_unref_node (GTK_TREE_MODEL (filter->priv->child_model), &iter);
3752 gtk_tree_path_up (p);
3755 gtk_tree_path_free (p);
3759 gtk_tree_model_filter_set_root (GtkTreeModelFilter *filter,
3762 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
3765 filter->priv->virtual_root = NULL;
3767 filter->priv->virtual_root = gtk_tree_path_copy (root);
3773 * gtk_tree_model_filter_new:
3774 * @child_model: A #GtkTreeModel.
3775 * @root: (allow-none): A #GtkTreePath or %NULL.
3777 * Creates a new #GtkTreeModel, with @child_model as the child_model
3778 * and @root as the virtual root.
3780 * Return value: (transfer full): A new #GtkTreeModel.
3785 gtk_tree_model_filter_new (GtkTreeModel *child_model,
3788 GtkTreeModel *retval;
3789 GtkTreeModelFilter *filter;
3791 g_return_val_if_fail (GTK_IS_TREE_MODEL (child_model), NULL);
3793 retval = g_object_new (GTK_TYPE_TREE_MODEL_FILTER,
3794 "child-model", child_model,
3795 "virtual-root", root,
3798 filter = GTK_TREE_MODEL_FILTER (retval);
3799 if (filter->priv->virtual_root)
3801 gtk_tree_model_filter_ref_path (filter, filter->priv->virtual_root);
3802 filter->priv->virtual_root_deleted = FALSE;
3809 * gtk_tree_model_filter_get_model:
3810 * @filter: A #GtkTreeModelFilter.
3812 * Returns a pointer to the child model of @filter.
3814 * Return value: (transfer none): A pointer to a #GtkTreeModel.
3819 gtk_tree_model_filter_get_model (GtkTreeModelFilter *filter)
3821 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (filter), NULL);
3823 return filter->priv->child_model;
3827 * gtk_tree_model_filter_set_visible_func:
3828 * @filter: A #GtkTreeModelFilter.
3829 * @func: A #GtkTreeModelFilterVisibleFunc, the visible function.
3830 * @data: (allow-none): User data to pass to the visible function, or %NULL.
3831 * @destroy: (allow-none): Destroy notifier of @data, or %NULL.
3833 * Sets the visible function used when filtering the @filter to be @func. The
3834 * function should return %TRUE if the given row should be visible and
3837 * If the condition calculated by the function changes over time (e.g. because
3838 * it depends on some global parameters), you must call
3839 * gtk_tree_model_filter_refilter() to keep the visibility information of
3840 * the model uptodate.
3842 * Note that @func is called whenever a row is inserted, when it may still be
3843 * empty. The visible function should therefore take special care of empty
3844 * rows, like in the example below.
3846 * <informalexample><programlisting>
3848 * visible_func (GtkTreeModel *model,
3849 * GtkTreeIter *iter,
3852 * /* Visible if row is non-empty and first column is "HI" */
3854 * gboolean visible = FALSE;
3856 * gtk_tree_model_get (model, iter, 0, &str, -1);
3857 * if (str && strcmp (str, "HI") == 0)
3863 * </programlisting></informalexample>
3868 gtk_tree_model_filter_set_visible_func (GtkTreeModelFilter *filter,
3869 GtkTreeModelFilterVisibleFunc func,
3871 GDestroyNotify destroy)
3873 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
3874 g_return_if_fail (func != NULL);
3875 g_return_if_fail (filter->priv->visible_method_set == FALSE);
3877 filter->priv->visible_func = func;
3878 filter->priv->visible_data = data;
3879 filter->priv->visible_destroy = destroy;
3881 filter->priv->visible_method_set = TRUE;
3885 * gtk_tree_model_filter_set_modify_func:
3886 * @filter: A #GtkTreeModelFilter.
3887 * @n_columns: The number of columns in the filter model.
3888 * @types: (array length=n_columns): The #GType<!-- -->s of the columns.
3889 * @func: A #GtkTreeModelFilterModifyFunc
3890 * @data: (allow-none): User data to pass to the modify function, or %NULL.
3891 * @destroy: (allow-none): Destroy notifier of @data, or %NULL.
3893 * With the @n_columns and @types parameters, you give an array of column
3894 * types for this model (which will be exposed to the parent model/view).
3895 * The @func, @data and @destroy parameters are for specifying the modify
3896 * function. The modify function will get called for <emphasis>each</emphasis>
3897 * data access, the goal of the modify function is to return the data which
3898 * should be displayed at the location specified using the parameters of the
3904 gtk_tree_model_filter_set_modify_func (GtkTreeModelFilter *filter,
3907 GtkTreeModelFilterModifyFunc func,
3909 GDestroyNotify destroy)
3911 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
3912 g_return_if_fail (func != NULL);
3913 g_return_if_fail (filter->priv->modify_func_set == FALSE);
3915 if (filter->priv->modify_destroy)
3917 GDestroyNotify d = filter->priv->modify_destroy;
3919 filter->priv->modify_destroy = NULL;
3920 d (filter->priv->modify_data);
3923 filter->priv->modify_n_columns = n_columns;
3924 filter->priv->modify_types = g_new0 (GType, n_columns);
3925 memcpy (filter->priv->modify_types, types, sizeof (GType) * n_columns);
3926 filter->priv->modify_func = func;
3927 filter->priv->modify_data = data;
3928 filter->priv->modify_destroy = destroy;
3930 filter->priv->modify_func_set = TRUE;
3934 * gtk_tree_model_filter_set_visible_column:
3935 * @filter: A #GtkTreeModelFilter.
3936 * @column: A #gint which is the column containing the visible information.
3938 * Sets @column of the child_model to be the column where @filter should
3939 * look for visibility information. @columns should be a column of type
3940 * %G_TYPE_BOOLEAN, where %TRUE means that a row is visible, and %FALSE
3946 gtk_tree_model_filter_set_visible_column (GtkTreeModelFilter *filter,
3949 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
3950 g_return_if_fail (column >= 0);
3951 g_return_if_fail (filter->priv->visible_method_set == FALSE);
3953 filter->priv->visible_column = column;
3955 filter->priv->visible_method_set = TRUE;
3961 * gtk_tree_model_filter_convert_child_iter_to_iter:
3962 * @filter: A #GtkTreeModelFilter.
3963 * @filter_iter: (out): An uninitialized #GtkTreeIter.
3964 * @child_iter: A valid #GtkTreeIter pointing to a row on the child model.
3966 * Sets @filter_iter to point to the row in @filter that corresponds to the
3967 * row pointed at by @child_iter. If @filter_iter was not set, %FALSE is
3970 * Return value: %TRUE, if @filter_iter was set, i.e. if @child_iter is a
3971 * valid iterator pointing to a visible row in child model.
3976 gtk_tree_model_filter_convert_child_iter_to_iter (GtkTreeModelFilter *filter,
3977 GtkTreeIter *filter_iter,
3978 GtkTreeIter *child_iter)
3981 GtkTreePath *child_path, *path;
3983 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (filter), FALSE);
3984 g_return_val_if_fail (filter->priv->child_model != NULL, FALSE);
3985 g_return_val_if_fail (filter_iter != NULL, FALSE);
3986 g_return_val_if_fail (child_iter != NULL, FALSE);
3987 g_return_val_if_fail (filter_iter != child_iter, FALSE);
3989 filter_iter->stamp = 0;
3991 child_path = gtk_tree_model_get_path (filter->priv->child_model, child_iter);
3992 g_return_val_if_fail (child_path != NULL, FALSE);
3994 path = gtk_tree_model_filter_convert_child_path_to_path (filter,
3996 gtk_tree_path_free (child_path);
4001 ret = gtk_tree_model_get_iter (GTK_TREE_MODEL (filter), filter_iter, path);
4002 gtk_tree_path_free (path);
4008 * gtk_tree_model_filter_convert_iter_to_child_iter:
4009 * @filter: A #GtkTreeModelFilter.
4010 * @child_iter: (out): An uninitialized #GtkTreeIter.
4011 * @filter_iter: A valid #GtkTreeIter pointing to a row on @filter.
4013 * Sets @child_iter to point to the row pointed to by @filter_iter.
4018 gtk_tree_model_filter_convert_iter_to_child_iter (GtkTreeModelFilter *filter,
4019 GtkTreeIter *child_iter,
4020 GtkTreeIter *filter_iter)
4022 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
4023 g_return_if_fail (filter->priv->child_model != NULL);
4024 g_return_if_fail (child_iter != NULL);
4025 g_return_if_fail (filter_iter != NULL);
4026 g_return_if_fail (filter_iter->stamp == filter->priv->stamp);
4027 g_return_if_fail (filter_iter != child_iter);
4029 if (GTK_TREE_MODEL_FILTER_CACHE_CHILD_ITERS (filter))
4031 *child_iter = FILTER_ELT (filter_iter->user_data2)->iter;
4036 gboolean valid = FALSE;
4038 path = gtk_tree_model_filter_elt_get_path (filter_iter->user_data,
4039 filter_iter->user_data2,
4040 filter->priv->virtual_root);
4041 valid = gtk_tree_model_get_iter (filter->priv->child_model, child_iter,
4043 gtk_tree_path_free (path);
4045 g_return_if_fail (valid == TRUE);
4049 /* The path returned can only be used internally in the filter model. */
4050 static GtkTreePath *
4051 gtk_real_tree_model_filter_convert_child_path_to_path (GtkTreeModelFilter *filter,
4052 GtkTreePath *child_path,
4053 gboolean build_levels,
4054 gboolean fetch_children)
4056 gint *child_indices;
4057 GtkTreePath *retval;
4058 GtkTreePath *real_path;
4063 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (filter), NULL);
4064 g_return_val_if_fail (filter->priv->child_model != NULL, NULL);
4065 g_return_val_if_fail (child_path != NULL, NULL);
4067 if (!filter->priv->virtual_root)
4068 real_path = gtk_tree_path_copy (child_path);
4070 real_path = gtk_tree_model_filter_remove_root (child_path,
4071 filter->priv->virtual_root);
4076 retval = gtk_tree_path_new ();
4077 child_indices = gtk_tree_path_get_indices (real_path);
4079 if (filter->priv->root == NULL && build_levels)
4080 gtk_tree_model_filter_build_level (filter, NULL, NULL, FALSE);
4081 level = FILTER_LEVEL (filter->priv->root);
4083 for (i = 0; i < gtk_tree_path_get_depth (real_path); i++)
4085 GSequenceIter *siter;
4086 gboolean found_child = FALSE;
4090 gtk_tree_path_free (real_path);
4091 gtk_tree_path_free (retval);
4095 tmp = lookup_elt_with_offset (level->seq, child_indices[i], &siter);
4098 gtk_tree_path_append_index (retval, g_sequence_iter_get_position (siter));
4099 if (!tmp->children && build_levels)
4100 gtk_tree_model_filter_build_level (filter, level, tmp, FALSE);
4101 level = tmp->children;
4105 if (!found_child && fetch_children)
4109 tmp = gtk_tree_model_filter_fetch_child (filter, level,
4113 /* didn't find the child, let's try to bring it back */
4114 if (!tmp || tmp->offset != child_indices[i])
4117 gtk_tree_path_free (real_path);
4118 gtk_tree_path_free (retval);
4122 gtk_tree_path_append_index (retval, j);
4123 if (!tmp->children && build_levels)
4124 gtk_tree_model_filter_build_level (filter, level, tmp, FALSE);
4125 level = tmp->children;
4128 else if (!found_child && !fetch_children)
4131 gtk_tree_path_free (real_path);
4132 gtk_tree_path_free (retval);
4137 gtk_tree_path_free (real_path);
4142 * gtk_tree_model_filter_convert_child_path_to_path:
4143 * @filter: A #GtkTreeModelFilter.
4144 * @child_path: A #GtkTreePath to convert.
4146 * Converts @child_path to a path relative to @filter. That is, @child_path
4147 * points to a path in the child model. The rerturned path will point to the
4148 * same row in the filtered model. If @child_path isn't a valid path on the
4149 * child model or points to a row which is not visible in @filter, then %NULL
4152 * Return value: A newly allocated #GtkTreePath, or %NULL.
4157 gtk_tree_model_filter_convert_child_path_to_path (GtkTreeModelFilter *filter,
4158 GtkTreePath *child_path)
4163 /* this function does the sanity checks */
4164 path = gtk_real_tree_model_filter_convert_child_path_to_path (filter,
4172 /* get a new path which only takes visible nodes into account.
4173 * -- if this gives any performance issues, we can write a special
4174 * version of convert_child_path_to_path immediately returning
4175 * a visible-nodes-only path.
4177 gtk_tree_model_filter_get_iter_full (GTK_TREE_MODEL (filter), &iter, path);
4179 gtk_tree_path_free (path);
4180 path = gtk_tree_model_get_path (GTK_TREE_MODEL (filter), &iter);
4186 * gtk_tree_model_filter_convert_path_to_child_path:
4187 * @filter: A #GtkTreeModelFilter.
4188 * @filter_path: A #GtkTreePath to convert.
4190 * Converts @filter_path to a path on the child model of @filter. That is,
4191 * @filter_path points to a location in @filter. The returned path will
4192 * point to the same location in the model not being filtered. If @filter_path
4193 * does not point to a location in the child model, %NULL is returned.
4195 * Return value: A newly allocated #GtkTreePath, or %NULL.
4200 gtk_tree_model_filter_convert_path_to_child_path (GtkTreeModelFilter *filter,
4201 GtkTreePath *filter_path)
4203 gint *filter_indices;
4204 GtkTreePath *retval;
4208 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (filter), NULL);
4209 g_return_val_if_fail (filter->priv->child_model != NULL, NULL);
4210 g_return_val_if_fail (filter_path != NULL, NULL);
4213 retval = gtk_tree_path_new ();
4214 filter_indices = gtk_tree_path_get_indices (filter_path);
4215 if (!filter->priv->root)
4216 gtk_tree_model_filter_build_level (filter, NULL, NULL, FALSE);
4217 level = FILTER_LEVEL (filter->priv->root);
4219 for (i = 0; i < gtk_tree_path_get_depth (filter_path); i++)
4222 GSequenceIter *siter;
4226 gtk_tree_path_free (retval);
4230 siter = g_sequence_get_iter_at_pos (level->visible_seq, filter_indices[i]);
4231 if (g_sequence_iter_is_end (siter))
4233 gtk_tree_path_free (retval);
4237 elt = GET_ELT (siter);
4238 if (elt->children == NULL)
4239 gtk_tree_model_filter_build_level (filter, level, elt, FALSE);
4241 gtk_tree_path_append_index (retval, elt->offset);
4242 level = elt->children;
4247 if (filter->priv->virtual_root)
4249 GtkTreePath *real_retval;
4251 real_retval = gtk_tree_model_filter_add_root (retval,
4252 filter->priv->virtual_root);
4253 gtk_tree_path_free (retval);
4262 gtk_tree_model_filter_refilter_helper (GtkTreeModel *model,
4267 /* evil, don't try this at home, but certainly speeds things up */
4268 gtk_tree_model_filter_row_changed (model, path, iter, data);
4274 * gtk_tree_model_filter_refilter:
4275 * @filter: A #GtkTreeModelFilter.
4277 * Emits ::row_changed for each row in the child model, which causes
4278 * the filter to re-evaluate whether a row is visible or not.
4283 gtk_tree_model_filter_refilter (GtkTreeModelFilter *filter)
4285 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
4288 gtk_tree_model_foreach (filter->priv->child_model,
4289 gtk_tree_model_filter_refilter_helper,
4294 * gtk_tree_model_filter_clear_cache:
4295 * @filter: A #GtkTreeModelFilter.
4297 * This function should almost never be called. It clears the @filter
4298 * of any cached iterators that haven't been reffed with
4299 * gtk_tree_model_ref_node(). This might be useful if the child model
4300 * being filtered is static (and doesn't change often) and there has been
4301 * a lot of unreffed access to nodes. As a side effect of this function,
4302 * all unreffed iters will be invalid.
4307 gtk_tree_model_filter_clear_cache (GtkTreeModelFilter *filter)
4309 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
4311 if (filter->priv->zero_ref_count > 0)
4312 gtk_tree_model_filter_clear_cache_helper (filter,
4313 FILTER_LEVEL (filter->priv->root));