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.
61 * iter->stamp = filter->priv->stamp
62 * iter->user_data = FilterLevel
63 * iter->user_data2 = FilterElt
66 /* all paths, iters, etc prefixed with c_ are paths, iters, etc relative to the
71 * There are three model/views involved, so there are two mappings:
72 * * this model -> child model: mapped via offset in FilterElt.
73 * * this model -> parent model (or view): mapped via the array index
76 * Note that there are two kinds of paths relative to the filter model
77 * (those generated from the array indices): paths taking non-visible
78 * nodes into account, and paths which don't. Paths which take
79 * non-visible nodes into account should only be used internally and
80 * NEVER be passed along with a signal emission.
82 * The filter model has a reference on every node that is not in the root
83 * level and has a parent with ref_count > 1. Exception is a virtual root
84 * level; all nodes in the virtual root level are referenced too.
87 typedef struct _FilterElt FilterElt;
88 typedef struct _FilterLevel FilterLevel;
93 FilterLevel *children;
108 FilterElt *parent_elt;
109 FilterLevel *parent_level;
113 struct _GtkTreeModelFilterPrivate
115 GtkTreeModel *child_model;
117 GtkTreePath *virtual_root;
124 GtkTreeModelFilterVisibleFunc visible_func;
125 gpointer visible_data;
126 GDestroyNotify visible_destroy;
129 GtkTreeModelFilterModifyFunc modify_func;
130 gpointer modify_data;
131 GDestroyNotify modify_destroy;
132 gint modify_n_columns;
134 guint visible_method_set : 1;
135 guint modify_func_set : 1;
137 guint in_row_deleted : 1;
138 guint virtual_root_deleted : 1;
143 gulong has_child_toggled_id;
156 /* Set this to 0 to disable caching of child iterators. This
157 * allows for more stringent testing. It is recommended to set this
158 * to one when refactoring this code and running the unit tests to
162 # define GTK_TREE_MODEL_FILTER_CACHE_CHILD_ITERS(filter) \
163 (((GtkTreeModelFilter *)filter)->priv->child_flags & GTK_TREE_MODEL_ITERS_PERSIST)
165 # define GTK_TREE_MODEL_FILTER_CACHE_CHILD_ITERS(filter) (FALSE)
168 #define FILTER_ELT(filter_elt) ((FilterElt *)filter_elt)
169 #define FILTER_LEVEL(filter_level) ((FilterLevel *)filter_level)
171 /* general code (object/interface init, properties, etc) */
172 static void gtk_tree_model_filter_tree_model_init (GtkTreeModelIface *iface);
173 static void gtk_tree_model_filter_drag_source_init (GtkTreeDragSourceIface *iface);
174 static void gtk_tree_model_filter_finalize (GObject *object);
175 static void gtk_tree_model_filter_set_property (GObject *object,
179 static void gtk_tree_model_filter_get_property (GObject *object,
184 /* signal handlers */
185 static void gtk_tree_model_filter_row_changed (GtkTreeModel *c_model,
189 static void gtk_tree_model_filter_row_inserted (GtkTreeModel *c_model,
193 static void gtk_tree_model_filter_row_has_child_toggled (GtkTreeModel *c_model,
197 static void gtk_tree_model_filter_row_deleted (GtkTreeModel *c_model,
200 static void gtk_tree_model_filter_rows_reordered (GtkTreeModel *c_model,
206 /* GtkTreeModel interface */
207 static GtkTreeModelFlags gtk_tree_model_filter_get_flags (GtkTreeModel *model);
208 static gint gtk_tree_model_filter_get_n_columns (GtkTreeModel *model);
209 static GType gtk_tree_model_filter_get_column_type (GtkTreeModel *model,
211 static gboolean gtk_tree_model_filter_get_iter_full (GtkTreeModel *model,
214 static gboolean gtk_tree_model_filter_get_iter (GtkTreeModel *model,
217 static GtkTreePath *gtk_tree_model_filter_get_path (GtkTreeModel *model,
219 static void gtk_tree_model_filter_get_value (GtkTreeModel *model,
223 static gboolean gtk_tree_model_filter_iter_next (GtkTreeModel *model,
225 static gboolean gtk_tree_model_filter_iter_previous (GtkTreeModel *model,
227 static gboolean gtk_tree_model_filter_iter_children (GtkTreeModel *model,
229 GtkTreeIter *parent);
230 static gboolean gtk_tree_model_filter_iter_has_child (GtkTreeModel *model,
232 static gint gtk_tree_model_filter_iter_n_children (GtkTreeModel *model,
234 static gboolean gtk_tree_model_filter_iter_nth_child (GtkTreeModel *model,
238 static gboolean gtk_tree_model_filter_iter_parent (GtkTreeModel *model,
241 static void gtk_tree_model_filter_ref_node (GtkTreeModel *model,
243 static void gtk_tree_model_filter_unref_node (GtkTreeModel *model,
246 /* TreeDragSource interface */
247 static gboolean gtk_tree_model_filter_row_draggable (GtkTreeDragSource *drag_source,
249 static gboolean gtk_tree_model_filter_drag_data_get (GtkTreeDragSource *drag_source,
251 GtkSelectionData *selection_data);
252 static gboolean gtk_tree_model_filter_drag_data_delete (GtkTreeDragSource *drag_source,
255 /* private functions */
256 static void gtk_tree_model_filter_build_level (GtkTreeModelFilter *filter,
257 FilterLevel *parent_level,
258 FilterElt *parent_elt,
259 gboolean emit_inserted);
261 static void gtk_tree_model_filter_free_level (GtkTreeModelFilter *filter,
262 FilterLevel *filter_level,
265 static GtkTreePath *gtk_tree_model_filter_elt_get_path (FilterLevel *level,
269 static GtkTreePath *gtk_tree_model_filter_add_root (GtkTreePath *src,
271 static GtkTreePath *gtk_tree_model_filter_remove_root (GtkTreePath *src,
274 static void gtk_tree_model_filter_increment_stamp (GtkTreeModelFilter *filter);
276 static void gtk_tree_model_filter_real_modify (GtkTreeModelFilter *self,
277 GtkTreeModel *child_model,
281 static gboolean gtk_tree_model_filter_real_visible (GtkTreeModelFilter *filter,
282 GtkTreeModel *child_model,
283 GtkTreeIter *child_iter);
284 static gboolean gtk_tree_model_filter_visible (GtkTreeModelFilter *filter,
285 GtkTreeIter *child_iter);
286 static void gtk_tree_model_filter_clear_cache_helper (GtkTreeModelFilter *filter,
289 static void gtk_tree_model_filter_real_ref_node (GtkTreeModel *model,
292 static void gtk_tree_model_filter_real_unref_node (GtkTreeModel *model,
295 gboolean propagate_unref);
297 static void gtk_tree_model_filter_set_model (GtkTreeModelFilter *filter,
298 GtkTreeModel *child_model);
299 static void gtk_tree_model_filter_ref_path (GtkTreeModelFilter *filter,
301 static void gtk_tree_model_filter_unref_path (GtkTreeModelFilter *filter,
304 static void gtk_tree_model_filter_set_root (GtkTreeModelFilter *filter,
307 static GtkTreePath *gtk_real_tree_model_filter_convert_child_path_to_path (GtkTreeModelFilter *filter,
308 GtkTreePath *child_path,
309 gboolean build_levels,
310 gboolean fetch_children);
312 static FilterElt *gtk_tree_model_filter_get_nth (GtkTreeModelFilter *filter,
315 static gboolean gtk_tree_model_filter_elt_is_visible_in_target (FilterLevel *level,
317 static FilterElt *gtk_tree_model_filter_get_nth_visible (GtkTreeModelFilter *filter,
321 static FilterElt *gtk_tree_model_filter_insert_elt_in_level (GtkTreeModelFilter *filter,
326 static FilterElt *gtk_tree_model_filter_fetch_child (GtkTreeModelFilter *filter,
330 static void gtk_tree_model_filter_remove_elt_from_level (GtkTreeModelFilter *filter,
333 static void gtk_tree_model_filter_update_children (GtkTreeModelFilter *filter,
336 static FilterElt *bsearch_elt_with_offset (GArray *array,
339 static void gtk_tree_model_filter_emit_row_inserted_for_path (GtkTreeModelFilter *filter,
340 GtkTreeModel *c_model,
342 GtkTreeIter *c_iter);
345 G_DEFINE_TYPE_WITH_CODE (GtkTreeModelFilter, gtk_tree_model_filter, G_TYPE_OBJECT,
346 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL,
347 gtk_tree_model_filter_tree_model_init)
348 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_SOURCE,
349 gtk_tree_model_filter_drag_source_init))
352 gtk_tree_model_filter_init (GtkTreeModelFilter *filter)
354 filter->priv = G_TYPE_INSTANCE_GET_PRIVATE (filter,
355 GTK_TYPE_TREE_MODEL_FILTER,
356 GtkTreeModelFilterPrivate);
358 filter->priv->visible_column = -1;
359 filter->priv->zero_ref_count = 0;
360 filter->priv->visible_method_set = FALSE;
361 filter->priv->modify_func_set = FALSE;
362 filter->priv->in_row_deleted = FALSE;
363 filter->priv->virtual_root_deleted = FALSE;
367 gtk_tree_model_filter_class_init (GtkTreeModelFilterClass *filter_class)
369 GObjectClass *object_class;
371 object_class = (GObjectClass *) filter_class;
373 object_class->set_property = gtk_tree_model_filter_set_property;
374 object_class->get_property = gtk_tree_model_filter_get_property;
376 object_class->finalize = gtk_tree_model_filter_finalize;
378 filter_class->visible = gtk_tree_model_filter_real_visible;
379 filter_class->modify = gtk_tree_model_filter_real_modify;
381 /* Properties -- FIXME: disabled translations for now, until I can come up with a
384 g_object_class_install_property (object_class,
386 g_param_spec_object ("child-model",
388 ("The model for the filtermodel to filter"),
390 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
392 g_object_class_install_property (object_class,
394 g_param_spec_boxed ("virtual-root",
395 ("The virtual root"),
396 ("The virtual root (relative to the child model) for this filtermodel"),
398 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
400 g_type_class_add_private (object_class, sizeof (GtkTreeModelFilterPrivate));
404 gtk_tree_model_filter_tree_model_init (GtkTreeModelIface *iface)
406 iface->get_flags = gtk_tree_model_filter_get_flags;
407 iface->get_n_columns = gtk_tree_model_filter_get_n_columns;
408 iface->get_column_type = gtk_tree_model_filter_get_column_type;
409 iface->get_iter = gtk_tree_model_filter_get_iter;
410 iface->get_path = gtk_tree_model_filter_get_path;
411 iface->get_value = gtk_tree_model_filter_get_value;
412 iface->iter_next = gtk_tree_model_filter_iter_next;
413 iface->iter_previous = gtk_tree_model_filter_iter_previous;
414 iface->iter_children = gtk_tree_model_filter_iter_children;
415 iface->iter_has_child = gtk_tree_model_filter_iter_has_child;
416 iface->iter_n_children = gtk_tree_model_filter_iter_n_children;
417 iface->iter_nth_child = gtk_tree_model_filter_iter_nth_child;
418 iface->iter_parent = gtk_tree_model_filter_iter_parent;
419 iface->ref_node = gtk_tree_model_filter_ref_node;
420 iface->unref_node = gtk_tree_model_filter_unref_node;
424 gtk_tree_model_filter_drag_source_init (GtkTreeDragSourceIface *iface)
426 iface->row_draggable = gtk_tree_model_filter_row_draggable;
427 iface->drag_data_delete = gtk_tree_model_filter_drag_data_delete;
428 iface->drag_data_get = gtk_tree_model_filter_drag_data_get;
433 gtk_tree_model_filter_finalize (GObject *object)
435 GtkTreeModelFilter *filter = (GtkTreeModelFilter *) object;
437 if (filter->priv->virtual_root && !filter->priv->virtual_root_deleted)
439 gtk_tree_model_filter_unref_path (filter, filter->priv->virtual_root,
441 filter->priv->virtual_root_deleted = TRUE;
444 gtk_tree_model_filter_set_model (filter, NULL);
446 if (filter->priv->virtual_root)
447 gtk_tree_path_free (filter->priv->virtual_root);
449 if (filter->priv->root)
450 gtk_tree_model_filter_free_level (filter, filter->priv->root, TRUE);
452 g_free (filter->priv->modify_types);
454 if (filter->priv->modify_destroy)
455 filter->priv->modify_destroy (filter->priv->modify_data);
457 if (filter->priv->visible_destroy)
458 filter->priv->visible_destroy (filter->priv->visible_data);
461 G_OBJECT_CLASS (gtk_tree_model_filter_parent_class)->finalize (object);
465 gtk_tree_model_filter_set_property (GObject *object,
470 GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (object);
474 case PROP_CHILD_MODEL:
475 gtk_tree_model_filter_set_model (filter, g_value_get_object (value));
477 case PROP_VIRTUAL_ROOT:
478 gtk_tree_model_filter_set_root (filter, g_value_get_boxed (value));
481 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
487 gtk_tree_model_filter_get_property (GObject *object,
492 GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (object);
496 case PROP_CHILD_MODEL:
497 g_value_set_object (value, filter->priv->child_model);
499 case PROP_VIRTUAL_ROOT:
500 g_value_set_boxed (value, filter->priv->virtual_root);
503 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
511 gtk_tree_model_filter_build_level (GtkTreeModelFilter *filter,
512 FilterLevel *parent_level,
513 FilterElt *parent_elt,
514 gboolean emit_inserted)
517 GtkTreeIter first_node;
519 FilterLevel *new_level;
520 FilterLevel *tmp_level;
526 g_assert (filter->priv->child_model != NULL);
528 /* Avoid building a level that already exists */
530 g_assert (parent_elt->children == NULL);
532 g_assert (filter->priv->root == NULL);
534 if (filter->priv->in_row_deleted)
539 if (filter->priv->virtual_root)
541 if (gtk_tree_model_get_iter (filter->priv->child_model, &root, filter->priv->virtual_root) == FALSE)
543 length = gtk_tree_model_iter_n_children (filter->priv->child_model, &root);
545 if (gtk_tree_model_iter_children (filter->priv->child_model, &iter, &root) == FALSE)
550 if (!gtk_tree_model_get_iter_first (filter->priv->child_model, &iter))
552 length = gtk_tree_model_iter_n_children (filter->priv->child_model, NULL);
557 GtkTreeIter parent_iter;
558 GtkTreeIter child_parent_iter;
560 parent_iter.stamp = filter->priv->stamp;
561 parent_iter.user_data = parent_level;
562 parent_iter.user_data2 = parent_elt;
564 gtk_tree_model_filter_convert_iter_to_child_iter (filter,
567 if (gtk_tree_model_iter_children (filter->priv->child_model, &iter, &child_parent_iter) == FALSE)
570 /* stamp may have changed */
571 gtk_tree_model_filter_convert_iter_to_child_iter (filter,
574 length = gtk_tree_model_iter_n_children (filter->priv->child_model, &child_parent_iter);
576 /* Take a reference on the parent */
577 gtk_tree_model_filter_real_ref_node (GTK_TREE_MODEL (filter),
578 &parent_iter, FALSE);
581 g_return_if_fail (length > 0);
583 new_level = g_new (FilterLevel, 1);
584 new_level->array = g_array_sized_new (FALSE, FALSE,
587 new_level->ref_count = 0;
588 new_level->ext_ref_count = 0;
589 new_level->visible_nodes = 0;
590 new_level->parent_elt = parent_elt;
591 new_level->parent_level = parent_level;
594 parent_elt->children = new_level;
596 filter->priv->root = new_level;
598 /* increase the count of zero ref_counts */
599 tmp_level = parent_level;
600 tmp_elt = parent_elt;
604 parent_elt->zero_ref_count++;
606 tmp_elt = tmp_level->parent_elt;
607 tmp_level = tmp_level->parent_level;
609 if (new_level != filter->priv->root)
610 filter->priv->zero_ref_count++;
618 if (gtk_tree_model_filter_visible (filter, &iter))
620 FilterElt filter_elt;
622 filter_elt.offset = i;
623 filter_elt.zero_ref_count = 0;
624 filter_elt.ref_count = 0;
625 filter_elt.ext_ref_count = 0;
626 filter_elt.children = NULL;
627 filter_elt.visible = TRUE;
629 if (GTK_TREE_MODEL_FILTER_CACHE_CHILD_ITERS (filter))
630 filter_elt.iter = iter;
632 g_array_append_val (new_level->array, filter_elt);
633 new_level->visible_nodes++;
639 GtkTreeIter children;
641 f_iter.stamp = filter->priv->stamp;
642 f_iter.user_data = new_level;
643 f_iter.user_data2 = &(g_array_index (new_level->array, FilterElt, new_level->array->len - 1));
645 f_path = gtk_tree_model_get_path (GTK_TREE_MODEL (filter),
647 gtk_tree_model_row_inserted (GTK_TREE_MODEL (filter),
649 gtk_tree_path_free (f_path);
651 if (gtk_tree_model_iter_children (filter->priv->child_model,
653 gtk_tree_model_filter_update_children (filter,
655 FILTER_ELT (f_iter.user_data2));
660 while (gtk_tree_model_iter_next (filter->priv->child_model, &iter));
662 /* The level does not contain any visible nodes. However, changes in
663 * this level might affect the parent node, which can either be visible
664 * or invisible. Therefore, this level can only be removed again,
665 * if the parent of the parent node is not visible. In that case,
666 * possible changes in state of the parent are not requested.
668 if (new_level->array->len == 0 &&
669 (parent_level && parent_level->parent_level &&
670 parent_level->parent_elt->ext_ref_count == 0))
672 gtk_tree_model_filter_free_level (filter, new_level, FALSE);
676 /* If none of the nodes are visible, we will just pull in the
677 * first node of the level.
679 if (new_level->array->len == 0)
681 FilterElt filter_elt;
683 filter_elt.offset = 0;
684 filter_elt.zero_ref_count = 0;
685 filter_elt.ref_count = 0;
686 filter_elt.ext_ref_count = 0;
687 filter_elt.children = NULL;
688 filter_elt.visible = FALSE;
690 if (GTK_TREE_MODEL_FILTER_CACHE_CHILD_ITERS (filter))
691 filter_elt.iter = first_node;
693 g_array_append_val (new_level->array, filter_elt);
696 /* Keep a reference on the first node of this level. We need this
697 * to make sure that we get all signals for this level.
699 f_iter.stamp = filter->priv->stamp;
700 f_iter.user_data = new_level;
701 f_iter.user_data2 = &(g_array_index (new_level->array, FilterElt, 0));
703 gtk_tree_model_filter_real_ref_node (GTK_TREE_MODEL (filter), &f_iter,
708 gtk_tree_model_filter_free_level (GtkTreeModelFilter *filter,
709 FilterLevel *filter_level,
714 g_assert (filter_level);
716 for (i = 0; i < filter_level->array->len; i++)
718 if (g_array_index (filter_level->array, FilterElt, i).children)
719 gtk_tree_model_filter_free_level (filter,
720 FILTER_LEVEL (g_array_index (filter_level->array, FilterElt, i).children),
724 /* Release the reference on the first item.
730 f_iter.stamp = filter->priv->stamp;
731 f_iter.user_data = filter_level;
732 f_iter.user_data2 = &(g_array_index (filter_level->array, FilterElt, 0));
734 gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter),
735 &f_iter, FALSE, TRUE);
738 if (filter_level->ext_ref_count == 0)
740 FilterLevel *parent_level = filter_level->parent_level;
741 FilterElt *parent_elt = filter_level->parent_elt;
745 parent_elt->zero_ref_count--;
747 parent_elt = parent_level->parent_elt;
748 parent_level = parent_level->parent_level;
751 if (filter_level != filter->priv->root)
752 filter->priv->zero_ref_count--;
755 if (filter_level->parent_elt)
757 /* Release reference on parent */
760 GtkTreeIter parent_iter;
762 parent_iter.stamp = filter->priv->stamp;
763 parent_iter.user_data = filter_level->parent_level;
764 parent_iter.user_data2 = filter_level->parent_elt;
766 gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter),
767 &parent_iter, FALSE, TRUE);
770 filter_level->parent_elt->children = NULL;
773 filter->priv->root = NULL;
775 g_array_free (filter_level->array, TRUE);
776 filter_level->array = NULL;
778 g_free (filter_level);
783 gtk_tree_model_filter_level_transfer_first_ref (GtkTreeModelFilter *filter,
790 f_iter.stamp = filter->priv->stamp;
791 f_iter.user_data = level;
792 f_iter.user_data2 = &(g_array_index (level->array, FilterElt, to_index));
794 gtk_tree_model_filter_real_ref_node (GTK_TREE_MODEL (filter),
797 f_iter.stamp = filter->priv->stamp;
798 f_iter.user_data = level;
799 f_iter.user_data2 = &(g_array_index (level->array, FilterElt, from_index));
801 gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter),
802 &f_iter, FALSE, TRUE);
806 /* Creates paths suitable for accessing the child model. */
808 gtk_tree_model_filter_elt_get_path (FilterLevel *level,
812 FilterLevel *walker = level;
813 FilterElt *walker2 = elt;
815 GtkTreePath *real_path;
817 g_return_val_if_fail (level != NULL, NULL);
818 g_return_val_if_fail (elt != NULL, NULL);
820 path = gtk_tree_path_new ();
824 gtk_tree_path_prepend_index (path, walker2->offset);
826 walker2 = walker->parent_elt;
827 walker = walker->parent_level;
832 real_path = gtk_tree_model_filter_add_root (path, root);
833 gtk_tree_path_free (path);
841 gtk_tree_model_filter_add_root (GtkTreePath *src,
847 retval = gtk_tree_path_copy (root);
849 for (i = 0; i < gtk_tree_path_get_depth (src); i++)
850 gtk_tree_path_append_index (retval, gtk_tree_path_get_indices (src)[i]);
856 gtk_tree_model_filter_remove_root (GtkTreePath *src,
864 if (gtk_tree_path_get_depth (src) <= gtk_tree_path_get_depth (root))
867 depth = gtk_tree_path_get_depth (src);
868 indices = gtk_tree_path_get_indices (src);
870 for (i = 0; i < gtk_tree_path_get_depth (root); i++)
871 if (indices[i] != gtk_tree_path_get_indices (root)[i])
874 retval = gtk_tree_path_new ();
876 for (; i < depth; i++)
877 gtk_tree_path_append_index (retval, indices[i]);
883 gtk_tree_model_filter_increment_stamp (GtkTreeModelFilter *filter)
887 filter->priv->stamp++;
889 while (filter->priv->stamp == 0);
891 gtk_tree_model_filter_clear_cache (filter);
895 gtk_tree_model_filter_real_visible (GtkTreeModelFilter *filter,
896 GtkTreeModel *child_model,
897 GtkTreeIter *child_iter)
899 if (filter->priv->visible_func)
901 return filter->priv->visible_func (child_model,
903 filter->priv->visible_data)
906 else if (filter->priv->visible_column >= 0)
910 gtk_tree_model_get_value (child_model, child_iter,
911 filter->priv->visible_column, &val);
913 if (g_value_get_boolean (&val))
915 g_value_unset (&val);
919 g_value_unset (&val);
923 /* no visible function set, so always visible */
928 gtk_tree_model_filter_visible (GtkTreeModelFilter *self,
929 GtkTreeIter *child_iter)
931 return GTK_TREE_MODEL_FILTER_GET_CLASS (self)->visible (self,
932 self->priv->child_model, child_iter);
936 gtk_tree_model_filter_clear_cache_helper (GtkTreeModelFilter *filter,
943 for (i = 0; i < level->array->len; i++)
945 if (g_array_index (level->array, FilterElt, i).zero_ref_count > 0)
946 gtk_tree_model_filter_clear_cache_helper (filter, g_array_index (level->array, FilterElt, i).children);
949 /* If the level's ext_ref_count is zero, it means the level is not visible
950 * and can be removed. But, since we support monitoring a child level
951 * of a parent for changes (these might affect the parent), we will only
952 * free the level if the parent's parent also has an external ref
953 * count of zero. In that case, changes concerning our parent are
956 if (level->ext_ref_count == 0 && level != filter->priv->root &&
957 level->parent_level && level->parent_elt &&
958 level->parent_level->parent_level &&
959 level->parent_level->parent_elt->ext_ref_count == 0)
961 gtk_tree_model_filter_free_level (filter, level, TRUE);
967 gtk_tree_model_filter_get_nth (GtkTreeModelFilter *filter,
971 if (level->array->len <= n)
974 return &g_array_index (level->array, FilterElt, n);
978 gtk_tree_model_filter_elt_is_visible_in_target (FilterLevel *level,
984 if (!level->parent_elt)
989 elt = level->parent_elt;
990 level = level->parent_level;
992 if (elt && !elt->visible)
1000 /* If a change has occurred in path (inserted, changed or deleted),
1001 * then this function is used to check all its ancestors. An ancestor
1002 * could have changed state as a result and this needs to be propagated
1003 * to the objects monitoring the filter model.
1006 gtk_tree_model_filter_check_ancestors (GtkTreeModelFilter *filter,
1010 int *indices = gtk_tree_path_get_indices (path);
1013 GtkTreeIter c_iter, tmp_iter;
1015 level = FILTER_LEVEL (filter->priv->root);
1020 if (filter->priv->virtual_root)
1021 gtk_tree_model_get_iter (filter->priv->child_model, &c_iter,
1022 filter->priv->virtual_root);
1025 gtk_tree_model_iter_nth_child (filter->priv->child_model, &c_iter,
1026 filter->priv->virtual_root ? &tmp_iter : NULL,
1029 while (i < gtk_tree_path_get_depth (path) - 1)
1032 gboolean requested_state;
1034 elt = bsearch_elt_with_offset (level->array,
1035 gtk_tree_path_get_indices (path)[i],
1038 requested_state = gtk_tree_model_filter_visible (filter, &c_iter);
1043 GtkTreePath *c_path;
1045 if (requested_state == FALSE)
1048 /* The elt does not exist in this level (so it is not
1049 * visible), but should now be visible. We emit the
1050 * row-inserted and row-has-child-toggled signals.
1052 elt = gtk_tree_model_filter_insert_elt_in_level (filter,
1058 /* insert_elt_in_level defaults to FALSE */
1059 elt->visible = TRUE;
1060 level->visible_nodes++;
1062 c_path = gtk_tree_model_get_path (filter->priv->child_model,
1065 gtk_tree_model_filter_emit_row_inserted_for_path (filter,
1066 filter->priv->child_model,
1070 gtk_tree_path_free (c_path);
1072 /* We can immediately return, because this node was not visible
1073 * before and its children will be checked for in response to
1074 * the emitted row-has-child-toggled signal.
1078 else if (elt->visible)
1080 if (!requested_state)
1082 /* A node has turned invisible. Remove it from the level
1083 * and emit row-deleted. Since this node is being
1084 * deleted. it makes no sense to look further up the
1087 gtk_tree_model_filter_remove_elt_from_level (filter,
1092 /* Otherwise continue up the chain */
1094 else if (!elt->visible)
1096 if (requested_state)
1098 /* A node is already in the cache, but invisible. This
1099 * is usually a node on which a reference is kept by
1100 * the filter model, or a node fetched on the filter's
1101 * request, and thus not shown. Therefore, we will
1102 * not emit row-inserted for this node. Instead,
1103 * we signal to its parent that a change has occurred.
1105 * Exception: root level, in this case, we must emit
1108 if (level->parent_level)
1111 GtkTreePath *f_path;
1113 elt->visible = TRUE;
1114 level->visible_nodes++;
1116 f_iter.stamp = filter->priv->stamp;
1117 f_iter.user_data = level->parent_level;
1118 f_iter.user_data2 = level->parent_elt;
1120 f_path = gtk_tree_model_get_path (GTK_TREE_MODEL (filter),
1122 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (filter),
1124 gtk_tree_path_free (f_path);
1128 GtkTreePath *c_path;
1130 elt->visible = TRUE;
1131 level->visible_nodes++;
1133 c_path = gtk_tree_model_get_path (filter->priv->child_model,
1136 gtk_tree_model_filter_emit_row_inserted_for_path (filter,
1137 filter->priv->child_model,
1141 gtk_tree_path_free (c_path);
1144 /* We can immediately return, because this node was not visible
1145 * before and the parent will check its children, including
1146 * this node, in response to the emitted row-has-child-toggled
1152 /* Not visible, so no need to continue. */
1158 /* If an elt does not have children, these are not visible.
1159 * Therefore, any signals emitted for these children will
1160 * be ignored, so we do not have to emit them.
1165 level = elt->children;
1169 gtk_tree_model_iter_nth_child (filter->priv->child_model, &c_iter,
1170 &tmp_iter, indices[i]);
1175 gtk_tree_model_filter_get_nth_visible (GtkTreeModelFilter *filter,
1182 if (level->visible_nodes <= n)
1185 elt = FILTER_ELT (level->array->data);
1186 while (!elt->visible)
1196 while (!elt->visible)
1203 gtk_tree_model_filter_insert_elt_in_level (GtkTreeModelFilter *filter,
1204 GtkTreeIter *c_iter,
1210 gint start, middle, end;
1213 if (GTK_TREE_MODEL_FILTER_CACHE_CHILD_ITERS (filter))
1216 elt.offset = offset;
1217 elt.zero_ref_count = 0;
1219 elt.ext_ref_count = 0;
1220 elt.children = NULL;
1221 /* visibility should be FALSE as we don't emit row_inserted */
1222 elt.visible = FALSE;
1224 /* find index (binary search on offset) */
1226 end = level->array->len;
1230 while (start != end)
1232 middle = (start + end) / 2;
1234 if (g_array_index (level->array, FilterElt, middle).offset <= offset)
1240 if (g_array_index (level->array, FilterElt, middle).offset <= offset)
1248 g_array_insert_val (level->array, i, elt);
1251 for (i = 0; i < level->array->len; i++)
1253 FilterElt *e = &(g_array_index (level->array, FilterElt, i));
1255 e->children->parent_elt = e;
1258 /* If the insert location is zero, we need to move our reference
1259 * on the old first node to the new first node.
1262 gtk_tree_model_filter_level_transfer_first_ref (filter, level,
1265 return &g_array_index (level->array, FilterElt, *index);
1269 gtk_tree_model_filter_fetch_child (GtkTreeModelFilter *filter,
1275 GtkTreePath *c_path = NULL;
1277 GtkTreePath *c_parent_path = NULL;
1278 GtkTreeIter c_parent_iter;
1280 /* check if child exists and is visible */
1281 if (level->parent_elt)
1284 gtk_tree_model_filter_elt_get_path (level->parent_level,
1286 filter->priv->virtual_root);
1292 if (filter->priv->virtual_root)
1293 c_parent_path = gtk_tree_path_copy (filter->priv->virtual_root);
1295 c_parent_path = NULL;
1300 gtk_tree_model_get_iter (filter->priv->child_model,
1303 len = gtk_tree_model_iter_n_children (filter->priv->child_model,
1306 c_path = gtk_tree_path_copy (c_parent_path);
1307 gtk_tree_path_free (c_parent_path);
1311 len = gtk_tree_model_iter_n_children (filter->priv->child_model, NULL);
1312 c_path = gtk_tree_path_new ();
1315 gtk_tree_path_append_index (c_path, offset);
1316 gtk_tree_model_get_iter (filter->priv->child_model, &c_iter, c_path);
1317 gtk_tree_path_free (c_path);
1319 if (offset >= len || !gtk_tree_model_filter_visible (filter, &c_iter))
1322 return gtk_tree_model_filter_insert_elt_in_level (filter, &c_iter,
1327 /* Note that this function is never called from the row-deleted handler.
1328 * This means that this function is only used for removing elements
1329 * which are still present in the child model. As a result, we must
1330 * take care to properly release the references the filter model has
1331 * on the child model nodes.
1334 gtk_tree_model_filter_remove_elt_from_level (GtkTreeModelFilter *filter,
1339 FilterLevel *parent_level;
1340 gint i, length, orig_level_ext_ref_count;
1342 GtkTreePath *path = NULL;
1344 gboolean emit_child_toggled = FALSE;
1346 iter.stamp = filter->priv->stamp;
1347 iter.user_data = level;
1348 iter.user_data2 = elt;
1350 path = gtk_tree_model_get_path (GTK_TREE_MODEL (filter), &iter);
1352 parent = level->parent_elt;
1353 parent_level = level->parent_level;
1355 length = level->array->len;
1357 /* We need to know about the level's ext ref count before removal
1360 orig_level_ext_ref_count = level->ext_ref_count;
1362 /* first register the node to be invisible */
1363 level->visible_nodes--;
1364 elt->visible = FALSE;
1366 /* we distinguish a couple of cases:
1367 * - root level, length > 1: emit row-deleted and remove.
1368 * - root level, length == 1: emit row-deleted and keep in cache.
1369 * - level, length == 1: parent->ext_ref_count > 0: emit row-deleted
1371 * - level, length > 1: emit row-deleted and remove.
1372 * - else, remove level.
1374 * if level != root level and visible nodes == 0, emit row-has-child-toggled.
1377 if (level != filter->priv->root
1378 && level->visible_nodes == 0
1381 emit_child_toggled = TRUE;
1387 /* We emit row-deleted, and remove the node from the cache.
1388 * If it has any children, these will be removed here as well.
1392 gtk_tree_model_filter_free_level (filter, elt->children, TRUE);
1394 /* If the first node is being removed, transfer, the reference */
1395 if (elt == &g_array_index (level->array, FilterElt, 0))
1397 gtk_tree_model_filter_level_transfer_first_ref (filter, level,
1401 while (elt->ext_ref_count > 0)
1402 gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter),
1403 &iter, TRUE, FALSE);
1404 while (elt->ref_count > 0)
1405 gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter),
1406 &iter, FALSE, FALSE);
1408 /* remove the node */
1409 tmp = bsearch_elt_with_offset (level->array, elt->offset, &i);
1413 g_array_remove_index (level->array, i);
1416 for (i = MAX (i, 0); i < level->array->len; i++)
1418 /* NOTE: here we do *not* decrease offsets, because the node was
1419 * not removed from the child model
1421 elt = &g_array_index (level->array, FilterElt, i);
1423 elt->children->parent_elt = elt;
1427 gtk_tree_model_filter_increment_stamp (filter);
1429 /* Only if the node is in the root level (parent == NULL) or
1430 * the level is visible, a row-deleted signal is necessary.
1432 if (!parent || orig_level_ext_ref_count > 0)
1433 gtk_tree_model_row_deleted (GTK_TREE_MODEL (filter), path);
1435 else if ((length == 1 && parent && parent->ext_ref_count > 0)
1436 || (length == 1 && level == filter->priv->root))
1438 /* We emit row-deleted, but keep the node in the cache and
1439 * referenced. Its children will be removed.
1444 gtk_tree_model_filter_free_level (filter, elt->children, TRUE);
1445 elt->children = NULL;
1448 gtk_tree_model_filter_increment_stamp (filter);
1450 /* Only if the node is in the root level (parent == NULL) or
1451 * the level is visible, a row-deleted signal is necessary.
1453 if (!parent || orig_level_ext_ref_count > 0)
1454 gtk_tree_model_row_deleted (GTK_TREE_MODEL (filter), path);
1458 while (elt->ext_ref_count > 0)
1459 gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter),
1460 &iter, TRUE, FALSE);
1461 while (elt->ref_count > 0)
1462 gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter),
1463 &iter, FALSE, FALSE);
1465 /* Blow level away, including any child levels */
1466 gtk_tree_model_filter_free_level (filter, level, TRUE);
1468 gtk_tree_model_filter_increment_stamp (filter);
1470 if (!parent || orig_level_ext_ref_count > 0)
1471 gtk_tree_model_row_deleted (GTK_TREE_MODEL (filter), path);
1474 gtk_tree_path_free (path);
1476 if (emit_child_toggled && parent->ext_ref_count > 0)
1481 piter.stamp = filter->priv->stamp;
1482 piter.user_data = parent_level;
1483 piter.user_data2 = parent;
1485 ppath = gtk_tree_model_get_path (GTK_TREE_MODEL (filter), &piter);
1487 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (filter),
1489 gtk_tree_path_free (ppath);
1493 /* This function is called after the given node has become visible.
1494 * When the node has children, we should build the level and
1495 * take a reference on the first child.
1498 gtk_tree_model_filter_update_children (GtkTreeModelFilter *filter,
1508 iter.stamp = filter->priv->stamp;
1509 iter.user_data = level;
1510 iter.user_data2 = elt;
1512 gtk_tree_model_filter_convert_iter_to_child_iter (filter, &c_iter, &iter);
1514 if ((!level->parent_level || level->parent_elt->ext_ref_count > 0) &&
1515 gtk_tree_model_iter_has_child (filter->priv->child_model, &c_iter))
1518 gtk_tree_model_filter_build_level (filter, level, elt, FALSE);
1520 if (elt->ext_ref_count > 0 && elt->children && elt->children->array->len)
1523 path = gtk_tree_model_get_path (GTK_TREE_MODEL (filter), &iter);
1524 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (filter),
1528 gtk_tree_path_free (path);
1534 bsearch_elt_with_offset (GArray *array,
1538 gint start, middle, end;
1549 elt = &g_array_index (array, FilterElt, 0);
1551 if (elt->offset == offset)
1562 middle = (start + end) / 2;
1564 elt = &g_array_index (array, FilterElt, middle);
1566 if (elt->offset < offset)
1568 else if (elt->offset > offset)
1573 while (start != end);
1575 if (elt->offset == offset)
1584 /* Path is relative to the child model (this is on search on elt offset)
1585 * but with the virtual root already removed if necesssary.
1588 find_elt_with_offset (GtkTreeModelFilter *filter,
1590 FilterLevel **level_,
1595 FilterLevel *parent_level = NULL;
1596 FilterElt *elt = NULL;
1598 level = FILTER_LEVEL (filter->priv->root);
1600 while (i < gtk_tree_path_get_depth (path))
1607 elt = bsearch_elt_with_offset (level->array,
1608 gtk_tree_path_get_indices (path)[i],
1614 parent_level = level;
1615 level = elt->children;
1620 *level_ = parent_level;
1628 /* TreeModel signals */
1630 gtk_tree_model_filter_emit_row_inserted_for_path (GtkTreeModelFilter *filter,
1631 GtkTreeModel *c_model,
1632 GtkTreePath *c_path,
1633 GtkTreeIter *c_iter)
1638 GtkTreeIter iter, children;
1639 gboolean signals_emitted = FALSE;
1641 if (!filter->priv->root)
1643 /* The root level has not been exposed to the view yet, so we
1644 * need to emit signals for any node that is being inserted.
1646 gtk_tree_model_filter_build_level (filter, NULL, NULL, TRUE);
1648 /* Check if the root level was built. Then child levels
1649 * that matter have also been built (due to update_children,
1650 * which triggers iter_n_children).
1652 if (filter->priv->root &&
1653 FILTER_LEVEL (filter->priv->root)->visible_nodes)
1654 signals_emitted = TRUE;
1657 gtk_tree_model_filter_increment_stamp (filter);
1659 /* We need to disallow to build new levels, because we are then pulling
1660 * in a child in an invisible level. We only want to find path if it
1661 * is in a visible level (and thus has a parent that is visible).
1663 path = gtk_real_tree_model_filter_convert_child_path_to_path (filter,
1669 /* parent is probably being filtered out */
1672 gtk_tree_model_filter_get_iter_full (GTK_TREE_MODEL (filter), &iter, path);
1674 level = FILTER_LEVEL (iter.user_data);
1675 elt = FILTER_ELT (iter.user_data2);
1677 /* Make sure elt is visible. elt can already be visible in case
1678 * it was pulled in above, so avoid increasing level->visible_nodes twice.
1682 elt->visible = TRUE;
1683 level->visible_nodes++;
1686 /* Check whether the node and all of its parents are visible */
1687 if (gtk_tree_model_filter_elt_is_visible_in_target (level, elt))
1689 /* visibility changed -- reget path */
1690 gtk_tree_path_free (path);
1691 path = gtk_tree_model_get_path (GTK_TREE_MODEL (filter), &iter);
1693 if (!signals_emitted &&
1694 (!level->parent_level || level->ext_ref_count > 0))
1695 gtk_tree_model_row_inserted (GTK_TREE_MODEL (filter), path, &iter);
1697 if (level->parent_level && level->parent_elt->ext_ref_count > 0 &&
1698 level->visible_nodes == 1)
1700 /* We know that this is the first visible node in this level, so
1701 * we need to emit row-has-child-toggled on the parent. This
1702 * does not apply to the root level.
1705 gtk_tree_path_up (path);
1706 gtk_tree_model_get_iter (GTK_TREE_MODEL (filter), &iter, path);
1708 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (filter),
1713 if (!signals_emitted
1714 && gtk_tree_model_iter_children (c_model, &children, c_iter))
1715 gtk_tree_model_filter_update_children (filter, level, elt);
1718 gtk_tree_path_free (path);
1722 gtk_tree_model_filter_row_changed (GtkTreeModel *c_model,
1723 GtkTreePath *c_path,
1724 GtkTreeIter *c_iter,
1727 GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (data);
1729 GtkTreeIter children;
1730 GtkTreeIter real_c_iter;
1731 GtkTreePath *path = NULL;
1732 GtkTreePath *real_path = NULL;
1737 gboolean requested_state;
1738 gboolean current_state;
1739 gboolean free_c_path = FALSE;
1741 g_return_if_fail (c_path != NULL || c_iter != NULL);
1745 c_path = gtk_tree_model_get_path (c_model, c_iter);
1749 if (filter->priv->virtual_root)
1750 real_path = gtk_tree_model_filter_remove_root (c_path,
1751 filter->priv->virtual_root);
1753 real_path = gtk_tree_path_copy (c_path);
1756 real_c_iter = *c_iter;
1758 gtk_tree_model_get_iter (c_model, &real_c_iter, c_path);
1760 /* is this node above the virtual root? */
1761 if (filter->priv->virtual_root &&
1762 (gtk_tree_path_get_depth (filter->priv->virtual_root)
1763 >= gtk_tree_path_get_depth (c_path)))
1766 /* what's the requested state? */
1767 requested_state = gtk_tree_model_filter_visible (filter, &real_c_iter);
1769 /* now, let's see whether the item is there */
1770 path = gtk_real_tree_model_filter_convert_child_path_to_path (filter,
1777 gtk_tree_model_filter_get_iter_full (GTK_TREE_MODEL (filter),
1779 current_state = FILTER_ELT (iter.user_data2)->visible;
1782 current_state = FALSE;
1784 if (current_state == FALSE && requested_state == FALSE)
1785 /* no changes required */
1788 if (current_state == TRUE && requested_state == FALSE)
1790 gtk_tree_model_filter_remove_elt_from_level (filter,
1791 FILTER_LEVEL (iter.user_data),
1792 FILTER_ELT (iter.user_data2));
1795 gtk_tree_model_filter_check_ancestors (filter, real_path);
1800 if (current_state == TRUE && requested_state == TRUE)
1802 /* propagate the signal; also get a path taking only visible
1803 * nodes into account.
1805 gtk_tree_path_free (path);
1806 path = gtk_tree_model_get_path (GTK_TREE_MODEL (filter), &iter);
1808 level = FILTER_LEVEL (iter.user_data);
1809 elt = FILTER_ELT (iter.user_data2);
1811 if (gtk_tree_model_filter_elt_is_visible_in_target (level, elt))
1813 if (level->ext_ref_count > 0)
1814 gtk_tree_model_row_changed (GTK_TREE_MODEL (filter), path, &iter);
1816 /* and update the children */
1817 if (gtk_tree_model_iter_children (c_model, &children, &real_c_iter))
1818 gtk_tree_model_filter_update_children (filter, level, elt);
1822 gtk_tree_model_filter_check_ancestors (filter, real_path);
1827 /* only current == FALSE and requested == TRUE is left,
1830 g_return_if_fail (current_state == FALSE && requested_state == TRUE);
1833 gtk_tree_model_filter_check_ancestors (filter, real_path);
1835 gtk_tree_model_filter_emit_row_inserted_for_path (filter, c_model,
1840 gtk_tree_path_free (path);
1843 gtk_tree_path_free (real_path);
1846 gtk_tree_path_free (c_path);
1850 gtk_tree_model_filter_row_inserted (GtkTreeModel *c_model,
1851 GtkTreePath *c_path,
1852 GtkTreeIter *c_iter,
1855 GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (data);
1856 GtkTreePath *real_path = NULL;
1858 GtkTreeIter real_c_iter;
1860 FilterElt *elt = NULL;
1861 FilterLevel *level = NULL;
1862 FilterLevel *parent_level = NULL;
1866 gboolean free_c_path = FALSE;
1867 gboolean emit_row_inserted = FALSE;
1869 g_return_if_fail (c_path != NULL || c_iter != NULL);
1873 c_path = gtk_tree_model_get_path (c_model, c_iter);
1878 real_c_iter = *c_iter;
1880 gtk_tree_model_get_iter (c_model, &real_c_iter, c_path);
1882 /* the row has already been inserted. so we need to fixup the
1883 * virtual root here first
1885 if (filter->priv->virtual_root)
1887 if (gtk_tree_path_get_depth (filter->priv->virtual_root) >=
1888 gtk_tree_path_get_depth (c_path))
1891 gint *v_indices, *c_indices;
1892 gboolean common_prefix = TRUE;
1894 level = gtk_tree_path_get_depth (c_path) - 1;
1895 v_indices = gtk_tree_path_get_indices (filter->priv->virtual_root);
1896 c_indices = gtk_tree_path_get_indices (c_path);
1898 for (i = 0; i < level; i++)
1899 if (v_indices[i] != c_indices[i])
1901 common_prefix = FALSE;
1905 if (common_prefix && v_indices[level] >= c_indices[level])
1906 (v_indices[level])++;
1910 /* subtract virtual root if necessary */
1911 if (filter->priv->virtual_root)
1913 real_path = gtk_tree_model_filter_remove_root (c_path,
1914 filter->priv->virtual_root);
1920 real_path = gtk_tree_path_copy (c_path);
1922 if (!filter->priv->root)
1924 /* The root level has not been exposed to the view yet, so we
1925 * need to emit signals for any node that is being inserted.
1927 gtk_tree_model_filter_build_level (filter, NULL, NULL, TRUE);
1929 /* Check if the root level was built. Then child levels
1930 * that matter have also been built (due to update_children,
1931 * which triggers iter_n_children).
1933 if (filter->priv->root)
1935 emit_row_inserted = FALSE;
1940 if (gtk_tree_path_get_depth (real_path) - 1 >= 1)
1942 gboolean found = FALSE;
1943 GtkTreePath *parent = gtk_tree_path_copy (real_path);
1944 gtk_tree_path_up (parent);
1946 found = find_elt_with_offset (filter, parent, &parent_level, &elt);
1948 gtk_tree_path_free (parent);
1951 /* Parent is not in the cache and probably being filtered out */
1954 level = elt->children;
1957 level = FILTER_LEVEL (filter->priv->root);
1961 if (elt && elt->visible)
1963 /* The level in which the new node should be inserted does not
1964 * exist, but the parent, elt, does. If elt is visible, emit
1965 * row-has-child-toggled.
1967 GtkTreePath *tmppath;
1968 GtkTreeIter tmpiter;
1970 tmpiter.stamp = filter->priv->stamp;
1971 tmpiter.user_data = parent_level;
1972 tmpiter.user_data2 = elt;
1974 tmppath = gtk_tree_model_get_path (GTK_TREE_MODEL (filter),
1979 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (filter),
1981 gtk_tree_path_free (tmppath);
1987 /* let's try to insert the value */
1988 offset = gtk_tree_path_get_indices (real_path)[gtk_tree_path_get_depth (real_path) - 1];
1990 /* update the offsets, yes if we didn't insert the node above, there will
1991 * be a gap here. This will be filled with the node (via fetch_child) when
1992 * it becomes visible
1994 for (i = 0; i < level->array->len; i++)
1996 FilterElt *e = &g_array_index (level->array, FilterElt, i);
1997 if ((e->offset >= offset))
2001 /* only insert when visible */
2002 if (gtk_tree_model_filter_visible (filter, &real_c_iter))
2006 felt = gtk_tree_model_filter_insert_elt_in_level (filter,
2011 /* insert_elt_in_level defaults to FALSE */
2012 felt->visible = TRUE;
2013 level->visible_nodes++;
2015 emit_row_inserted = TRUE;
2019 gtk_tree_model_filter_check_ancestors (filter, real_path);
2021 if (emit_row_inserted)
2022 gtk_tree_model_filter_emit_row_inserted_for_path (filter, c_model,
2026 gtk_tree_path_free (real_path);
2029 gtk_tree_path_free (c_path);
2033 gtk_tree_model_filter_row_has_child_toggled (GtkTreeModel *c_model,
2034 GtkTreePath *c_path,
2035 GtkTreeIter *c_iter,
2038 GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (data);
2043 gboolean requested_state;
2045 g_return_if_fail (c_path != NULL && c_iter != NULL);
2047 /* If we get row-has-child-toggled on the virtual root, and there is
2048 * no root level; try to build it now.
2050 if (filter->priv->virtual_root && !filter->priv->root
2051 && !gtk_tree_path_compare (c_path, filter->priv->virtual_root))
2053 gtk_tree_model_filter_build_level (filter, NULL, NULL, TRUE);
2057 /* For all other levels, there is a chance that the visibility state
2058 * of the parent has changed now.
2061 path = gtk_real_tree_model_filter_convert_child_path_to_path (filter,
2068 gtk_tree_model_filter_get_iter_full (GTK_TREE_MODEL (data), &iter, path);
2070 level = FILTER_LEVEL (iter.user_data);
2071 elt = FILTER_ELT (iter.user_data2);
2073 gtk_tree_path_free (path);
2075 requested_state = gtk_tree_model_filter_visible (filter, c_iter);
2077 if (!elt->visible && !requested_state)
2079 /* The parent node currently is not visible and will not become
2080 * visible, so we will not pass on the row-has-child-toggled event.
2084 else if (elt->visible && !requested_state)
2086 /* The node is no longer visible, so it has to be removed.
2087 * _remove_elt_from_level() takes care of emitting row-has-child-toggled
2090 gtk_tree_model_filter_remove_elt_from_level (filter, level, elt);
2094 else if (!elt->visible && requested_state)
2096 elt->visible = TRUE;
2097 level->visible_nodes++;
2099 /* Only insert if the parent is visible in the target */
2100 if (gtk_tree_model_filter_elt_is_visible_in_target (level, elt))
2102 path = gtk_tree_model_get_path (GTK_TREE_MODEL (filter), &iter);
2103 gtk_tree_model_row_inserted (GTK_TREE_MODEL (filter), path, &iter);
2104 gtk_tree_path_free (path);
2106 /* We do not update children now, because that will happen
2111 /* For the remaining possibility, elt->visible && requested_state
2112 * no action is required.
2115 /* If this node is referenced and has children, build the level so we
2116 * can monitor it for changes.
2118 if (elt->ref_count > 1 && !elt->children &&
2119 gtk_tree_model_iter_has_child (c_model, c_iter))
2120 gtk_tree_model_filter_build_level (filter, level, elt, FALSE);
2122 /* get a path taking only visible nodes into account */
2123 path = gtk_tree_model_get_path (GTK_TREE_MODEL (data), &iter);
2124 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (data), path, &iter);
2125 gtk_tree_path_free (path);
2129 gtk_tree_model_filter_virtual_root_deleted (GtkTreeModelFilter *filter,
2130 GtkTreePath *c_path)
2134 FilterLevel *level = FILTER_LEVEL (filter->priv->root);
2136 /* The virtual root (or one of its ancestors) has been deleted. This
2137 * means that all content for our model is now gone. We deal with
2138 * this by removing everything in the filter model: we just iterate
2139 * over the root level and emit a row-deleted for each FilterElt.
2140 * (FIXME: Should we emit row-deleted for child nodes as well? This
2141 * has never been fully clear in TreeModel).
2144 /* We unref the path of the virtual root, up to and not including the
2145 * deleted node which can no longer be unreffed.
2147 gtk_tree_model_filter_unref_path (filter, filter->priv->virtual_root,
2148 gtk_tree_path_get_depth (c_path) - 1);
2149 filter->priv->virtual_root_deleted = TRUE;
2154 nodes = level->visible_nodes;
2156 /* We should not propagate the unref here. An unref for any of these
2157 * nodes will fail, since the respective nodes in the child model are
2160 gtk_tree_model_filter_free_level (filter, filter->priv->root, FALSE);
2162 gtk_tree_model_filter_increment_stamp (filter);
2164 path = gtk_tree_path_new ();
2165 gtk_tree_path_append_index (path, 0);
2167 for (i = 0; i < nodes; i++)
2168 gtk_tree_model_row_deleted (GTK_TREE_MODEL (filter), path);
2170 gtk_tree_path_free (path);
2174 gtk_tree_model_filter_adjust_virtual_root (GtkTreeModelFilter *filter,
2175 GtkTreePath *c_path)
2179 gint *v_indices, *c_indices;
2180 gboolean common_prefix = TRUE;
2182 level = gtk_tree_path_get_depth (c_path) - 1;
2183 v_indices = gtk_tree_path_get_indices (filter->priv->virtual_root);
2184 c_indices = gtk_tree_path_get_indices (c_path);
2186 for (i = 0; i < level; i++)
2187 if (v_indices[i] != c_indices[i])
2189 common_prefix = FALSE;
2193 if (common_prefix && v_indices[level] > c_indices[level])
2194 (v_indices[level])--;
2198 gtk_tree_model_filter_row_deleted_invisible_node (GtkTreeModelFilter *filter,
2199 GtkTreePath *c_path)
2203 GtkTreePath *real_path;
2207 /* The node deleted in the child model is not visible in the
2208 * filter model. We will not emit a signal, just fixup the offsets
2209 * of the other nodes.
2212 if (!filter->priv->root)
2215 level = FILTER_LEVEL (filter->priv->root);
2217 /* subtract vroot if necessary */
2218 if (filter->priv->virtual_root)
2220 real_path = gtk_tree_model_filter_remove_root (c_path,
2221 filter->priv->virtual_root);
2222 /* we don't handle this */
2227 real_path = gtk_tree_path_copy (c_path);
2229 if (gtk_tree_path_get_depth (real_path) - 1 >= 1)
2231 gboolean found = FALSE;
2232 GtkTreePath *parent = gtk_tree_path_copy (real_path);
2233 gtk_tree_path_up (parent);
2235 found = find_elt_with_offset (filter, parent, &level, &elt);
2237 gtk_tree_path_free (parent);
2241 /* parent is filtered out, so no level */
2242 gtk_tree_path_free (real_path);
2246 level = elt->children;
2249 offset = gtk_tree_path_get_indices (real_path)[gtk_tree_path_get_depth (real_path) - 1];
2250 gtk_tree_path_free (real_path);
2255 /* decrease offset of all nodes following the deleted node */
2256 for (i = 0; i < level->array->len; i++)
2258 elt = &g_array_index (level->array, FilterElt, i);
2259 if (elt->offset > offset)
2262 elt->children->parent_elt = elt;
2267 gtk_tree_model_filter_row_deleted (GtkTreeModel *c_model,
2268 GtkTreePath *c_path,
2271 GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (data);
2274 FilterElt *elt, *parent_elt = NULL;
2275 FilterLevel *level, *parent_level = NULL;
2276 gboolean emit_child_toggled = FALSE;
2277 gboolean emit_row_deleted = FALSE;
2280 gint orig_level_ext_ref_count;
2282 g_return_if_fail (c_path != NULL);
2284 /* special case the deletion of an ancestor of the virtual root */
2285 if (filter->priv->virtual_root &&
2286 (gtk_tree_path_is_ancestor (c_path, filter->priv->virtual_root) ||
2287 !gtk_tree_path_compare (c_path, filter->priv->virtual_root)))
2289 gtk_tree_model_filter_virtual_root_deleted (filter, c_path);
2293 /* adjust the virtual root for the deleted row */
2294 if (filter->priv->virtual_root &&
2295 gtk_tree_path_get_depth (filter->priv->virtual_root) >=
2296 gtk_tree_path_get_depth (c_path))
2297 gtk_tree_model_filter_adjust_virtual_root (filter, c_path);
2299 path = gtk_real_tree_model_filter_convert_child_path_to_path (filter,
2306 gtk_tree_model_filter_row_deleted_invisible_node (filter, c_path);
2310 /* a node was deleted, which was in our cache */
2311 gtk_tree_model_filter_get_iter_full (GTK_TREE_MODEL (data), &iter, path);
2313 level = FILTER_LEVEL (iter.user_data);
2314 elt = FILTER_ELT (iter.user_data2);
2315 offset = elt->offset;
2316 orig_level_ext_ref_count = level->ext_ref_count;
2320 /* get a path taking only visible nodes into account */
2321 gtk_tree_path_free (path);
2322 path = gtk_tree_model_get_path (GTK_TREE_MODEL (filter), &iter);
2324 level->visible_nodes--;
2326 if (level->visible_nodes == 0)
2328 emit_child_toggled = TRUE;
2329 parent_level = level->parent_level;
2330 parent_elt = level->parent_elt;
2333 emit_row_deleted = TRUE;
2336 /* Release the references on this node, without propagation because
2337 * the node does not exist anymore in the child model. The filter
2338 * model's references on the node in case of level->parent or use
2339 * of a virtual root are automatically destroyed by the child model.
2341 while (elt->ext_ref_count > 0)
2342 gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (data), &iter,
2344 while (elt->ref_count > 0)
2345 gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (data), &iter,
2348 if (level->array->len == 1)
2351 gtk_tree_model_filter_free_level (filter, level, FALSE);
2358 is_first = elt == &g_array_index (level->array, FilterElt, 0);
2360 /* remove the row */
2361 tmp = bsearch_elt_with_offset (level->array, elt->offset, &i);
2363 offset = tmp->offset;
2364 g_array_remove_index (level->array, i);
2367 for (i = MAX (i, 0); i < level->array->len; i++)
2369 elt = &g_array_index (level->array, FilterElt, i);
2370 if (elt->offset > offset)
2373 elt->children->parent_elt = elt;
2376 /* Take a reference on the new first node. The first node previously
2377 * keeping this reference has been removed above.
2383 f_iter.stamp = filter->priv->stamp;
2384 f_iter.user_data = level;
2385 f_iter.user_data2 = &(g_array_index (level->array, FilterElt, 0));
2387 gtk_tree_model_filter_real_ref_node (GTK_TREE_MODEL (filter),
2392 if (emit_row_deleted)
2394 /* emit row_deleted */
2395 gtk_tree_model_filter_increment_stamp (filter);
2397 if (!parent_elt || orig_level_ext_ref_count > 0)
2398 gtk_tree_model_row_deleted (GTK_TREE_MODEL (data), path);
2401 if (emit_child_toggled && parent_level)
2406 iter2.stamp = filter->priv->stamp;
2407 iter2.user_data = parent_level;
2408 iter2.user_data2 = parent_elt;
2410 /* We set in_row_deleted to TRUE to avoid a level build triggered
2411 * by row-has-child-toggled (parent model could call iter_has_child
2414 filter->priv->in_row_deleted = TRUE;
2415 path2 = gtk_tree_model_get_path (GTK_TREE_MODEL (filter), &iter2);
2416 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (filter),
2418 gtk_tree_path_free (path2);
2419 filter->priv->in_row_deleted = FALSE;
2422 if (filter->priv->virtual_root)
2424 GtkTreePath *real_path;
2426 real_path = gtk_tree_model_filter_remove_root (c_path,
2427 filter->priv->root);
2430 gtk_tree_model_filter_check_ancestors (filter, real_path);
2431 gtk_tree_path_free (real_path);
2435 gtk_tree_model_filter_check_ancestors (filter, c_path);
2437 gtk_tree_path_free (path);
2441 gtk_tree_model_filter_rows_reordered (GtkTreeModel *c_model,
2442 GtkTreePath *c_path,
2443 GtkTreeIter *c_iter,
2449 GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (data);
2455 gint i, j, elt_count;
2457 gint first_elt_new_index = -1;
2461 g_return_if_fail (new_order != NULL);
2463 if (c_path == NULL || gtk_tree_path_get_depth (c_path) == 0)
2465 length = gtk_tree_model_iter_n_children (c_model, NULL);
2467 if (filter->priv->virtual_root)
2471 /* reorder root level of path */
2472 for (i = 0; i < length; i++)
2473 if (new_order[i] == gtk_tree_path_get_indices (filter->priv->virtual_root)[0])
2479 gtk_tree_path_get_indices (filter->priv->virtual_root)[0] = new_pos;
2483 path = gtk_tree_path_new ();
2484 level = FILTER_LEVEL (filter->priv->root);
2488 GtkTreeIter child_iter;
2490 /* virtual root anchor reordering */
2491 if (filter->priv->virtual_root &&
2492 gtk_tree_path_is_ancestor (c_path, filter->priv->virtual_root))
2497 GtkTreeIter real_c_iter;
2499 level = gtk_tree_path_get_depth (c_path);
2502 real_c_iter = *c_iter;
2504 gtk_tree_model_get_iter (c_model, &real_c_iter, c_path);
2506 length = gtk_tree_model_iter_n_children (c_model, &real_c_iter);
2508 for (i = 0; i < length; i++)
2509 if (new_order[i] == gtk_tree_path_get_indices (filter->priv->virtual_root)[level])
2515 gtk_tree_path_get_indices (filter->priv->virtual_root)[level] = new_pos;
2519 path = gtk_real_tree_model_filter_convert_child_path_to_path (filter,
2524 if (!path && filter->priv->virtual_root &&
2525 gtk_tree_path_compare (c_path, filter->priv->virtual_root))
2528 if (!path && !filter->priv->virtual_root)
2533 /* root level mode */
2535 gtk_tree_model_get_iter (c_model, c_iter, c_path);
2536 length = gtk_tree_model_iter_n_children (c_model, c_iter);
2537 path = gtk_tree_path_new ();
2538 level = FILTER_LEVEL (filter->priv->root);
2542 gtk_tree_model_filter_get_iter_full (GTK_TREE_MODEL (data),
2545 level = FILTER_LEVEL (iter.user_data);
2546 elt = FILTER_ELT (iter.user_data2);
2550 gtk_tree_path_free (path);
2554 level = elt->children;
2556 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (filter), &child_iter, &iter);
2557 length = gtk_tree_model_iter_n_children (c_model, &child_iter);
2561 if (!level || level->array->len < 1)
2563 gtk_tree_path_free (path);
2567 /* NOTE: we do not bail out here if level->array->len < 2 like
2568 * GtkTreeModelSort does. This because we do some special tricky
2572 /* construct a new array */
2573 new_array = g_array_sized_new (FALSE, FALSE, sizeof (FilterElt),
2575 tmp_array = g_new (gint, level->array->len);
2577 for (i = 0, elt_count = 0; i < length; i++)
2579 FilterElt *e = NULL;
2580 gint old_offset = -1;
2582 for (j = 0; j < level->array->len; j++)
2583 if (g_array_index (level->array, FilterElt, j).offset == new_order[i])
2585 e = &g_array_index (level->array, FilterElt, j);
2593 if (old_offset == 0)
2594 first_elt_new_index = elt_count;
2596 tmp_array[elt_count] = old_offset;
2597 g_array_append_val (new_array, *e);
2598 g_array_index (new_array, FilterElt, elt_count).offset = i;
2602 g_array_free (level->array, TRUE);
2603 level->array = new_array;
2606 for (i = 0; i < level->array->len; i++)
2608 FilterElt *e = &g_array_index (level->array, FilterElt, i);
2610 e->children->parent_elt = e;
2613 /* Transfer the reference from the old item at position 0 to the
2614 * new item at position 0.
2616 if (first_elt_new_index != -1 && first_elt_new_index != 0)
2617 gtk_tree_model_filter_level_transfer_first_ref (filter,
2619 first_elt_new_index, 0);
2622 /* emit rows_reordered */
2623 if (level->visible_nodes > 0)
2625 if (!gtk_tree_path_get_indices (path))
2626 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (data), path, NULL,
2630 /* get a path taking only visible nodes into account */
2631 gtk_tree_path_free (path);
2632 path = gtk_tree_model_get_path (GTK_TREE_MODEL (data), &iter);
2634 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (data), path, &iter,
2641 gtk_tree_path_free (path);
2644 /* TreeModelIface implementation */
2645 static GtkTreeModelFlags
2646 gtk_tree_model_filter_get_flags (GtkTreeModel *model)
2648 GtkTreeModelFlags flags;
2650 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), 0);
2651 g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL, 0);
2653 flags = gtk_tree_model_get_flags (GTK_TREE_MODEL_FILTER (model)->priv->child_model);
2655 if ((flags & GTK_TREE_MODEL_LIST_ONLY) == GTK_TREE_MODEL_LIST_ONLY)
2656 return GTK_TREE_MODEL_LIST_ONLY;
2662 gtk_tree_model_filter_get_n_columns (GtkTreeModel *model)
2664 GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
2666 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), 0);
2667 g_return_val_if_fail (filter->priv->child_model != NULL, 0);
2669 if (filter->priv->child_model == NULL)
2672 /* so we can't modify the modify func after this ... */
2673 filter->priv->modify_func_set = TRUE;
2675 if (filter->priv->modify_n_columns > 0)
2676 return filter->priv->modify_n_columns;
2678 return gtk_tree_model_get_n_columns (filter->priv->child_model);
2682 gtk_tree_model_filter_get_column_type (GtkTreeModel *model,
2685 GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
2687 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), G_TYPE_INVALID);
2688 g_return_val_if_fail (filter->priv->child_model != NULL, G_TYPE_INVALID);
2690 /* so we can't modify the modify func after this ... */
2691 filter->priv->modify_func_set = TRUE;
2693 if (filter->priv->modify_types)
2695 g_return_val_if_fail (index < filter->priv->modify_n_columns, G_TYPE_INVALID);
2697 return filter->priv->modify_types[index];
2700 return gtk_tree_model_get_column_type (filter->priv->child_model, index);
2703 /* A special case of _get_iter; this function can also get iters which
2704 * are not visible. These iters should ONLY be passed internally, never
2705 * pass those along with a signal emission.
2708 gtk_tree_model_filter_get_iter_full (GtkTreeModel *model,
2712 GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
2717 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
2718 g_return_val_if_fail (filter->priv->child_model != NULL, FALSE);
2720 indices = gtk_tree_path_get_indices (path);
2722 if (filter->priv->root == NULL)
2723 gtk_tree_model_filter_build_level (filter, NULL, NULL, FALSE);
2724 level = FILTER_LEVEL (filter->priv->root);
2726 depth = gtk_tree_path_get_depth (path);
2733 for (i = 0; i < depth - 1; i++)
2735 if (!level || indices[i] >= level->array->len)
2741 elt = gtk_tree_model_filter_get_nth (filter, level, indices[i]);
2744 gtk_tree_model_filter_build_level (filter, level, elt, FALSE);
2745 level = elt->children;
2748 if (!level || indices[i] >= level->array->len)
2754 iter->stamp = filter->priv->stamp;
2755 iter->user_data = level;
2757 elt = gtk_tree_model_filter_get_nth (filter, level, indices[depth - 1]);
2758 iter->user_data2 = elt;
2764 gtk_tree_model_filter_get_iter (GtkTreeModel *model,
2768 GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
2773 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
2774 g_return_val_if_fail (filter->priv->child_model != NULL, FALSE);
2776 indices = gtk_tree_path_get_indices (path);
2778 if (filter->priv->root == NULL)
2779 gtk_tree_model_filter_build_level (filter, NULL, NULL, FALSE);
2780 level = FILTER_LEVEL (filter->priv->root);
2782 depth = gtk_tree_path_get_depth (path);
2789 for (i = 0; i < depth - 1; i++)
2791 if (!level || indices[i] >= level->visible_nodes)
2797 elt = gtk_tree_model_filter_get_nth_visible (filter, level, indices[i]);
2800 gtk_tree_model_filter_build_level (filter, level, elt, FALSE);
2801 level = elt->children;
2804 if (!level || indices[i] >= level->visible_nodes)
2810 iter->stamp = filter->priv->stamp;
2811 iter->user_data = level;
2813 elt = gtk_tree_model_filter_get_nth_visible (filter, level,
2814 indices[depth - 1]);
2815 iter->user_data2 = elt;
2820 static GtkTreePath *
2821 gtk_tree_model_filter_get_path (GtkTreeModel *model,
2824 GtkTreePath *retval;
2828 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), NULL);
2829 g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL, NULL);
2830 g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->stamp == iter->stamp, NULL);
2832 level = iter->user_data;
2833 elt = iter->user_data2;
2838 retval = gtk_tree_path_new ();
2842 int i = 0, index = 0;
2844 while (&g_array_index (level->array, FilterElt, i) != elt)
2846 if (g_array_index (level->array, FilterElt, i).visible)
2850 g_assert (i < level->array->len);
2853 gtk_tree_path_prepend_index (retval, index);
2854 elt = level->parent_elt;
2855 level = level->parent_level;
2862 gtk_tree_model_filter_real_modify (GtkTreeModelFilter *self,
2863 GtkTreeModel *child_model,
2868 if (self->priv->modify_func)
2870 g_return_if_fail (column < self->priv->modify_n_columns);
2872 g_value_init (value, self->priv->modify_types[column]);
2873 self->priv->modify_func (GTK_TREE_MODEL (self),
2877 self->priv->modify_data);
2881 GtkTreeIter child_iter;
2883 gtk_tree_model_filter_convert_iter_to_child_iter (
2884 GTK_TREE_MODEL_FILTER (self), &child_iter, iter);
2885 gtk_tree_model_get_value (child_model,
2886 &child_iter, column, value);
2891 gtk_tree_model_filter_get_value (GtkTreeModel *model,
2896 GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (model);
2898 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (model));
2899 g_return_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL);
2900 g_return_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->stamp == iter->stamp);
2902 GTK_TREE_MODEL_FILTER_GET_CLASS (model)->modify (filter,
2903 filter->priv->child_model, iter, value, column);
2907 gtk_tree_model_filter_iter_next (GtkTreeModel *model,
2914 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
2915 g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL, FALSE);
2916 g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->stamp == iter->stamp, FALSE);
2918 level = iter->user_data;
2919 elt = iter->user_data2;
2921 i = elt - FILTER_ELT (level->array->data);
2923 while (i < level->array->len - 1)
2930 iter->user_data2 = elt;
2935 /* no next visible iter */
2942 gtk_tree_model_filter_iter_previous (GtkTreeModel *model,
2949 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
2950 g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL, FALSE);
2951 g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->stamp == iter->stamp, FALSE);
2953 level = iter->user_data;
2954 elt = iter->user_data2;
2956 i = elt - FILTER_ELT (level->array->data);
2965 iter->user_data2 = elt;
2970 /* no previous visible iter */
2977 gtk_tree_model_filter_iter_children (GtkTreeModel *model,
2979 GtkTreeIter *parent)
2981 GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
2985 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
2986 g_return_val_if_fail (filter->priv->child_model != NULL, FALSE);
2988 g_return_val_if_fail (filter->priv->stamp == parent->stamp, FALSE);
2994 if (!filter->priv->root)
2995 gtk_tree_model_filter_build_level (filter, NULL, NULL, FALSE);
2996 if (!filter->priv->root)
2999 level = filter->priv->root;
3001 if (!level->visible_nodes)
3004 iter->stamp = filter->priv->stamp;
3005 iter->user_data = level;
3007 while (i < level->array->len)
3009 if (!g_array_index (level->array, FilterElt, i).visible)
3015 iter->user_data2 = &g_array_index (level->array, FilterElt, i);
3026 if (FILTER_ELT (parent->user_data2)->children == NULL)
3027 gtk_tree_model_filter_build_level (filter,
3028 FILTER_LEVEL (parent->user_data),
3029 FILTER_ELT (parent->user_data2),
3031 if (FILTER_ELT (parent->user_data2)->children == NULL)
3034 if (FILTER_ELT (parent->user_data2)->children->visible_nodes <= 0)
3037 iter->stamp = filter->priv->stamp;
3038 iter->user_data = FILTER_ELT (parent->user_data2)->children;
3040 level = FILTER_LEVEL (iter->user_data);
3042 while (i < level->array->len)
3044 if (!g_array_index (level->array, FilterElt, i).visible)
3050 iter->user_data2 = &g_array_index (level->array, FilterElt, i);
3063 gtk_tree_model_filter_iter_has_child (GtkTreeModel *model,
3066 GtkTreeIter child_iter;
3067 GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
3070 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
3071 g_return_val_if_fail (filter->priv->child_model != NULL, FALSE);
3072 g_return_val_if_fail (filter->priv->stamp == iter->stamp, FALSE);
3074 filter = GTK_TREE_MODEL_FILTER (model);
3076 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_iter, iter);
3077 elt = FILTER_ELT (iter->user_data2);
3082 /* we need to build the level to check if not all children are filtered
3086 && gtk_tree_model_iter_has_child (filter->priv->child_model, &child_iter))
3087 gtk_tree_model_filter_build_level (filter, FILTER_LEVEL (iter->user_data),
3090 if (elt->children && elt->children->visible_nodes > 0)
3097 gtk_tree_model_filter_iter_n_children (GtkTreeModel *model,
3100 GtkTreeIter child_iter;
3101 GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
3104 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), 0);
3105 g_return_val_if_fail (filter->priv->child_model != NULL, 0);
3107 g_return_val_if_fail (filter->priv->stamp == iter->stamp, 0);
3111 if (!filter->priv->root)
3112 gtk_tree_model_filter_build_level (filter, NULL, NULL, FALSE);
3114 if (filter->priv->root)
3115 return FILTER_LEVEL (filter->priv->root)->visible_nodes;
3120 elt = FILTER_ELT (iter->user_data2);
3125 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_iter, iter);
3127 if (!elt->children &&
3128 gtk_tree_model_iter_has_child (filter->priv->child_model, &child_iter))
3129 gtk_tree_model_filter_build_level (filter,
3130 FILTER_LEVEL (iter->user_data),
3134 return elt->children->visible_nodes;
3140 gtk_tree_model_filter_iter_nth_child (GtkTreeModel *model,
3142 GtkTreeIter *parent,
3147 GtkTreeIter children;
3149 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
3151 g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->stamp == parent->stamp, FALSE);
3153 /* use this instead of has_child to force us to build the level, if needed */
3154 if (gtk_tree_model_filter_iter_children (model, &children, parent) == FALSE)
3160 level = children.user_data;
3161 elt = FILTER_ELT (level->array->data);
3163 if (n >= level->visible_nodes)
3169 elt = gtk_tree_model_filter_get_nth_visible (GTK_TREE_MODEL_FILTER (model),
3172 iter->stamp = GTK_TREE_MODEL_FILTER (model)->priv->stamp;
3173 iter->user_data = level;
3174 iter->user_data2 = elt;
3180 gtk_tree_model_filter_iter_parent (GtkTreeModel *model,
3187 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
3188 g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL, FALSE);
3189 g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->stamp == child->stamp, FALSE);
3191 level = child->user_data;
3193 if (level->parent_level)
3195 iter->stamp = GTK_TREE_MODEL_FILTER (model)->priv->stamp;
3196 iter->user_data = level->parent_level;
3197 iter->user_data2 = level->parent_elt;
3206 gtk_tree_model_filter_ref_node (GtkTreeModel *model,
3209 gtk_tree_model_filter_real_ref_node (model, iter, TRUE);
3213 gtk_tree_model_filter_real_ref_node (GtkTreeModel *model,
3217 GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
3218 GtkTreeIter child_iter;
3222 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (model));
3223 g_return_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL);
3224 g_return_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->stamp == iter->stamp);
3226 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_iter, iter);
3228 gtk_tree_model_ref_node (filter->priv->child_model, &child_iter);
3230 level = iter->user_data;
3231 elt = iter->user_data2;
3238 elt->ext_ref_count++;
3239 level->ext_ref_count++;
3241 if (level->ext_ref_count == 1)
3243 FilterLevel *parent_level = level->parent_level;
3244 FilterElt *parent_elt = level->parent_elt;
3246 /* we were at zero -- time to decrease the zero_ref_count val */
3247 while (parent_level)
3249 parent_elt->zero_ref_count--;
3251 parent_elt = parent_level->parent_elt;
3252 parent_level = parent_level->parent_level;
3255 if (filter->priv->root != level)
3256 filter->priv->zero_ref_count--;
3262 gtk_tree_model_filter_unref_node (GtkTreeModel *model,
3265 gtk_tree_model_filter_real_unref_node (model, iter, TRUE, TRUE);
3269 gtk_tree_model_filter_real_unref_node (GtkTreeModel *model,
3272 gboolean propagate_unref)
3274 GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
3278 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (model));
3279 g_return_if_fail (filter->priv->child_model != NULL);
3280 g_return_if_fail (filter->priv->stamp == iter->stamp);
3282 if (propagate_unref)
3284 GtkTreeIter child_iter;
3285 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_iter, iter);
3286 gtk_tree_model_unref_node (filter->priv->child_model, &child_iter);
3289 level = iter->user_data;
3290 elt = iter->user_data2;
3292 g_return_if_fail (elt->ref_count > 0);
3299 elt->ext_ref_count--;
3300 level->ext_ref_count--;
3302 if (level->ext_ref_count == 0)
3304 FilterLevel *parent_level = level->parent_level;
3305 FilterElt *parent_elt = level->parent_elt;
3307 /* we are at zero -- time to increase 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++;
3322 /* TreeDragSource interface implementation */
3324 gtk_tree_model_filter_row_draggable (GtkTreeDragSource *drag_source,
3327 GtkTreeModelFilter *tree_model_filter = (GtkTreeModelFilter *)drag_source;
3328 GtkTreePath *child_path;
3331 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (drag_source), FALSE);
3332 g_return_val_if_fail (path != NULL, FALSE);
3334 child_path = gtk_tree_model_filter_convert_path_to_child_path (tree_model_filter, path);
3335 draggable = gtk_tree_drag_source_row_draggable (GTK_TREE_DRAG_SOURCE (tree_model_filter->priv->child_model), child_path);
3336 gtk_tree_path_free (child_path);
3342 gtk_tree_model_filter_drag_data_get (GtkTreeDragSource *drag_source,
3344 GtkSelectionData *selection_data)
3346 GtkTreeModelFilter *tree_model_filter = (GtkTreeModelFilter *)drag_source;
3347 GtkTreePath *child_path;
3350 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (drag_source), FALSE);
3351 g_return_val_if_fail (path != NULL, FALSE);
3353 child_path = gtk_tree_model_filter_convert_path_to_child_path (tree_model_filter, path);
3354 gotten = gtk_tree_drag_source_drag_data_get (GTK_TREE_DRAG_SOURCE (tree_model_filter->priv->child_model), child_path, selection_data);
3355 gtk_tree_path_free (child_path);
3361 gtk_tree_model_filter_drag_data_delete (GtkTreeDragSource *drag_source,
3364 GtkTreeModelFilter *tree_model_filter = (GtkTreeModelFilter *)drag_source;
3365 GtkTreePath *child_path;
3368 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (drag_source), FALSE);
3369 g_return_val_if_fail (path != NULL, FALSE);
3371 child_path = gtk_tree_model_filter_convert_path_to_child_path (tree_model_filter, path);
3372 deleted = gtk_tree_drag_source_drag_data_delete (GTK_TREE_DRAG_SOURCE (tree_model_filter->priv->child_model), child_path);
3373 gtk_tree_path_free (child_path);
3378 /* bits and pieces */
3380 gtk_tree_model_filter_set_model (GtkTreeModelFilter *filter,
3381 GtkTreeModel *child_model)
3383 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
3385 if (filter->priv->child_model)
3387 g_signal_handler_disconnect (filter->priv->child_model,
3388 filter->priv->changed_id);
3389 g_signal_handler_disconnect (filter->priv->child_model,
3390 filter->priv->inserted_id);
3391 g_signal_handler_disconnect (filter->priv->child_model,
3392 filter->priv->has_child_toggled_id);
3393 g_signal_handler_disconnect (filter->priv->child_model,
3394 filter->priv->deleted_id);
3395 g_signal_handler_disconnect (filter->priv->child_model,
3396 filter->priv->reordered_id);
3398 /* reset our state */
3399 if (filter->priv->root)
3400 gtk_tree_model_filter_free_level (filter, filter->priv->root, TRUE);
3402 filter->priv->root = NULL;
3403 g_object_unref (filter->priv->child_model);
3404 filter->priv->visible_column = -1;
3406 /* FIXME: do we need to destroy more here? */
3409 filter->priv->child_model = child_model;
3413 g_object_ref (filter->priv->child_model);
3414 filter->priv->changed_id =
3415 g_signal_connect (child_model, "row-changed",
3416 G_CALLBACK (gtk_tree_model_filter_row_changed),
3418 filter->priv->inserted_id =
3419 g_signal_connect (child_model, "row-inserted",
3420 G_CALLBACK (gtk_tree_model_filter_row_inserted),
3422 filter->priv->has_child_toggled_id =
3423 g_signal_connect (child_model, "row-has-child-toggled",
3424 G_CALLBACK (gtk_tree_model_filter_row_has_child_toggled),
3426 filter->priv->deleted_id =
3427 g_signal_connect (child_model, "row-deleted",
3428 G_CALLBACK (gtk_tree_model_filter_row_deleted),
3430 filter->priv->reordered_id =
3431 g_signal_connect (child_model, "rows-reordered",
3432 G_CALLBACK (gtk_tree_model_filter_rows_reordered),
3435 filter->priv->child_flags = gtk_tree_model_get_flags (child_model);
3436 filter->priv->stamp = g_random_int ();
3441 gtk_tree_model_filter_ref_path (GtkTreeModelFilter *filter,
3447 len = gtk_tree_path_get_depth (path);
3448 p = gtk_tree_path_copy (path);
3453 gtk_tree_model_get_iter (GTK_TREE_MODEL (filter->priv->child_model), &iter, p);
3454 gtk_tree_model_ref_node (GTK_TREE_MODEL (filter->priv->child_model), &iter);
3455 gtk_tree_path_up (p);
3458 gtk_tree_path_free (p);
3462 gtk_tree_model_filter_unref_path (GtkTreeModelFilter *filter,
3472 len = gtk_tree_path_get_depth (path);
3474 p = gtk_tree_path_copy (path);
3479 gtk_tree_model_get_iter (GTK_TREE_MODEL (filter->priv->child_model), &iter, p);
3480 gtk_tree_model_unref_node (GTK_TREE_MODEL (filter->priv->child_model), &iter);
3481 gtk_tree_path_up (p);
3484 gtk_tree_path_free (p);
3488 gtk_tree_model_filter_set_root (GtkTreeModelFilter *filter,
3491 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
3494 filter->priv->virtual_root = NULL;
3496 filter->priv->virtual_root = gtk_tree_path_copy (root);
3502 * gtk_tree_model_filter_new:
3503 * @child_model: A #GtkTreeModel.
3504 * @root: (allow-none): A #GtkTreePath or %NULL.
3506 * Creates a new #GtkTreeModel, with @child_model as the child_model
3507 * and @root as the virtual root.
3509 * Return value: (transfer full): A new #GtkTreeModel.
3514 gtk_tree_model_filter_new (GtkTreeModel *child_model,
3517 GtkTreeModel *retval;
3518 GtkTreeModelFilter *filter;
3520 g_return_val_if_fail (GTK_IS_TREE_MODEL (child_model), NULL);
3522 retval = g_object_new (GTK_TYPE_TREE_MODEL_FILTER,
3523 "child-model", child_model,
3524 "virtual-root", root,
3527 filter = GTK_TREE_MODEL_FILTER (retval);
3528 if (filter->priv->virtual_root)
3530 gtk_tree_model_filter_ref_path (filter, filter->priv->virtual_root);
3531 filter->priv->virtual_root_deleted = FALSE;
3538 * gtk_tree_model_filter_get_model:
3539 * @filter: A #GtkTreeModelFilter.
3541 * Returns a pointer to the child model of @filter.
3543 * Return value: (transfer none): A pointer to a #GtkTreeModel.
3548 gtk_tree_model_filter_get_model (GtkTreeModelFilter *filter)
3550 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (filter), NULL);
3552 return filter->priv->child_model;
3556 * gtk_tree_model_filter_set_visible_func:
3557 * @filter: A #GtkTreeModelFilter.
3558 * @func: A #GtkTreeModelFilterVisibleFunc, the visible function.
3559 * @data: (allow-none): User data to pass to the visible function, or %NULL.
3560 * @destroy: (allow-none): Destroy notifier of @data, or %NULL.
3562 * Sets the visible function used when filtering the @filter to be @func. The
3563 * function should return %TRUE if the given row should be visible and
3566 * If the condition calculated by the function changes over time (e.g. because
3567 * it depends on some global parameters), you must call
3568 * gtk_tree_model_filter_refilter() to keep the visibility information of
3569 * the model uptodate.
3571 * Note that @func is called whenever a row is inserted, when it may still be
3572 * empty. The visible function should therefore take special care of empty
3573 * rows, like in the example below.
3575 * <informalexample><programlisting>
3577 * visible_func (GtkTreeModel *model,
3578 * GtkTreeIter *iter,
3581 * /* Visible if row is non-empty and first column is "HI" */
3583 * gboolean visible = FALSE;
3585 * gtk_tree_model_get (model, iter, 0, &str, -1);
3586 * if (str && strcmp (str, "HI") == 0)
3592 * </programlisting></informalexample>
3597 gtk_tree_model_filter_set_visible_func (GtkTreeModelFilter *filter,
3598 GtkTreeModelFilterVisibleFunc func,
3600 GDestroyNotify destroy)
3602 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
3603 g_return_if_fail (func != NULL);
3604 g_return_if_fail (filter->priv->visible_method_set == FALSE);
3606 filter->priv->visible_func = func;
3607 filter->priv->visible_data = data;
3608 filter->priv->visible_destroy = destroy;
3610 filter->priv->visible_method_set = TRUE;
3614 * gtk_tree_model_filter_set_modify_func:
3615 * @filter: A #GtkTreeModelFilter.
3616 * @n_columns: The number of columns in the filter model.
3617 * @types: (array length=n_columns): The #GType<!-- -->s of the columns.
3618 * @func: A #GtkTreeModelFilterModifyFunc
3619 * @data: (allow-none): User data to pass to the modify function, or %NULL.
3620 * @destroy: (allow-none): Destroy notifier of @data, or %NULL.
3622 * With the @n_columns and @types parameters, you give an array of column
3623 * types for this model (which will be exposed to the parent model/view).
3624 * The @func, @data and @destroy parameters are for specifying the modify
3625 * function. The modify function will get called for <emphasis>each</emphasis>
3626 * data access, the goal of the modify function is to return the data which
3627 * should be displayed at the location specified using the parameters of the
3633 gtk_tree_model_filter_set_modify_func (GtkTreeModelFilter *filter,
3636 GtkTreeModelFilterModifyFunc func,
3638 GDestroyNotify destroy)
3640 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
3641 g_return_if_fail (func != NULL);
3642 g_return_if_fail (filter->priv->modify_func_set == FALSE);
3644 if (filter->priv->modify_destroy)
3646 GDestroyNotify d = filter->priv->modify_destroy;
3648 filter->priv->modify_destroy = NULL;
3649 d (filter->priv->modify_data);
3652 filter->priv->modify_n_columns = n_columns;
3653 filter->priv->modify_types = g_new0 (GType, n_columns);
3654 memcpy (filter->priv->modify_types, types, sizeof (GType) * n_columns);
3655 filter->priv->modify_func = func;
3656 filter->priv->modify_data = data;
3657 filter->priv->modify_destroy = destroy;
3659 filter->priv->modify_func_set = TRUE;
3663 * gtk_tree_model_filter_set_visible_column:
3664 * @filter: A #GtkTreeModelFilter.
3665 * @column: A #gint which is the column containing the visible information.
3667 * Sets @column of the child_model to be the column where @filter should
3668 * look for visibility information. @columns should be a column of type
3669 * %G_TYPE_BOOLEAN, where %TRUE means that a row is visible, and %FALSE
3675 gtk_tree_model_filter_set_visible_column (GtkTreeModelFilter *filter,
3678 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
3679 g_return_if_fail (column >= 0);
3680 g_return_if_fail (filter->priv->visible_method_set == FALSE);
3682 filter->priv->visible_column = column;
3684 filter->priv->visible_method_set = TRUE;
3690 * gtk_tree_model_filter_convert_child_iter_to_iter:
3691 * @filter: A #GtkTreeModelFilter.
3692 * @filter_iter: (out): An uninitialized #GtkTreeIter.
3693 * @child_iter: A valid #GtkTreeIter pointing to a row on the child model.
3695 * Sets @filter_iter to point to the row in @filter that corresponds to the
3696 * row pointed at by @child_iter. If @filter_iter was not set, %FALSE is
3699 * Return value: %TRUE, if @filter_iter was set, i.e. if @child_iter is a
3700 * valid iterator pointing to a visible row in child model.
3705 gtk_tree_model_filter_convert_child_iter_to_iter (GtkTreeModelFilter *filter,
3706 GtkTreeIter *filter_iter,
3707 GtkTreeIter *child_iter)
3710 GtkTreePath *child_path, *path;
3712 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (filter), FALSE);
3713 g_return_val_if_fail (filter->priv->child_model != NULL, FALSE);
3714 g_return_val_if_fail (filter_iter != NULL, FALSE);
3715 g_return_val_if_fail (child_iter != NULL, FALSE);
3716 g_return_val_if_fail (filter_iter != child_iter, FALSE);
3718 filter_iter->stamp = 0;
3720 child_path = gtk_tree_model_get_path (filter->priv->child_model, child_iter);
3721 g_return_val_if_fail (child_path != NULL, FALSE);
3723 path = gtk_tree_model_filter_convert_child_path_to_path (filter,
3725 gtk_tree_path_free (child_path);
3730 ret = gtk_tree_model_get_iter (GTK_TREE_MODEL (filter), filter_iter, path);
3731 gtk_tree_path_free (path);
3737 * gtk_tree_model_filter_convert_iter_to_child_iter:
3738 * @filter: A #GtkTreeModelFilter.
3739 * @child_iter: (out): An uninitialized #GtkTreeIter.
3740 * @filter_iter: A valid #GtkTreeIter pointing to a row on @filter.
3742 * Sets @child_iter to point to the row pointed to by @filter_iter.
3747 gtk_tree_model_filter_convert_iter_to_child_iter (GtkTreeModelFilter *filter,
3748 GtkTreeIter *child_iter,
3749 GtkTreeIter *filter_iter)
3751 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
3752 g_return_if_fail (filter->priv->child_model != NULL);
3753 g_return_if_fail (child_iter != NULL);
3754 g_return_if_fail (filter_iter != NULL);
3755 g_return_if_fail (filter_iter->stamp == filter->priv->stamp);
3756 g_return_if_fail (filter_iter != child_iter);
3758 if (GTK_TREE_MODEL_FILTER_CACHE_CHILD_ITERS (filter))
3760 *child_iter = FILTER_ELT (filter_iter->user_data2)->iter;
3765 gboolean valid = FALSE;
3767 path = gtk_tree_model_filter_elt_get_path (filter_iter->user_data,
3768 filter_iter->user_data2,
3769 filter->priv->virtual_root);
3770 valid = gtk_tree_model_get_iter (filter->priv->child_model, child_iter,
3772 gtk_tree_path_free (path);
3774 g_return_if_fail (valid == TRUE);
3778 /* The path returned can only be used internally in the filter model. */
3779 static GtkTreePath *
3780 gtk_real_tree_model_filter_convert_child_path_to_path (GtkTreeModelFilter *filter,
3781 GtkTreePath *child_path,
3782 gboolean build_levels,
3783 gboolean fetch_children)
3785 gint *child_indices;
3786 GtkTreePath *retval;
3787 GtkTreePath *real_path;
3792 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (filter), NULL);
3793 g_return_val_if_fail (filter->priv->child_model != NULL, NULL);
3794 g_return_val_if_fail (child_path != NULL, NULL);
3796 if (!filter->priv->virtual_root)
3797 real_path = gtk_tree_path_copy (child_path);
3799 real_path = gtk_tree_model_filter_remove_root (child_path,
3800 filter->priv->virtual_root);
3805 retval = gtk_tree_path_new ();
3806 child_indices = gtk_tree_path_get_indices (real_path);
3808 if (filter->priv->root == NULL && build_levels)
3809 gtk_tree_model_filter_build_level (filter, NULL, NULL, FALSE);
3810 level = FILTER_LEVEL (filter->priv->root);
3812 for (i = 0; i < gtk_tree_path_get_depth (real_path); i++)
3815 gboolean found_child = FALSE;
3819 gtk_tree_path_free (real_path);
3820 gtk_tree_path_free (retval);
3824 tmp = bsearch_elt_with_offset (level->array, child_indices[i], &j);
3827 gtk_tree_path_append_index (retval, j);
3828 if (!tmp->children && build_levels)
3829 gtk_tree_model_filter_build_level (filter, level, tmp, FALSE);
3830 level = tmp->children;
3834 if (!found_child && fetch_children)
3836 tmp = gtk_tree_model_filter_fetch_child (filter, level,
3840 /* didn't find the child, let's try to bring it back */
3841 if (!tmp || tmp->offset != child_indices[i])
3844 gtk_tree_path_free (real_path);
3845 gtk_tree_path_free (retval);
3849 gtk_tree_path_append_index (retval, j);
3850 if (!tmp->children && build_levels)
3851 gtk_tree_model_filter_build_level (filter, level, tmp, FALSE);
3852 level = tmp->children;
3855 else if (!found_child && !fetch_children)
3858 gtk_tree_path_free (real_path);
3859 gtk_tree_path_free (retval);
3864 gtk_tree_path_free (real_path);
3869 * gtk_tree_model_filter_convert_child_path_to_path:
3870 * @filter: A #GtkTreeModelFilter.
3871 * @child_path: A #GtkTreePath to convert.
3873 * Converts @child_path to a path relative to @filter. That is, @child_path
3874 * points to a path in the child model. The rerturned path will point to the
3875 * same row in the filtered model. If @child_path isn't a valid path on the
3876 * child model or points to a row which is not visible in @filter, then %NULL
3879 * Return value: A newly allocated #GtkTreePath, or %NULL.
3884 gtk_tree_model_filter_convert_child_path_to_path (GtkTreeModelFilter *filter,
3885 GtkTreePath *child_path)
3890 /* this function does the sanity checks */
3891 path = gtk_real_tree_model_filter_convert_child_path_to_path (filter,
3899 /* get a new path which only takes visible nodes into account.
3900 * -- if this gives any performance issues, we can write a special
3901 * version of convert_child_path_to_path immediately returning
3902 * a visible-nodes-only path.
3904 gtk_tree_model_filter_get_iter_full (GTK_TREE_MODEL (filter), &iter, path);
3906 gtk_tree_path_free (path);
3907 path = gtk_tree_model_get_path (GTK_TREE_MODEL (filter), &iter);
3913 * gtk_tree_model_filter_convert_path_to_child_path:
3914 * @filter: A #GtkTreeModelFilter.
3915 * @filter_path: A #GtkTreePath to convert.
3917 * Converts @filter_path to a path on the child model of @filter. That is,
3918 * @filter_path points to a location in @filter. The returned path will
3919 * point to the same location in the model not being filtered. If @filter_path
3920 * does not point to a location in the child model, %NULL is returned.
3922 * Return value: A newly allocated #GtkTreePath, or %NULL.
3927 gtk_tree_model_filter_convert_path_to_child_path (GtkTreeModelFilter *filter,
3928 GtkTreePath *filter_path)
3930 gint *filter_indices;
3931 GtkTreePath *retval;
3935 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (filter), NULL);
3936 g_return_val_if_fail (filter->priv->child_model != NULL, NULL);
3937 g_return_val_if_fail (filter_path != NULL, NULL);
3940 retval = gtk_tree_path_new ();
3941 filter_indices = gtk_tree_path_get_indices (filter_path);
3942 if (!filter->priv->root)
3943 gtk_tree_model_filter_build_level (filter, NULL, NULL, FALSE);
3944 level = FILTER_LEVEL (filter->priv->root);
3946 for (i = 0; i < gtk_tree_path_get_depth (filter_path); i++)
3950 if (!level || level->visible_nodes <= filter_indices[i])
3952 gtk_tree_path_free (retval);
3956 elt = gtk_tree_model_filter_get_nth_visible (filter, level,
3959 if (elt->children == NULL)
3960 gtk_tree_model_filter_build_level (filter, level, elt, FALSE);
3962 if (!level || level->visible_nodes <= filter_indices[i])
3964 gtk_tree_path_free (retval);
3968 gtk_tree_path_append_index (retval, elt->offset);
3969 level = elt->children;
3974 if (filter->priv->virtual_root)
3976 GtkTreePath *real_retval;
3978 real_retval = gtk_tree_model_filter_add_root (retval,
3979 filter->priv->virtual_root);
3980 gtk_tree_path_free (retval);
3989 gtk_tree_model_filter_refilter_helper (GtkTreeModel *model,
3994 /* evil, don't try this at home, but certainly speeds things up */
3995 gtk_tree_model_filter_row_changed (model, path, iter, data);
4001 * gtk_tree_model_filter_refilter:
4002 * @filter: A #GtkTreeModelFilter.
4004 * Emits ::row_changed for each row in the child model, which causes
4005 * the filter to re-evaluate whether a row is visible or not.
4010 gtk_tree_model_filter_refilter (GtkTreeModelFilter *filter)
4012 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
4015 gtk_tree_model_foreach (filter->priv->child_model,
4016 gtk_tree_model_filter_refilter_helper,
4021 * gtk_tree_model_filter_clear_cache:
4022 * @filter: A #GtkTreeModelFilter.
4024 * This function should almost never be called. It clears the @filter
4025 * of any cached iterators that haven't been reffed with
4026 * gtk_tree_model_ref_node(). This might be useful if the child model
4027 * being filtered is static (and doesn't change often) and there has been
4028 * a lot of unreffed access to nodes. As a side effect of this function,
4029 * all unreffed iters will be invalid.
4034 gtk_tree_model_filter_clear_cache (GtkTreeModelFilter *filter)
4036 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
4038 if (filter->priv->zero_ref_count > 0)
4039 gtk_tree_model_filter_clear_cache_helper (filter,
4040 FILTER_LEVEL (filter->priv->root));