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"
29 * iter->stamp = filter->priv->stamp
30 * iter->user_data = FilterLevel
31 * iter->user_data2 = FilterElt
34 /* all paths, iters, etc prefixed with c_ are paths, iters, etc relative to the
38 typedef struct _FilterElt FilterElt;
39 typedef struct _FilterLevel FilterLevel;
44 FilterLevel *children;
56 FilterElt *parent_elt;
57 FilterLevel *parent_level;
60 #define GTK_TREE_MODEL_FILTER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_TREE_MODEL_FILTER, GtkTreeModelFilterPrivate))
62 struct _GtkTreeModelFilterPrivate
67 GtkTreeModel *child_model;
70 guint root_level_visible;
72 GtkTreePath *virtual_root;
74 GtkTreeModelFilterVisibleFunc visible_func;
75 gpointer visible_data;
76 GtkDestroyNotify visible_destroy;
78 gint modify_n_columns;
80 GtkTreeModelFilterModifyFunc modify_func;
82 gpointer modify_destroy;
86 gboolean visible_method_set;
87 gboolean modify_func_set;
92 guint has_child_toggled_id;
105 #define GTK_TREE_MODEL_FILTER_CACHE_CHILD_ITERS(filter) \
106 (((GtkTreeModelFilter *)filter)->priv->child_flags & GTK_TREE_MODEL_ITERS_PERSIST)
108 #define FILTER_ELT(filter_elt) ((FilterElt *)filter_elt)
109 #define FILTER_LEVEL(filter_level) ((FilterLevel *)filter_level)
111 /* general code (object/interface init, properties, etc) */
112 static void gtk_tree_model_filter_init (GtkTreeModelFilter *filter);
113 static void gtk_tree_model_filter_class_init (GtkTreeModelFilterClass *filter_class);
114 static void gtk_tree_model_filter_tree_model_init (GtkTreeModelIface *iface);
115 static void gtk_tree_model_filter_drag_source_init (GtkTreeDragSourceIface *iface);
116 static void gtk_tree_model_filter_finalize (GObject *object);
117 static void gtk_tree_model_filter_set_property (GObject *object,
121 static void gtk_tree_model_filter_get_property (GObject *object,
126 /* signal handlers */
127 static void gtk_tree_model_filter_row_changed (GtkTreeModel *c_model,
131 static void gtk_tree_model_filter_row_inserted (GtkTreeModel *c_model,
135 static void gtk_tree_model_filter_row_has_child_toggled (GtkTreeModel *c_model,
139 static void gtk_tree_model_filter_row_deleted (GtkTreeModel *c_model,
142 static void gtk_tree_model_filter_rows_reordered (GtkTreeModel *c_model,
148 /* GtkTreeModel interface */
149 static GtkTreeModelFlags gtk_tree_model_filter_get_flags (GtkTreeModel *model);
150 static gint gtk_tree_model_filter_get_n_columns (GtkTreeModel *model);
151 static GType gtk_tree_model_filter_get_column_type (GtkTreeModel *model,
153 static gboolean gtk_tree_model_filter_get_iter (GtkTreeModel *model,
156 static GtkTreePath *gtk_tree_model_filter_get_path (GtkTreeModel *model,
158 static void gtk_tree_model_filter_get_value (GtkTreeModel *model,
162 static gboolean gtk_tree_model_filter_iter_next (GtkTreeModel *model,
164 static gboolean gtk_tree_model_filter_iter_children (GtkTreeModel *model,
166 GtkTreeIter *parent);
167 static gboolean gtk_tree_model_filter_iter_has_child (GtkTreeModel *model,
169 static gint gtk_tree_model_filter_iter_n_children (GtkTreeModel *model,
171 static gboolean gtk_tree_model_filter_iter_nth_child (GtkTreeModel *model,
175 static gboolean gtk_tree_model_filter_iter_parent (GtkTreeModel *model,
178 static void gtk_tree_model_filter_ref_node (GtkTreeModel *model,
180 static void gtk_tree_model_filter_unref_node (GtkTreeModel *model,
183 /* TreeDragSource interface */
184 static gboolean gtk_tree_model_filter_row_draggable (GtkTreeDragSource *drag_source,
186 static gboolean gtk_tree_model_filter_drag_data_get (GtkTreeDragSource *drag_source,
188 GtkSelectionData *selection_data);
189 static gboolean gtk_tree_model_filter_drag_data_delete (GtkTreeDragSource *drag_source,
192 /* private functions */
193 static void gtk_tree_model_filter_build_level (GtkTreeModelFilter *filter,
194 FilterLevel *parent_level,
195 FilterElt *parent_elt);
196 static void gtk_tree_model_filter_free_level (GtkTreeModelFilter *filter,
197 FilterLevel *filter_level);
199 static GtkTreePath *gtk_tree_model_filter_elt_get_path (FilterLevel *level,
203 static GtkTreePath *gtk_tree_model_filter_add_root (GtkTreePath *src,
205 static GtkTreePath *gtk_tree_model_filter_remove_root (GtkTreePath *src,
208 static void gtk_tree_model_filter_increment_stamp (GtkTreeModelFilter *filter);
210 static gboolean gtk_tree_model_filter_visible (GtkTreeModelFilter *filter,
211 GtkTreeIter *child_iter);
212 static void gtk_tree_model_filter_clear_cache_helper (GtkTreeModelFilter *filter,
215 static void gtk_tree_model_filter_real_unref_node (GtkTreeModel *model,
217 gboolean propagate_unref);
219 static void gtk_tree_model_filter_set_model (GtkTreeModelFilter *filter,
220 GtkTreeModel *child_model);
221 static void gtk_tree_model_filter_set_root (GtkTreeModelFilter *filter,
224 static GtkTreePath *gtk_real_tree_model_filter_convert_child_path_to_path (GtkTreeModelFilter *filter,
225 GtkTreePath *child_path,
226 gboolean build_levels,
227 gboolean fetch_children);
229 static FilterElt *gtk_tree_model_filter_fetch_child (GtkTreeModelFilter *filter,
233 static void gtk_tree_model_filter_remove_node (GtkTreeModelFilter *filter,
235 gboolean emit_signal);
236 static void gtk_tree_model_filter_update_children (GtkTreeModelFilter *filter,
239 static FilterElt *bsearch_elt_with_offset (GArray *array,
244 static GObjectClass *parent_class = NULL;
247 gtk_tree_model_filter_get_type (void)
249 static GType tree_model_filter_type = 0;
251 if (!tree_model_filter_type)
253 static const GTypeInfo tree_model_filter_info =
255 sizeof (GtkTreeModelFilterClass),
256 NULL, /* base_init */
257 NULL, /* base_finalize */
258 (GClassInitFunc) gtk_tree_model_filter_class_init,
259 NULL, /* class_finalize */
260 NULL, /* class_data */
261 sizeof (GtkTreeModelFilter),
263 (GInstanceInitFunc) gtk_tree_model_filter_init
266 static const GInterfaceInfo tree_model_info =
268 (GInterfaceInitFunc) gtk_tree_model_filter_tree_model_init,
273 static const GInterfaceInfo drag_source_info =
275 (GInterfaceInitFunc) gtk_tree_model_filter_drag_source_init,
280 tree_model_filter_type = g_type_register_static (G_TYPE_OBJECT,
281 "GtkTreeModelFilter",
282 &tree_model_filter_info, 0);
284 g_type_add_interface_static (tree_model_filter_type,
288 g_type_add_interface_static (tree_model_filter_type,
289 GTK_TYPE_TREE_DRAG_SOURCE,
293 return tree_model_filter_type;
297 gtk_tree_model_filter_init (GtkTreeModelFilter *filter)
299 filter->priv = GTK_TREE_MODEL_FILTER_GET_PRIVATE (filter);
301 filter->priv->visible_column = -1;
302 filter->priv->zero_ref_count = 0;
303 filter->priv->visible_method_set = FALSE;
304 filter->priv->modify_func_set = FALSE;
308 gtk_tree_model_filter_class_init (GtkTreeModelFilterClass *filter_class)
310 GObjectClass *object_class;
312 object_class = (GObjectClass *) filter_class;
313 parent_class = g_type_class_peek_parent (filter_class);
315 object_class->set_property = gtk_tree_model_filter_set_property;
316 object_class->get_property = gtk_tree_model_filter_get_property;
318 object_class->finalize = gtk_tree_model_filter_finalize;
320 /* Properties -- FIXME: disabled translations for now, until I can come up with a
323 g_object_class_install_property (object_class,
325 g_param_spec_object ("child_model",
327 ("The model for the filtermodel to filter"),
329 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
331 g_object_class_install_property (object_class,
333 g_param_spec_boxed ("virtual_root",
334 ("The virtual root"),
335 ("The virtual root (relative to the child model) for this filtermodel"),
337 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
339 g_type_class_add_private (object_class, sizeof (GtkTreeModelFilterPrivate));
343 gtk_tree_model_filter_tree_model_init (GtkTreeModelIface *iface)
345 iface->get_flags = gtk_tree_model_filter_get_flags;
346 iface->get_n_columns = gtk_tree_model_filter_get_n_columns;
347 iface->get_column_type = gtk_tree_model_filter_get_column_type;
348 iface->get_iter = gtk_tree_model_filter_get_iter;
349 iface->get_path = gtk_tree_model_filter_get_path;
350 iface->get_value = gtk_tree_model_filter_get_value;
351 iface->iter_next = gtk_tree_model_filter_iter_next;
352 iface->iter_children = gtk_tree_model_filter_iter_children;
353 iface->iter_has_child = gtk_tree_model_filter_iter_has_child;
354 iface->iter_n_children = gtk_tree_model_filter_iter_n_children;
355 iface->iter_nth_child = gtk_tree_model_filter_iter_nth_child;
356 iface->iter_parent = gtk_tree_model_filter_iter_parent;
357 iface->ref_node = gtk_tree_model_filter_ref_node;
358 iface->unref_node = gtk_tree_model_filter_unref_node;
362 gtk_tree_model_filter_drag_source_init (GtkTreeDragSourceIface *iface)
364 iface->row_draggable = gtk_tree_model_filter_row_draggable;
365 iface->drag_data_delete = gtk_tree_model_filter_drag_data_delete;
366 iface->drag_data_get = gtk_tree_model_filter_drag_data_get;
371 gtk_tree_model_filter_finalize (GObject *object)
373 GtkTreeModelFilter *filter = (GtkTreeModelFilter *) object;
375 gtk_tree_model_filter_set_model (filter, NULL);
377 if (filter->priv->virtual_root)
378 gtk_tree_path_free (filter->priv->virtual_root);
380 if (filter->priv->root)
381 gtk_tree_model_filter_free_level (filter, filter->priv->root);
383 if (filter->priv->modify_types)
384 g_free (filter->priv->modify_types);
387 parent_class->finalize (object);
391 gtk_tree_model_filter_set_property (GObject *object,
396 GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (object);
400 case PROP_CHILD_MODEL:
401 gtk_tree_model_filter_set_model (filter, g_value_get_object (value));
403 case PROP_VIRTUAL_ROOT:
404 gtk_tree_model_filter_set_root (filter, g_value_get_boxed (value));
407 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
413 gtk_tree_model_filter_get_property (GObject *object,
418 GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (object);
422 case PROP_CHILD_MODEL:
423 g_value_set_object (value, filter->priv->child_model);
425 case PROP_VIRTUAL_ROOT:
426 g_value_set_boxed (value, filter->priv->virtual_root);
429 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
437 gtk_tree_model_filter_build_level (GtkTreeModelFilter *filter,
438 FilterLevel *parent_level,
439 FilterElt *parent_elt)
443 FilterLevel *new_level;
447 g_assert (filter->priv->child_model != NULL);
451 if (filter->priv->virtual_root)
453 if (gtk_tree_model_get_iter (filter->priv->child_model, &root, filter->priv->virtual_root) == FALSE)
455 length = gtk_tree_model_iter_n_children (filter->priv->child_model, &root);
457 if (gtk_tree_model_iter_children (filter->priv->child_model, &iter, &root) == FALSE)
462 if (!gtk_tree_model_get_iter_first (filter->priv->child_model, &iter))
464 length = gtk_tree_model_iter_n_children (filter->priv->child_model, NULL);
469 GtkTreeIter parent_iter;
470 GtkTreeIter child_parent_iter;
472 parent_iter.stamp = filter->priv->stamp;
473 parent_iter.user_data = parent_level;
474 parent_iter.user_data2 = parent_elt;
476 gtk_tree_model_filter_convert_iter_to_child_iter (filter,
479 if (gtk_tree_model_iter_children (filter->priv->child_model, &iter, &child_parent_iter) == FALSE)
482 /* stamp may have changed */
483 gtk_tree_model_filter_convert_iter_to_child_iter (filter,
486 length = gtk_tree_model_iter_n_children (filter->priv->child_model, &child_parent_iter);
489 g_return_if_fail (length > 0);
491 new_level = g_new (FilterLevel, 1);
492 new_level->array = g_array_sized_new (FALSE, FALSE,
495 new_level->ref_count = 0;
496 new_level->parent_elt = parent_elt;
497 new_level->parent_level = parent_level;
500 parent_elt->children = new_level;
502 filter->priv->root = new_level;
504 /* increase the count of zero ref_counts */
507 parent_elt->zero_ref_count++;
509 parent_elt = parent_level->parent_elt;
510 parent_level = parent_level->parent_level;
512 filter->priv->zero_ref_count++;
516 if (!new_level->parent_level)
517 filter->priv->root_level_visible = 0;
521 if (gtk_tree_model_filter_visible (filter, &iter))
523 FilterElt filter_elt;
525 filter_elt.offset = i;
526 filter_elt.zero_ref_count = 0;
527 filter_elt.ref_count = 0;
528 filter_elt.children = NULL;
529 filter_elt.visible = TRUE;
531 if (GTK_TREE_MODEL_FILTER_CACHE_CHILD_ITERS (filter))
532 filter_elt.iter = iter;
534 g_array_append_val (new_level->array, filter_elt);
536 if (!new_level->parent_level)
537 filter->priv->root_level_visible++;
541 while (gtk_tree_model_iter_next (filter->priv->child_model, &iter));
545 gtk_tree_model_filter_free_level (GtkTreeModelFilter *filter,
546 FilterLevel *filter_level)
550 g_assert (filter_level);
552 if (filter_level->ref_count == 0)
554 FilterLevel *parent_level = filter_level->parent_level;
555 FilterElt *parent_elt = filter_level->parent_elt;
560 parent_elt->zero_ref_count--;
564 parent_elt = parent_level->parent_elt;
565 parent_level = parent_level->parent_level;
568 while (parent_level);
569 filter->priv->zero_ref_count--;
572 for (i = 0; i < filter_level->array->len; i++)
574 if (g_array_index (filter_level->array, FilterElt, i).children)
575 gtk_tree_model_filter_free_level (filter,
576 FILTER_LEVEL (g_array_index (filter_level->array, FilterElt, i).children));
579 if (!filter_level->parent_level)
580 filter->priv->root_level_visible = 0;
582 if (filter_level->parent_elt)
583 filter_level->parent_elt->children = NULL;
585 filter->priv->root = NULL;
587 g_array_free (filter_level->array, TRUE);
588 filter_level->array = NULL;
590 g_free (filter_level);
595 gtk_tree_model_filter_elt_get_path (FilterLevel *level,
599 FilterLevel *walker = level;
600 FilterElt *walker2 = elt;
602 GtkTreePath *real_path;
604 g_return_val_if_fail (level != NULL, NULL);
605 g_return_val_if_fail (elt != NULL, NULL);
607 path = gtk_tree_path_new ();
611 gtk_tree_path_prepend_index (path, walker2->offset);
613 walker2 = walker->parent_elt;
614 walker = walker->parent_level;
619 real_path = gtk_tree_model_filter_add_root (path, root);
620 gtk_tree_path_free (path);
628 gtk_tree_model_filter_add_root (GtkTreePath *src,
634 retval = gtk_tree_path_copy (root);
636 for (i = 0; i < gtk_tree_path_get_depth (src); i++)
637 gtk_tree_path_append_index (retval, gtk_tree_path_get_indices (src)[i]);
643 gtk_tree_model_filter_remove_root (GtkTreePath *src,
651 if (gtk_tree_path_get_depth (src) <= gtk_tree_path_get_depth (root))
654 depth = gtk_tree_path_get_depth (src);
655 indices = gtk_tree_path_get_indices (src);
657 for (i = 0; i < gtk_tree_path_get_depth (root); i++)
658 if (indices[i] != gtk_tree_path_get_indices (root)[i])
661 retval = gtk_tree_path_new ();
663 for (; i < depth; i++)
664 gtk_tree_path_append_index (retval, indices[i]);
670 gtk_tree_model_filter_increment_stamp (GtkTreeModelFilter *filter)
674 filter->priv->stamp++;
676 while (filter->priv->stamp == 0);
678 gtk_tree_model_filter_clear_cache (filter);
682 gtk_tree_model_filter_visible (GtkTreeModelFilter *filter,
683 GtkTreeIter *child_iter)
685 if (filter->priv->visible_func)
687 return (filter->priv->visible_func (filter->priv->child_model,
689 filter->priv->visible_data));
691 else if (filter->priv->visible_column >= 0)
695 gtk_tree_model_get_value (filter->priv->child_model, child_iter,
696 filter->priv->visible_column, &val);
698 if (g_value_get_boolean (&val))
700 g_value_unset (&val);
704 g_value_unset (&val);
708 /* no filter thing set, so always visible */
713 gtk_tree_model_filter_clear_cache_helper (GtkTreeModelFilter *filter,
720 for (i = 0; i < level->array->len; i++)
722 if (g_array_index (level->array, FilterElt, i).zero_ref_count > 0)
723 gtk_tree_model_filter_clear_cache_helper (filter, g_array_index (level->array, FilterElt, i).children);
726 if (level->ref_count == 0 && level != filter->priv->root)
728 gtk_tree_model_filter_free_level (filter, level);
734 gtk_tree_model_filter_fetch_child (GtkTreeModelFilter *filter,
740 gint start, middle, end;
742 GtkTreePath *c_path = NULL;
744 GtkTreePath *c_parent_path = NULL;
745 GtkTreeIter c_parent_iter;
748 /* check if child exists and is visible */
749 if (level->parent_elt)
752 gtk_tree_model_filter_elt_get_path (level->parent_level,
754 filter->priv->virtual_root);
760 if (filter->priv->virtual_root)
761 c_parent_path = gtk_tree_path_copy (filter->priv->virtual_root);
763 c_parent_path = NULL;
768 gtk_tree_model_get_iter (filter->priv->child_model,
771 len = gtk_tree_model_iter_n_children (filter->priv->child_model,
774 c_path = gtk_tree_path_copy (c_parent_path);
775 gtk_tree_path_free (c_parent_path);
779 len = gtk_tree_model_iter_n_children (filter->priv->child_model, NULL);
780 c_path = gtk_tree_path_new ();
783 gtk_tree_path_append_index (c_path, offset);
784 gtk_tree_model_get_iter (filter->priv->child_model, &c_iter, c_path);
785 gtk_tree_path_free (c_path);
787 if (offset >= len || !gtk_tree_model_filter_visible (filter, &c_iter))
792 elt.zero_ref_count = 0;
795 /* visibility should be FALSE as we don't emit row_inserted */
798 if (GTK_TREE_MODEL_FILTER_CACHE_CHILD_ITERS (filter))
801 /* find index (binary search on offset) */
803 end = level->array->len;
809 middle = (start + end) / 2;
811 if (g_array_index (level->array, FilterElt, middle).offset <= offset)
817 if (g_array_index (level->array, FilterElt, middle).offset <= offset)
825 g_array_insert_val (level->array, i, elt);
828 for (i = MAX (--i, 0); i < level->array->len; i++)
830 FilterElt *e = &(g_array_index (level->array, FilterElt, i));
832 e->children->parent_elt = e;
835 return &g_array_index (level->array, FilterElt, *index);
839 gtk_tree_model_filter_remove_node (GtkTreeModelFilter *filter,
841 gboolean emit_signal)
843 FilterElt *elt, *parent;
844 FilterLevel *level, *parent_level;
845 gint offset, i, length, level_refcount;
847 /* FIXME: this function is very ugly. I need to rethink and
848 * rewrite it someday.
851 level = FILTER_LEVEL (iter->user_data);
852 elt = FILTER_ELT (iter->user_data2);
854 parent = level->parent_elt;
855 parent_level = level->parent_level;
856 length = level->array->len;
857 offset = elt->offset;
860 while (elt->ref_count > 0)
861 gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter),
864 level_refcount = level->ref_count;
866 /* do the ref counting first! this touches the stamp */
871 path = gtk_tree_model_get_path (GTK_TREE_MODEL (filter), iter);
872 gtk_tree_model_filter_increment_stamp (filter);
873 gtk_tree_model_row_deleted (GTK_TREE_MODEL (filter), path);
874 gtk_tree_path_free (path);
877 if ((length == 1 || level_refcount == 0) &&
878 emit_signal && iter->user_data != filter->priv->root)
880 /* above code destroyed the level */
881 goto emit_has_child_toggled;
887 gtk_tree_model_filter_free_level (filter, level);
889 if (!filter->priv->root)
890 /* we killed the root */
897 /* remove the node */
898 tmp = bsearch_elt_with_offset (level->array, elt->offset, &i);
902 g_array_remove_index (level->array, i);
904 for (i = MAX (--i, 0); i < level->array->len; i++)
906 /* NOTE: here we do *not* decrease offsets, because the node was
907 * not removed from the child model
909 elt = &g_array_index (level->array, FilterElt, i);
911 elt->children->parent_elt = elt;
916 emit_has_child_toggled:
917 /* children are being handled first, so we can check it this way
919 * yes this if-statement is ugly
921 if ((parent && parent->children && parent->children->array->len <= 1) ||
922 (length == 1 && emit_signal && iter->user_data != filter->priv->root))
924 /* latest child has been removed, level has been destroyed */
928 piter.stamp = filter->priv->stamp;
929 piter.user_data = parent_level;
930 piter.user_data2 = parent;
932 ppath = gtk_tree_model_get_path (GTK_TREE_MODEL (filter), &piter);
934 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (filter),
936 gtk_tree_path_free (ppath);
941 gtk_tree_model_filter_update_children (GtkTreeModelFilter *filter,
951 iter.stamp = filter->priv->stamp;
952 iter.user_data = level;
953 iter.user_data2 = elt;
955 gtk_tree_model_filter_convert_iter_to_child_iter (filter, &c_iter, &iter);
957 if (gtk_tree_model_iter_has_child (filter->priv->child_model, &c_iter))
959 GtkTreePath *path = gtk_tree_model_get_path (GTK_TREE_MODEL (filter),
961 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (filter),
965 gtk_tree_path_free (path);
970 bsearch_elt_with_offset (GArray *array,
974 gint start, middle, end;
985 elt = &g_array_index (array, FilterElt, 0);
987 if (elt->offset == offset)
998 middle = (start + end) / 2;
1000 elt = &g_array_index (array, FilterElt, middle);
1002 if (elt->offset < offset)
1004 else if (elt->offset > offset)
1009 while (start != end);
1011 if (elt->offset == offset)
1020 /* TreeModel signals */
1022 gtk_tree_model_filter_row_changed (GtkTreeModel *c_model,
1023 GtkTreePath *c_path,
1024 GtkTreeIter *c_iter,
1027 GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (data);
1029 GtkTreeIter children;
1030 GtkTreeIter real_c_iter;
1031 GtkTreePath *path = NULL;
1036 gboolean requested_state;
1037 gboolean current_state;
1038 gboolean free_c_path = FALSE;
1040 g_return_if_fail (c_path != NULL || c_iter != NULL);
1044 c_path = gtk_tree_model_get_path (c_model, c_iter);
1049 real_c_iter = *c_iter;
1051 gtk_tree_model_get_iter (c_model, &real_c_iter, c_path);
1053 /* is this node above the virtual root? */
1054 if (filter->priv->virtual_root
1055 && (gtk_tree_path_get_depth (filter->priv->virtual_root)
1056 >= gtk_tree_path_get_depth (c_path)))
1059 /* what's the requested state? */
1060 requested_state = gtk_tree_model_filter_visible (filter, &real_c_iter);
1062 /* now, let's see whether the item is there */
1063 path = gtk_real_tree_model_filter_convert_child_path_to_path (filter,
1070 gtk_tree_model_get_iter (GTK_TREE_MODEL (filter), &iter, path);
1071 current_state = FILTER_ELT (iter.user_data2)->visible;
1074 current_state = FALSE;
1076 if (current_state == FALSE && requested_state == FALSE)
1077 /* no changes required */
1080 if (current_state == TRUE && requested_state == FALSE)
1082 /* get rid of this node */
1083 gtk_tree_model_get_iter (GTK_TREE_MODEL (filter), &iter, path);
1085 level = FILTER_LEVEL (iter.user_data);
1087 if (!level->parent_level)
1088 filter->priv->root_level_visible--;
1090 gtk_tree_model_filter_remove_node (filter, &iter, TRUE);
1095 if (current_state == TRUE && requested_state == TRUE)
1097 /* progate the signal */
1098 gtk_tree_model_get_iter (GTK_TREE_MODEL (filter), &iter, path);
1099 gtk_tree_model_row_changed (GTK_TREE_MODEL (filter), path, &iter);
1101 level = FILTER_LEVEL (iter.user_data);
1102 elt = FILTER_ELT (iter.user_data2);
1104 /* and update the children */
1105 if (gtk_tree_model_iter_children (c_model, &children, &real_c_iter))
1106 gtk_tree_model_filter_update_children (filter, level, elt);
1111 /* only current == FALSE and requested == TRUE is left,
1114 g_return_if_fail (current_state == FALSE && requested_state == TRUE);
1116 /* make sure the new item has been pulled in */
1117 if (!filter->priv->root)
1122 gtk_tree_model_filter_build_level (filter, NULL, NULL);
1124 root = FILTER_LEVEL (filter->priv->root);
1128 for (i = 0; i < root->array->len; i++)
1129 g_array_index (root->array, FilterElt, i).visible = FALSE;
1130 filter->priv->root_level_visible = 0;
1135 path = gtk_real_tree_model_filter_convert_child_path_to_path (filter,
1140 g_return_if_fail (path != NULL);
1142 gtk_tree_model_filter_increment_stamp (filter);
1143 gtk_tree_model_get_iter (GTK_TREE_MODEL (filter), &iter, path);
1145 level = FILTER_LEVEL (iter.user_data);
1146 elt = FILTER_ELT (iter.user_data2);
1148 elt->visible = TRUE;
1150 if (!level->parent_level)
1151 filter->priv->root_level_visible++;
1154 gtk_tree_model_row_inserted (GTK_TREE_MODEL (filter), path, &iter);
1156 if (gtk_tree_model_iter_children (c_model, &children, c_iter))
1157 gtk_tree_model_filter_update_children (filter, level, elt);
1161 gtk_tree_path_free (path);
1164 gtk_tree_path_free (c_path);
1168 gtk_tree_model_filter_row_inserted (GtkTreeModel *c_model,
1169 GtkTreePath *c_path,
1170 GtkTreeIter *c_iter,
1173 GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (data);
1174 GtkTreePath *path = NULL;
1175 GtkTreePath *real_path = NULL;
1178 GtkTreeIter real_c_iter;
1182 FilterLevel *parent_level;
1184 gint i = 0, offset, index = -1;
1186 gboolean free_c_path = FALSE;
1188 g_return_if_fail (c_path != NULL || c_iter != NULL);
1192 c_path = gtk_tree_model_get_path (c_model, c_iter);
1197 real_c_iter = *c_iter;
1199 gtk_tree_model_get_iter (c_model, &real_c_iter, c_path);
1201 /* the row has already been inserted. so we need to fixup the
1202 * virtual root here first
1204 if (filter->priv->virtual_root)
1206 if (gtk_tree_path_get_depth (filter->priv->virtual_root) >=
1207 gtk_tree_path_get_depth (c_path))
1210 gint *v_indices, *c_indices;
1212 level = gtk_tree_path_get_depth (c_path) - 1;
1213 v_indices = gtk_tree_path_get_indices (filter->priv->virtual_root);
1214 c_indices = gtk_tree_path_get_indices (c_path);
1216 if (v_indices[level] >= c_indices[level])
1217 (v_indices[level])++;
1221 if (!filter->priv->root)
1223 gtk_tree_model_filter_build_level (filter, NULL, NULL);
1224 /* that already put the inserted iter in the level */
1229 parent_level = level = FILTER_LEVEL (filter->priv->root);
1231 /* subtract virtual root if necessary */
1232 if (filter->priv->virtual_root)
1234 real_path = gtk_tree_model_filter_remove_root (c_path,
1235 filter->priv->virtual_root);
1241 real_path = gtk_tree_path_copy (c_path);
1243 if (gtk_tree_path_get_depth (real_path) - 1 >= 1)
1245 /* find the parent level */
1246 while (i < gtk_tree_path_get_depth (real_path) - 1)
1251 /* we don't cover this signal */
1254 elt = bsearch_elt_with_offset (level->array,
1255 gtk_tree_path_get_indices (real_path)[i],
1259 /* parent is probably being filtered out */
1264 GtkTreePath *tmppath;
1265 GtkTreeIter tmpiter;
1267 tmpiter.stamp = filter->priv->stamp;
1268 tmpiter.user_data = level;
1269 tmpiter.user_data2 = elt;
1271 tmppath = gtk_tree_model_get_path (GTK_TREE_MODEL (data),
1276 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (data),
1278 gtk_tree_path_free (tmppath);
1281 /* not covering this signal */
1285 level = elt->children;
1286 parent_level = level;
1294 /* let's try to insert the value */
1295 offset = gtk_tree_path_get_indices (real_path)[gtk_tree_path_get_depth (real_path) - 1];
1297 /* update the offsets, yes if we didn't insert the node above, there will
1298 * be a gap here. This will be filled with the node (via fetch_child) when
1299 * it becomes visible
1301 for (i = 0; i < level->array->len; i++)
1303 FilterElt *e = &g_array_index (level->array, FilterElt, i);
1304 if ((e->offset >= offset))
1308 /* only insert when visible */
1309 if (gtk_tree_model_filter_visible (filter, &real_c_iter))
1313 if (GTK_TREE_MODEL_FILTER_CACHE_CHILD_ITERS (filter))
1314 felt.iter = real_c_iter;
1316 felt.offset = offset;
1317 felt.zero_ref_count = 0;
1319 felt.visible = TRUE;
1320 felt.children = NULL;
1322 for (i = 0; i < level->array->len; i++)
1323 if (g_array_index (level->array, FilterElt, i).offset > offset)
1326 g_array_insert_val (level->array, i, felt);
1329 if (!level->parent_level)
1330 filter->priv->root_level_visible++;
1333 /* another iteration to update the references of children to parents. */
1334 for (i = 0; i < level->array->len; i++)
1336 FilterElt *e = &g_array_index (level->array, FilterElt, i);
1338 e->children->parent_elt = e;
1341 /* don't emit the signal if we aren't visible */
1342 if (!gtk_tree_model_filter_visible (filter, &real_c_iter))
1346 /* NOTE: pass c_path here and NOT real_path. This function does
1347 * root subtraction itself
1349 path = gtk_real_tree_model_filter_convert_child_path_to_path (filter,
1356 gtk_tree_model_filter_increment_stamp (filter);
1358 gtk_tree_model_get_iter (GTK_TREE_MODEL (data), &iter, path);
1359 gtk_tree_model_row_inserted (GTK_TREE_MODEL (data), path, &iter);
1361 gtk_tree_path_free (path);
1365 gtk_tree_path_free (real_path);
1368 gtk_tree_path_free (c_path);
1372 gtk_tree_model_filter_row_has_child_toggled (GtkTreeModel *c_model,
1373 GtkTreePath *c_path,
1374 GtkTreeIter *c_iter,
1377 GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (data);
1381 g_return_if_fail (c_path != NULL && c_iter != NULL);
1383 /* FIXME: does this code work? */
1385 if (!gtk_tree_model_filter_visible (filter, c_iter))
1388 path = gtk_real_tree_model_filter_convert_child_path_to_path (filter,
1395 gtk_tree_model_get_iter (GTK_TREE_MODEL (data), &iter, path);
1396 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (data), path, &iter);
1398 gtk_tree_path_free (path);
1402 gtk_tree_model_filter_row_deleted (GtkTreeModel *c_model,
1403 GtkTreePath *c_path,
1406 GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (data);
1412 gboolean emit_signal = TRUE;
1415 g_return_if_fail (c_path != NULL);
1417 /* special case the deletion of an ancestor of the virtual root */
1418 if (filter->priv->virtual_root &&
1419 (gtk_tree_path_is_ancestor (c_path, filter->priv->virtual_root) ||
1420 !gtk_tree_path_compare (c_path, filter->priv->virtual_root)))
1424 FilterLevel *level = FILTER_LEVEL (filter->priv->root);
1429 /* remove everything in the filter model
1431 * For now, we just iterate over the root level and emit a
1432 * row_deleted for each FilterElt. Not sure if this is correct.
1435 gtk_tree_model_filter_increment_stamp (filter);
1436 path = gtk_tree_path_new ();
1437 gtk_tree_path_append_index (path, 0);
1439 for (i = 0; i < level->array->len; i++)
1440 gtk_tree_model_row_deleted (GTK_TREE_MODEL (data), path);
1442 gtk_tree_path_free (path);
1443 gtk_tree_model_filter_free_level (filter, filter->priv->root);
1448 /* fixup virtual root */
1449 if (filter->priv->virtual_root)
1451 if (gtk_tree_path_get_depth (filter->priv->virtual_root) >=
1452 gtk_tree_path_get_depth (c_path))
1455 gint *v_indices, *c_indices;
1457 level = gtk_tree_path_get_depth (c_path) - 1;
1458 v_indices = gtk_tree_path_get_indices (filter->priv->virtual_root);
1459 c_indices = gtk_tree_path_get_indices (c_path);
1461 if (v_indices[level] > c_indices[level])
1462 (v_indices[level])--;
1466 path = gtk_real_tree_model_filter_convert_child_path_to_path (filter,
1473 /* fixup the offsets */
1474 GtkTreePath *real_path;
1476 if (!filter->priv->root)
1479 level = FILTER_LEVEL (filter->priv->root);
1481 /* subtract vroot if necessary */
1482 if (filter->priv->virtual_root)
1484 real_path = gtk_tree_model_filter_remove_root (c_path,
1485 filter->priv->virtual_root);
1486 /* we don't handle this */
1491 real_path = gtk_tree_path_copy (c_path);
1494 if (gtk_tree_path_get_depth (real_path) - 1 >= 1)
1496 while (i < gtk_tree_path_get_depth (real_path) - 1)
1502 /* we don't cover this */
1503 gtk_tree_path_free (real_path);
1507 elt = bsearch_elt_with_offset (level->array,
1508 gtk_tree_path_get_indices (real_path)[i],
1511 if (!elt || !elt->children)
1513 /* parent is filtered out, so no level */
1514 gtk_tree_path_free (real_path);
1518 level = elt->children;
1523 offset = gtk_tree_path_get_indices (real_path)[gtk_tree_path_get_depth (real_path) - 1];
1524 gtk_tree_path_free (real_path);
1530 * - the offset of the removed item
1533 for (i = 0; i < level->array->len; i++)
1535 elt = &g_array_index (level->array, FilterElt, i);
1536 if (elt->offset > offset)
1539 elt->children->parent_elt = elt;
1545 gtk_tree_model_get_iter (GTK_TREE_MODEL (data), &iter, path);
1547 level = FILTER_LEVEL (iter.user_data);
1548 elt = FILTER_ELT (iter.user_data2);
1549 offset = elt->offset;
1551 if (!level->parent_level && elt->visible)
1552 filter->priv->root_level_visible--;
1556 if (level->ref_count == 0 && level != filter->priv->root)
1558 gtk_tree_model_filter_increment_stamp (filter);
1559 gtk_tree_model_row_deleted (GTK_TREE_MODEL (data), path);
1561 gtk_tree_path_free (path);
1565 gtk_tree_model_filter_increment_stamp (filter);
1566 gtk_tree_model_row_deleted (GTK_TREE_MODEL (data), path);
1567 iter.stamp = filter->priv->stamp;
1569 while (elt->ref_count > 0)
1570 gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (data), &iter,
1574 if (level->array->len == 1)
1577 gtk_tree_model_filter_free_level (filter, level);
1583 /* remove the row */
1584 tmp = bsearch_elt_with_offset (level->array, elt->offset, &i);
1586 offset = tmp->offset;
1587 g_array_remove_index (level->array, i);
1589 for (i = MAX (--i, 0); i < level->array->len; i++)
1591 elt = &g_array_index (level->array, FilterElt, i);
1592 if (elt->offset > offset)
1595 elt->children->parent_elt = elt;
1599 gtk_tree_path_free (path);
1603 gtk_tree_model_filter_rows_reordered (GtkTreeModel *c_model,
1604 GtkTreePath *c_path,
1605 GtkTreeIter *c_iter,
1611 GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (data);
1617 gint i, j, elt_count;
1622 g_return_if_fail (new_order != NULL);
1624 if (c_path == NULL || gtk_tree_path_get_indices (c_path) == NULL)
1626 if (!filter->priv->root)
1629 length = gtk_tree_model_iter_n_children (c_model, NULL);
1631 if (filter->priv->virtual_root)
1635 /* reorder root level of path */
1636 for (i = 0; i < length; i++)
1637 if (new_order[i] == gtk_tree_path_get_indices (filter->priv->virtual_root)[0])
1643 gtk_tree_path_get_indices (filter->priv->virtual_root)[0] = new_pos;
1647 path = gtk_tree_path_new ();
1648 level = FILTER_LEVEL (filter->priv->root);
1652 GtkTreeIter child_iter;
1654 /* virtual root anchor reordering */
1655 if (filter->priv->virtual_root &&
1656 gtk_tree_path_get_depth (c_path) <
1657 gtk_tree_path_get_depth (filter->priv->virtual_root))
1662 GtkTreeIter real_c_iter;
1664 level = gtk_tree_path_get_depth (c_path);
1667 real_c_iter = *c_iter;
1669 gtk_tree_model_get_iter (c_model, &real_c_iter, c_path);
1671 length = gtk_tree_model_iter_n_children (c_model, &real_c_iter);
1673 for (i = 0; i < length; i++)
1674 if (new_order[i] == gtk_tree_path_get_indices (filter->priv->virtual_root)[level])
1680 gtk_tree_path_get_indices (filter->priv->virtual_root)[level] = new_pos;
1684 path = gtk_real_tree_model_filter_convert_child_path_to_path (filter,
1688 if (!path && filter->priv->virtual_root &&
1689 gtk_tree_path_compare (c_path, filter->priv->virtual_root))
1692 if (!path && !filter->priv->virtual_root)
1697 /* root level mode */
1699 gtk_tree_model_get_iter (c_model, c_iter, c_path);
1700 length = gtk_tree_model_iter_n_children (c_model, c_iter);
1701 path = gtk_tree_path_new ();
1702 level = FILTER_LEVEL (filter->priv->root);
1706 gtk_tree_model_get_iter (GTK_TREE_MODEL (data), &iter, path);
1708 level = FILTER_LEVEL (iter.user_data);
1709 elt = FILTER_ELT (iter.user_data2);
1713 gtk_tree_path_free (path);
1717 level = elt->children;
1719 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (filter), &child_iter, &iter);
1720 length = gtk_tree_model_iter_n_children (c_model, &child_iter);
1724 if (level->array->len < 1)
1726 gtk_tree_path_free (path);
1730 /* NOTE: we do not bail out here if level->array->len < 2 like
1731 * GtkTreeModelSort does. This because we do some special tricky
1735 /* construct a new array */
1736 new_array = g_array_sized_new (FALSE, FALSE, sizeof (FilterElt),
1738 tmp_array = g_new (gint, level->array->len);
1740 for (i = 0, elt_count = 0; i < length; i++)
1742 FilterElt *e = NULL;
1743 gint old_offset = -1;
1745 for (j = 0; j < level->array->len; j++)
1746 if (g_array_index (level->array, FilterElt, j).offset == new_order[i])
1748 e = &g_array_index (level->array, FilterElt, j);
1756 tmp_array[elt_count] = old_offset;
1757 g_array_append_val (new_array, *e);
1758 g_array_index (new_array, FilterElt, elt_count).offset = i;
1762 g_array_free (level->array, TRUE);
1763 level->array = new_array;
1766 for (i = 0; i < level->array->len; i++)
1768 FilterElt *e = &g_array_index (level->array, FilterElt, i);
1770 e->children->parent_elt = e;
1773 /* emit rows_reordered */
1774 if (!gtk_tree_path_get_indices (path))
1775 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (data), path, NULL,
1778 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (data), path, &iter,
1783 gtk_tree_path_free (path);
1786 /* TreeModelIface implementation */
1787 static GtkTreeModelFlags
1788 gtk_tree_model_filter_get_flags (GtkTreeModel *model)
1790 GtkTreeModelFlags flags;
1792 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), 0);
1793 g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL, 0);
1795 flags = gtk_tree_model_get_flags (GTK_TREE_MODEL_FILTER (model)->priv->child_model);
1797 if ((flags & GTK_TREE_MODEL_LIST_ONLY) == GTK_TREE_MODEL_LIST_ONLY)
1798 return GTK_TREE_MODEL_LIST_ONLY;
1804 gtk_tree_model_filter_get_n_columns (GtkTreeModel *model)
1806 GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
1808 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), 0);
1809 g_return_val_if_fail (filter->priv->child_model != NULL, 0);
1811 if (filter->priv->child_model == NULL)
1814 /* so we can't modify the modify func after this ... */
1815 filter->priv->modify_func_set = TRUE;
1817 if (filter->priv->modify_n_columns > 0)
1818 return filter->priv->modify_n_columns;
1820 return gtk_tree_model_get_n_columns (filter->priv->child_model);
1824 gtk_tree_model_filter_get_column_type (GtkTreeModel *model,
1827 GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
1829 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), G_TYPE_INVALID);
1830 g_return_val_if_fail (filter->priv->child_model != NULL, G_TYPE_INVALID);
1832 /* so we can't modify the modify func after this ... */
1833 filter->priv->modify_func_set = TRUE;
1835 if (filter->priv->modify_types)
1837 g_return_val_if_fail (index < filter->priv->modify_n_columns, G_TYPE_INVALID);
1839 return filter->priv->modify_types[index];
1842 return gtk_tree_model_get_column_type (filter->priv->child_model, index);
1846 gtk_tree_model_filter_get_iter (GtkTreeModel *model,
1850 GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
1855 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
1856 g_return_val_if_fail (filter->priv->child_model != NULL, FALSE);
1858 indices = gtk_tree_path_get_indices (path);
1860 if (filter->priv->root == NULL)
1861 gtk_tree_model_filter_build_level (filter, NULL, NULL);
1862 level = FILTER_LEVEL (filter->priv->root);
1864 depth = gtk_tree_path_get_depth (path);
1871 for (i = 0; i < depth - 1; i++)
1873 if (!level || indices[i] >= level->array->len)
1878 if (!g_array_index (level->array, FilterElt, indices[i]).children)
1879 gtk_tree_model_filter_build_level (filter, level,
1880 &g_array_index (level->array,
1883 level = g_array_index (level->array, FilterElt, indices[i]).children;
1886 if (!level || indices[i] >= level->array->len)
1892 iter->stamp = filter->priv->stamp;
1893 iter->user_data = level;
1894 iter->user_data2 = &g_array_index (level->array, FilterElt,
1895 indices[depth - 1]);
1900 static GtkTreePath *
1901 gtk_tree_model_filter_get_path (GtkTreeModel *model,
1904 GtkTreePath *retval;
1908 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), NULL);
1909 g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL, NULL);
1910 g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->stamp == iter->stamp, NULL);
1912 retval = gtk_tree_path_new ();
1913 level = iter->user_data;
1914 elt = iter->user_data2;
1918 gtk_tree_path_prepend_index (retval,
1919 elt - FILTER_ELT (level->array->data));
1920 elt = level->parent_elt;
1921 level = level->parent_level;
1928 gtk_tree_model_filter_get_value (GtkTreeModel *model,
1933 GtkTreeIter child_iter;
1934 GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (model);
1936 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (model));
1937 g_return_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL);
1938 g_return_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->stamp == iter->stamp);
1940 if (filter->priv->modify_func)
1942 g_return_if_fail (column < filter->priv->modify_n_columns);
1944 g_value_init (value, filter->priv->modify_types[column]);
1945 filter->priv->modify_func (model,
1949 filter->priv->modify_data);
1954 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_iter, iter);
1955 gtk_tree_model_get_value (GTK_TREE_MODEL_FILTER (model)->priv->child_model,
1956 &child_iter, column, value);
1960 gtk_tree_model_filter_iter_next (GtkTreeModel *model,
1966 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
1967 g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL, FALSE);
1968 g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->stamp == iter->stamp, FALSE);
1970 level = iter->user_data;
1971 elt = iter->user_data2;
1973 if (elt - FILTER_ELT (level->array->data) >= level->array->len - 1)
1979 iter->user_data2 = elt + 1;
1985 gtk_tree_model_filter_iter_children (GtkTreeModel *model,
1987 GtkTreeIter *parent)
1989 GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
1993 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
1994 g_return_val_if_fail (filter->priv->child_model != NULL, FALSE);
1996 g_return_val_if_fail (filter->priv->stamp == parent->stamp, FALSE);
2000 if (!filter->priv->root)
2001 gtk_tree_model_filter_build_level (filter, NULL, NULL);
2002 if (!filter->priv->root)
2005 level = filter->priv->root;
2006 iter->stamp = filter->priv->stamp;
2007 iter->user_data = level;
2008 iter->user_data2 = level->array->data;
2012 if (FILTER_ELT (parent->user_data2)->children == NULL)
2013 gtk_tree_model_filter_build_level (filter,
2014 FILTER_LEVEL (parent->user_data),
2015 FILTER_ELT (parent->user_data2));
2016 if (FILTER_ELT (parent->user_data2)->children == NULL)
2020 if (FILTER_ELT (parent->user_data2)->children->array->len <= 0)
2023 iter->stamp = filter->priv->stamp;
2024 iter->user_data = FILTER_ELT (parent->user_data2)->children;
2025 iter->user_data2 = FILTER_LEVEL (iter->user_data)->array->data;
2032 gtk_tree_model_filter_iter_has_child (GtkTreeModel *model,
2035 GtkTreeIter child_iter;
2036 GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
2039 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
2040 g_return_val_if_fail (filter->priv->child_model != NULL, FALSE);
2041 g_return_val_if_fail (filter->priv->stamp == iter->stamp, FALSE);
2043 filter = GTK_TREE_MODEL_FILTER (model);
2045 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_iter, iter);
2046 elt = FILTER_ELT (iter->user_data2);
2048 /* we need to build the level to check if not all children are filtered
2052 && gtk_tree_model_iter_has_child (filter->priv->child_model, &child_iter))
2053 gtk_tree_model_filter_build_level (filter, FILTER_LEVEL (iter->user_data),
2056 /* FIXME: we should prolly count the visible nodes here, just like in
2059 if (elt->children && elt->children->array->len > 0)
2066 gtk_tree_model_filter_iter_n_children (GtkTreeModel *model,
2069 GtkTreeIter child_iter;
2070 GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
2073 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), 0);
2074 g_return_val_if_fail (filter->priv->child_model != NULL, 0);
2076 g_return_val_if_fail (filter->priv->stamp == iter->stamp, 0);
2080 if (!filter->priv->root)
2081 gtk_tree_model_filter_build_level (filter, NULL, NULL);
2083 /* count visible nodes */
2084 return filter->priv->root_level_visible;
2087 elt = FILTER_ELT (iter->user_data2);
2088 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_iter, iter);
2090 if (!elt->children &&
2091 gtk_tree_model_iter_has_child (filter->priv->child_model, &child_iter))
2092 gtk_tree_model_filter_build_level (filter,
2093 FILTER_LEVEL (iter->user_data),
2096 if (elt->children && elt->children->array->len)
2100 GArray *a = elt->children->array;
2102 /* count visible nodes */
2103 for (i = 0; i < a->len; i++)
2104 if (g_array_index (a, FilterElt, i).visible)
2114 gtk_tree_model_filter_iter_nth_child (GtkTreeModel *model,
2116 GtkTreeIter *parent,
2120 GtkTreeIter children;
2122 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
2124 g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->stamp == parent->stamp, FALSE);
2126 /* use this instead of has_Child to force us to build the level, if needed */
2127 if (gtk_tree_model_filter_iter_children (model, &children, parent) == FALSE)
2133 level = children.user_data;
2134 if (n >= level->array->len)
2140 iter->stamp = GTK_TREE_MODEL_FILTER (model)->priv->stamp;
2141 iter->user_data = level;
2142 iter->user_data2 = &g_array_index (level->array, FilterElt, n);
2148 gtk_tree_model_filter_iter_parent (GtkTreeModel *model,
2155 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
2156 g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL, FALSE);
2157 g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->stamp == child->stamp, FALSE);
2159 level = child->user_data;
2161 if (level->parent_level)
2163 iter->stamp = GTK_TREE_MODEL_FILTER (model)->priv->stamp;
2164 iter->user_data = level->parent_level;
2165 iter->user_data2 = level->parent_elt;
2174 gtk_tree_model_filter_ref_node (GtkTreeModel *model,
2177 GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
2178 GtkTreeIter child_iter;
2182 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (model));
2183 g_return_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL);
2184 g_return_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->stamp == iter->stamp);
2186 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_iter, iter);
2188 gtk_tree_model_ref_node (filter->priv->child_model, &child_iter);
2190 level = iter->user_data;
2191 elt = iter->user_data2;
2195 if (level->ref_count == 1)
2197 FilterLevel *parent_level = level->parent_level;
2198 FilterElt *parent_elt = level->parent_elt;
2200 /* we were at zero -- time to decrease the zero_ref_count val */
2204 parent_elt->zero_ref_count--;
2208 parent_elt = parent_level->parent_elt;
2209 parent_level = parent_level->parent_level;
2212 while (parent_level);
2213 filter->priv->zero_ref_count--;
2218 gtk_tree_model_filter_unref_node (GtkTreeModel *model,
2221 gtk_tree_model_filter_real_unref_node (model, iter, TRUE);
2225 gtk_tree_model_filter_real_unref_node (GtkTreeModel *model,
2227 gboolean propagate_unref)
2229 GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
2233 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (model));
2234 g_return_if_fail (filter->priv->child_model != NULL);
2235 g_return_if_fail (filter->priv->stamp == iter->stamp);
2237 if (propagate_unref)
2239 GtkTreeIter child_iter;
2240 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_iter, iter);
2241 gtk_tree_model_unref_node (filter->priv->child_model, &child_iter);
2244 level = iter->user_data;
2245 elt = iter->user_data2;
2247 g_return_if_fail (elt->ref_count > 0);
2251 if (level->ref_count == 0)
2253 FilterLevel *parent_level = level->parent_level;
2254 FilterElt *parent_elt = level->parent_elt;
2256 /* we are at zero -- time to increase the zero_ref_count val */
2257 while (parent_level)
2259 parent_elt->zero_ref_count++;
2261 parent_elt = parent_level->parent_elt;
2262 parent_level = parent_level->parent_level;
2264 filter->priv->zero_ref_count++;
2268 /* TreeDragSource interface implementation */
2270 gtk_tree_model_filter_row_draggable (GtkTreeDragSource *drag_source,
2273 GtkTreeModelFilter *tree_model_filter = (GtkTreeModelFilter *)drag_source;
2274 GtkTreePath *child_path;
2277 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (drag_source), FALSE);
2278 g_return_val_if_fail (path != NULL, FALSE);
2280 child_path = gtk_tree_model_filter_convert_path_to_child_path (tree_model_filter, path);
2281 draggable = gtk_tree_drag_source_row_draggable (GTK_TREE_DRAG_SOURCE (tree_model_filter->priv->child_model), child_path);
2282 gtk_tree_path_free (child_path);
2288 gtk_tree_model_filter_drag_data_get (GtkTreeDragSource *drag_source,
2290 GtkSelectionData *selection_data)
2292 GtkTreeModelFilter *tree_model_filter = (GtkTreeModelFilter *)drag_source;
2293 GtkTreePath *child_path;
2296 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (drag_source), FALSE);
2297 g_return_val_if_fail (path != NULL, FALSE);
2299 child_path = gtk_tree_model_filter_convert_path_to_child_path (tree_model_filter, path);
2300 gotten = gtk_tree_drag_source_drag_data_get (GTK_TREE_DRAG_SOURCE (tree_model_filter->priv->child_model), child_path, selection_data);
2301 gtk_tree_path_free (child_path);
2307 gtk_tree_model_filter_drag_data_delete (GtkTreeDragSource *drag_source,
2310 GtkTreeModelFilter *tree_model_filter = (GtkTreeModelFilter *)drag_source;
2311 GtkTreePath *child_path;
2314 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (drag_source), FALSE);
2315 g_return_val_if_fail (path != NULL, FALSE);
2317 child_path = gtk_tree_model_filter_convert_path_to_child_path (tree_model_filter, path);
2318 deleted = gtk_tree_drag_source_drag_data_delete (GTK_TREE_DRAG_SOURCE (tree_model_filter->priv->child_model), child_path);
2319 gtk_tree_path_free (child_path);
2324 /* bits and pieces */
2326 gtk_tree_model_filter_set_model (GtkTreeModelFilter *filter,
2327 GtkTreeModel *child_model)
2329 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
2331 if (filter->priv->child_model)
2333 g_signal_handler_disconnect (G_OBJECT (filter->priv->child_model),
2334 filter->priv->changed_id);
2335 g_signal_handler_disconnect (G_OBJECT (filter->priv->child_model),
2336 filter->priv->inserted_id);
2337 g_signal_handler_disconnect (G_OBJECT (filter->priv->child_model),
2338 filter->priv->has_child_toggled_id);
2339 g_signal_handler_disconnect (G_OBJECT (filter->priv->child_model),
2340 filter->priv->deleted_id);
2341 g_signal_handler_disconnect (G_OBJECT (filter->priv->child_model),
2342 filter->priv->reordered_id);
2344 /* reset our state */
2345 if (filter->priv->root)
2346 gtk_tree_model_filter_free_level (filter, filter->priv->root);
2348 filter->priv->root = NULL;
2349 g_object_unref (G_OBJECT (filter->priv->child_model));
2350 filter->priv->visible_column = -1;
2351 /* FIXME: destroy more crack here? the funcs? */
2354 filter->priv->child_model = child_model;
2358 g_object_ref (G_OBJECT (filter->priv->child_model));
2359 filter->priv->changed_id =
2360 g_signal_connect (child_model, "row_changed",
2361 G_CALLBACK (gtk_tree_model_filter_row_changed),
2363 filter->priv->inserted_id =
2364 g_signal_connect (child_model, "row_inserted",
2365 G_CALLBACK (gtk_tree_model_filter_row_inserted),
2367 filter->priv->has_child_toggled_id =
2368 g_signal_connect (child_model, "row_has_child_toggled",
2369 G_CALLBACK (gtk_tree_model_filter_row_has_child_toggled),
2371 filter->priv->deleted_id =
2372 g_signal_connect (child_model, "row_deleted",
2373 G_CALLBACK (gtk_tree_model_filter_row_deleted),
2375 filter->priv->reordered_id =
2376 g_signal_connect (child_model, "rows_reordered",
2377 G_CALLBACK (gtk_tree_model_filter_rows_reordered),
2380 filter->priv->child_flags = gtk_tree_model_get_flags (child_model);
2381 filter->priv->stamp = g_random_int ();
2386 gtk_tree_model_filter_set_root (GtkTreeModelFilter *filter,
2389 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
2392 filter->priv->virtual_root = NULL;
2394 filter->priv->virtual_root = gtk_tree_path_copy (root);
2400 * gtk_tree_model_filter_new:
2401 * @child_model: A #GtkTreeModel.
2402 * @root: A #GtkTreePath or %NULL.
2404 * Creates a new #GtkTreeModel, with @child_model as the child_model
2405 * and @root as the virtual root.
2407 * Return value: A new #GtkTreeModel.
2412 gtk_tree_model_filter_new (GtkTreeModel *child_model,
2415 GtkTreeModel *retval;
2417 g_return_val_if_fail (GTK_IS_TREE_MODEL (child_model), NULL);
2419 retval = GTK_TREE_MODEL (g_object_new (gtk_tree_model_filter_get_type (), NULL));
2421 gtk_tree_model_filter_set_model (GTK_TREE_MODEL_FILTER (retval),
2423 gtk_tree_model_filter_set_root (GTK_TREE_MODEL_FILTER (retval), root);
2429 * gtk_tree_model_filter_get_model:
2430 * @filter: A #GtkTreeModelFilter.
2432 * Returns a pointer to the child model of @filter.
2434 * Return value: A pointer to a #GtkTreeModel.
2439 gtk_tree_model_filter_get_model (GtkTreeModelFilter *filter)
2441 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (filter), NULL);
2443 return filter->priv->child_model;
2447 * gtk_tree_model_filter_set_visible_func:
2448 * @filter: A #GtkTreeModelFilter.
2449 * @func: A #GtkTreeModelFilterVisibleFunc, the visible function.
2450 * @data: User data to pass to the visible function, or %NULL.
2451 * @destroy: Destroy notifier of @data, or %NULL.
2453 * Sets the visible function used when filtering the @filter to be @func. The
2454 * function should return %TRUE if the given row should be visible and
2460 gtk_tree_model_filter_set_visible_func (GtkTreeModelFilter *filter,
2461 GtkTreeModelFilterVisibleFunc func,
2463 GtkDestroyNotify destroy)
2465 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
2466 g_return_if_fail (func != NULL);
2467 g_return_if_fail (filter->priv->visible_method_set == FALSE);
2469 if (filter->priv->visible_func)
2471 GtkDestroyNotify d = filter->priv->visible_destroy;
2473 filter->priv->visible_destroy = NULL;
2474 d (filter->priv->visible_data);
2477 filter->priv->visible_func = func;
2478 filter->priv->visible_data = data;
2479 filter->priv->visible_destroy = destroy;
2481 filter->priv->visible_method_set = TRUE;
2485 * gtk_tree_model_filter_set_modify_func:
2486 * @filter: A #GtkTreeModelFilter.
2487 * @n_columns: The number of columns in the filter model.
2488 * @types: The #GType<!-- -->s of the columns.
2489 * @func: A #GtkTreeModelFilterModifyFunc
2490 * @data: User data to pass to the modify function, or %NULL.
2491 * @destroy: Destroy notifier of @data, or %NULL.
2493 * With the @n_columns and @types parameters, you give an array of column
2494 * types for this model (which will be exposed to the parent model/view).
2495 * The @func, @data and @destroy parameters are for specifying the modify
2496 * function. The modify function will get called for <emphasis>each</emphasis>
2497 * data access, the goal of the modify function is to return the data which
2498 * should be displayed at the location specified using the parameters of the
2504 gtk_tree_model_filter_set_modify_func (GtkTreeModelFilter *filter,
2507 GtkTreeModelFilterModifyFunc func,
2509 GtkDestroyNotify destroy)
2511 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
2512 g_return_if_fail (func != NULL);
2513 g_return_if_fail (filter->priv->modify_func_set == FALSE);
2515 if (filter->priv->modify_destroy)
2517 GtkDestroyNotify d = filter->priv->modify_destroy;
2519 filter->priv->modify_destroy = NULL;
2520 d (filter->priv->modify_data);
2523 filter->priv->modify_n_columns = n_columns;
2524 filter->priv->modify_types = g_new0 (GType, n_columns);
2525 memcpy (filter->priv->modify_types, types, sizeof (GType) * n_columns);
2526 filter->priv->modify_func = func;
2527 filter->priv->modify_data = data;
2528 filter->priv->modify_destroy = destroy;
2530 filter->priv->modify_func_set = TRUE;
2534 * gtk_tree_model_filter_set_visible_column:
2535 * @filter: A #GtkTreeModelFilter.
2536 * @column: A #gint which is the column containing the visible information.
2538 * Sets @column of the child_model to be the column where @filter should
2539 * look for visibility information. @columns should be a column of type
2540 * %G_TYPE_BOOLEAN, where %TRUE means that a row is visible, and %FALSE
2546 gtk_tree_model_filter_set_visible_column (GtkTreeModelFilter *filter,
2549 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
2550 g_return_if_fail (column >= 0);
2551 g_return_if_fail (filter->priv->visible_method_set == FALSE);
2553 filter->priv->visible_column = column;
2555 filter->priv->visible_method_set = TRUE;
2561 * gtk_tree_model_filter_convert_child_iter_to_iter:
2562 * @filter: A #GtkTreeModelFilter.
2563 * @filter_iter: An uninitialized #GtkTreeIter.
2564 * @child_iter: A valid #GtkTreeIter pointing to a row on the child model.
2566 * Sets @filter_iter to point to the row in @filter that corresponds to the
2567 * row pointed at by @child_iter.
2572 gtk_tree_model_filter_convert_child_iter_to_iter (GtkTreeModelFilter *filter,
2573 GtkTreeIter *filter_iter,
2574 GtkTreeIter *child_iter)
2576 GtkTreePath *child_path, *path;
2578 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
2579 g_return_if_fail (filter->priv->child_model != NULL);
2580 g_return_if_fail (filter_iter != NULL);
2581 g_return_if_fail (child_iter != NULL);
2583 filter_iter->stamp = 0;
2585 child_path = gtk_tree_model_get_path (filter->priv->child_model, child_iter);
2586 g_return_if_fail (child_path != NULL);
2588 path = gtk_tree_model_filter_convert_child_path_to_path (filter,
2590 gtk_tree_path_free (child_path);
2591 g_return_if_fail (path != NULL);
2593 gtk_tree_model_get_iter (GTK_TREE_MODEL (filter), filter_iter, path);
2594 gtk_tree_path_free (path);
2598 * gtk_tree_model_filter_convert_iter_to_child_iter:
2599 * @filter: A #GtkTreeModelFilter.
2600 * @child_iter: An uninitialized #GtkTreeIter.
2601 * @filter_iter: A valid #GtkTreeIter pointing to a row on @filter.
2603 * Sets @child_iter to point to the row pointed to by @filter_iter.
2608 gtk_tree_model_filter_convert_iter_to_child_iter (GtkTreeModelFilter *filter,
2609 GtkTreeIter *child_iter,
2610 GtkTreeIter *filter_iter)
2612 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
2613 g_return_if_fail (filter->priv->child_model != NULL);
2614 g_return_if_fail (child_iter != NULL);
2615 g_return_if_fail (filter_iter != NULL);
2616 g_return_if_fail (filter_iter->stamp == filter->priv->stamp);
2618 if (GTK_TREE_MODEL_FILTER_CACHE_CHILD_ITERS (filter))
2620 *child_iter = FILTER_ELT (filter_iter->user_data2)->iter;
2626 path = gtk_tree_model_filter_elt_get_path (filter_iter->user_data,
2627 filter_iter->user_data2,
2628 filter->priv->virtual_root);
2629 gtk_tree_model_get_iter (filter->priv->child_model, child_iter, path);
2630 gtk_tree_path_free (path);
2634 static GtkTreePath *
2635 gtk_real_tree_model_filter_convert_child_path_to_path (GtkTreeModelFilter *filter,
2636 GtkTreePath *child_path,
2637 gboolean build_levels,
2638 gboolean fetch_children)
2640 gint *child_indices;
2641 GtkTreePath *retval;
2642 GtkTreePath *real_path;
2647 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (filter), NULL);
2648 g_return_val_if_fail (filter->priv->child_model != NULL, NULL);
2649 g_return_val_if_fail (child_path != NULL, NULL);
2651 if (!filter->priv->virtual_root)
2652 real_path = gtk_tree_path_copy (child_path);
2654 real_path = gtk_tree_model_filter_remove_root (child_path,
2655 filter->priv->virtual_root);
2660 retval = gtk_tree_path_new ();
2661 child_indices = gtk_tree_path_get_indices (real_path);
2663 if (filter->priv->root == NULL && build_levels)
2664 gtk_tree_model_filter_build_level (filter, NULL, NULL);
2665 level = FILTER_LEVEL (filter->priv->root);
2667 for (i = 0; i < gtk_tree_path_get_depth (real_path); i++)
2670 gboolean found_child = FALSE;
2674 gtk_tree_path_free (real_path);
2675 gtk_tree_path_free (retval);
2679 tmp = bsearch_elt_with_offset (level->array, child_indices[i], &j);
2682 gtk_tree_path_append_index (retval, j);
2683 if (!tmp->children && build_levels)
2684 gtk_tree_model_filter_build_level (filter, level, tmp);
2685 level = tmp->children;
2689 if (!found_child && fetch_children)
2691 tmp = gtk_tree_model_filter_fetch_child (filter, level,
2695 /* didn't find the child, let's try to bring it back */
2696 if (!tmp || tmp->offset != child_indices[i])
2699 gtk_tree_path_free (real_path);
2700 gtk_tree_path_free (retval);
2704 gtk_tree_path_append_index (retval, j);
2705 if (!tmp->children && build_levels)
2706 gtk_tree_model_filter_build_level (filter, level, tmp);
2707 level = tmp->children;
2710 else if (!found_child && !fetch_children)
2713 gtk_tree_path_free (real_path);
2714 gtk_tree_path_free (retval);
2719 gtk_tree_path_free (real_path);
2724 * gtk_tree_model_filter_convert_child_path_to_path:
2725 * @filter: A #GtkTreeModelFilter.
2726 * @child_path: A #GtkTreePath to convert.
2728 * Converts @child_path to a path relative to @filter. That is, @child_path
2729 * points to a path in the child model. The rerturned path will point to the
2730 * same row in the filtered model. If @child_path isn't a valid path on the
2731 * child model, then %NULL is returned.
2733 * Return value: A newly allocated #GtkTreePath, or %NULL.
2738 gtk_tree_model_filter_convert_child_path_to_path (GtkTreeModelFilter *filter,
2739 GtkTreePath *child_path)
2741 /* this function does the sanity checks */
2742 return gtk_real_tree_model_filter_convert_child_path_to_path (filter,
2749 * gtk_tree_model_filter_convert_path_to_child_path:
2750 * @filter: A #GtkTreeModelFilter.
2751 * @filter_path: A #GtkTreePath to convert.
2753 * Converts @filter_path to a path on the child model of @filter. That is,
2754 * @filter_path points to a location in @filter. The returned path will
2755 * point to the same location in the model not being filtered. If @filter_path
2756 * does not point to a location in the child model, %NULL is returned.
2758 * Return value: A newly allocated #GtkTreePath, or %NULL.
2763 gtk_tree_model_filter_convert_path_to_child_path (GtkTreeModelFilter *filter,
2764 GtkTreePath *filter_path)
2766 gint *filter_indices;
2767 GtkTreePath *retval;
2771 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (filter), NULL);
2772 g_return_val_if_fail (filter->priv->child_model != NULL, NULL);
2773 g_return_val_if_fail (filter_path != NULL, NULL);
2776 retval = gtk_tree_path_new ();
2777 filter_indices = gtk_tree_path_get_indices (filter_path);
2778 if (!filter->priv->root)
2779 gtk_tree_model_filter_build_level (filter, NULL, NULL);
2780 level = FILTER_LEVEL (filter->priv->root);
2782 for (i = 0; i < gtk_tree_path_get_depth (filter_path); i++)
2784 gint count = filter_indices[i];
2786 if (!level || level->array->len <= filter_indices[i])
2788 gtk_tree_path_free (retval);
2792 if (g_array_index (level->array, FilterElt, count).children == NULL)
2793 gtk_tree_model_filter_build_level (filter, level, &g_array_index (level->array, FilterElt, count));
2795 if (!level || level->array->len <= filter_indices[i])
2797 gtk_tree_path_free (retval);
2801 gtk_tree_path_append_index (retval, g_array_index (level->array, FilterElt, count).offset);
2802 level = g_array_index (level->array, FilterElt, count).children;
2807 if (filter->priv->virtual_root)
2809 GtkTreePath *real_retval;
2811 real_retval = gtk_tree_model_filter_add_root (retval,
2812 filter->priv->virtual_root);
2813 gtk_tree_path_free (retval);
2822 gtk_tree_model_filter_refilter_helper (GtkTreeModel *model,
2827 /* evil, don't try this at home, but certainly speeds things up */
2828 gtk_tree_model_filter_row_changed (model, path, iter, data);
2834 * gtk_tree_model_filter_refilter:
2835 * @filter: A #GtkTreeModelFilter.
2837 * Emits ::row_changed for each row in the child model, which causes
2838 * the filter to re-evaluate whether a row is visible or not.
2843 gtk_tree_model_filter_refilter (GtkTreeModelFilter *filter)
2845 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
2848 gtk_tree_model_foreach (filter->priv->child_model,
2849 gtk_tree_model_filter_refilter_helper,
2854 * gtk_tree_model_filter_clear_cache:
2855 * @filter: A #GtkTreeModelFilter.
2857 * This function should almost never be called. It clears the @filter
2858 * of any cached iterators that haven't been reffed with
2859 * gtk_tree_model_ref_node(). This might be useful if the child model
2860 * being filtered is static (and doesn't change often) and there has been
2861 * a lot of unreffed access to nodes. As a side effect of this function,
2862 * all unreffed itters will be invalid.
2867 gtk_tree_model_filter_clear_cache (GtkTreeModelFilter *filter)
2869 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
2871 if (filter->priv->zero_ref_count)
2872 gtk_tree_model_filter_clear_cache_helper (filter,
2873 FILTER_LEVEL (filter->priv->root));