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 has an external ref count of zero. Otherwise, monitoring
229 * this level is necessary to possibly update the visibility state
230 * of the parent. This is an important difference from GtkTreeModelSort!
232 * Signals are only required for levels with an external ref count > 0.
233 * This due to reference counting rule 3, see the GtkTreeModel
234 * documentation. In the GtkTreeModelFilter we try hard to stick to this
235 * rule and not emit redundant signals (though redundant emissions of
236 * row-has-child-toggled could appear frequently; it does happen that
237 * we simply forward the signal emitted by e.g. GtkTreeStore but also
238 * emit our own copy).
242 typedef struct _FilterElt FilterElt;
243 typedef struct _FilterLevel FilterLevel;
248 FilterLevel *children;
253 GSequenceIter *visible_siter; /* iter into visible_seq */
259 GSequence *visible_seq;
263 FilterElt *parent_elt;
264 FilterLevel *parent_level;
268 struct _GtkTreeModelFilterPrivate
270 GtkTreeModel *child_model;
272 GtkTreePath *virtual_root;
279 GtkTreeModelFilterVisibleFunc visible_func;
280 gpointer visible_data;
281 GDestroyNotify visible_destroy;
284 GtkTreeModelFilterModifyFunc modify_func;
285 gpointer modify_data;
286 GDestroyNotify modify_destroy;
287 gint modify_n_columns;
289 guint visible_method_set : 1;
290 guint modify_func_set : 1;
292 guint in_row_deleted : 1;
293 guint virtual_root_deleted : 1;
298 gulong has_child_toggled_id;
311 /* Set this to 0 to disable caching of child iterators. This
312 * allows for more stringent testing. It is recommended to set this
313 * to one when refactoring this code and running the unit tests to
317 # define GTK_TREE_MODEL_FILTER_CACHE_CHILD_ITERS(filter) \
318 (((GtkTreeModelFilter *)filter)->priv->child_flags & GTK_TREE_MODEL_ITERS_PERSIST)
320 # define GTK_TREE_MODEL_FILTER_CACHE_CHILD_ITERS(filter) (FALSE)
323 #define FILTER_ELT(filter_elt) ((FilterElt *)filter_elt)
324 #define FILTER_LEVEL(filter_level) ((FilterLevel *)filter_level)
325 #define GET_ELT(siter) ((FilterElt*) (siter ? g_sequence_get (siter) : NULL))
327 /* general code (object/interface init, properties, etc) */
328 static void gtk_tree_model_filter_tree_model_init (GtkTreeModelIface *iface);
329 static void gtk_tree_model_filter_drag_source_init (GtkTreeDragSourceIface *iface);
330 static void gtk_tree_model_filter_finalize (GObject *object);
331 static void gtk_tree_model_filter_set_property (GObject *object,
335 static void gtk_tree_model_filter_get_property (GObject *object,
340 /* signal handlers */
341 static void gtk_tree_model_filter_row_changed (GtkTreeModel *c_model,
345 static void gtk_tree_model_filter_row_inserted (GtkTreeModel *c_model,
349 static void gtk_tree_model_filter_row_has_child_toggled (GtkTreeModel *c_model,
353 static void gtk_tree_model_filter_row_deleted (GtkTreeModel *c_model,
356 static void gtk_tree_model_filter_rows_reordered (GtkTreeModel *c_model,
362 /* GtkTreeModel interface */
363 static GtkTreeModelFlags gtk_tree_model_filter_get_flags (GtkTreeModel *model);
364 static gint gtk_tree_model_filter_get_n_columns (GtkTreeModel *model);
365 static GType gtk_tree_model_filter_get_column_type (GtkTreeModel *model,
367 static gboolean gtk_tree_model_filter_get_iter_full (GtkTreeModel *model,
370 static gboolean gtk_tree_model_filter_get_iter (GtkTreeModel *model,
373 static GtkTreePath *gtk_tree_model_filter_get_path (GtkTreeModel *model,
375 static void gtk_tree_model_filter_get_value (GtkTreeModel *model,
379 static gboolean gtk_tree_model_filter_iter_next (GtkTreeModel *model,
381 static gboolean gtk_tree_model_filter_iter_previous (GtkTreeModel *model,
383 static gboolean gtk_tree_model_filter_iter_children (GtkTreeModel *model,
385 GtkTreeIter *parent);
386 static gboolean gtk_tree_model_filter_iter_has_child (GtkTreeModel *model,
388 static gint gtk_tree_model_filter_iter_n_children (GtkTreeModel *model,
390 static gboolean gtk_tree_model_filter_iter_nth_child (GtkTreeModel *model,
394 static gboolean gtk_tree_model_filter_iter_parent (GtkTreeModel *model,
397 static void gtk_tree_model_filter_ref_node (GtkTreeModel *model,
399 static void gtk_tree_model_filter_unref_node (GtkTreeModel *model,
402 /* TreeDragSource interface */
403 static gboolean gtk_tree_model_filter_row_draggable (GtkTreeDragSource *drag_source,
405 static gboolean gtk_tree_model_filter_drag_data_get (GtkTreeDragSource *drag_source,
407 GtkSelectionData *selection_data);
408 static gboolean gtk_tree_model_filter_drag_data_delete (GtkTreeDragSource *drag_source,
411 /* private functions */
412 static void gtk_tree_model_filter_build_level (GtkTreeModelFilter *filter,
413 FilterLevel *parent_level,
414 FilterElt *parent_elt,
415 gboolean emit_inserted);
417 static void gtk_tree_model_filter_free_level (GtkTreeModelFilter *filter,
418 FilterLevel *filter_level,
421 static GtkTreePath *gtk_tree_model_filter_elt_get_path (FilterLevel *level,
425 static GtkTreePath *gtk_tree_model_filter_add_root (GtkTreePath *src,
427 static GtkTreePath *gtk_tree_model_filter_remove_root (GtkTreePath *src,
430 static void gtk_tree_model_filter_increment_stamp (GtkTreeModelFilter *filter);
432 static void gtk_tree_model_filter_real_modify (GtkTreeModelFilter *self,
433 GtkTreeModel *child_model,
437 static gboolean gtk_tree_model_filter_real_visible (GtkTreeModelFilter *filter,
438 GtkTreeModel *child_model,
439 GtkTreeIter *child_iter);
440 static gboolean gtk_tree_model_filter_visible (GtkTreeModelFilter *filter,
441 GtkTreeIter *child_iter);
442 static void gtk_tree_model_filter_clear_cache_helper (GtkTreeModelFilter *filter,
445 static void gtk_tree_model_filter_real_ref_node (GtkTreeModel *model,
448 static void gtk_tree_model_filter_real_unref_node (GtkTreeModel *model,
451 gboolean propagate_unref);
453 static void gtk_tree_model_filter_set_model (GtkTreeModelFilter *filter,
454 GtkTreeModel *child_model);
455 static void gtk_tree_model_filter_ref_path (GtkTreeModelFilter *filter,
457 static void gtk_tree_model_filter_unref_path (GtkTreeModelFilter *filter,
460 static void gtk_tree_model_filter_set_root (GtkTreeModelFilter *filter,
463 static GtkTreePath *gtk_real_tree_model_filter_convert_child_path_to_path (GtkTreeModelFilter *filter,
464 GtkTreePath *child_path,
465 gboolean build_levels,
466 gboolean fetch_children);
468 static gboolean gtk_tree_model_filter_elt_is_visible_in_target (FilterLevel *level,
471 static FilterElt *gtk_tree_model_filter_insert_elt_in_level (GtkTreeModelFilter *filter,
476 static FilterElt *gtk_tree_model_filter_fetch_child (GtkTreeModelFilter *filter,
480 static void gtk_tree_model_filter_remove_elt_from_level (GtkTreeModelFilter *filter,
483 static void gtk_tree_model_filter_update_children (GtkTreeModelFilter *filter,
486 static void gtk_tree_model_filter_emit_row_inserted_for_path (GtkTreeModelFilter *filter,
487 GtkTreeModel *c_model,
489 GtkTreeIter *c_iter);
492 G_DEFINE_TYPE_WITH_CODE (GtkTreeModelFilter, gtk_tree_model_filter, G_TYPE_OBJECT,
493 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL,
494 gtk_tree_model_filter_tree_model_init)
495 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_SOURCE,
496 gtk_tree_model_filter_drag_source_init))
499 gtk_tree_model_filter_init (GtkTreeModelFilter *filter)
501 filter->priv = G_TYPE_INSTANCE_GET_PRIVATE (filter,
502 GTK_TYPE_TREE_MODEL_FILTER,
503 GtkTreeModelFilterPrivate);
505 filter->priv->visible_column = -1;
506 filter->priv->zero_ref_count = 0;
507 filter->priv->visible_method_set = FALSE;
508 filter->priv->modify_func_set = FALSE;
509 filter->priv->in_row_deleted = FALSE;
510 filter->priv->virtual_root_deleted = FALSE;
514 gtk_tree_model_filter_class_init (GtkTreeModelFilterClass *filter_class)
516 GObjectClass *object_class;
518 object_class = (GObjectClass *) filter_class;
520 object_class->set_property = gtk_tree_model_filter_set_property;
521 object_class->get_property = gtk_tree_model_filter_get_property;
523 object_class->finalize = gtk_tree_model_filter_finalize;
525 filter_class->visible = gtk_tree_model_filter_real_visible;
526 filter_class->modify = gtk_tree_model_filter_real_modify;
528 /* Properties -- FIXME: disabled translations for now, until I can come up with a
531 g_object_class_install_property (object_class,
533 g_param_spec_object ("child-model",
535 ("The model for the filtermodel to filter"),
537 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
539 g_object_class_install_property (object_class,
541 g_param_spec_boxed ("virtual-root",
542 ("The virtual root"),
543 ("The virtual root (relative to the child model) for this filtermodel"),
545 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
547 g_type_class_add_private (object_class, sizeof (GtkTreeModelFilterPrivate));
551 gtk_tree_model_filter_tree_model_init (GtkTreeModelIface *iface)
553 iface->get_flags = gtk_tree_model_filter_get_flags;
554 iface->get_n_columns = gtk_tree_model_filter_get_n_columns;
555 iface->get_column_type = gtk_tree_model_filter_get_column_type;
556 iface->get_iter = gtk_tree_model_filter_get_iter;
557 iface->get_path = gtk_tree_model_filter_get_path;
558 iface->get_value = gtk_tree_model_filter_get_value;
559 iface->iter_next = gtk_tree_model_filter_iter_next;
560 iface->iter_previous = gtk_tree_model_filter_iter_previous;
561 iface->iter_children = gtk_tree_model_filter_iter_children;
562 iface->iter_has_child = gtk_tree_model_filter_iter_has_child;
563 iface->iter_n_children = gtk_tree_model_filter_iter_n_children;
564 iface->iter_nth_child = gtk_tree_model_filter_iter_nth_child;
565 iface->iter_parent = gtk_tree_model_filter_iter_parent;
566 iface->ref_node = gtk_tree_model_filter_ref_node;
567 iface->unref_node = gtk_tree_model_filter_unref_node;
571 gtk_tree_model_filter_drag_source_init (GtkTreeDragSourceIface *iface)
573 iface->row_draggable = gtk_tree_model_filter_row_draggable;
574 iface->drag_data_delete = gtk_tree_model_filter_drag_data_delete;
575 iface->drag_data_get = gtk_tree_model_filter_drag_data_get;
580 gtk_tree_model_filter_finalize (GObject *object)
582 GtkTreeModelFilter *filter = (GtkTreeModelFilter *) object;
584 if (filter->priv->virtual_root && !filter->priv->virtual_root_deleted)
586 gtk_tree_model_filter_unref_path (filter, filter->priv->virtual_root,
588 filter->priv->virtual_root_deleted = TRUE;
591 gtk_tree_model_filter_set_model (filter, NULL);
593 if (filter->priv->virtual_root)
594 gtk_tree_path_free (filter->priv->virtual_root);
596 if (filter->priv->root)
597 gtk_tree_model_filter_free_level (filter, filter->priv->root, TRUE);
599 g_free (filter->priv->modify_types);
601 if (filter->priv->modify_destroy)
602 filter->priv->modify_destroy (filter->priv->modify_data);
604 if (filter->priv->visible_destroy)
605 filter->priv->visible_destroy (filter->priv->visible_data);
608 G_OBJECT_CLASS (gtk_tree_model_filter_parent_class)->finalize (object);
612 gtk_tree_model_filter_set_property (GObject *object,
617 GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (object);
621 case PROP_CHILD_MODEL:
622 gtk_tree_model_filter_set_model (filter, g_value_get_object (value));
624 case PROP_VIRTUAL_ROOT:
625 gtk_tree_model_filter_set_root (filter, g_value_get_boxed (value));
628 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
634 gtk_tree_model_filter_get_property (GObject *object,
639 GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (object);
643 case PROP_CHILD_MODEL:
644 g_value_set_object (value, filter->priv->child_model);
646 case PROP_VIRTUAL_ROOT:
647 g_value_set_boxed (value, filter->priv->virtual_root);
650 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
658 filter_elt_new (void)
660 return g_slice_new (FilterElt);
664 filter_elt_free (gpointer elt)
666 g_slice_free (FilterElt, elt);
670 filter_elt_cmp (gconstpointer a,
674 const FilterElt *elt_a = a;
675 const FilterElt *elt_b = b;
677 if (elt_a->offset > elt_b->offset)
679 else if (elt_a->offset < elt_b->offset)
686 lookup_elt_with_offset (GSequence *seq,
688 GSequenceIter **ret_siter)
690 GSequenceIter *siter;
693 dummy.offset = offset;
694 siter = g_sequence_lookup (seq, &dummy, filter_elt_cmp, NULL);
699 return GET_ELT (siter);
703 increase_offset_iter (gpointer data,
706 FilterElt *elt = data;
707 gint offset = GPOINTER_TO_INT (user_data);
709 if (elt->offset >= offset)
714 decrease_offset_iter (gpointer data,
717 FilterElt *elt = data;
718 gint offset = GPOINTER_TO_INT (user_data);
720 if (elt->offset > offset)
725 gtk_tree_model_filter_build_level (GtkTreeModelFilter *filter,
726 FilterLevel *parent_level,
727 FilterElt *parent_elt,
728 gboolean emit_inserted)
731 GtkTreeIter first_node;
733 FilterLevel *new_level;
734 FilterLevel *tmp_level;
739 gboolean empty = TRUE;
741 g_assert (filter->priv->child_model != NULL);
743 /* Avoid building a level that already exists */
745 g_assert (parent_elt->children == NULL);
747 g_assert (filter->priv->root == NULL);
749 if (filter->priv->in_row_deleted)
754 if (filter->priv->virtual_root)
756 if (gtk_tree_model_get_iter (filter->priv->child_model, &root, filter->priv->virtual_root) == FALSE)
758 length = gtk_tree_model_iter_n_children (filter->priv->child_model, &root);
760 if (gtk_tree_model_iter_children (filter->priv->child_model, &iter, &root) == FALSE)
765 if (!gtk_tree_model_get_iter_first (filter->priv->child_model, &iter))
767 length = gtk_tree_model_iter_n_children (filter->priv->child_model, NULL);
772 GtkTreeIter parent_iter;
773 GtkTreeIter child_parent_iter;
775 parent_iter.stamp = filter->priv->stamp;
776 parent_iter.user_data = parent_level;
777 parent_iter.user_data2 = parent_elt;
779 gtk_tree_model_filter_convert_iter_to_child_iter (filter,
782 if (gtk_tree_model_iter_children (filter->priv->child_model, &iter, &child_parent_iter) == FALSE)
785 /* stamp may have changed */
786 gtk_tree_model_filter_convert_iter_to_child_iter (filter,
789 length = gtk_tree_model_iter_n_children (filter->priv->child_model, &child_parent_iter);
791 /* Take a reference on the parent */
792 gtk_tree_model_filter_real_ref_node (GTK_TREE_MODEL (filter),
793 &parent_iter, FALSE);
796 g_return_if_fail (length > 0);
798 new_level = g_new (FilterLevel, 1);
799 new_level->seq = g_sequence_new (filter_elt_free);
800 new_level->visible_seq = g_sequence_new (NULL);
801 new_level->ref_count = 0;
802 new_level->ext_ref_count = 0;
803 new_level->parent_elt = parent_elt;
804 new_level->parent_level = parent_level;
807 parent_elt->children = new_level;
809 filter->priv->root = new_level;
811 /* increase the count of zero ref_counts */
812 tmp_level = parent_level;
813 tmp_elt = parent_elt;
817 parent_elt->zero_ref_count++;
819 tmp_elt = tmp_level->parent_elt;
820 tmp_level = tmp_level->parent_level;
822 if (new_level != filter->priv->root)
823 filter->priv->zero_ref_count++;
831 if (gtk_tree_model_filter_visible (filter, &iter))
833 FilterElt *filter_elt;
835 filter_elt = filter_elt_new ();
836 filter_elt->offset = i;
837 filter_elt->zero_ref_count = 0;
838 filter_elt->ref_count = 0;
839 filter_elt->ext_ref_count = 0;
840 filter_elt->children = NULL;
841 filter_elt->visible_siter = NULL;
843 if (GTK_TREE_MODEL_FILTER_CACHE_CHILD_ITERS (filter))
844 filter_elt->iter = iter;
846 g_sequence_append (new_level->seq, filter_elt);
847 filter_elt->visible_siter = g_sequence_append (new_level->visible_seq, filter_elt);
854 GtkTreeIter children;
856 f_iter.stamp = filter->priv->stamp;
857 f_iter.user_data = new_level;
858 f_iter.user_data2 = filter_elt;
860 f_path = gtk_tree_model_get_path (GTK_TREE_MODEL (filter),
862 gtk_tree_model_row_inserted (GTK_TREE_MODEL (filter),
864 gtk_tree_path_free (f_path);
866 if (gtk_tree_model_iter_children (filter->priv->child_model,
868 gtk_tree_model_filter_update_children (filter,
870 FILTER_ELT (f_iter.user_data2));
875 while (gtk_tree_model_iter_next (filter->priv->child_model, &iter));
877 /* The level does not contain any visible nodes. However, changes in
878 * this level might affect the parent node, which can either be visible
879 * or invisible. Therefore, this level can only be removed again,
880 * if the parent of the parent node is not visible. In that case,
881 * possible changes in state of the parent are not requested.
884 (parent_level && parent_level->parent_level &&
885 parent_level->parent_elt->ext_ref_count == 0))
887 gtk_tree_model_filter_free_level (filter, new_level, FALSE);
891 /* If none of the nodes are visible, we will just pull in the
892 * first node of the level.
896 FilterElt *filter_elt;
898 filter_elt = filter_elt_new ();
899 filter_elt->offset = 0;
900 filter_elt->zero_ref_count = 0;
901 filter_elt->ref_count = 0;
902 filter_elt->ext_ref_count = 0;
903 filter_elt->children = NULL;
904 filter_elt->visible_siter = NULL;
906 if (GTK_TREE_MODEL_FILTER_CACHE_CHILD_ITERS (filter))
907 filter_elt->iter = first_node;
909 g_sequence_append (new_level->seq, filter_elt);
912 /* Keep a reference on the first node of this level. We need this
913 * to make sure that we get all signals for this level.
915 f_iter.stamp = filter->priv->stamp;
916 f_iter.user_data = new_level;
917 f_iter.user_data2 = g_sequence_get (g_sequence_get_begin_iter (new_level->seq));
919 gtk_tree_model_filter_real_ref_node (GTK_TREE_MODEL (filter), &f_iter,
924 gtk_tree_model_filter_free_level (GtkTreeModelFilter *filter,
925 FilterLevel *filter_level,
928 GSequenceIter *siter;
929 GSequenceIter *end_siter;
931 g_assert (filter_level);
933 end_siter = g_sequence_get_end_iter (filter_level->seq);
934 for (siter = g_sequence_get_begin_iter (filter_level->seq);
936 siter = g_sequence_iter_next (siter))
938 FilterElt *elt = g_sequence_get (siter);
941 gtk_tree_model_filter_free_level (filter,
942 FILTER_LEVEL (elt->children),
946 /* Release the reference on the first item.
952 f_iter.stamp = filter->priv->stamp;
953 f_iter.user_data = filter_level;
954 f_iter.user_data2 = g_sequence_get (g_sequence_get_begin_iter (filter_level->seq));
956 gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter),
957 &f_iter, FALSE, TRUE);
960 if (filter_level->ext_ref_count == 0)
962 FilterLevel *parent_level = filter_level->parent_level;
963 FilterElt *parent_elt = filter_level->parent_elt;
967 parent_elt->zero_ref_count--;
969 parent_elt = parent_level->parent_elt;
970 parent_level = parent_level->parent_level;
973 if (filter_level != filter->priv->root)
974 filter->priv->zero_ref_count--;
977 if (filter_level->parent_elt)
979 /* Release reference on parent */
982 GtkTreeIter parent_iter;
984 parent_iter.stamp = filter->priv->stamp;
985 parent_iter.user_data = filter_level->parent_level;
986 parent_iter.user_data2 = filter_level->parent_elt;
988 gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter),
989 &parent_iter, FALSE, TRUE);
992 filter_level->parent_elt->children = NULL;
995 filter->priv->root = NULL;
997 g_sequence_free (filter_level->seq);
998 g_sequence_free (filter_level->visible_seq);
999 g_free (filter_level);
1003 gtk_tree_model_filter_level_transfer_first_ref (GtkTreeModelFilter *filter,
1005 GSequenceIter *from_iter,
1006 GSequenceIter *to_iter)
1010 f_iter.stamp = filter->priv->stamp;
1011 f_iter.user_data = level;
1012 f_iter.user_data2 = g_sequence_get (to_iter);
1014 gtk_tree_model_filter_real_ref_node (GTK_TREE_MODEL (filter),
1017 f_iter.stamp = filter->priv->stamp;
1018 f_iter.user_data = level;
1019 f_iter.user_data2 = g_sequence_get (from_iter);
1021 gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter),
1022 &f_iter, FALSE, TRUE);
1026 gtk_tree_model_filter_level_transfer_first_ref_with_index (GtkTreeModelFilter *filter,
1031 gtk_tree_model_filter_level_transfer_first_ref (filter, level,
1032 g_sequence_get_iter_at_pos (level->seq, from_index),
1033 g_sequence_get_iter_at_pos (level->seq, to_index));
1036 /* Creates paths suitable for accessing the child model. */
1037 static GtkTreePath *
1038 gtk_tree_model_filter_elt_get_path (FilterLevel *level,
1042 FilterLevel *walker = level;
1043 FilterElt *walker2 = elt;
1045 GtkTreePath *real_path;
1047 g_return_val_if_fail (level != NULL, NULL);
1048 g_return_val_if_fail (elt != NULL, NULL);
1050 path = gtk_tree_path_new ();
1054 gtk_tree_path_prepend_index (path, walker2->offset);
1056 walker2 = walker->parent_elt;
1057 walker = walker->parent_level;
1062 real_path = gtk_tree_model_filter_add_root (path, root);
1063 gtk_tree_path_free (path);
1070 static GtkTreePath *
1071 gtk_tree_model_filter_add_root (GtkTreePath *src,
1074 GtkTreePath *retval;
1077 retval = gtk_tree_path_copy (root);
1079 for (i = 0; i < gtk_tree_path_get_depth (src); i++)
1080 gtk_tree_path_append_index (retval, gtk_tree_path_get_indices (src)[i]);
1085 static GtkTreePath *
1086 gtk_tree_model_filter_remove_root (GtkTreePath *src,
1089 GtkTreePath *retval;
1094 if (gtk_tree_path_get_depth (src) <= gtk_tree_path_get_depth (root))
1097 depth = gtk_tree_path_get_depth (src);
1098 indices = gtk_tree_path_get_indices (src);
1100 for (i = 0; i < gtk_tree_path_get_depth (root); i++)
1101 if (indices[i] != gtk_tree_path_get_indices (root)[i])
1104 retval = gtk_tree_path_new ();
1106 for (; i < depth; i++)
1107 gtk_tree_path_append_index (retval, indices[i]);
1113 gtk_tree_model_filter_increment_stamp (GtkTreeModelFilter *filter)
1117 filter->priv->stamp++;
1119 while (filter->priv->stamp == 0);
1121 gtk_tree_model_filter_clear_cache (filter);
1125 gtk_tree_model_filter_real_visible (GtkTreeModelFilter *filter,
1126 GtkTreeModel *child_model,
1127 GtkTreeIter *child_iter)
1129 if (filter->priv->visible_func)
1131 return filter->priv->visible_func (child_model,
1133 filter->priv->visible_data)
1136 else if (filter->priv->visible_column >= 0)
1140 gtk_tree_model_get_value (child_model, child_iter,
1141 filter->priv->visible_column, &val);
1143 if (g_value_get_boolean (&val))
1145 g_value_unset (&val);
1149 g_value_unset (&val);
1153 /* no visible function set, so always visible */
1158 gtk_tree_model_filter_visible (GtkTreeModelFilter *self,
1159 GtkTreeIter *child_iter)
1161 return GTK_TREE_MODEL_FILTER_GET_CLASS (self)->visible (self,
1162 self->priv->child_model, child_iter);
1166 gtk_tree_model_filter_clear_cache_helper_iter (gpointer data,
1169 GtkTreeModelFilter *filter = user_data;
1170 FilterElt *elt = data;
1172 if (elt->zero_ref_count > 0)
1173 gtk_tree_model_filter_clear_cache_helper (filter, elt->children);
1177 gtk_tree_model_filter_clear_cache_helper (GtkTreeModelFilter *filter,
1182 g_sequence_foreach (level->seq, gtk_tree_model_filter_clear_cache_helper_iter, filter);
1184 /* If the level's ext_ref_count is zero, it means the level is not visible
1185 * and can be removed. But, since we support monitoring a child level
1186 * of a parent for changes (these might affect the parent), we will only
1187 * free the level if the parent's parent also has an external ref
1188 * count of zero. In that case, changes concerning our parent are
1191 if (level->ext_ref_count == 0 && level != filter->priv->root &&
1192 level->parent_level && level->parent_elt &&
1193 level->parent_level->parent_level &&
1194 level->parent_level->parent_elt->ext_ref_count == 0)
1196 gtk_tree_model_filter_free_level (filter, level, TRUE);
1202 gtk_tree_model_filter_elt_is_visible_in_target (FilterLevel *level,
1205 if (!elt->visible_siter)
1208 if (!level->parent_elt)
1213 elt = level->parent_elt;
1214 level = level->parent_level;
1216 if (elt && !elt->visible_siter)
1224 /* If a change has occurred in path (inserted, changed or deleted),
1225 * then this function is used to check all its ancestors. An ancestor
1226 * could have changed state as a result and this needs to be propagated
1227 * to the objects monitoring the filter model.
1230 gtk_tree_model_filter_check_ancestors (GtkTreeModelFilter *filter,
1234 int *indices = gtk_tree_path_get_indices (path);
1237 GtkTreeIter c_iter, tmp_iter;
1239 level = FILTER_LEVEL (filter->priv->root);
1244 if (filter->priv->virtual_root)
1245 gtk_tree_model_get_iter (filter->priv->child_model, &c_iter,
1246 filter->priv->virtual_root);
1249 gtk_tree_model_iter_nth_child (filter->priv->child_model, &c_iter,
1250 filter->priv->virtual_root ? &tmp_iter : NULL,
1253 while (i < gtk_tree_path_get_depth (path) - 1)
1255 gboolean requested_state;
1257 elt = lookup_elt_with_offset (level->seq,
1258 gtk_tree_path_get_indices (path)[i], NULL);
1260 requested_state = gtk_tree_model_filter_visible (filter, &c_iter);
1265 GtkTreePath *c_path;
1267 if (requested_state == FALSE)
1270 /* The elt does not exist in this level (so it is not
1271 * visible), but should now be visible. We emit the
1272 * row-inserted and row-has-child-toggled signals.
1274 elt = gtk_tree_model_filter_insert_elt_in_level (filter,
1280 /* insert_elt_in_level defaults to FALSE */
1281 elt->visible_siter = g_sequence_insert_sorted (level->visible_seq,
1283 filter_elt_cmp, NULL);
1285 c_path = gtk_tree_model_get_path (filter->priv->child_model,
1288 gtk_tree_model_filter_emit_row_inserted_for_path (filter,
1289 filter->priv->child_model,
1293 gtk_tree_path_free (c_path);
1295 /* We can immediately return, because this node was not visible
1296 * before and its children will be checked for in response to
1297 * the emitted row-has-child-toggled signal.
1301 else if (elt->visible_siter)
1303 if (!requested_state)
1305 /* A node has turned invisible. Remove it from the level
1306 * and emit row-deleted. Since this node is being
1307 * deleted. it makes no sense to look further up the
1310 gtk_tree_model_filter_remove_elt_from_level (filter,
1315 /* Otherwise continue up the chain */
1317 else if (!elt->visible_siter)
1319 if (requested_state)
1321 /* A node is already in the cache, but invisible. This
1322 * is usually a node on which a reference is kept by
1323 * the filter model, or a node fetched on the filter's
1324 * request, and thus not shown. Therefore, we will
1325 * not emit row-inserted for this node. Instead,
1326 * we signal to its parent that a change has occurred.
1328 * Exception: root level, in this case, we must emit
1331 if (level->parent_level)
1334 GtkTreePath *f_path;
1336 elt->visible_siter = g_sequence_insert_sorted (level->visible_seq, elt,
1337 filter_elt_cmp, NULL);
1339 f_iter.stamp = filter->priv->stamp;
1340 f_iter.user_data = level->parent_level;
1341 f_iter.user_data2 = level->parent_elt;
1343 f_path = gtk_tree_model_get_path (GTK_TREE_MODEL (filter),
1345 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (filter),
1347 gtk_tree_path_free (f_path);
1351 GtkTreePath *c_path;
1353 elt->visible_siter = g_sequence_insert_sorted (level->visible_seq, elt,
1354 filter_elt_cmp, NULL);
1356 c_path = gtk_tree_model_get_path (filter->priv->child_model,
1359 gtk_tree_model_filter_emit_row_inserted_for_path (filter,
1360 filter->priv->child_model,
1364 gtk_tree_path_free (c_path);
1367 /* We can immediately return, because this node was not visible
1368 * before and the parent will check its children, including
1369 * this node, in response to the emitted row-has-child-toggled
1375 /* Not visible, so no need to continue. */
1381 /* If an elt does not have children, these are not visible.
1382 * Therefore, any signals emitted for these children will
1383 * be ignored, so we do not have to emit them.
1388 level = elt->children;
1392 gtk_tree_model_iter_nth_child (filter->priv->child_model, &c_iter,
1393 &tmp_iter, indices[i]);
1398 gtk_tree_model_filter_insert_elt_in_level (GtkTreeModelFilter *filter,
1399 GtkTreeIter *c_iter,
1405 GSequenceIter *siter;
1407 elt = filter_elt_new ();
1409 if (GTK_TREE_MODEL_FILTER_CACHE_CHILD_ITERS (filter))
1410 elt->iter = *c_iter;
1412 elt->offset = offset;
1413 elt->zero_ref_count = 0;
1415 elt->ext_ref_count = 0;
1416 elt->children = NULL;
1418 /* Because we don't emit row_inserted, the node is invisible and thus
1419 * not inserted in visible_seq
1421 elt->visible_siter = NULL;
1423 siter = g_sequence_insert_sorted (level->seq, elt, filter_elt_cmp, NULL);
1424 *index = g_sequence_iter_get_position (siter);
1426 /* If the insert location is zero, we need to move our reference
1427 * on the old first node to the new first node.
1430 gtk_tree_model_filter_level_transfer_first_ref_with_index (filter, level,
1437 gtk_tree_model_filter_fetch_child (GtkTreeModelFilter *filter,
1443 GtkTreePath *c_path = NULL;
1445 GtkTreePath *c_parent_path = NULL;
1446 GtkTreeIter c_parent_iter;
1448 /* check if child exists and is visible */
1449 if (level->parent_elt)
1452 gtk_tree_model_filter_elt_get_path (level->parent_level,
1454 filter->priv->virtual_root);
1460 if (filter->priv->virtual_root)
1461 c_parent_path = gtk_tree_path_copy (filter->priv->virtual_root);
1463 c_parent_path = NULL;
1468 gtk_tree_model_get_iter (filter->priv->child_model,
1471 len = gtk_tree_model_iter_n_children (filter->priv->child_model,
1474 c_path = gtk_tree_path_copy (c_parent_path);
1475 gtk_tree_path_free (c_parent_path);
1479 len = gtk_tree_model_iter_n_children (filter->priv->child_model, NULL);
1480 c_path = gtk_tree_path_new ();
1483 gtk_tree_path_append_index (c_path, offset);
1484 gtk_tree_model_get_iter (filter->priv->child_model, &c_iter, c_path);
1485 gtk_tree_path_free (c_path);
1487 if (offset >= len || !gtk_tree_model_filter_visible (filter, &c_iter))
1490 return gtk_tree_model_filter_insert_elt_in_level (filter, &c_iter,
1495 /* Note that this function is never called from the row-deleted handler.
1496 * This means that this function is only used for removing elements
1497 * which are still present in the child model. As a result, we must
1498 * take care to properly release the references the filter model has
1499 * on the child model nodes.
1502 gtk_tree_model_filter_remove_elt_from_level (GtkTreeModelFilter *filter,
1507 FilterLevel *parent_level;
1508 gint length, orig_level_ext_ref_count;
1510 GtkTreePath *path = NULL;
1512 gboolean emit_child_toggled = FALSE;
1514 iter.stamp = filter->priv->stamp;
1515 iter.user_data = level;
1516 iter.user_data2 = elt;
1518 path = gtk_tree_model_get_path (GTK_TREE_MODEL (filter), &iter);
1520 parent = level->parent_elt;
1521 parent_level = level->parent_level;
1523 length = g_sequence_get_length (level->seq);
1525 /* We need to know about the level's ext ref count before removal
1528 orig_level_ext_ref_count = level->ext_ref_count;
1530 /* first register the node to be invisible */
1531 g_sequence_remove (elt->visible_siter);
1532 elt->visible_siter = NULL;
1534 /* we distinguish a couple of cases:
1535 * - root level, length > 1: emit row-deleted and remove.
1536 * - root level, length == 1: emit row-deleted and keep in cache.
1537 * - level, length == 1: parent->ext_ref_count > 0: emit row-deleted
1539 * - level, length > 1: emit row-deleted and remove.
1540 * - else, remove level.
1542 * if level != root level and the number of visible nodes is 0 (ie. this
1543 * is the last node to be removed from the level), emit
1544 * row-has-child-toggled.
1547 if (level != filter->priv->root
1548 && g_sequence_get_length (level->visible_seq) == 0
1550 && parent->visible_siter)
1551 emit_child_toggled = TRUE;
1555 GSequenceIter *siter;
1557 /* We emit row-deleted, and remove the node from the cache.
1558 * If it has any children, these will be removed here as well.
1562 gtk_tree_model_filter_free_level (filter, elt->children, TRUE);
1564 /* If the first node is being removed, transfer, the reference */
1565 if (elt == g_sequence_get (g_sequence_get_begin_iter (level->seq)))
1567 gtk_tree_model_filter_level_transfer_first_ref_with_index (filter, level,
1571 while (elt->ext_ref_count > 0)
1572 gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter),
1573 &iter, TRUE, FALSE);
1574 while (elt->ref_count > 0)
1575 gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter),
1576 &iter, FALSE, FALSE);
1578 /* remove the node */
1579 lookup_elt_with_offset (level->seq, elt->offset, &siter);
1580 g_sequence_remove (siter);
1582 gtk_tree_model_filter_increment_stamp (filter);
1584 /* Only if the node is in the root level (parent == NULL) or
1585 * the level is visible, a row-deleted signal is necessary.
1587 if (!parent || orig_level_ext_ref_count > 0)
1588 gtk_tree_model_row_deleted (GTK_TREE_MODEL (filter), path);
1590 else if ((length == 1 && parent && parent->ext_ref_count > 0)
1591 || (length == 1 && level == filter->priv->root))
1593 /* We emit row-deleted, but keep the node in the cache and
1594 * referenced. Its children will be removed.
1599 gtk_tree_model_filter_free_level (filter, elt->children, TRUE);
1600 elt->children = NULL;
1603 gtk_tree_model_filter_increment_stamp (filter);
1605 /* Only if the node is in the root level (parent == NULL) or
1606 * the level is visible, a row-deleted signal is necessary.
1608 if (!parent || orig_level_ext_ref_count > 0)
1609 gtk_tree_model_row_deleted (GTK_TREE_MODEL (filter), path);
1613 while (elt->ext_ref_count > 0)
1614 gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter),
1615 &iter, TRUE, FALSE);
1616 while (elt->ref_count > 0)
1617 gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter),
1618 &iter, FALSE, FALSE);
1620 /* Blow level away, including any child levels */
1621 gtk_tree_model_filter_free_level (filter, level, TRUE);
1623 gtk_tree_model_filter_increment_stamp (filter);
1625 if (!parent || orig_level_ext_ref_count > 0)
1626 gtk_tree_model_row_deleted (GTK_TREE_MODEL (filter), path);
1629 gtk_tree_path_free (path);
1631 if (emit_child_toggled && parent->ext_ref_count > 0)
1636 piter.stamp = filter->priv->stamp;
1637 piter.user_data = parent_level;
1638 piter.user_data2 = parent;
1640 ppath = gtk_tree_model_get_path (GTK_TREE_MODEL (filter), &piter);
1642 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (filter),
1644 gtk_tree_path_free (ppath);
1648 /* This function is called after the given node has become visible.
1649 * When the node has children, we should build the level and
1650 * take a reference on the first child.
1653 gtk_tree_model_filter_update_children (GtkTreeModelFilter *filter,
1660 if (!elt->visible_siter)
1663 iter.stamp = filter->priv->stamp;
1664 iter.user_data = level;
1665 iter.user_data2 = elt;
1667 gtk_tree_model_filter_convert_iter_to_child_iter (filter, &c_iter, &iter);
1669 if ((!level->parent_level || level->parent_elt->ext_ref_count > 0) &&
1670 gtk_tree_model_iter_has_child (filter->priv->child_model, &c_iter))
1673 gtk_tree_model_filter_build_level (filter, level, elt, FALSE);
1675 if (elt->ext_ref_count > 0 && elt->children &&
1676 g_sequence_get_length (elt->children->seq))
1679 path = gtk_tree_model_get_path (GTK_TREE_MODEL (filter), &iter);
1680 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (filter),
1684 gtk_tree_path_free (path);
1689 /* Path is relative to the child model (this is on search on elt offset)
1690 * but with the virtual root already removed if necesssary.
1693 find_elt_with_offset (GtkTreeModelFilter *filter,
1695 FilterLevel **level_,
1700 FilterLevel *parent_level = NULL;
1701 FilterElt *elt = NULL;
1703 level = FILTER_LEVEL (filter->priv->root);
1705 while (i < gtk_tree_path_get_depth (path))
1710 elt = lookup_elt_with_offset (level->seq,
1711 gtk_tree_path_get_indices (path)[i],
1717 parent_level = level;
1718 level = elt->children;
1723 *level_ = parent_level;
1731 /* TreeModel signals */
1733 gtk_tree_model_filter_emit_row_inserted_for_path (GtkTreeModelFilter *filter,
1734 GtkTreeModel *c_model,
1735 GtkTreePath *c_path,
1736 GtkTreeIter *c_iter)
1741 GtkTreeIter iter, children;
1742 gboolean signals_emitted = FALSE;
1744 if (!filter->priv->root)
1746 /* The root level has not been exposed to the view yet, so we
1747 * need to emit signals for any node that is being inserted.
1749 gtk_tree_model_filter_build_level (filter, NULL, NULL, TRUE);
1751 /* Check if the root level was built. Then child levels
1752 * that matter have also been built (due to update_children,
1753 * which triggers iter_n_children).
1755 if (filter->priv->root &&
1756 g_sequence_get_length (FILTER_LEVEL (filter->priv->root)->visible_seq) > 0)
1757 signals_emitted = TRUE;
1760 gtk_tree_model_filter_increment_stamp (filter);
1762 /* We need to disallow to build new levels, because we are then pulling
1763 * in a child in an invisible level. We only want to find path if it
1764 * is in a visible level (and thus has a parent that is visible).
1766 path = gtk_real_tree_model_filter_convert_child_path_to_path (filter,
1772 /* parent is probably being filtered out */
1775 gtk_tree_model_filter_get_iter_full (GTK_TREE_MODEL (filter), &iter, path);
1777 level = FILTER_LEVEL (iter.user_data);
1778 elt = FILTER_ELT (iter.user_data2);
1780 /* Make sure elt is visible. elt can already be visible in case
1781 * it was pulled in above, so avoid inserted it into visible_seq twice.
1783 if (!elt->visible_siter)
1785 elt->visible_siter = g_sequence_insert_sorted (level->visible_seq,
1786 elt, filter_elt_cmp,
1790 /* Check whether the node and all of its parents are visible */
1791 if (gtk_tree_model_filter_elt_is_visible_in_target (level, elt))
1793 /* visibility changed -- reget path */
1794 gtk_tree_path_free (path);
1795 path = gtk_tree_model_get_path (GTK_TREE_MODEL (filter), &iter);
1797 if (!signals_emitted &&
1798 (!level->parent_level || level->ext_ref_count > 0))
1799 gtk_tree_model_row_inserted (GTK_TREE_MODEL (filter), path, &iter);
1801 if (level->parent_level && level->parent_elt->ext_ref_count > 0 &&
1802 g_sequence_get_length (level->visible_seq) == 1)
1804 /* We know that this is the first visible node in this level, so
1805 * we need to emit row-has-child-toggled on the parent. This
1806 * does not apply to the root level.
1809 gtk_tree_path_up (path);
1810 gtk_tree_model_get_iter (GTK_TREE_MODEL (filter), &iter, path);
1812 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (filter),
1817 if (!signals_emitted
1818 && gtk_tree_model_iter_children (c_model, &children, c_iter))
1819 gtk_tree_model_filter_update_children (filter, level, elt);
1822 gtk_tree_path_free (path);
1826 gtk_tree_model_filter_row_changed (GtkTreeModel *c_model,
1827 GtkTreePath *c_path,
1828 GtkTreeIter *c_iter,
1831 GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (data);
1833 GtkTreeIter children;
1834 GtkTreeIter real_c_iter;
1835 GtkTreePath *path = NULL;
1836 GtkTreePath *real_path = NULL;
1841 gboolean requested_state;
1842 gboolean current_state;
1843 gboolean free_c_path = FALSE;
1845 g_return_if_fail (c_path != NULL || c_iter != NULL);
1849 c_path = gtk_tree_model_get_path (c_model, c_iter);
1853 if (filter->priv->virtual_root)
1854 real_path = gtk_tree_model_filter_remove_root (c_path,
1855 filter->priv->virtual_root);
1857 real_path = gtk_tree_path_copy (c_path);
1860 real_c_iter = *c_iter;
1862 gtk_tree_model_get_iter (c_model, &real_c_iter, c_path);
1864 /* is this node above the virtual root? */
1865 if (filter->priv->virtual_root &&
1866 (gtk_tree_path_get_depth (filter->priv->virtual_root)
1867 >= gtk_tree_path_get_depth (c_path)))
1870 /* what's the requested state? */
1871 requested_state = gtk_tree_model_filter_visible (filter, &real_c_iter);
1873 /* now, let's see whether the item is there */
1874 path = gtk_real_tree_model_filter_convert_child_path_to_path (filter,
1881 gtk_tree_model_filter_get_iter_full (GTK_TREE_MODEL (filter),
1883 current_state = FILTER_ELT (iter.user_data2)->visible_siter != NULL;
1886 current_state = FALSE;
1888 if (current_state == FALSE && requested_state == FALSE)
1889 /* no changes required */
1892 if (current_state == TRUE && requested_state == FALSE)
1894 gtk_tree_model_filter_remove_elt_from_level (filter,
1895 FILTER_LEVEL (iter.user_data),
1896 FILTER_ELT (iter.user_data2));
1899 gtk_tree_model_filter_check_ancestors (filter, real_path);
1904 if (current_state == TRUE && requested_state == TRUE)
1906 /* propagate the signal; also get a path taking only visible
1907 * nodes into account.
1909 gtk_tree_path_free (path);
1910 path = gtk_tree_model_get_path (GTK_TREE_MODEL (filter), &iter);
1912 level = FILTER_LEVEL (iter.user_data);
1913 elt = FILTER_ELT (iter.user_data2);
1915 if (gtk_tree_model_filter_elt_is_visible_in_target (level, elt))
1917 if (level->ext_ref_count > 0)
1918 gtk_tree_model_row_changed (GTK_TREE_MODEL (filter), path, &iter);
1920 /* and update the children */
1921 if (gtk_tree_model_iter_children (c_model, &children, &real_c_iter))
1922 gtk_tree_model_filter_update_children (filter, level, elt);
1926 gtk_tree_model_filter_check_ancestors (filter, real_path);
1931 /* only current == FALSE and requested == TRUE is left,
1934 g_return_if_fail (current_state == FALSE && requested_state == TRUE);
1937 gtk_tree_model_filter_check_ancestors (filter, real_path);
1939 gtk_tree_model_filter_emit_row_inserted_for_path (filter, c_model,
1944 gtk_tree_path_free (path);
1947 gtk_tree_path_free (real_path);
1950 gtk_tree_path_free (c_path);
1954 gtk_tree_model_filter_row_inserted (GtkTreeModel *c_model,
1955 GtkTreePath *c_path,
1956 GtkTreeIter *c_iter,
1959 GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (data);
1960 GtkTreePath *real_path = NULL;
1962 GtkTreeIter real_c_iter;
1964 FilterElt *elt = NULL;
1965 FilterLevel *level = NULL;
1966 FilterLevel *parent_level = NULL;
1967 GSequenceIter *siter;
1972 gboolean free_c_path = FALSE;
1973 gboolean emit_row_inserted = FALSE;
1975 g_return_if_fail (c_path != NULL || c_iter != NULL);
1979 c_path = gtk_tree_model_get_path (c_model, c_iter);
1984 real_c_iter = *c_iter;
1986 gtk_tree_model_get_iter (c_model, &real_c_iter, c_path);
1988 /* the row has already been inserted. so we need to fixup the
1989 * virtual root here first
1991 if (filter->priv->virtual_root)
1993 if (gtk_tree_path_get_depth (filter->priv->virtual_root) >=
1994 gtk_tree_path_get_depth (c_path))
1997 gint *v_indices, *c_indices;
1998 gboolean common_prefix = TRUE;
2000 level = gtk_tree_path_get_depth (c_path) - 1;
2001 v_indices = gtk_tree_path_get_indices (filter->priv->virtual_root);
2002 c_indices = gtk_tree_path_get_indices (c_path);
2004 for (i = 0; i < level; i++)
2005 if (v_indices[i] != c_indices[i])
2007 common_prefix = FALSE;
2011 if (common_prefix && v_indices[level] >= c_indices[level])
2012 (v_indices[level])++;
2016 /* subtract virtual root if necessary */
2017 if (filter->priv->virtual_root)
2019 real_path = gtk_tree_model_filter_remove_root (c_path,
2020 filter->priv->virtual_root);
2026 real_path = gtk_tree_path_copy (c_path);
2028 if (!filter->priv->root)
2030 /* The root level has not been exposed to the view yet, so we
2031 * need to emit signals for any node that is being inserted.
2033 gtk_tree_model_filter_build_level (filter, NULL, NULL, TRUE);
2035 /* Check if the root level was built. Then child levels
2036 * that matter have also been built (due to update_children,
2037 * which triggers iter_n_children).
2039 if (filter->priv->root)
2041 emit_row_inserted = FALSE;
2046 if (gtk_tree_path_get_depth (real_path) - 1 >= 1)
2048 gboolean found = FALSE;
2049 GtkTreePath *parent = gtk_tree_path_copy (real_path);
2050 gtk_tree_path_up (parent);
2052 found = find_elt_with_offset (filter, parent, &parent_level, &elt);
2054 gtk_tree_path_free (parent);
2057 /* Parent is not in the cache and probably being filtered out */
2060 level = elt->children;
2063 level = FILTER_LEVEL (filter->priv->root);
2067 if (elt && elt->visible_siter)
2069 /* The level in which the new node should be inserted does not
2070 * exist, but the parent, elt, does. If elt is visible, emit
2071 * row-has-child-toggled.
2073 GtkTreePath *tmppath;
2074 GtkTreeIter tmpiter;
2076 tmpiter.stamp = filter->priv->stamp;
2077 tmpiter.user_data = parent_level;
2078 tmpiter.user_data2 = elt;
2080 tmppath = gtk_tree_model_get_path (GTK_TREE_MODEL (filter),
2085 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (filter),
2087 gtk_tree_path_free (tmppath);
2093 /* let's try to insert the value */
2094 offset = gtk_tree_path_get_indices (real_path)[gtk_tree_path_get_depth (real_path) - 1];
2096 /* update the offsets, yes if we didn't insert the node above, there will
2097 * be a gap here. This will be filled with the node (via fetch_child) when
2098 * it becomes visible
2100 dummy.offset = offset;
2101 siter = g_sequence_search (level->seq, &dummy, filter_elt_cmp, NULL);
2102 siter = g_sequence_iter_prev (siter);
2103 g_sequence_foreach_range (siter, g_sequence_get_end_iter (level->seq),
2104 increase_offset_iter, GINT_TO_POINTER (offset));
2106 /* only insert when visible */
2107 if (gtk_tree_model_filter_visible (filter, &real_c_iter))
2111 felt = gtk_tree_model_filter_insert_elt_in_level (filter,
2116 /* insert_elt_in_level defaults to FALSE */
2117 felt->visible_siter = g_sequence_insert_sorted (level->visible_seq,
2119 filter_elt_cmp, NULL);
2120 emit_row_inserted = TRUE;
2124 gtk_tree_model_filter_check_ancestors (filter, real_path);
2126 if (emit_row_inserted)
2127 gtk_tree_model_filter_emit_row_inserted_for_path (filter, c_model,
2131 gtk_tree_path_free (real_path);
2134 gtk_tree_path_free (c_path);
2138 gtk_tree_model_filter_row_has_child_toggled (GtkTreeModel *c_model,
2139 GtkTreePath *c_path,
2140 GtkTreeIter *c_iter,
2143 GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (data);
2148 gboolean requested_state;
2150 g_return_if_fail (c_path != NULL && c_iter != NULL);
2152 /* If we get row-has-child-toggled on the virtual root, and there is
2153 * no root level; try to build it now.
2155 if (filter->priv->virtual_root && !filter->priv->root
2156 && !gtk_tree_path_compare (c_path, filter->priv->virtual_root))
2158 gtk_tree_model_filter_build_level (filter, NULL, NULL, TRUE);
2162 /* For all other levels, there is a chance that the visibility state
2163 * of the parent has changed now.
2166 path = gtk_real_tree_model_filter_convert_child_path_to_path (filter,
2173 gtk_tree_model_filter_get_iter_full (GTK_TREE_MODEL (data), &iter, path);
2175 level = FILTER_LEVEL (iter.user_data);
2176 elt = FILTER_ELT (iter.user_data2);
2178 gtk_tree_path_free (path);
2180 requested_state = gtk_tree_model_filter_visible (filter, c_iter);
2182 if (!elt->visible_siter && !requested_state)
2184 /* The parent node currently is not visible and will not become
2185 * visible, so we will not pass on the row-has-child-toggled event.
2189 else if (elt->visible_siter && !requested_state)
2191 /* The node is no longer visible, so it has to be removed.
2192 * _remove_elt_from_level() takes care of emitting row-has-child-toggled
2195 gtk_tree_model_filter_remove_elt_from_level (filter, level, elt);
2199 else if (!elt->visible_siter && requested_state)
2201 elt->visible_siter = g_sequence_insert_sorted (level->visible_seq,
2202 elt, filter_elt_cmp,
2205 /* Only insert if the parent is visible in the target */
2206 if (gtk_tree_model_filter_elt_is_visible_in_target (level, elt))
2208 path = gtk_tree_model_get_path (GTK_TREE_MODEL (filter), &iter);
2209 gtk_tree_model_row_inserted (GTK_TREE_MODEL (filter), path, &iter);
2210 gtk_tree_path_free (path);
2212 /* We do not update children now, because that will happen
2217 /* For the remaining possibility, elt->visible && requested_state
2218 * no action is required.
2221 /* If this node is referenced and has children, build the level so we
2222 * can monitor it for changes.
2224 if (elt->ref_count > 1 && !elt->children &&
2225 gtk_tree_model_iter_has_child (c_model, c_iter))
2226 gtk_tree_model_filter_build_level (filter, level, elt, FALSE);
2228 /* get a path taking only visible nodes into account */
2229 path = gtk_tree_model_get_path (GTK_TREE_MODEL (data), &iter);
2230 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (data), path, &iter);
2231 gtk_tree_path_free (path);
2235 gtk_tree_model_filter_virtual_root_deleted (GtkTreeModelFilter *filter,
2236 GtkTreePath *c_path)
2240 FilterLevel *level = FILTER_LEVEL (filter->priv->root);
2242 /* The virtual root (or one of its ancestors) has been deleted. This
2243 * means that all content for our model is now gone. We deal with
2244 * this by removing everything in the filter model: we just iterate
2245 * over the root level and emit a row-deleted for each FilterElt.
2246 * (FIXME: Should we emit row-deleted for child nodes as well? This
2247 * has never been fully clear in TreeModel).
2250 /* We unref the path of the virtual root, up to and not including the
2251 * deleted node which can no longer be unreffed.
2253 gtk_tree_model_filter_unref_path (filter, filter->priv->virtual_root,
2254 gtk_tree_path_get_depth (c_path) - 1);
2255 filter->priv->virtual_root_deleted = TRUE;
2260 nodes = g_sequence_get_length (level->visible_seq);
2262 /* We should not propagate the unref here. An unref for any of these
2263 * nodes will fail, since the respective nodes in the child model are
2266 gtk_tree_model_filter_free_level (filter, filter->priv->root, FALSE);
2268 gtk_tree_model_filter_increment_stamp (filter);
2270 path = gtk_tree_path_new ();
2271 gtk_tree_path_append_index (path, 0);
2273 for (i = 0; i < nodes; i++)
2274 gtk_tree_model_row_deleted (GTK_TREE_MODEL (filter), path);
2276 gtk_tree_path_free (path);
2280 gtk_tree_model_filter_adjust_virtual_root (GtkTreeModelFilter *filter,
2281 GtkTreePath *c_path)
2285 gint *v_indices, *c_indices;
2286 gboolean common_prefix = TRUE;
2288 level = gtk_tree_path_get_depth (c_path) - 1;
2289 v_indices = gtk_tree_path_get_indices (filter->priv->virtual_root);
2290 c_indices = gtk_tree_path_get_indices (c_path);
2292 for (i = 0; i < level; i++)
2293 if (v_indices[i] != c_indices[i])
2295 common_prefix = FALSE;
2299 if (common_prefix && v_indices[level] > c_indices[level])
2300 (v_indices[level])--;
2304 gtk_tree_model_filter_row_deleted_invisible_node (GtkTreeModelFilter *filter,
2305 GtkTreePath *c_path)
2308 GtkTreePath *real_path;
2312 GSequenceIter *siter;
2314 /* The node deleted in the child model is not visible in the
2315 * filter model. We will not emit a signal, just fixup the offsets
2316 * of the other nodes.
2319 if (!filter->priv->root)
2322 level = FILTER_LEVEL (filter->priv->root);
2324 /* subtract vroot if necessary */
2325 if (filter->priv->virtual_root)
2327 real_path = gtk_tree_model_filter_remove_root (c_path,
2328 filter->priv->virtual_root);
2329 /* we don't handle this */
2334 real_path = gtk_tree_path_copy (c_path);
2336 if (gtk_tree_path_get_depth (real_path) - 1 >= 1)
2338 gboolean found = FALSE;
2339 GtkTreePath *parent = gtk_tree_path_copy (real_path);
2340 gtk_tree_path_up (parent);
2342 found = find_elt_with_offset (filter, parent, &level, &elt);
2344 gtk_tree_path_free (parent);
2348 /* parent is filtered out, so no level */
2349 gtk_tree_path_free (real_path);
2353 level = elt->children;
2356 offset = gtk_tree_path_get_indices (real_path)[gtk_tree_path_get_depth (real_path) - 1];
2357 gtk_tree_path_free (real_path);
2362 /* decrease offset of all nodes following the deleted node */
2363 dummy.offset = offset;
2364 siter = g_sequence_search (level->seq, &dummy, filter_elt_cmp, NULL);
2365 g_sequence_foreach_range (siter, g_sequence_get_end_iter (level->seq),
2366 decrease_offset_iter, GINT_TO_POINTER (offset));
2370 gtk_tree_model_filter_row_deleted (GtkTreeModel *c_model,
2371 GtkTreePath *c_path,
2374 GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (data);
2377 FilterElt *elt, *parent_elt = NULL;
2378 FilterLevel *level, *parent_level = NULL;
2379 GSequenceIter *siter;
2380 gboolean emit_child_toggled = FALSE;
2381 gboolean emit_row_deleted = FALSE;
2383 gint orig_level_ext_ref_count;
2385 g_return_if_fail (c_path != NULL);
2387 /* special case the deletion of an ancestor of the virtual root */
2388 if (filter->priv->virtual_root &&
2389 (gtk_tree_path_is_ancestor (c_path, filter->priv->virtual_root) ||
2390 !gtk_tree_path_compare (c_path, filter->priv->virtual_root)))
2392 gtk_tree_model_filter_virtual_root_deleted (filter, c_path);
2396 /* adjust the virtual root for the deleted row */
2397 if (filter->priv->virtual_root &&
2398 gtk_tree_path_get_depth (filter->priv->virtual_root) >=
2399 gtk_tree_path_get_depth (c_path))
2400 gtk_tree_model_filter_adjust_virtual_root (filter, c_path);
2402 path = gtk_real_tree_model_filter_convert_child_path_to_path (filter,
2409 gtk_tree_model_filter_row_deleted_invisible_node (filter, c_path);
2413 /* a node was deleted, which was in our cache */
2414 gtk_tree_model_filter_get_iter_full (GTK_TREE_MODEL (data), &iter, path);
2416 level = FILTER_LEVEL (iter.user_data);
2417 elt = FILTER_ELT (iter.user_data2);
2418 offset = elt->offset;
2419 orig_level_ext_ref_count = level->ext_ref_count;
2421 if (elt->visible_siter)
2423 /* get a path taking only visible nodes into account */
2424 gtk_tree_path_free (path);
2425 path = gtk_tree_model_get_path (GTK_TREE_MODEL (filter), &iter);
2427 if (g_sequence_get_length (level->visible_seq) == 1)
2429 emit_child_toggled = TRUE;
2430 parent_level = level->parent_level;
2431 parent_elt = level->parent_elt;
2434 emit_row_deleted = TRUE;
2437 /* Release the references on this node, without propagation because
2438 * the node does not exist anymore in the child model. The filter
2439 * model's references on the node in case of level->parent or use
2440 * of a virtual root are automatically destroyed by the child model.
2442 while (elt->ext_ref_count > 0)
2443 gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (data), &iter,
2445 while (elt->ref_count > 0)
2446 gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (data), &iter,
2449 if (g_sequence_get_length (level->seq) == 1)
2452 gtk_tree_model_filter_free_level (filter, level, FALSE);
2459 lookup_elt_with_offset (level->seq, elt->offset, &siter);
2460 is_first = g_sequence_get_begin_iter (level->seq) == siter;
2462 /* remove the row */
2463 g_sequence_remove (elt->visible_siter);
2464 tmp = g_sequence_iter_next (siter);
2465 g_sequence_remove (siter);
2466 g_sequence_foreach_range (tmp, g_sequence_get_end_iter (level->seq),
2467 decrease_offset_iter, GINT_TO_POINTER (offset));
2469 /* Take a reference on the new first node. The first node previously
2470 * keeping this reference has been removed above.
2476 f_iter.stamp = filter->priv->stamp;
2477 f_iter.user_data = level;
2478 f_iter.user_data2 = g_sequence_get (g_sequence_get_begin_iter (level->seq));
2480 gtk_tree_model_filter_real_ref_node (GTK_TREE_MODEL (filter),
2485 if (emit_row_deleted)
2487 /* emit row_deleted */
2488 gtk_tree_model_filter_increment_stamp (filter);
2490 if (!parent_elt || orig_level_ext_ref_count > 0)
2491 gtk_tree_model_row_deleted (GTK_TREE_MODEL (data), path);
2494 if (emit_child_toggled && parent_level)
2499 iter2.stamp = filter->priv->stamp;
2500 iter2.user_data = parent_level;
2501 iter2.user_data2 = parent_elt;
2503 /* We set in_row_deleted to TRUE to avoid a level build triggered
2504 * by row-has-child-toggled (parent model could call iter_has_child
2507 filter->priv->in_row_deleted = TRUE;
2508 path2 = gtk_tree_model_get_path (GTK_TREE_MODEL (filter), &iter2);
2509 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (filter),
2511 gtk_tree_path_free (path2);
2512 filter->priv->in_row_deleted = FALSE;
2515 if (filter->priv->virtual_root)
2517 GtkTreePath *real_path;
2519 real_path = gtk_tree_model_filter_remove_root (c_path,
2520 filter->priv->root);
2523 gtk_tree_model_filter_check_ancestors (filter, real_path);
2524 gtk_tree_path_free (real_path);
2528 gtk_tree_model_filter_check_ancestors (filter, c_path);
2530 gtk_tree_path_free (path);
2534 gtk_tree_model_filter_rows_reordered (GtkTreeModel *c_model,
2535 GtkTreePath *c_path,
2536 GtkTreeIter *c_iter,
2542 GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (data);
2548 GSequenceIter *tmp_end_iter;
2549 GSequenceIter *old_first_elt = NULL;
2554 g_return_if_fail (new_order != NULL);
2556 if (c_path == NULL || gtk_tree_path_get_depth (c_path) == 0)
2558 length = gtk_tree_model_iter_n_children (c_model, NULL);
2560 if (filter->priv->virtual_root)
2564 /* reorder root level of path */
2565 for (i = 0; i < length; i++)
2566 if (new_order[i] == gtk_tree_path_get_indices (filter->priv->virtual_root)[0])
2572 gtk_tree_path_get_indices (filter->priv->virtual_root)[0] = new_pos;
2576 path = gtk_tree_path_new ();
2577 level = FILTER_LEVEL (filter->priv->root);
2581 GtkTreeIter child_iter;
2583 /* virtual root anchor reordering */
2584 if (filter->priv->virtual_root &&
2585 gtk_tree_path_is_ancestor (c_path, filter->priv->virtual_root))
2590 GtkTreeIter real_c_iter;
2592 level = gtk_tree_path_get_depth (c_path);
2595 real_c_iter = *c_iter;
2597 gtk_tree_model_get_iter (c_model, &real_c_iter, c_path);
2599 length = gtk_tree_model_iter_n_children (c_model, &real_c_iter);
2601 for (i = 0; i < length; i++)
2602 if (new_order[i] == gtk_tree_path_get_indices (filter->priv->virtual_root)[level])
2608 gtk_tree_path_get_indices (filter->priv->virtual_root)[level] = new_pos;
2612 path = gtk_real_tree_model_filter_convert_child_path_to_path (filter,
2617 if (!path && filter->priv->virtual_root &&
2618 gtk_tree_path_compare (c_path, filter->priv->virtual_root))
2621 if (!path && !filter->priv->virtual_root)
2626 /* root level mode */
2628 gtk_tree_model_get_iter (c_model, c_iter, c_path);
2629 length = gtk_tree_model_iter_n_children (c_model, c_iter);
2630 path = gtk_tree_path_new ();
2631 level = FILTER_LEVEL (filter->priv->root);
2635 gtk_tree_model_filter_get_iter_full (GTK_TREE_MODEL (data),
2638 level = FILTER_LEVEL (iter.user_data);
2639 elt = FILTER_ELT (iter.user_data2);
2643 gtk_tree_path_free (path);
2647 level = elt->children;
2649 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (filter), &child_iter, &iter);
2650 length = gtk_tree_model_iter_n_children (c_model, &child_iter);
2654 if (!level || g_sequence_get_length (level->seq) < 1)
2656 gtk_tree_path_free (path);
2660 /* NOTE: we do not bail out here if level->seq->len < 2 like
2661 * GtkTreeModelSort does. This because we do some special tricky
2665 tmp_seq = g_sequence_new (filter_elt_free);
2666 tmp_end_iter = g_sequence_get_end_iter (tmp_seq);
2667 tmp_array = g_new (gint, g_sequence_get_length (level->visible_seq));
2670 for (i = 0; i < length; i++)
2673 GSequenceIter *siter;
2675 elt = lookup_elt_with_offset (level->seq, new_order[i], &siter);
2679 /* Keep a reference if this elt has old_pos == 0 */
2680 if (new_order[i] == 0)
2681 old_first_elt = siter;
2683 /* Only for visible items an entry should be present in the order array
2686 if (elt->visible_siter)
2687 tmp_array[elt_count++] = g_sequence_iter_get_position (elt->visible_siter);
2689 /* Steal elt from level->seq and append it to tmp_seq */
2690 g_sequence_move (siter, tmp_end_iter);
2694 g_warn_if_fail (g_sequence_get_length (level->seq) == 0);
2695 g_sequence_free (level->seq);
2696 level->seq = tmp_seq;
2697 g_sequence_sort (level->visible_seq, filter_elt_cmp, NULL);
2699 /* Transfer the reference from the old item at position 0 to the
2700 * new item at position 0.
2702 if (old_first_elt && g_sequence_iter_get_position (old_first_elt))
2703 gtk_tree_model_filter_level_transfer_first_ref (filter,
2706 g_sequence_get_iter_at_pos (level->seq, 0));
2709 /* emit rows_reordered */
2710 if (g_sequence_get_length (level->visible_seq) > 0)
2712 if (!gtk_tree_path_get_indices (path))
2713 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (data), path, NULL,
2717 /* get a path taking only visible nodes into account */
2718 gtk_tree_path_free (path);
2719 path = gtk_tree_model_get_path (GTK_TREE_MODEL (data), &iter);
2721 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (data), path, &iter,
2728 gtk_tree_path_free (path);
2731 /* TreeModelIface implementation */
2732 static GtkTreeModelFlags
2733 gtk_tree_model_filter_get_flags (GtkTreeModel *model)
2735 GtkTreeModelFlags flags;
2737 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), 0);
2738 g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL, 0);
2740 flags = gtk_tree_model_get_flags (GTK_TREE_MODEL_FILTER (model)->priv->child_model);
2742 if ((flags & GTK_TREE_MODEL_LIST_ONLY) == GTK_TREE_MODEL_LIST_ONLY)
2743 return GTK_TREE_MODEL_LIST_ONLY;
2749 gtk_tree_model_filter_get_n_columns (GtkTreeModel *model)
2751 GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
2753 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), 0);
2754 g_return_val_if_fail (filter->priv->child_model != NULL, 0);
2756 if (filter->priv->child_model == NULL)
2759 /* so we can't modify the modify func after this ... */
2760 filter->priv->modify_func_set = TRUE;
2762 if (filter->priv->modify_n_columns > 0)
2763 return filter->priv->modify_n_columns;
2765 return gtk_tree_model_get_n_columns (filter->priv->child_model);
2769 gtk_tree_model_filter_get_column_type (GtkTreeModel *model,
2772 GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
2774 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), G_TYPE_INVALID);
2775 g_return_val_if_fail (filter->priv->child_model != NULL, G_TYPE_INVALID);
2777 /* so we can't modify the modify func after this ... */
2778 filter->priv->modify_func_set = TRUE;
2780 if (filter->priv->modify_types)
2782 g_return_val_if_fail (index < filter->priv->modify_n_columns, G_TYPE_INVALID);
2784 return filter->priv->modify_types[index];
2787 return gtk_tree_model_get_column_type (filter->priv->child_model, index);
2790 /* A special case of _get_iter; this function can also get iters which
2791 * are not visible. These iters should ONLY be passed internally, never
2792 * pass those along with a signal emission.
2795 gtk_tree_model_filter_get_iter_full (GtkTreeModel *model,
2799 GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
2804 GSequenceIter *siter;
2806 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
2807 g_return_val_if_fail (filter->priv->child_model != NULL, FALSE);
2809 indices = gtk_tree_path_get_indices (path);
2811 if (filter->priv->root == NULL)
2812 gtk_tree_model_filter_build_level (filter, NULL, NULL, FALSE);
2813 level = FILTER_LEVEL (filter->priv->root);
2815 depth = gtk_tree_path_get_depth (path);
2822 for (i = 0; i < depth - 1; i++)
2824 if (!level || indices[i] >= g_sequence_get_length (level->seq))
2830 siter = g_sequence_get_iter_at_pos (level->seq, indices[i]);
2831 if (g_sequence_iter_is_end (siter))
2837 elt = GET_ELT (siter);
2840 gtk_tree_model_filter_build_level (filter, level, elt, FALSE);
2841 level = elt->children;
2844 if (!level || indices[i] >= g_sequence_get_length (level->seq))
2850 iter->stamp = filter->priv->stamp;
2851 iter->user_data = level;
2853 siter = g_sequence_get_iter_at_pos (level->seq, indices[depth - 1]);
2854 if (g_sequence_iter_is_end (siter))
2859 iter->user_data2 = GET_ELT (siter);
2865 gtk_tree_model_filter_get_iter (GtkTreeModel *model,
2869 GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
2873 GSequenceIter *siter;
2876 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
2877 g_return_val_if_fail (filter->priv->child_model != NULL, FALSE);
2879 indices = gtk_tree_path_get_indices (path);
2881 if (filter->priv->root == NULL)
2882 gtk_tree_model_filter_build_level (filter, NULL, NULL, FALSE);
2883 level = FILTER_LEVEL (filter->priv->root);
2885 depth = gtk_tree_path_get_depth (path);
2892 for (i = 0; i < depth - 1; i++)
2894 if (!level || indices[i] >= g_sequence_get_length (level->visible_seq))
2900 siter = g_sequence_get_iter_at_pos (level->visible_seq, indices[i]);
2901 if (g_sequence_iter_is_end (siter))
2907 elt = GET_ELT (siter);
2909 gtk_tree_model_filter_build_level (filter, level, elt, FALSE);
2910 level = elt->children;
2913 if (!level || indices[i] >= g_sequence_get_length (level->visible_seq))
2919 iter->stamp = filter->priv->stamp;
2920 iter->user_data = level;
2922 siter = g_sequence_get_iter_at_pos (level->visible_seq, indices[depth - 1]);
2923 if (g_sequence_iter_is_end (siter))
2928 iter->user_data2 = GET_ELT (siter);
2933 static GtkTreePath *
2934 gtk_tree_model_filter_get_path (GtkTreeModel *model,
2937 GtkTreePath *retval;
2941 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), NULL);
2942 g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL, NULL);
2943 g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->stamp == iter->stamp, NULL);
2945 level = iter->user_data;
2946 elt = iter->user_data2;
2948 if (!elt->visible_siter)
2951 retval = gtk_tree_path_new ();
2957 index = g_sequence_iter_get_position (elt->visible_siter);
2958 gtk_tree_path_prepend_index (retval, index);
2960 elt = level->parent_elt;
2961 level = level->parent_level;
2968 gtk_tree_model_filter_real_modify (GtkTreeModelFilter *self,
2969 GtkTreeModel *child_model,
2974 if (self->priv->modify_func)
2976 g_return_if_fail (column < self->priv->modify_n_columns);
2978 g_value_init (value, self->priv->modify_types[column]);
2979 self->priv->modify_func (GTK_TREE_MODEL (self),
2983 self->priv->modify_data);
2987 GtkTreeIter child_iter;
2989 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (self),
2991 gtk_tree_model_get_value (child_model, &child_iter, column, value);
2996 gtk_tree_model_filter_get_value (GtkTreeModel *model,
3001 GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (model);
3003 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (model));
3004 g_return_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL);
3005 g_return_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->stamp == iter->stamp);
3007 GTK_TREE_MODEL_FILTER_GET_CLASS (model)->modify (filter,
3008 filter->priv->child_model, iter, value, column);
3012 gtk_tree_model_filter_iter_next (GtkTreeModel *model,
3017 GSequenceIter *siter;
3019 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
3020 g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL, FALSE);
3021 g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->stamp == iter->stamp, FALSE);
3023 level = iter->user_data;
3024 elt = iter->user_data2;
3026 siter = g_sequence_iter_next (elt->visible_siter);
3027 if (g_sequence_iter_is_end (siter))
3033 iter->user_data2 = GET_ELT (siter);
3039 gtk_tree_model_filter_iter_previous (GtkTreeModel *model,
3044 GSequenceIter *siter;
3046 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
3047 g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL, FALSE);
3048 g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->stamp == iter->stamp, FALSE);
3050 level = iter->user_data;
3051 elt = iter->user_data2;
3053 siter = g_sequence_iter_prev (elt->visible_siter);
3054 if (g_sequence_iter_is_begin (siter))
3060 iter->user_data2 = GET_ELT (siter);
3066 gtk_tree_model_filter_iter_children (GtkTreeModel *model,
3068 GtkTreeIter *parent)
3070 GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
3072 GSequenceIter *siter;
3075 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
3076 g_return_val_if_fail (filter->priv->child_model != NULL, FALSE);
3078 g_return_val_if_fail (filter->priv->stamp == parent->stamp, FALSE);
3082 if (!filter->priv->root)
3083 gtk_tree_model_filter_build_level (filter, NULL, NULL, FALSE);
3084 if (!filter->priv->root)
3087 level = filter->priv->root;
3088 siter = g_sequence_get_begin_iter (level->visible_seq);
3089 if (g_sequence_iter_is_end (siter))
3095 iter->stamp = filter->priv->stamp;
3096 iter->user_data = level;
3097 iter->user_data2 = GET_ELT (siter);
3103 if (FILTER_ELT (parent->user_data2)->children == NULL)
3104 gtk_tree_model_filter_build_level (filter,
3105 FILTER_LEVEL (parent->user_data),
3106 FILTER_ELT (parent->user_data2),
3108 if (FILTER_ELT (parent->user_data2)->children == NULL)
3111 level = FILTER_ELT (parent->user_data2)->children;
3112 siter = g_sequence_get_begin_iter (level->visible_seq);
3113 if (g_sequence_iter_is_end (siter))
3119 iter->stamp = filter->priv->stamp;
3120 iter->user_data = level;
3121 iter->user_data2 = GET_ELT (siter);
3131 gtk_tree_model_filter_iter_has_child (GtkTreeModel *model,
3134 GtkTreeIter child_iter;
3135 GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
3138 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
3139 g_return_val_if_fail (filter->priv->child_model != NULL, FALSE);
3140 g_return_val_if_fail (filter->priv->stamp == iter->stamp, FALSE);
3142 filter = GTK_TREE_MODEL_FILTER (model);
3144 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_iter, iter);
3145 elt = FILTER_ELT (iter->user_data2);
3147 if (!elt->visible_siter)
3150 /* we need to build the level to check if not all children are filtered
3154 && gtk_tree_model_iter_has_child (filter->priv->child_model, &child_iter))
3155 gtk_tree_model_filter_build_level (filter, FILTER_LEVEL (iter->user_data),
3158 if (elt->children && g_sequence_get_length (elt->children->visible_seq) > 0)
3165 gtk_tree_model_filter_iter_n_children (GtkTreeModel *model,
3168 GtkTreeIter child_iter;
3169 GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
3172 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), 0);
3173 g_return_val_if_fail (filter->priv->child_model != NULL, 0);
3175 g_return_val_if_fail (filter->priv->stamp == iter->stamp, 0);
3179 if (!filter->priv->root)
3180 gtk_tree_model_filter_build_level (filter, NULL, NULL, FALSE);
3182 if (filter->priv->root)
3183 return g_sequence_get_length (FILTER_LEVEL (filter->priv->root)->visible_seq);
3188 elt = FILTER_ELT (iter->user_data2);
3190 if (!elt->visible_siter)
3193 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_iter, iter);
3195 if (!elt->children &&
3196 gtk_tree_model_iter_has_child (filter->priv->child_model, &child_iter))
3197 gtk_tree_model_filter_build_level (filter,
3198 FILTER_LEVEL (iter->user_data),
3202 return g_sequence_get_length (elt->children->visible_seq);
3208 gtk_tree_model_filter_iter_nth_child (GtkTreeModel *model,
3210 GtkTreeIter *parent,
3214 GtkTreeIter children;
3215 GSequenceIter *siter;
3217 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
3219 g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->stamp == parent->stamp, FALSE);
3221 /* use this instead of has_child to force us to build the level, if needed */
3222 if (gtk_tree_model_filter_iter_children (model, &children, parent) == FALSE)
3228 level = children.user_data;
3229 siter = g_sequence_get_iter_at_pos (level->visible_seq, n);
3230 if (g_sequence_iter_is_end (siter))
3233 iter->stamp = GTK_TREE_MODEL_FILTER (model)->priv->stamp;
3234 iter->user_data = level;
3235 iter->user_data2 = GET_ELT (siter);
3241 gtk_tree_model_filter_iter_parent (GtkTreeModel *model,
3248 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
3249 g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL, FALSE);
3250 g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->stamp == child->stamp, FALSE);
3252 level = child->user_data;
3254 if (level->parent_level)
3256 iter->stamp = GTK_TREE_MODEL_FILTER (model)->priv->stamp;
3257 iter->user_data = level->parent_level;
3258 iter->user_data2 = level->parent_elt;
3267 gtk_tree_model_filter_ref_node (GtkTreeModel *model,
3270 gtk_tree_model_filter_real_ref_node (model, iter, TRUE);
3274 gtk_tree_model_filter_real_ref_node (GtkTreeModel *model,
3278 GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
3279 GtkTreeIter child_iter;
3283 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (model));
3284 g_return_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL);
3285 g_return_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->stamp == iter->stamp);
3287 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_iter, iter);
3289 gtk_tree_model_ref_node (filter->priv->child_model, &child_iter);
3291 level = iter->user_data;
3292 elt = iter->user_data2;
3299 elt->ext_ref_count++;
3300 level->ext_ref_count++;
3302 if (level->ext_ref_count == 1)
3304 FilterLevel *parent_level = level->parent_level;
3305 FilterElt *parent_elt = level->parent_elt;
3307 /* we were at zero -- time to decrease the zero_ref_count val */
3308 while (parent_level)
3310 parent_elt->zero_ref_count--;
3312 parent_elt = parent_level->parent_elt;
3313 parent_level = parent_level->parent_level;
3316 if (filter->priv->root != level)
3317 filter->priv->zero_ref_count--;
3323 gtk_tree_model_filter_unref_node (GtkTreeModel *model,
3326 gtk_tree_model_filter_real_unref_node (model, iter, TRUE, TRUE);
3330 gtk_tree_model_filter_real_unref_node (GtkTreeModel *model,
3333 gboolean propagate_unref)
3335 GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
3339 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (model));
3340 g_return_if_fail (filter->priv->child_model != NULL);
3341 g_return_if_fail (filter->priv->stamp == iter->stamp);
3343 if (propagate_unref)
3345 GtkTreeIter child_iter;
3346 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_iter, iter);
3347 gtk_tree_model_unref_node (filter->priv->child_model, &child_iter);
3350 level = iter->user_data;
3351 elt = iter->user_data2;
3353 g_return_if_fail (elt->ref_count > 0);
3360 elt->ext_ref_count--;
3361 level->ext_ref_count--;
3363 if (level->ext_ref_count == 0)
3365 FilterLevel *parent_level = level->parent_level;
3366 FilterElt *parent_elt = level->parent_elt;
3368 /* we are at zero -- time to increase the zero_ref_count val */
3369 while (parent_level)
3371 parent_elt->zero_ref_count++;
3373 parent_elt = parent_level->parent_elt;
3374 parent_level = parent_level->parent_level;
3377 if (filter->priv->root != level)
3378 filter->priv->zero_ref_count++;
3383 /* TreeDragSource interface implementation */
3385 gtk_tree_model_filter_row_draggable (GtkTreeDragSource *drag_source,
3388 GtkTreeModelFilter *tree_model_filter = (GtkTreeModelFilter *)drag_source;
3389 GtkTreePath *child_path;
3392 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (drag_source), FALSE);
3393 g_return_val_if_fail (path != NULL, FALSE);
3395 child_path = gtk_tree_model_filter_convert_path_to_child_path (tree_model_filter, path);
3396 draggable = gtk_tree_drag_source_row_draggable (GTK_TREE_DRAG_SOURCE (tree_model_filter->priv->child_model), child_path);
3397 gtk_tree_path_free (child_path);
3403 gtk_tree_model_filter_drag_data_get (GtkTreeDragSource *drag_source,
3405 GtkSelectionData *selection_data)
3407 GtkTreeModelFilter *tree_model_filter = (GtkTreeModelFilter *)drag_source;
3408 GtkTreePath *child_path;
3411 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (drag_source), FALSE);
3412 g_return_val_if_fail (path != NULL, FALSE);
3414 child_path = gtk_tree_model_filter_convert_path_to_child_path (tree_model_filter, path);
3415 gotten = gtk_tree_drag_source_drag_data_get (GTK_TREE_DRAG_SOURCE (tree_model_filter->priv->child_model), child_path, selection_data);
3416 gtk_tree_path_free (child_path);
3422 gtk_tree_model_filter_drag_data_delete (GtkTreeDragSource *drag_source,
3425 GtkTreeModelFilter *tree_model_filter = (GtkTreeModelFilter *)drag_source;
3426 GtkTreePath *child_path;
3429 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (drag_source), FALSE);
3430 g_return_val_if_fail (path != NULL, FALSE);
3432 child_path = gtk_tree_model_filter_convert_path_to_child_path (tree_model_filter, path);
3433 deleted = gtk_tree_drag_source_drag_data_delete (GTK_TREE_DRAG_SOURCE (tree_model_filter->priv->child_model), child_path);
3434 gtk_tree_path_free (child_path);
3439 /* bits and pieces */
3441 gtk_tree_model_filter_set_model (GtkTreeModelFilter *filter,
3442 GtkTreeModel *child_model)
3444 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
3446 if (filter->priv->child_model)
3448 g_signal_handler_disconnect (filter->priv->child_model,
3449 filter->priv->changed_id);
3450 g_signal_handler_disconnect (filter->priv->child_model,
3451 filter->priv->inserted_id);
3452 g_signal_handler_disconnect (filter->priv->child_model,
3453 filter->priv->has_child_toggled_id);
3454 g_signal_handler_disconnect (filter->priv->child_model,
3455 filter->priv->deleted_id);
3456 g_signal_handler_disconnect (filter->priv->child_model,
3457 filter->priv->reordered_id);
3459 /* reset our state */
3460 if (filter->priv->root)
3461 gtk_tree_model_filter_free_level (filter, filter->priv->root, TRUE);
3463 filter->priv->root = NULL;
3464 g_object_unref (filter->priv->child_model);
3465 filter->priv->visible_column = -1;
3467 /* FIXME: do we need to destroy more here? */
3470 filter->priv->child_model = child_model;
3474 g_object_ref (filter->priv->child_model);
3475 filter->priv->changed_id =
3476 g_signal_connect (child_model, "row-changed",
3477 G_CALLBACK (gtk_tree_model_filter_row_changed),
3479 filter->priv->inserted_id =
3480 g_signal_connect (child_model, "row-inserted",
3481 G_CALLBACK (gtk_tree_model_filter_row_inserted),
3483 filter->priv->has_child_toggled_id =
3484 g_signal_connect (child_model, "row-has-child-toggled",
3485 G_CALLBACK (gtk_tree_model_filter_row_has_child_toggled),
3487 filter->priv->deleted_id =
3488 g_signal_connect (child_model, "row-deleted",
3489 G_CALLBACK (gtk_tree_model_filter_row_deleted),
3491 filter->priv->reordered_id =
3492 g_signal_connect (child_model, "rows-reordered",
3493 G_CALLBACK (gtk_tree_model_filter_rows_reordered),
3496 filter->priv->child_flags = gtk_tree_model_get_flags (child_model);
3497 filter->priv->stamp = g_random_int ();
3502 gtk_tree_model_filter_ref_path (GtkTreeModelFilter *filter,
3508 len = gtk_tree_path_get_depth (path);
3509 p = gtk_tree_path_copy (path);
3514 gtk_tree_model_get_iter (GTK_TREE_MODEL (filter->priv->child_model), &iter, p);
3515 gtk_tree_model_ref_node (GTK_TREE_MODEL (filter->priv->child_model), &iter);
3516 gtk_tree_path_up (p);
3519 gtk_tree_path_free (p);
3523 gtk_tree_model_filter_unref_path (GtkTreeModelFilter *filter,
3533 len = gtk_tree_path_get_depth (path);
3535 p = gtk_tree_path_copy (path);
3540 gtk_tree_model_get_iter (GTK_TREE_MODEL (filter->priv->child_model), &iter, p);
3541 gtk_tree_model_unref_node (GTK_TREE_MODEL (filter->priv->child_model), &iter);
3542 gtk_tree_path_up (p);
3545 gtk_tree_path_free (p);
3549 gtk_tree_model_filter_set_root (GtkTreeModelFilter *filter,
3552 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
3555 filter->priv->virtual_root = NULL;
3557 filter->priv->virtual_root = gtk_tree_path_copy (root);
3563 * gtk_tree_model_filter_new:
3564 * @child_model: A #GtkTreeModel.
3565 * @root: (allow-none): A #GtkTreePath or %NULL.
3567 * Creates a new #GtkTreeModel, with @child_model as the child_model
3568 * and @root as the virtual root.
3570 * Return value: (transfer full): A new #GtkTreeModel.
3575 gtk_tree_model_filter_new (GtkTreeModel *child_model,
3578 GtkTreeModel *retval;
3579 GtkTreeModelFilter *filter;
3581 g_return_val_if_fail (GTK_IS_TREE_MODEL (child_model), NULL);
3583 retval = g_object_new (GTK_TYPE_TREE_MODEL_FILTER,
3584 "child-model", child_model,
3585 "virtual-root", root,
3588 filter = GTK_TREE_MODEL_FILTER (retval);
3589 if (filter->priv->virtual_root)
3591 gtk_tree_model_filter_ref_path (filter, filter->priv->virtual_root);
3592 filter->priv->virtual_root_deleted = FALSE;
3599 * gtk_tree_model_filter_get_model:
3600 * @filter: A #GtkTreeModelFilter.
3602 * Returns a pointer to the child model of @filter.
3604 * Return value: (transfer none): A pointer to a #GtkTreeModel.
3609 gtk_tree_model_filter_get_model (GtkTreeModelFilter *filter)
3611 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (filter), NULL);
3613 return filter->priv->child_model;
3617 * gtk_tree_model_filter_set_visible_func:
3618 * @filter: A #GtkTreeModelFilter.
3619 * @func: A #GtkTreeModelFilterVisibleFunc, the visible function.
3620 * @data: (allow-none): User data to pass to the visible function, or %NULL.
3621 * @destroy: (allow-none): Destroy notifier of @data, or %NULL.
3623 * Sets the visible function used when filtering the @filter to be @func. The
3624 * function should return %TRUE if the given row should be visible and
3627 * If the condition calculated by the function changes over time (e.g. because
3628 * it depends on some global parameters), you must call
3629 * gtk_tree_model_filter_refilter() to keep the visibility information of
3630 * the model uptodate.
3632 * Note that @func is called whenever a row is inserted, when it may still be
3633 * empty. The visible function should therefore take special care of empty
3634 * rows, like in the example below.
3636 * <informalexample><programlisting>
3638 * visible_func (GtkTreeModel *model,
3639 * GtkTreeIter *iter,
3642 * /* Visible if row is non-empty and first column is "HI" */
3644 * gboolean visible = FALSE;
3646 * gtk_tree_model_get (model, iter, 0, &str, -1);
3647 * if (str && strcmp (str, "HI") == 0)
3653 * </programlisting></informalexample>
3658 gtk_tree_model_filter_set_visible_func (GtkTreeModelFilter *filter,
3659 GtkTreeModelFilterVisibleFunc func,
3661 GDestroyNotify destroy)
3663 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
3664 g_return_if_fail (func != NULL);
3665 g_return_if_fail (filter->priv->visible_method_set == FALSE);
3667 filter->priv->visible_func = func;
3668 filter->priv->visible_data = data;
3669 filter->priv->visible_destroy = destroy;
3671 filter->priv->visible_method_set = TRUE;
3675 * gtk_tree_model_filter_set_modify_func:
3676 * @filter: A #GtkTreeModelFilter.
3677 * @n_columns: The number of columns in the filter model.
3678 * @types: (array length=n_columns): The #GType<!-- -->s of the columns.
3679 * @func: A #GtkTreeModelFilterModifyFunc
3680 * @data: (allow-none): User data to pass to the modify function, or %NULL.
3681 * @destroy: (allow-none): Destroy notifier of @data, or %NULL.
3683 * With the @n_columns and @types parameters, you give an array of column
3684 * types for this model (which will be exposed to the parent model/view).
3685 * The @func, @data and @destroy parameters are for specifying the modify
3686 * function. The modify function will get called for <emphasis>each</emphasis>
3687 * data access, the goal of the modify function is to return the data which
3688 * should be displayed at the location specified using the parameters of the
3694 gtk_tree_model_filter_set_modify_func (GtkTreeModelFilter *filter,
3697 GtkTreeModelFilterModifyFunc func,
3699 GDestroyNotify destroy)
3701 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
3702 g_return_if_fail (func != NULL);
3703 g_return_if_fail (filter->priv->modify_func_set == FALSE);
3705 if (filter->priv->modify_destroy)
3707 GDestroyNotify d = filter->priv->modify_destroy;
3709 filter->priv->modify_destroy = NULL;
3710 d (filter->priv->modify_data);
3713 filter->priv->modify_n_columns = n_columns;
3714 filter->priv->modify_types = g_new0 (GType, n_columns);
3715 memcpy (filter->priv->modify_types, types, sizeof (GType) * n_columns);
3716 filter->priv->modify_func = func;
3717 filter->priv->modify_data = data;
3718 filter->priv->modify_destroy = destroy;
3720 filter->priv->modify_func_set = TRUE;
3724 * gtk_tree_model_filter_set_visible_column:
3725 * @filter: A #GtkTreeModelFilter.
3726 * @column: A #gint which is the column containing the visible information.
3728 * Sets @column of the child_model to be the column where @filter should
3729 * look for visibility information. @columns should be a column of type
3730 * %G_TYPE_BOOLEAN, where %TRUE means that a row is visible, and %FALSE
3736 gtk_tree_model_filter_set_visible_column (GtkTreeModelFilter *filter,
3739 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
3740 g_return_if_fail (column >= 0);
3741 g_return_if_fail (filter->priv->visible_method_set == FALSE);
3743 filter->priv->visible_column = column;
3745 filter->priv->visible_method_set = TRUE;
3751 * gtk_tree_model_filter_convert_child_iter_to_iter:
3752 * @filter: A #GtkTreeModelFilter.
3753 * @filter_iter: (out): An uninitialized #GtkTreeIter.
3754 * @child_iter: A valid #GtkTreeIter pointing to a row on the child model.
3756 * Sets @filter_iter to point to the row in @filter that corresponds to the
3757 * row pointed at by @child_iter. If @filter_iter was not set, %FALSE is
3760 * Return value: %TRUE, if @filter_iter was set, i.e. if @child_iter is a
3761 * valid iterator pointing to a visible row in child model.
3766 gtk_tree_model_filter_convert_child_iter_to_iter (GtkTreeModelFilter *filter,
3767 GtkTreeIter *filter_iter,
3768 GtkTreeIter *child_iter)
3771 GtkTreePath *child_path, *path;
3773 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (filter), FALSE);
3774 g_return_val_if_fail (filter->priv->child_model != NULL, FALSE);
3775 g_return_val_if_fail (filter_iter != NULL, FALSE);
3776 g_return_val_if_fail (child_iter != NULL, FALSE);
3777 g_return_val_if_fail (filter_iter != child_iter, FALSE);
3779 filter_iter->stamp = 0;
3781 child_path = gtk_tree_model_get_path (filter->priv->child_model, child_iter);
3782 g_return_val_if_fail (child_path != NULL, FALSE);
3784 path = gtk_tree_model_filter_convert_child_path_to_path (filter,
3786 gtk_tree_path_free (child_path);
3791 ret = gtk_tree_model_get_iter (GTK_TREE_MODEL (filter), filter_iter, path);
3792 gtk_tree_path_free (path);
3798 * gtk_tree_model_filter_convert_iter_to_child_iter:
3799 * @filter: A #GtkTreeModelFilter.
3800 * @child_iter: (out): An uninitialized #GtkTreeIter.
3801 * @filter_iter: A valid #GtkTreeIter pointing to a row on @filter.
3803 * Sets @child_iter to point to the row pointed to by @filter_iter.
3808 gtk_tree_model_filter_convert_iter_to_child_iter (GtkTreeModelFilter *filter,
3809 GtkTreeIter *child_iter,
3810 GtkTreeIter *filter_iter)
3812 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
3813 g_return_if_fail (filter->priv->child_model != NULL);
3814 g_return_if_fail (child_iter != NULL);
3815 g_return_if_fail (filter_iter != NULL);
3816 g_return_if_fail (filter_iter->stamp == filter->priv->stamp);
3817 g_return_if_fail (filter_iter != child_iter);
3819 if (GTK_TREE_MODEL_FILTER_CACHE_CHILD_ITERS (filter))
3821 *child_iter = FILTER_ELT (filter_iter->user_data2)->iter;
3826 gboolean valid = FALSE;
3828 path = gtk_tree_model_filter_elt_get_path (filter_iter->user_data,
3829 filter_iter->user_data2,
3830 filter->priv->virtual_root);
3831 valid = gtk_tree_model_get_iter (filter->priv->child_model, child_iter,
3833 gtk_tree_path_free (path);
3835 g_return_if_fail (valid == TRUE);
3839 /* The path returned can only be used internally in the filter model. */
3840 static GtkTreePath *
3841 gtk_real_tree_model_filter_convert_child_path_to_path (GtkTreeModelFilter *filter,
3842 GtkTreePath *child_path,
3843 gboolean build_levels,
3844 gboolean fetch_children)
3846 gint *child_indices;
3847 GtkTreePath *retval;
3848 GtkTreePath *real_path;
3853 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (filter), NULL);
3854 g_return_val_if_fail (filter->priv->child_model != NULL, NULL);
3855 g_return_val_if_fail (child_path != NULL, NULL);
3857 if (!filter->priv->virtual_root)
3858 real_path = gtk_tree_path_copy (child_path);
3860 real_path = gtk_tree_model_filter_remove_root (child_path,
3861 filter->priv->virtual_root);
3866 retval = gtk_tree_path_new ();
3867 child_indices = gtk_tree_path_get_indices (real_path);
3869 if (filter->priv->root == NULL && build_levels)
3870 gtk_tree_model_filter_build_level (filter, NULL, NULL, FALSE);
3871 level = FILTER_LEVEL (filter->priv->root);
3873 for (i = 0; i < gtk_tree_path_get_depth (real_path); i++)
3875 GSequenceIter *siter;
3876 gboolean found_child = FALSE;
3880 gtk_tree_path_free (real_path);
3881 gtk_tree_path_free (retval);
3885 tmp = lookup_elt_with_offset (level->seq, child_indices[i], &siter);
3888 gtk_tree_path_append_index (retval, g_sequence_iter_get_position (siter));
3889 if (!tmp->children && build_levels)
3890 gtk_tree_model_filter_build_level (filter, level, tmp, FALSE);
3891 level = tmp->children;
3895 if (!found_child && fetch_children)
3899 tmp = gtk_tree_model_filter_fetch_child (filter, level,
3903 /* didn't find the child, let's try to bring it back */
3904 if (!tmp || tmp->offset != child_indices[i])
3907 gtk_tree_path_free (real_path);
3908 gtk_tree_path_free (retval);
3912 gtk_tree_path_append_index (retval, j);
3913 if (!tmp->children && build_levels)
3914 gtk_tree_model_filter_build_level (filter, level, tmp, FALSE);
3915 level = tmp->children;
3918 else if (!found_child && !fetch_children)
3921 gtk_tree_path_free (real_path);
3922 gtk_tree_path_free (retval);
3927 gtk_tree_path_free (real_path);
3932 * gtk_tree_model_filter_convert_child_path_to_path:
3933 * @filter: A #GtkTreeModelFilter.
3934 * @child_path: A #GtkTreePath to convert.
3936 * Converts @child_path to a path relative to @filter. That is, @child_path
3937 * points to a path in the child model. The rerturned path will point to the
3938 * same row in the filtered model. If @child_path isn't a valid path on the
3939 * child model or points to a row which is not visible in @filter, then %NULL
3942 * Return value: A newly allocated #GtkTreePath, or %NULL.
3947 gtk_tree_model_filter_convert_child_path_to_path (GtkTreeModelFilter *filter,
3948 GtkTreePath *child_path)
3953 /* this function does the sanity checks */
3954 path = gtk_real_tree_model_filter_convert_child_path_to_path (filter,
3962 /* get a new path which only takes visible nodes into account.
3963 * -- if this gives any performance issues, we can write a special
3964 * version of convert_child_path_to_path immediately returning
3965 * a visible-nodes-only path.
3967 gtk_tree_model_filter_get_iter_full (GTK_TREE_MODEL (filter), &iter, path);
3969 gtk_tree_path_free (path);
3970 path = gtk_tree_model_get_path (GTK_TREE_MODEL (filter), &iter);
3976 * gtk_tree_model_filter_convert_path_to_child_path:
3977 * @filter: A #GtkTreeModelFilter.
3978 * @filter_path: A #GtkTreePath to convert.
3980 * Converts @filter_path to a path on the child model of @filter. That is,
3981 * @filter_path points to a location in @filter. The returned path will
3982 * point to the same location in the model not being filtered. If @filter_path
3983 * does not point to a location in the child model, %NULL is returned.
3985 * Return value: A newly allocated #GtkTreePath, or %NULL.
3990 gtk_tree_model_filter_convert_path_to_child_path (GtkTreeModelFilter *filter,
3991 GtkTreePath *filter_path)
3993 gint *filter_indices;
3994 GtkTreePath *retval;
3998 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (filter), NULL);
3999 g_return_val_if_fail (filter->priv->child_model != NULL, NULL);
4000 g_return_val_if_fail (filter_path != NULL, NULL);
4003 retval = gtk_tree_path_new ();
4004 filter_indices = gtk_tree_path_get_indices (filter_path);
4005 if (!filter->priv->root)
4006 gtk_tree_model_filter_build_level (filter, NULL, NULL, FALSE);
4007 level = FILTER_LEVEL (filter->priv->root);
4009 for (i = 0; i < gtk_tree_path_get_depth (filter_path); i++)
4012 GSequenceIter *siter;
4016 gtk_tree_path_free (retval);
4020 siter = g_sequence_get_iter_at_pos (level->visible_seq, filter_indices[i]);
4021 if (g_sequence_iter_is_end (siter))
4023 gtk_tree_path_free (retval);
4027 elt = GET_ELT (siter);
4028 if (elt->children == NULL)
4029 gtk_tree_model_filter_build_level (filter, level, elt, FALSE);
4031 gtk_tree_path_append_index (retval, elt->offset);
4032 level = elt->children;
4037 if (filter->priv->virtual_root)
4039 GtkTreePath *real_retval;
4041 real_retval = gtk_tree_model_filter_add_root (retval,
4042 filter->priv->virtual_root);
4043 gtk_tree_path_free (retval);
4052 gtk_tree_model_filter_refilter_helper (GtkTreeModel *model,
4057 /* evil, don't try this at home, but certainly speeds things up */
4058 gtk_tree_model_filter_row_changed (model, path, iter, data);
4064 * gtk_tree_model_filter_refilter:
4065 * @filter: A #GtkTreeModelFilter.
4067 * Emits ::row_changed for each row in the child model, which causes
4068 * the filter to re-evaluate whether a row is visible or not.
4073 gtk_tree_model_filter_refilter (GtkTreeModelFilter *filter)
4075 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
4078 gtk_tree_model_foreach (filter->priv->child_model,
4079 gtk_tree_model_filter_refilter_helper,
4084 * gtk_tree_model_filter_clear_cache:
4085 * @filter: A #GtkTreeModelFilter.
4087 * This function should almost never be called. It clears the @filter
4088 * of any cached iterators that haven't been reffed with
4089 * gtk_tree_model_ref_node(). This might be useful if the child model
4090 * being filtered is static (and doesn't change often) and there has been
4091 * a lot of unreffed access to nodes. As a side effect of this function,
4092 * all unreffed iters will be invalid.
4097 gtk_tree_model_filter_clear_cache (GtkTreeModelFilter *filter)
4099 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
4101 if (filter->priv->zero_ref_count > 0)
4102 gtk_tree_model_filter_clear_cache_helper (filter,
4103 FILTER_LEVEL (filter->priv->root));