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"
26 #include "gtkprivate.h"
31 * iter->stamp = filter->priv->stamp
32 * iter->user_data = FilterLevel
33 * iter->user_data2 = FilterElt
36 /* all paths, iters, etc prefixed with c_ are paths, iters, etc relative to the
40 typedef struct _FilterElt FilterElt;
41 typedef struct _FilterLevel FilterLevel;
46 FilterLevel *children;
58 FilterElt *parent_elt;
59 FilterLevel *parent_level;
62 #define GTK_TREE_MODEL_FILTER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_TREE_MODEL_FILTER, GtkTreeModelFilterPrivate))
64 struct _GtkTreeModelFilterPrivate
69 GtkTreeModel *child_model;
72 guint root_level_visible;
74 GtkTreePath *virtual_root;
76 GtkTreeModelFilterVisibleFunc visible_func;
77 gpointer visible_data;
78 GtkDestroyNotify visible_destroy;
80 gint modify_n_columns;
82 GtkTreeModelFilterModifyFunc modify_func;
84 gpointer modify_destroy;
88 gboolean visible_method_set;
89 gboolean modify_func_set;
94 guint has_child_toggled_id;
107 #define GTK_TREE_MODEL_FILTER_CACHE_CHILD_ITERS(filter) \
108 (((GtkTreeModelFilter *)filter)->priv->child_flags & GTK_TREE_MODEL_ITERS_PERSIST)
110 #define FILTER_ELT(filter_elt) ((FilterElt *)filter_elt)
111 #define FILTER_LEVEL(filter_level) ((FilterLevel *)filter_level)
113 /* general code (object/interface init, properties, etc) */
114 static void gtk_tree_model_filter_init (GtkTreeModelFilter *filter);
115 static void gtk_tree_model_filter_class_init (GtkTreeModelFilterClass *filter_class);
116 static void gtk_tree_model_filter_tree_model_init (GtkTreeModelIface *iface);
117 static void gtk_tree_model_filter_drag_source_init (GtkTreeDragSourceIface *iface);
118 static void gtk_tree_model_filter_finalize (GObject *object);
119 static void gtk_tree_model_filter_set_property (GObject *object,
123 static void gtk_tree_model_filter_get_property (GObject *object,
128 /* signal handlers */
129 static void gtk_tree_model_filter_row_changed (GtkTreeModel *c_model,
133 static void gtk_tree_model_filter_row_inserted (GtkTreeModel *c_model,
137 static void gtk_tree_model_filter_row_has_child_toggled (GtkTreeModel *c_model,
141 static void gtk_tree_model_filter_row_deleted (GtkTreeModel *c_model,
144 static void gtk_tree_model_filter_rows_reordered (GtkTreeModel *c_model,
150 /* GtkTreeModel interface */
151 static GtkTreeModelFlags gtk_tree_model_filter_get_flags (GtkTreeModel *model);
152 static gint gtk_tree_model_filter_get_n_columns (GtkTreeModel *model);
153 static GType gtk_tree_model_filter_get_column_type (GtkTreeModel *model,
155 static gboolean gtk_tree_model_filter_get_iter (GtkTreeModel *model,
158 static GtkTreePath *gtk_tree_model_filter_get_path (GtkTreeModel *model,
160 static void gtk_tree_model_filter_get_value (GtkTreeModel *model,
164 static gboolean gtk_tree_model_filter_iter_next (GtkTreeModel *model,
166 static gboolean gtk_tree_model_filter_iter_children (GtkTreeModel *model,
168 GtkTreeIter *parent);
169 static gboolean gtk_tree_model_filter_iter_has_child (GtkTreeModel *model,
171 static gint gtk_tree_model_filter_iter_n_children (GtkTreeModel *model,
173 static gboolean gtk_tree_model_filter_iter_nth_child (GtkTreeModel *model,
177 static gboolean gtk_tree_model_filter_iter_parent (GtkTreeModel *model,
180 static void gtk_tree_model_filter_ref_node (GtkTreeModel *model,
182 static void gtk_tree_model_filter_unref_node (GtkTreeModel *model,
185 /* TreeDragSource interface */
186 static gboolean gtk_tree_model_filter_row_draggable (GtkTreeDragSource *drag_source,
188 static gboolean gtk_tree_model_filter_drag_data_get (GtkTreeDragSource *drag_source,
190 GtkSelectionData *selection_data);
191 static gboolean gtk_tree_model_filter_drag_data_delete (GtkTreeDragSource *drag_source,
194 /* private functions */
195 static void gtk_tree_model_filter_build_level (GtkTreeModelFilter *filter,
196 FilterLevel *parent_level,
197 FilterElt *parent_elt);
198 static void gtk_tree_model_filter_free_level (GtkTreeModelFilter *filter,
199 FilterLevel *filter_level);
201 static GtkTreePath *gtk_tree_model_filter_elt_get_path (FilterLevel *level,
205 static GtkTreePath *gtk_tree_model_filter_add_root (GtkTreePath *src,
207 static GtkTreePath *gtk_tree_model_filter_remove_root (GtkTreePath *src,
210 static void gtk_tree_model_filter_increment_stamp (GtkTreeModelFilter *filter);
212 static gboolean gtk_tree_model_filter_visible (GtkTreeModelFilter *filter,
213 GtkTreeIter *child_iter);
214 static void gtk_tree_model_filter_clear_cache_helper (GtkTreeModelFilter *filter,
217 static void gtk_tree_model_filter_real_unref_node (GtkTreeModel *model,
219 gboolean propagate_unref);
221 static void gtk_tree_model_filter_set_model (GtkTreeModelFilter *filter,
222 GtkTreeModel *child_model);
223 static void gtk_tree_model_filter_set_root (GtkTreeModelFilter *filter,
226 static GtkTreePath *gtk_real_tree_model_filter_convert_child_path_to_path (GtkTreeModelFilter *filter,
227 GtkTreePath *child_path,
228 gboolean build_levels,
229 gboolean fetch_children);
231 static FilterElt *gtk_tree_model_filter_fetch_child (GtkTreeModelFilter *filter,
235 static void gtk_tree_model_filter_remove_node (GtkTreeModelFilter *filter,
237 gboolean emit_signal);
238 static void gtk_tree_model_filter_update_children (GtkTreeModelFilter *filter,
241 static FilterElt *bsearch_elt_with_offset (GArray *array,
246 static GObjectClass *parent_class = NULL;
249 gtk_tree_model_filter_get_type (void)
251 static GType tree_model_filter_type = 0;
253 if (!tree_model_filter_type)
255 static const GTypeInfo tree_model_filter_info =
257 sizeof (GtkTreeModelFilterClass),
258 NULL, /* base_init */
259 NULL, /* base_finalize */
260 (GClassInitFunc) gtk_tree_model_filter_class_init,
261 NULL, /* class_finalize */
262 NULL, /* class_data */
263 sizeof (GtkTreeModelFilter),
265 (GInstanceInitFunc) gtk_tree_model_filter_init
268 static const GInterfaceInfo tree_model_info =
270 (GInterfaceInitFunc) gtk_tree_model_filter_tree_model_init,
275 static const GInterfaceInfo drag_source_info =
277 (GInterfaceInitFunc) gtk_tree_model_filter_drag_source_init,
282 tree_model_filter_type = g_type_register_static (G_TYPE_OBJECT,
283 "GtkTreeModelFilter",
284 &tree_model_filter_info, 0);
286 g_type_add_interface_static (tree_model_filter_type,
290 g_type_add_interface_static (tree_model_filter_type,
291 GTK_TYPE_TREE_DRAG_SOURCE,
295 return tree_model_filter_type;
299 gtk_tree_model_filter_init (GtkTreeModelFilter *filter)
301 filter->priv = GTK_TREE_MODEL_FILTER_GET_PRIVATE (filter);
303 filter->priv->visible_column = -1;
304 filter->priv->zero_ref_count = 0;
305 filter->priv->visible_method_set = FALSE;
306 filter->priv->modify_func_set = FALSE;
310 gtk_tree_model_filter_class_init (GtkTreeModelFilterClass *filter_class)
312 GObjectClass *object_class;
314 object_class = (GObjectClass *) filter_class;
315 parent_class = g_type_class_peek_parent (filter_class);
317 object_class->set_property = gtk_tree_model_filter_set_property;
318 object_class->get_property = gtk_tree_model_filter_get_property;
320 object_class->finalize = gtk_tree_model_filter_finalize;
322 /* Properties -- FIXME: disabled translations for now, until I can come up with a
325 g_object_class_install_property (object_class,
327 g_param_spec_object ("child-model",
329 ("The model for the filtermodel to filter"),
331 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
333 g_object_class_install_property (object_class,
335 g_param_spec_boxed ("virtual-root",
336 ("The virtual root"),
337 ("The virtual root (relative to the child model) for this filtermodel"),
339 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
341 g_type_class_add_private (object_class, sizeof (GtkTreeModelFilterPrivate));
345 gtk_tree_model_filter_tree_model_init (GtkTreeModelIface *iface)
347 iface->get_flags = gtk_tree_model_filter_get_flags;
348 iface->get_n_columns = gtk_tree_model_filter_get_n_columns;
349 iface->get_column_type = gtk_tree_model_filter_get_column_type;
350 iface->get_iter = gtk_tree_model_filter_get_iter;
351 iface->get_path = gtk_tree_model_filter_get_path;
352 iface->get_value = gtk_tree_model_filter_get_value;
353 iface->iter_next = gtk_tree_model_filter_iter_next;
354 iface->iter_children = gtk_tree_model_filter_iter_children;
355 iface->iter_has_child = gtk_tree_model_filter_iter_has_child;
356 iface->iter_n_children = gtk_tree_model_filter_iter_n_children;
357 iface->iter_nth_child = gtk_tree_model_filter_iter_nth_child;
358 iface->iter_parent = gtk_tree_model_filter_iter_parent;
359 iface->ref_node = gtk_tree_model_filter_ref_node;
360 iface->unref_node = gtk_tree_model_filter_unref_node;
364 gtk_tree_model_filter_drag_source_init (GtkTreeDragSourceIface *iface)
366 iface->row_draggable = gtk_tree_model_filter_row_draggable;
367 iface->drag_data_delete = gtk_tree_model_filter_drag_data_delete;
368 iface->drag_data_get = gtk_tree_model_filter_drag_data_get;
373 gtk_tree_model_filter_finalize (GObject *object)
375 GtkTreeModelFilter *filter = (GtkTreeModelFilter *) object;
377 gtk_tree_model_filter_set_model (filter, NULL);
379 if (filter->priv->virtual_root)
380 gtk_tree_path_free (filter->priv->virtual_root);
382 if (filter->priv->root)
383 gtk_tree_model_filter_free_level (filter, filter->priv->root);
385 if (filter->priv->modify_types)
386 g_free (filter->priv->modify_types);
389 parent_class->finalize (object);
393 gtk_tree_model_filter_set_property (GObject *object,
398 GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (object);
402 case PROP_CHILD_MODEL:
403 gtk_tree_model_filter_set_model (filter, g_value_get_object (value));
405 case PROP_VIRTUAL_ROOT:
406 gtk_tree_model_filter_set_root (filter, g_value_get_boxed (value));
409 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
415 gtk_tree_model_filter_get_property (GObject *object,
420 GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (object);
424 case PROP_CHILD_MODEL:
425 g_value_set_object (value, filter->priv->child_model);
427 case PROP_VIRTUAL_ROOT:
428 g_value_set_boxed (value, filter->priv->virtual_root);
431 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
439 gtk_tree_model_filter_build_level (GtkTreeModelFilter *filter,
440 FilterLevel *parent_level,
441 FilterElt *parent_elt)
445 FilterLevel *new_level;
449 g_assert (filter->priv->child_model != NULL);
453 if (filter->priv->virtual_root)
455 if (gtk_tree_model_get_iter (filter->priv->child_model, &root, filter->priv->virtual_root) == FALSE)
457 length = gtk_tree_model_iter_n_children (filter->priv->child_model, &root);
459 if (gtk_tree_model_iter_children (filter->priv->child_model, &iter, &root) == FALSE)
464 if (!gtk_tree_model_get_iter_first (filter->priv->child_model, &iter))
466 length = gtk_tree_model_iter_n_children (filter->priv->child_model, NULL);
471 GtkTreeIter parent_iter;
472 GtkTreeIter child_parent_iter;
474 parent_iter.stamp = filter->priv->stamp;
475 parent_iter.user_data = parent_level;
476 parent_iter.user_data2 = parent_elt;
478 gtk_tree_model_filter_convert_iter_to_child_iter (filter,
481 if (gtk_tree_model_iter_children (filter->priv->child_model, &iter, &child_parent_iter) == FALSE)
484 /* stamp may have changed */
485 gtk_tree_model_filter_convert_iter_to_child_iter (filter,
488 length = gtk_tree_model_iter_n_children (filter->priv->child_model, &child_parent_iter);
491 g_return_if_fail (length > 0);
493 new_level = g_new (FilterLevel, 1);
494 new_level->array = g_array_sized_new (FALSE, FALSE,
497 new_level->ref_count = 0;
498 new_level->parent_elt = parent_elt;
499 new_level->parent_level = parent_level;
502 parent_elt->children = new_level;
504 filter->priv->root = new_level;
506 /* increase the count of zero ref_counts */
509 parent_elt->zero_ref_count++;
511 parent_elt = parent_level->parent_elt;
512 parent_level = parent_level->parent_level;
514 filter->priv->zero_ref_count++;
518 if (!new_level->parent_level)
519 filter->priv->root_level_visible = 0;
523 if (gtk_tree_model_filter_visible (filter, &iter))
525 FilterElt filter_elt;
527 filter_elt.offset = i;
528 filter_elt.zero_ref_count = 0;
529 filter_elt.ref_count = 0;
530 filter_elt.children = NULL;
531 filter_elt.visible = TRUE;
533 if (GTK_TREE_MODEL_FILTER_CACHE_CHILD_ITERS (filter))
534 filter_elt.iter = iter;
536 g_array_append_val (new_level->array, filter_elt);
538 if (!new_level->parent_level)
539 filter->priv->root_level_visible++;
543 while (gtk_tree_model_iter_next (filter->priv->child_model, &iter));
547 gtk_tree_model_filter_free_level (GtkTreeModelFilter *filter,
548 FilterLevel *filter_level)
552 g_assert (filter_level);
554 if (filter_level->ref_count == 0)
556 FilterLevel *parent_level = filter_level->parent_level;
557 FilterElt *parent_elt = filter_level->parent_elt;
562 parent_elt->zero_ref_count--;
566 parent_elt = parent_level->parent_elt;
567 parent_level = parent_level->parent_level;
570 while (parent_level);
571 filter->priv->zero_ref_count--;
574 for (i = 0; i < filter_level->array->len; i++)
576 if (g_array_index (filter_level->array, FilterElt, i).children)
577 gtk_tree_model_filter_free_level (filter,
578 FILTER_LEVEL (g_array_index (filter_level->array, FilterElt, i).children));
581 if (!filter_level->parent_level)
582 filter->priv->root_level_visible = 0;
584 if (filter_level->parent_elt)
585 filter_level->parent_elt->children = NULL;
587 filter->priv->root = NULL;
589 g_array_free (filter_level->array, TRUE);
590 filter_level->array = NULL;
592 g_free (filter_level);
597 gtk_tree_model_filter_elt_get_path (FilterLevel *level,
601 FilterLevel *walker = level;
602 FilterElt *walker2 = elt;
604 GtkTreePath *real_path;
606 g_return_val_if_fail (level != NULL, NULL);
607 g_return_val_if_fail (elt != NULL, NULL);
609 path = gtk_tree_path_new ();
613 gtk_tree_path_prepend_index (path, walker2->offset);
615 walker2 = walker->parent_elt;
616 walker = walker->parent_level;
621 real_path = gtk_tree_model_filter_add_root (path, root);
622 gtk_tree_path_free (path);
630 gtk_tree_model_filter_add_root (GtkTreePath *src,
636 retval = gtk_tree_path_copy (root);
638 for (i = 0; i < gtk_tree_path_get_depth (src); i++)
639 gtk_tree_path_append_index (retval, gtk_tree_path_get_indices (src)[i]);
645 gtk_tree_model_filter_remove_root (GtkTreePath *src,
653 if (gtk_tree_path_get_depth (src) <= gtk_tree_path_get_depth (root))
656 depth = gtk_tree_path_get_depth (src);
657 indices = gtk_tree_path_get_indices (src);
659 for (i = 0; i < gtk_tree_path_get_depth (root); i++)
660 if (indices[i] != gtk_tree_path_get_indices (root)[i])
663 retval = gtk_tree_path_new ();
665 for (; i < depth; i++)
666 gtk_tree_path_append_index (retval, indices[i]);
672 gtk_tree_model_filter_increment_stamp (GtkTreeModelFilter *filter)
676 filter->priv->stamp++;
678 while (filter->priv->stamp == 0);
680 gtk_tree_model_filter_clear_cache (filter);
684 gtk_tree_model_filter_visible (GtkTreeModelFilter *filter,
685 GtkTreeIter *child_iter)
687 if (filter->priv->visible_func)
689 return (filter->priv->visible_func (filter->priv->child_model,
691 filter->priv->visible_data));
693 else if (filter->priv->visible_column >= 0)
697 gtk_tree_model_get_value (filter->priv->child_model, child_iter,
698 filter->priv->visible_column, &val);
700 if (g_value_get_boolean (&val))
702 g_value_unset (&val);
706 g_value_unset (&val);
710 /* no filter thing set, so always visible */
715 gtk_tree_model_filter_clear_cache_helper (GtkTreeModelFilter *filter,
722 for (i = 0; i < level->array->len; i++)
724 if (g_array_index (level->array, FilterElt, i).zero_ref_count > 0)
725 gtk_tree_model_filter_clear_cache_helper (filter, g_array_index (level->array, FilterElt, i).children);
728 if (level->ref_count == 0 && level != filter->priv->root)
730 gtk_tree_model_filter_free_level (filter, level);
736 gtk_tree_model_filter_fetch_child (GtkTreeModelFilter *filter,
742 gint start, middle, end;
744 GtkTreePath *c_path = NULL;
746 GtkTreePath *c_parent_path = NULL;
747 GtkTreeIter c_parent_iter;
750 /* check if child exists and is visible */
751 if (level->parent_elt)
754 gtk_tree_model_filter_elt_get_path (level->parent_level,
756 filter->priv->virtual_root);
762 if (filter->priv->virtual_root)
763 c_parent_path = gtk_tree_path_copy (filter->priv->virtual_root);
765 c_parent_path = NULL;
770 gtk_tree_model_get_iter (filter->priv->child_model,
773 len = gtk_tree_model_iter_n_children (filter->priv->child_model,
776 c_path = gtk_tree_path_copy (c_parent_path);
777 gtk_tree_path_free (c_parent_path);
781 len = gtk_tree_model_iter_n_children (filter->priv->child_model, NULL);
782 c_path = gtk_tree_path_new ();
785 gtk_tree_path_append_index (c_path, offset);
786 gtk_tree_model_get_iter (filter->priv->child_model, &c_iter, c_path);
787 gtk_tree_path_free (c_path);
789 if (offset >= len || !gtk_tree_model_filter_visible (filter, &c_iter))
794 elt.zero_ref_count = 0;
797 /* visibility should be FALSE as we don't emit row_inserted */
800 if (GTK_TREE_MODEL_FILTER_CACHE_CHILD_ITERS (filter))
803 /* find index (binary search on offset) */
805 end = level->array->len;
811 middle = (start + end) / 2;
813 if (g_array_index (level->array, FilterElt, middle).offset <= offset)
819 if (g_array_index (level->array, FilterElt, middle).offset <= offset)
827 g_array_insert_val (level->array, i, elt);
833 for ( ; i < level->array->len; i++)
835 FilterElt *e = &(g_array_index (level->array, FilterElt, i));
837 e->children->parent_elt = e;
840 return &g_array_index (level->array, FilterElt, *index);
844 gtk_tree_model_filter_remove_node (GtkTreeModelFilter *filter,
846 gboolean emit_signal)
848 FilterElt *elt, *parent;
849 FilterLevel *level, *parent_level;
850 gint offset, i, length, level_refcount;
852 /* FIXME: this function is very ugly. I need to rethink and
853 * rewrite it someday.
856 level = FILTER_LEVEL (iter->user_data);
857 elt = FILTER_ELT (iter->user_data2);
859 parent = level->parent_elt;
860 parent_level = level->parent_level;
861 length = level->array->len;
862 offset = elt->offset;
865 while (elt->ref_count > 0)
866 gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter),
869 level_refcount = level->ref_count;
871 /* do the ref counting first! this touches the stamp */
876 path = gtk_tree_model_get_path (GTK_TREE_MODEL (filter), iter);
877 gtk_tree_model_filter_increment_stamp (filter);
878 gtk_tree_model_row_deleted (GTK_TREE_MODEL (filter), path);
879 gtk_tree_path_free (path);
882 if ((length == 1 || level_refcount == 0) &&
883 emit_signal && iter->user_data != filter->priv->root)
885 /* above code destroyed the level */
886 goto emit_has_child_toggled;
892 gtk_tree_model_filter_free_level (filter, level);
894 if (!filter->priv->root)
895 /* we killed the root */
902 /* remove the node */
903 tmp = bsearch_elt_with_offset (level->array, elt->offset, &i);
907 g_array_remove_index (level->array, i);
909 for (i = MAX (--i, 0); i < level->array->len; i++)
911 /* NOTE: here we do *not* decrease offsets, because the node was
912 * not removed from the child model
914 elt = &g_array_index (level->array, FilterElt, i);
916 elt->children->parent_elt = elt;
921 emit_has_child_toggled:
922 /* children are being handled first, so we can check it this way
924 * yes this if-statement is ugly
926 if ((parent && parent->children && parent->children->array->len <= 1) ||
927 (length == 1 && emit_signal && iter->user_data != filter->priv->root))
929 /* latest child has been removed, level has been destroyed */
933 piter.stamp = filter->priv->stamp;
934 piter.user_data = parent_level;
935 piter.user_data2 = parent;
937 ppath = gtk_tree_model_get_path (GTK_TREE_MODEL (filter), &piter);
939 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (filter),
941 gtk_tree_path_free (ppath);
946 gtk_tree_model_filter_update_children (GtkTreeModelFilter *filter,
956 iter.stamp = filter->priv->stamp;
957 iter.user_data = level;
958 iter.user_data2 = elt;
960 gtk_tree_model_filter_convert_iter_to_child_iter (filter, &c_iter, &iter);
962 if (gtk_tree_model_iter_has_child (filter->priv->child_model, &c_iter))
964 GtkTreePath *path = gtk_tree_model_get_path (GTK_TREE_MODEL (filter),
966 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (filter),
970 gtk_tree_path_free (path);
975 bsearch_elt_with_offset (GArray *array,
979 gint start, middle, end;
990 elt = &g_array_index (array, FilterElt, 0);
992 if (elt->offset == offset)
1003 middle = (start + end) / 2;
1005 elt = &g_array_index (array, FilterElt, middle);
1007 if (elt->offset < offset)
1009 else if (elt->offset > offset)
1014 while (start != end);
1016 if (elt->offset == offset)
1025 /* TreeModel signals */
1027 gtk_tree_model_filter_row_changed (GtkTreeModel *c_model,
1028 GtkTreePath *c_path,
1029 GtkTreeIter *c_iter,
1032 GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (data);
1034 GtkTreeIter children;
1035 GtkTreeIter real_c_iter;
1036 GtkTreePath *path = NULL;
1041 gboolean requested_state;
1042 gboolean current_state;
1043 gboolean free_c_path = FALSE;
1045 g_return_if_fail (c_path != NULL || c_iter != NULL);
1049 c_path = gtk_tree_model_get_path (c_model, c_iter);
1054 real_c_iter = *c_iter;
1056 gtk_tree_model_get_iter (c_model, &real_c_iter, c_path);
1058 /* is this node above the virtual root? */
1059 if (filter->priv->virtual_root
1060 && (gtk_tree_path_get_depth (filter->priv->virtual_root)
1061 >= gtk_tree_path_get_depth (c_path)))
1064 /* what's the requested state? */
1065 requested_state = gtk_tree_model_filter_visible (filter, &real_c_iter);
1067 /* now, let's see whether the item is there */
1068 path = gtk_real_tree_model_filter_convert_child_path_to_path (filter,
1075 gtk_tree_model_get_iter (GTK_TREE_MODEL (filter), &iter, path);
1076 current_state = FILTER_ELT (iter.user_data2)->visible;
1079 current_state = FALSE;
1081 if (current_state == FALSE && requested_state == FALSE)
1082 /* no changes required */
1085 if (current_state == TRUE && requested_state == FALSE)
1087 /* get rid of this node */
1088 gtk_tree_model_get_iter (GTK_TREE_MODEL (filter), &iter, path);
1090 level = FILTER_LEVEL (iter.user_data);
1092 if (!level->parent_level)
1093 filter->priv->root_level_visible--;
1095 gtk_tree_model_filter_remove_node (filter, &iter, TRUE);
1100 if (current_state == TRUE && requested_state == TRUE)
1102 /* progate the signal */
1103 gtk_tree_model_get_iter (GTK_TREE_MODEL (filter), &iter, path);
1104 gtk_tree_model_row_changed (GTK_TREE_MODEL (filter), path, &iter);
1106 level = FILTER_LEVEL (iter.user_data);
1107 elt = FILTER_ELT (iter.user_data2);
1109 /* and update the children */
1110 if (gtk_tree_model_iter_children (c_model, &children, &real_c_iter))
1111 gtk_tree_model_filter_update_children (filter, level, elt);
1116 /* only current == FALSE and requested == TRUE is left,
1119 g_return_if_fail (current_state == FALSE && requested_state == TRUE);
1121 /* make sure the new item has been pulled in */
1122 if (!filter->priv->root)
1127 gtk_tree_model_filter_build_level (filter, NULL, NULL);
1129 root = FILTER_LEVEL (filter->priv->root);
1133 for (i = 0; i < root->array->len; i++)
1134 g_array_index (root->array, FilterElt, i).visible = FALSE;
1135 filter->priv->root_level_visible = 0;
1139 gtk_tree_model_filter_increment_stamp (filter);
1142 path = gtk_real_tree_model_filter_convert_child_path_to_path (filter,
1148 /* parent is probably being filtered out */
1151 gtk_tree_model_get_iter (GTK_TREE_MODEL (filter), &iter, path);
1153 level = FILTER_LEVEL (iter.user_data);
1154 elt = FILTER_ELT (iter.user_data2);
1156 elt->visible = TRUE;
1158 if (!level->parent_level)
1159 filter->priv->root_level_visible++;
1162 gtk_tree_model_row_inserted (GTK_TREE_MODEL (filter), path, &iter);
1164 if (gtk_tree_model_iter_children (c_model, &children, c_iter))
1165 gtk_tree_model_filter_update_children (filter, level, elt);
1169 gtk_tree_path_free (path);
1172 gtk_tree_path_free (c_path);
1176 gtk_tree_model_filter_row_inserted (GtkTreeModel *c_model,
1177 GtkTreePath *c_path,
1178 GtkTreeIter *c_iter,
1181 GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (data);
1182 GtkTreePath *path = NULL;
1183 GtkTreePath *real_path = NULL;
1186 GtkTreeIter real_c_iter;
1190 FilterLevel *parent_level;
1192 gint i = 0, offset, index = -1;
1194 gboolean free_c_path = FALSE;
1196 g_return_if_fail (c_path != NULL || c_iter != NULL);
1200 c_path = gtk_tree_model_get_path (c_model, c_iter);
1205 real_c_iter = *c_iter;
1207 gtk_tree_model_get_iter (c_model, &real_c_iter, c_path);
1209 /* the row has already been inserted. so we need to fixup the
1210 * virtual root here first
1212 if (filter->priv->virtual_root)
1214 if (gtk_tree_path_get_depth (filter->priv->virtual_root) >=
1215 gtk_tree_path_get_depth (c_path))
1218 gint *v_indices, *c_indices;
1220 level = gtk_tree_path_get_depth (c_path) - 1;
1221 v_indices = gtk_tree_path_get_indices (filter->priv->virtual_root);
1222 c_indices = gtk_tree_path_get_indices (c_path);
1224 if (v_indices[level] >= c_indices[level])
1225 (v_indices[level])++;
1229 if (!filter->priv->root)
1231 gtk_tree_model_filter_build_level (filter, NULL, NULL);
1232 /* that already put the inserted iter in the level */
1237 parent_level = level = FILTER_LEVEL (filter->priv->root);
1239 /* subtract virtual root if necessary */
1240 if (filter->priv->virtual_root)
1242 real_path = gtk_tree_model_filter_remove_root (c_path,
1243 filter->priv->virtual_root);
1249 real_path = gtk_tree_path_copy (c_path);
1251 if (gtk_tree_path_get_depth (real_path) - 1 >= 1)
1253 /* find the parent level */
1254 while (i < gtk_tree_path_get_depth (real_path) - 1)
1259 /* we don't cover this signal */
1262 elt = bsearch_elt_with_offset (level->array,
1263 gtk_tree_path_get_indices (real_path)[i],
1267 /* parent is probably being filtered out */
1272 GtkTreePath *tmppath;
1273 GtkTreeIter tmpiter;
1275 tmpiter.stamp = filter->priv->stamp;
1276 tmpiter.user_data = level;
1277 tmpiter.user_data2 = elt;
1279 tmppath = gtk_tree_model_get_path (GTK_TREE_MODEL (data),
1284 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (data),
1286 gtk_tree_path_free (tmppath);
1289 /* not covering this signal */
1293 level = elt->children;
1294 parent_level = level;
1302 /* let's try to insert the value */
1303 offset = gtk_tree_path_get_indices (real_path)[gtk_tree_path_get_depth (real_path) - 1];
1305 /* update the offsets, yes if we didn't insert the node above, there will
1306 * be a gap here. This will be filled with the node (via fetch_child) when
1307 * it becomes visible
1309 for (i = 0; i < level->array->len; i++)
1311 FilterElt *e = &g_array_index (level->array, FilterElt, i);
1312 if ((e->offset >= offset))
1316 /* only insert when visible */
1317 if (gtk_tree_model_filter_visible (filter, &real_c_iter))
1321 if (GTK_TREE_MODEL_FILTER_CACHE_CHILD_ITERS (filter))
1322 felt.iter = real_c_iter;
1324 felt.offset = offset;
1325 felt.zero_ref_count = 0;
1327 felt.visible = TRUE;
1328 felt.children = NULL;
1330 for (i = 0; i < level->array->len; i++)
1331 if (g_array_index (level->array, FilterElt, i).offset > offset)
1334 g_array_insert_val (level->array, i, felt);
1337 if (!level->parent_level)
1338 filter->priv->root_level_visible++;
1341 /* another iteration to update the references of children to parents. */
1342 for (i = 0; i < level->array->len; i++)
1344 FilterElt *e = &g_array_index (level->array, FilterElt, i);
1346 e->children->parent_elt = e;
1349 /* don't emit the signal if we aren't visible */
1350 if (!gtk_tree_model_filter_visible (filter, &real_c_iter))
1354 /* NOTE: pass c_path here and NOT real_path. This function does
1355 * root subtraction itself
1357 path = gtk_real_tree_model_filter_convert_child_path_to_path (filter,
1364 gtk_tree_model_filter_increment_stamp (filter);
1366 gtk_tree_model_get_iter (GTK_TREE_MODEL (data), &iter, path);
1367 gtk_tree_model_row_inserted (GTK_TREE_MODEL (data), path, &iter);
1369 gtk_tree_path_free (path);
1373 gtk_tree_path_free (real_path);
1376 gtk_tree_path_free (c_path);
1380 gtk_tree_model_filter_row_has_child_toggled (GtkTreeModel *c_model,
1381 GtkTreePath *c_path,
1382 GtkTreeIter *c_iter,
1385 GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (data);
1389 g_return_if_fail (c_path != NULL && c_iter != NULL);
1391 /* FIXME: does this code work? */
1393 if (!gtk_tree_model_filter_visible (filter, c_iter))
1396 path = gtk_real_tree_model_filter_convert_child_path_to_path (filter,
1403 gtk_tree_model_get_iter (GTK_TREE_MODEL (data), &iter, path);
1404 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (data), path, &iter);
1406 gtk_tree_path_free (path);
1410 gtk_tree_model_filter_row_deleted (GtkTreeModel *c_model,
1411 GtkTreePath *c_path,
1414 GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (data);
1420 gboolean emit_signal = TRUE;
1423 g_return_if_fail (c_path != NULL);
1425 /* special case the deletion of an ancestor of the virtual root */
1426 if (filter->priv->virtual_root &&
1427 (gtk_tree_path_is_ancestor (c_path, filter->priv->virtual_root) ||
1428 !gtk_tree_path_compare (c_path, filter->priv->virtual_root)))
1432 FilterLevel *level = FILTER_LEVEL (filter->priv->root);
1437 /* remove everything in the filter model
1439 * For now, we just iterate over the root level and emit a
1440 * row_deleted for each FilterElt. Not sure if this is correct.
1443 gtk_tree_model_filter_increment_stamp (filter);
1444 path = gtk_tree_path_new ();
1445 gtk_tree_path_append_index (path, 0);
1447 for (i = 0; i < level->array->len; i++)
1448 gtk_tree_model_row_deleted (GTK_TREE_MODEL (data), path);
1450 gtk_tree_path_free (path);
1451 gtk_tree_model_filter_free_level (filter, filter->priv->root);
1456 /* fixup virtual root */
1457 if (filter->priv->virtual_root)
1459 if (gtk_tree_path_get_depth (filter->priv->virtual_root) >=
1460 gtk_tree_path_get_depth (c_path))
1463 gint *v_indices, *c_indices;
1465 level = gtk_tree_path_get_depth (c_path) - 1;
1466 v_indices = gtk_tree_path_get_indices (filter->priv->virtual_root);
1467 c_indices = gtk_tree_path_get_indices (c_path);
1469 if (v_indices[level] > c_indices[level])
1470 (v_indices[level])--;
1474 path = gtk_real_tree_model_filter_convert_child_path_to_path (filter,
1481 /* fixup the offsets */
1482 GtkTreePath *real_path;
1484 if (!filter->priv->root)
1487 level = FILTER_LEVEL (filter->priv->root);
1489 /* subtract vroot if necessary */
1490 if (filter->priv->virtual_root)
1492 real_path = gtk_tree_model_filter_remove_root (c_path,
1493 filter->priv->virtual_root);
1494 /* we don't handle this */
1499 real_path = gtk_tree_path_copy (c_path);
1502 if (gtk_tree_path_get_depth (real_path) - 1 >= 1)
1504 while (i < gtk_tree_path_get_depth (real_path) - 1)
1510 /* we don't cover this */
1511 gtk_tree_path_free (real_path);
1515 elt = bsearch_elt_with_offset (level->array,
1516 gtk_tree_path_get_indices (real_path)[i],
1519 if (!elt || !elt->children)
1521 /* parent is filtered out, so no level */
1522 gtk_tree_path_free (real_path);
1526 level = elt->children;
1531 offset = gtk_tree_path_get_indices (real_path)[gtk_tree_path_get_depth (real_path) - 1];
1532 gtk_tree_path_free (real_path);
1538 * - the offset of the removed item
1541 for (i = 0; i < level->array->len; i++)
1543 elt = &g_array_index (level->array, FilterElt, i);
1544 if (elt->offset > offset)
1547 elt->children->parent_elt = elt;
1553 gtk_tree_model_get_iter (GTK_TREE_MODEL (data), &iter, path);
1555 level = FILTER_LEVEL (iter.user_data);
1556 elt = FILTER_ELT (iter.user_data2);
1557 offset = elt->offset;
1559 if (!level->parent_level && elt->visible)
1560 filter->priv->root_level_visible--;
1564 if (level->ref_count == 0 && level != filter->priv->root)
1566 gtk_tree_model_filter_increment_stamp (filter);
1567 gtk_tree_model_row_deleted (GTK_TREE_MODEL (data), path);
1569 gtk_tree_path_free (path);
1573 gtk_tree_model_filter_increment_stamp (filter);
1574 gtk_tree_model_row_deleted (GTK_TREE_MODEL (data), path);
1575 iter.stamp = filter->priv->stamp;
1577 while (elt->ref_count > 0)
1578 gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (data), &iter,
1582 if (level->array->len == 1)
1585 gtk_tree_model_filter_free_level (filter, level);
1591 /* remove the row */
1592 tmp = bsearch_elt_with_offset (level->array, elt->offset, &i);
1594 offset = tmp->offset;
1595 g_array_remove_index (level->array, i);
1597 for (i = MAX (--i, 0); i < level->array->len; i++)
1599 elt = &g_array_index (level->array, FilterElt, i);
1600 if (elt->offset > offset)
1603 elt->children->parent_elt = elt;
1607 gtk_tree_path_free (path);
1611 gtk_tree_model_filter_rows_reordered (GtkTreeModel *c_model,
1612 GtkTreePath *c_path,
1613 GtkTreeIter *c_iter,
1619 GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (data);
1625 gint i, j, elt_count;
1630 g_return_if_fail (new_order != NULL);
1632 if (c_path == NULL || gtk_tree_path_get_indices (c_path) == NULL)
1634 if (!filter->priv->root)
1637 length = gtk_tree_model_iter_n_children (c_model, NULL);
1639 if (filter->priv->virtual_root)
1643 /* reorder root level of path */
1644 for (i = 0; i < length; i++)
1645 if (new_order[i] == gtk_tree_path_get_indices (filter->priv->virtual_root)[0])
1651 gtk_tree_path_get_indices (filter->priv->virtual_root)[0] = new_pos;
1655 path = gtk_tree_path_new ();
1656 level = FILTER_LEVEL (filter->priv->root);
1660 GtkTreeIter child_iter;
1662 /* virtual root anchor reordering */
1663 if (filter->priv->virtual_root &&
1664 gtk_tree_path_get_depth (c_path) <
1665 gtk_tree_path_get_depth (filter->priv->virtual_root))
1670 GtkTreeIter real_c_iter;
1672 level = gtk_tree_path_get_depth (c_path);
1675 real_c_iter = *c_iter;
1677 gtk_tree_model_get_iter (c_model, &real_c_iter, c_path);
1679 length = gtk_tree_model_iter_n_children (c_model, &real_c_iter);
1681 for (i = 0; i < length; i++)
1682 if (new_order[i] == gtk_tree_path_get_indices (filter->priv->virtual_root)[level])
1688 gtk_tree_path_get_indices (filter->priv->virtual_root)[level] = new_pos;
1692 path = gtk_real_tree_model_filter_convert_child_path_to_path (filter,
1696 if (!path && filter->priv->virtual_root &&
1697 gtk_tree_path_compare (c_path, filter->priv->virtual_root))
1700 if (!path && !filter->priv->virtual_root)
1705 /* root level mode */
1707 gtk_tree_model_get_iter (c_model, c_iter, c_path);
1708 length = gtk_tree_model_iter_n_children (c_model, c_iter);
1709 path = gtk_tree_path_new ();
1710 level = FILTER_LEVEL (filter->priv->root);
1714 gtk_tree_model_get_iter (GTK_TREE_MODEL (data), &iter, path);
1716 level = FILTER_LEVEL (iter.user_data);
1717 elt = FILTER_ELT (iter.user_data2);
1721 gtk_tree_path_free (path);
1725 level = elt->children;
1727 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (filter), &child_iter, &iter);
1728 length = gtk_tree_model_iter_n_children (c_model, &child_iter);
1732 if (level->array->len < 1)
1734 gtk_tree_path_free (path);
1738 /* NOTE: we do not bail out here if level->array->len < 2 like
1739 * GtkTreeModelSort does. This because we do some special tricky
1743 /* construct a new array */
1744 new_array = g_array_sized_new (FALSE, FALSE, sizeof (FilterElt),
1746 tmp_array = g_new (gint, level->array->len);
1748 for (i = 0, elt_count = 0; i < length; i++)
1750 FilterElt *e = NULL;
1751 gint old_offset = -1;
1753 for (j = 0; j < level->array->len; j++)
1754 if (g_array_index (level->array, FilterElt, j).offset == new_order[i])
1756 e = &g_array_index (level->array, FilterElt, j);
1764 tmp_array[elt_count] = old_offset;
1765 g_array_append_val (new_array, *e);
1766 g_array_index (new_array, FilterElt, elt_count).offset = i;
1770 g_array_free (level->array, TRUE);
1771 level->array = new_array;
1774 for (i = 0; i < level->array->len; i++)
1776 FilterElt *e = &g_array_index (level->array, FilterElt, i);
1778 e->children->parent_elt = e;
1781 /* emit rows_reordered */
1782 if (!gtk_tree_path_get_indices (path))
1783 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (data), path, NULL,
1786 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (data), path, &iter,
1791 gtk_tree_path_free (path);
1794 /* TreeModelIface implementation */
1795 static GtkTreeModelFlags
1796 gtk_tree_model_filter_get_flags (GtkTreeModel *model)
1798 GtkTreeModelFlags flags;
1800 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), 0);
1801 g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL, 0);
1803 flags = gtk_tree_model_get_flags (GTK_TREE_MODEL_FILTER (model)->priv->child_model);
1805 if ((flags & GTK_TREE_MODEL_LIST_ONLY) == GTK_TREE_MODEL_LIST_ONLY)
1806 return GTK_TREE_MODEL_LIST_ONLY;
1812 gtk_tree_model_filter_get_n_columns (GtkTreeModel *model)
1814 GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
1816 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), 0);
1817 g_return_val_if_fail (filter->priv->child_model != NULL, 0);
1819 if (filter->priv->child_model == NULL)
1822 /* so we can't modify the modify func after this ... */
1823 filter->priv->modify_func_set = TRUE;
1825 if (filter->priv->modify_n_columns > 0)
1826 return filter->priv->modify_n_columns;
1828 return gtk_tree_model_get_n_columns (filter->priv->child_model);
1832 gtk_tree_model_filter_get_column_type (GtkTreeModel *model,
1835 GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
1837 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), G_TYPE_INVALID);
1838 g_return_val_if_fail (filter->priv->child_model != NULL, G_TYPE_INVALID);
1840 /* so we can't modify the modify func after this ... */
1841 filter->priv->modify_func_set = TRUE;
1843 if (filter->priv->modify_types)
1845 g_return_val_if_fail (index < filter->priv->modify_n_columns, G_TYPE_INVALID);
1847 return filter->priv->modify_types[index];
1850 return gtk_tree_model_get_column_type (filter->priv->child_model, index);
1854 gtk_tree_model_filter_get_iter (GtkTreeModel *model,
1858 GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
1863 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
1864 g_return_val_if_fail (filter->priv->child_model != NULL, FALSE);
1866 indices = gtk_tree_path_get_indices (path);
1868 if (filter->priv->root == NULL)
1869 gtk_tree_model_filter_build_level (filter, NULL, NULL);
1870 level = FILTER_LEVEL (filter->priv->root);
1872 depth = gtk_tree_path_get_depth (path);
1879 for (i = 0; i < depth - 1; i++)
1881 if (!level || indices[i] >= level->array->len)
1886 if (!g_array_index (level->array, FilterElt, indices[i]).children)
1887 gtk_tree_model_filter_build_level (filter, level,
1888 &g_array_index (level->array,
1891 level = g_array_index (level->array, FilterElt, indices[i]).children;
1894 if (!level || indices[i] >= level->array->len)
1900 iter->stamp = filter->priv->stamp;
1901 iter->user_data = level;
1902 iter->user_data2 = &g_array_index (level->array, FilterElt,
1903 indices[depth - 1]);
1908 static GtkTreePath *
1909 gtk_tree_model_filter_get_path (GtkTreeModel *model,
1912 GtkTreePath *retval;
1916 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), NULL);
1917 g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL, NULL);
1918 g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->stamp == iter->stamp, NULL);
1920 retval = gtk_tree_path_new ();
1921 level = iter->user_data;
1922 elt = iter->user_data2;
1926 gtk_tree_path_prepend_index (retval,
1927 elt - FILTER_ELT (level->array->data));
1928 elt = level->parent_elt;
1929 level = level->parent_level;
1936 gtk_tree_model_filter_get_value (GtkTreeModel *model,
1941 GtkTreeIter child_iter;
1942 GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (model);
1944 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (model));
1945 g_return_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL);
1946 g_return_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->stamp == iter->stamp);
1948 if (filter->priv->modify_func)
1950 g_return_if_fail (column < filter->priv->modify_n_columns);
1952 g_value_init (value, filter->priv->modify_types[column]);
1953 filter->priv->modify_func (model,
1957 filter->priv->modify_data);
1962 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_iter, iter);
1963 gtk_tree_model_get_value (GTK_TREE_MODEL_FILTER (model)->priv->child_model,
1964 &child_iter, column, value);
1968 gtk_tree_model_filter_iter_next (GtkTreeModel *model,
1974 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
1975 g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL, FALSE);
1976 g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->stamp == iter->stamp, FALSE);
1978 level = iter->user_data;
1979 elt = iter->user_data2;
1981 if (elt - FILTER_ELT (level->array->data) >= level->array->len - 1)
1987 iter->user_data2 = elt + 1;
1993 gtk_tree_model_filter_iter_children (GtkTreeModel *model,
1995 GtkTreeIter *parent)
1997 GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
2001 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
2002 g_return_val_if_fail (filter->priv->child_model != NULL, FALSE);
2004 g_return_val_if_fail (filter->priv->stamp == parent->stamp, FALSE);
2008 if (!filter->priv->root)
2009 gtk_tree_model_filter_build_level (filter, NULL, NULL);
2010 if (!filter->priv->root)
2013 level = filter->priv->root;
2014 iter->stamp = filter->priv->stamp;
2015 iter->user_data = level;
2016 iter->user_data2 = level->array->data;
2020 if (FILTER_ELT (parent->user_data2)->children == NULL)
2021 gtk_tree_model_filter_build_level (filter,
2022 FILTER_LEVEL (parent->user_data),
2023 FILTER_ELT (parent->user_data2));
2024 if (FILTER_ELT (parent->user_data2)->children == NULL)
2028 if (FILTER_ELT (parent->user_data2)->children->array->len <= 0)
2031 iter->stamp = filter->priv->stamp;
2032 iter->user_data = FILTER_ELT (parent->user_data2)->children;
2033 iter->user_data2 = FILTER_LEVEL (iter->user_data)->array->data;
2040 gtk_tree_model_filter_iter_has_child (GtkTreeModel *model,
2043 GtkTreeIter child_iter;
2044 GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
2047 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
2048 g_return_val_if_fail (filter->priv->child_model != NULL, FALSE);
2049 g_return_val_if_fail (filter->priv->stamp == iter->stamp, FALSE);
2051 filter = GTK_TREE_MODEL_FILTER (model);
2053 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_iter, iter);
2054 elt = FILTER_ELT (iter->user_data2);
2056 /* we need to build the level to check if not all children are filtered
2060 && gtk_tree_model_iter_has_child (filter->priv->child_model, &child_iter))
2061 gtk_tree_model_filter_build_level (filter, FILTER_LEVEL (iter->user_data),
2064 /* FIXME: we should prolly count the visible nodes here, just like in
2067 if (elt->children && elt->children->array->len > 0)
2074 gtk_tree_model_filter_iter_n_children (GtkTreeModel *model,
2077 GtkTreeIter child_iter;
2078 GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
2081 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), 0);
2082 g_return_val_if_fail (filter->priv->child_model != NULL, 0);
2084 g_return_val_if_fail (filter->priv->stamp == iter->stamp, 0);
2088 if (!filter->priv->root)
2089 gtk_tree_model_filter_build_level (filter, NULL, NULL);
2091 /* count visible nodes */
2092 return filter->priv->root_level_visible;
2095 elt = FILTER_ELT (iter->user_data2);
2096 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_iter, iter);
2098 if (!elt->children &&
2099 gtk_tree_model_iter_has_child (filter->priv->child_model, &child_iter))
2100 gtk_tree_model_filter_build_level (filter,
2101 FILTER_LEVEL (iter->user_data),
2104 if (elt->children && elt->children->array->len)
2108 GArray *a = elt->children->array;
2110 /* count visible nodes */
2111 for (i = 0; i < a->len; i++)
2112 if (g_array_index (a, FilterElt, i).visible)
2122 gtk_tree_model_filter_iter_nth_child (GtkTreeModel *model,
2124 GtkTreeIter *parent,
2128 GtkTreeIter children;
2130 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
2132 g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->stamp == parent->stamp, FALSE);
2134 /* use this instead of has_Child to force us to build the level, if needed */
2135 if (gtk_tree_model_filter_iter_children (model, &children, parent) == FALSE)
2141 level = children.user_data;
2142 if (n >= level->array->len)
2148 iter->stamp = GTK_TREE_MODEL_FILTER (model)->priv->stamp;
2149 iter->user_data = level;
2150 iter->user_data2 = &g_array_index (level->array, FilterElt, n);
2156 gtk_tree_model_filter_iter_parent (GtkTreeModel *model,
2163 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
2164 g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL, FALSE);
2165 g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->stamp == child->stamp, FALSE);
2167 level = child->user_data;
2169 if (level->parent_level)
2171 iter->stamp = GTK_TREE_MODEL_FILTER (model)->priv->stamp;
2172 iter->user_data = level->parent_level;
2173 iter->user_data2 = level->parent_elt;
2182 gtk_tree_model_filter_ref_node (GtkTreeModel *model,
2185 GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
2186 GtkTreeIter child_iter;
2190 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (model));
2191 g_return_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL);
2192 g_return_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->stamp == iter->stamp);
2194 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_iter, iter);
2196 gtk_tree_model_ref_node (filter->priv->child_model, &child_iter);
2198 level = iter->user_data;
2199 elt = iter->user_data2;
2203 if (level->ref_count == 1)
2205 FilterLevel *parent_level = level->parent_level;
2206 FilterElt *parent_elt = level->parent_elt;
2208 /* we were at zero -- time to decrease the zero_ref_count val */
2212 parent_elt->zero_ref_count--;
2216 parent_elt = parent_level->parent_elt;
2217 parent_level = parent_level->parent_level;
2220 while (parent_level);
2221 filter->priv->zero_ref_count--;
2226 gtk_tree_model_filter_unref_node (GtkTreeModel *model,
2229 gtk_tree_model_filter_real_unref_node (model, iter, TRUE);
2233 gtk_tree_model_filter_real_unref_node (GtkTreeModel *model,
2235 gboolean propagate_unref)
2237 GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
2241 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (model));
2242 g_return_if_fail (filter->priv->child_model != NULL);
2243 g_return_if_fail (filter->priv->stamp == iter->stamp);
2245 if (propagate_unref)
2247 GtkTreeIter child_iter;
2248 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_iter, iter);
2249 gtk_tree_model_unref_node (filter->priv->child_model, &child_iter);
2252 level = iter->user_data;
2253 elt = iter->user_data2;
2255 g_return_if_fail (elt->ref_count > 0);
2259 if (level->ref_count == 0)
2261 FilterLevel *parent_level = level->parent_level;
2262 FilterElt *parent_elt = level->parent_elt;
2264 /* we are at zero -- time to increase the zero_ref_count val */
2265 while (parent_level)
2267 parent_elt->zero_ref_count++;
2269 parent_elt = parent_level->parent_elt;
2270 parent_level = parent_level->parent_level;
2272 filter->priv->zero_ref_count++;
2276 /* TreeDragSource interface implementation */
2278 gtk_tree_model_filter_row_draggable (GtkTreeDragSource *drag_source,
2281 GtkTreeModelFilter *tree_model_filter = (GtkTreeModelFilter *)drag_source;
2282 GtkTreePath *child_path;
2285 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (drag_source), FALSE);
2286 g_return_val_if_fail (path != NULL, FALSE);
2288 child_path = gtk_tree_model_filter_convert_path_to_child_path (tree_model_filter, path);
2289 draggable = gtk_tree_drag_source_row_draggable (GTK_TREE_DRAG_SOURCE (tree_model_filter->priv->child_model), child_path);
2290 gtk_tree_path_free (child_path);
2296 gtk_tree_model_filter_drag_data_get (GtkTreeDragSource *drag_source,
2298 GtkSelectionData *selection_data)
2300 GtkTreeModelFilter *tree_model_filter = (GtkTreeModelFilter *)drag_source;
2301 GtkTreePath *child_path;
2304 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (drag_source), FALSE);
2305 g_return_val_if_fail (path != NULL, FALSE);
2307 child_path = gtk_tree_model_filter_convert_path_to_child_path (tree_model_filter, path);
2308 gotten = gtk_tree_drag_source_drag_data_get (GTK_TREE_DRAG_SOURCE (tree_model_filter->priv->child_model), child_path, selection_data);
2309 gtk_tree_path_free (child_path);
2315 gtk_tree_model_filter_drag_data_delete (GtkTreeDragSource *drag_source,
2318 GtkTreeModelFilter *tree_model_filter = (GtkTreeModelFilter *)drag_source;
2319 GtkTreePath *child_path;
2322 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (drag_source), FALSE);
2323 g_return_val_if_fail (path != NULL, FALSE);
2325 child_path = gtk_tree_model_filter_convert_path_to_child_path (tree_model_filter, path);
2326 deleted = gtk_tree_drag_source_drag_data_delete (GTK_TREE_DRAG_SOURCE (tree_model_filter->priv->child_model), child_path);
2327 gtk_tree_path_free (child_path);
2332 /* bits and pieces */
2334 gtk_tree_model_filter_set_model (GtkTreeModelFilter *filter,
2335 GtkTreeModel *child_model)
2337 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
2339 if (filter->priv->child_model)
2341 g_signal_handler_disconnect (filter->priv->child_model,
2342 filter->priv->changed_id);
2343 g_signal_handler_disconnect (filter->priv->child_model,
2344 filter->priv->inserted_id);
2345 g_signal_handler_disconnect (filter->priv->child_model,
2346 filter->priv->has_child_toggled_id);
2347 g_signal_handler_disconnect (filter->priv->child_model,
2348 filter->priv->deleted_id);
2349 g_signal_handler_disconnect (filter->priv->child_model,
2350 filter->priv->reordered_id);
2352 /* reset our state */
2353 if (filter->priv->root)
2354 gtk_tree_model_filter_free_level (filter, filter->priv->root);
2356 filter->priv->root = NULL;
2357 g_object_unref (filter->priv->child_model);
2358 filter->priv->visible_column = -1;
2359 /* FIXME: destroy more crack here? the funcs? */
2362 filter->priv->child_model = child_model;
2366 g_object_ref (filter->priv->child_model);
2367 filter->priv->changed_id =
2368 g_signal_connect (child_model, "row_changed",
2369 G_CALLBACK (gtk_tree_model_filter_row_changed),
2371 filter->priv->inserted_id =
2372 g_signal_connect (child_model, "row_inserted",
2373 G_CALLBACK (gtk_tree_model_filter_row_inserted),
2375 filter->priv->has_child_toggled_id =
2376 g_signal_connect (child_model, "row_has_child_toggled",
2377 G_CALLBACK (gtk_tree_model_filter_row_has_child_toggled),
2379 filter->priv->deleted_id =
2380 g_signal_connect (child_model, "row_deleted",
2381 G_CALLBACK (gtk_tree_model_filter_row_deleted),
2383 filter->priv->reordered_id =
2384 g_signal_connect (child_model, "rows_reordered",
2385 G_CALLBACK (gtk_tree_model_filter_rows_reordered),
2388 filter->priv->child_flags = gtk_tree_model_get_flags (child_model);
2389 filter->priv->stamp = g_random_int ();
2394 gtk_tree_model_filter_set_root (GtkTreeModelFilter *filter,
2397 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
2400 filter->priv->virtual_root = NULL;
2402 filter->priv->virtual_root = gtk_tree_path_copy (root);
2408 * gtk_tree_model_filter_new:
2409 * @child_model: A #GtkTreeModel.
2410 * @root: A #GtkTreePath or %NULL.
2412 * Creates a new #GtkTreeModel, with @child_model as the child_model
2413 * and @root as the virtual root.
2415 * Return value: A new #GtkTreeModel.
2420 gtk_tree_model_filter_new (GtkTreeModel *child_model,
2423 GtkTreeModel *retval;
2425 g_return_val_if_fail (GTK_IS_TREE_MODEL (child_model), NULL);
2427 retval = g_object_new (GTK_TYPE_TREE_MODEL_FILTER,
2428 "child-model", child_model,
2429 "virtual-root", root,
2436 * gtk_tree_model_filter_get_model:
2437 * @filter: A #GtkTreeModelFilter.
2439 * Returns a pointer to the child model of @filter.
2441 * Return value: A pointer to a #GtkTreeModel.
2446 gtk_tree_model_filter_get_model (GtkTreeModelFilter *filter)
2448 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (filter), NULL);
2450 return filter->priv->child_model;
2454 * gtk_tree_model_filter_set_visible_func:
2455 * @filter: A #GtkTreeModelFilter.
2456 * @func: A #GtkTreeModelFilterVisibleFunc, the visible function.
2457 * @data: User data to pass to the visible function, or %NULL.
2458 * @destroy: Destroy notifier of @data, or %NULL.
2460 * Sets the visible function used when filtering the @filter to be @func. The
2461 * function should return %TRUE if the given row should be visible and
2464 * If the condition calculated by the function changes over time (e.g. because
2465 * it depends on some global parameters), you must call
2466 * gtk_tree_model_filter_refilter() to keep the visibility information of
2467 * the model uptodate.
2472 gtk_tree_model_filter_set_visible_func (GtkTreeModelFilter *filter,
2473 GtkTreeModelFilterVisibleFunc func,
2475 GtkDestroyNotify destroy)
2477 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
2478 g_return_if_fail (func != NULL);
2479 g_return_if_fail (filter->priv->visible_method_set == FALSE);
2481 if (filter->priv->visible_func)
2483 GtkDestroyNotify d = filter->priv->visible_destroy;
2485 filter->priv->visible_destroy = NULL;
2486 d (filter->priv->visible_data);
2489 filter->priv->visible_func = func;
2490 filter->priv->visible_data = data;
2491 filter->priv->visible_destroy = destroy;
2493 filter->priv->visible_method_set = TRUE;
2497 * gtk_tree_model_filter_set_modify_func:
2498 * @filter: A #GtkTreeModelFilter.
2499 * @n_columns: The number of columns in the filter model.
2500 * @types: The #GType<!-- -->s of the columns.
2501 * @func: A #GtkTreeModelFilterModifyFunc
2502 * @data: User data to pass to the modify function, or %NULL.
2503 * @destroy: Destroy notifier of @data, or %NULL.
2505 * With the @n_columns and @types parameters, you give an array of column
2506 * types for this model (which will be exposed to the parent model/view).
2507 * The @func, @data and @destroy parameters are for specifying the modify
2508 * function. The modify function will get called for <emphasis>each</emphasis>
2509 * data access, the goal of the modify function is to return the data which
2510 * should be displayed at the location specified using the parameters of the
2516 gtk_tree_model_filter_set_modify_func (GtkTreeModelFilter *filter,
2519 GtkTreeModelFilterModifyFunc func,
2521 GtkDestroyNotify destroy)
2523 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
2524 g_return_if_fail (func != NULL);
2525 g_return_if_fail (filter->priv->modify_func_set == FALSE);
2527 if (filter->priv->modify_destroy)
2529 GtkDestroyNotify d = filter->priv->modify_destroy;
2531 filter->priv->modify_destroy = NULL;
2532 d (filter->priv->modify_data);
2535 filter->priv->modify_n_columns = n_columns;
2536 filter->priv->modify_types = g_new0 (GType, n_columns);
2537 memcpy (filter->priv->modify_types, types, sizeof (GType) * n_columns);
2538 filter->priv->modify_func = func;
2539 filter->priv->modify_data = data;
2540 filter->priv->modify_destroy = destroy;
2542 filter->priv->modify_func_set = TRUE;
2546 * gtk_tree_model_filter_set_visible_column:
2547 * @filter: A #GtkTreeModelFilter.
2548 * @column: A #gint which is the column containing the visible information.
2550 * Sets @column of the child_model to be the column where @filter should
2551 * look for visibility information. @columns should be a column of type
2552 * %G_TYPE_BOOLEAN, where %TRUE means that a row is visible, and %FALSE
2558 gtk_tree_model_filter_set_visible_column (GtkTreeModelFilter *filter,
2561 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
2562 g_return_if_fail (column >= 0);
2563 g_return_if_fail (filter->priv->visible_method_set == FALSE);
2565 filter->priv->visible_column = column;
2567 filter->priv->visible_method_set = TRUE;
2573 * gtk_tree_model_filter_convert_child_iter_to_iter:
2574 * @filter: A #GtkTreeModelFilter.
2575 * @filter_iter: An uninitialized #GtkTreeIter.
2576 * @child_iter: A valid #GtkTreeIter pointing to a row on the child model.
2578 * Sets @filter_iter to point to the row in @filter that corresponds to the
2579 * row pointed at by @child_iter.
2584 gtk_tree_model_filter_convert_child_iter_to_iter (GtkTreeModelFilter *filter,
2585 GtkTreeIter *filter_iter,
2586 GtkTreeIter *child_iter)
2588 GtkTreePath *child_path, *path;
2590 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
2591 g_return_if_fail (filter->priv->child_model != NULL);
2592 g_return_if_fail (filter_iter != NULL);
2593 g_return_if_fail (child_iter != NULL);
2595 filter_iter->stamp = 0;
2597 child_path = gtk_tree_model_get_path (filter->priv->child_model, child_iter);
2598 g_return_if_fail (child_path != NULL);
2600 path = gtk_tree_model_filter_convert_child_path_to_path (filter,
2602 gtk_tree_path_free (child_path);
2603 g_return_if_fail (path != NULL);
2605 gtk_tree_model_get_iter (GTK_TREE_MODEL (filter), filter_iter, path);
2606 gtk_tree_path_free (path);
2610 * gtk_tree_model_filter_convert_iter_to_child_iter:
2611 * @filter: A #GtkTreeModelFilter.
2612 * @child_iter: An uninitialized #GtkTreeIter.
2613 * @filter_iter: A valid #GtkTreeIter pointing to a row on @filter.
2615 * Sets @child_iter to point to the row pointed to by @filter_iter.
2620 gtk_tree_model_filter_convert_iter_to_child_iter (GtkTreeModelFilter *filter,
2621 GtkTreeIter *child_iter,
2622 GtkTreeIter *filter_iter)
2624 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
2625 g_return_if_fail (filter->priv->child_model != NULL);
2626 g_return_if_fail (child_iter != NULL);
2627 g_return_if_fail (filter_iter != NULL);
2628 g_return_if_fail (filter_iter->stamp == filter->priv->stamp);
2630 if (GTK_TREE_MODEL_FILTER_CACHE_CHILD_ITERS (filter))
2632 *child_iter = FILTER_ELT (filter_iter->user_data2)->iter;
2638 path = gtk_tree_model_filter_elt_get_path (filter_iter->user_data,
2639 filter_iter->user_data2,
2640 filter->priv->virtual_root);
2641 gtk_tree_model_get_iter (filter->priv->child_model, child_iter, path);
2642 gtk_tree_path_free (path);
2646 static GtkTreePath *
2647 gtk_real_tree_model_filter_convert_child_path_to_path (GtkTreeModelFilter *filter,
2648 GtkTreePath *child_path,
2649 gboolean build_levels,
2650 gboolean fetch_children)
2652 gint *child_indices;
2653 GtkTreePath *retval;
2654 GtkTreePath *real_path;
2659 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (filter), NULL);
2660 g_return_val_if_fail (filter->priv->child_model != NULL, NULL);
2661 g_return_val_if_fail (child_path != NULL, NULL);
2663 if (!filter->priv->virtual_root)
2664 real_path = gtk_tree_path_copy (child_path);
2666 real_path = gtk_tree_model_filter_remove_root (child_path,
2667 filter->priv->virtual_root);
2672 retval = gtk_tree_path_new ();
2673 child_indices = gtk_tree_path_get_indices (real_path);
2675 if (filter->priv->root == NULL && build_levels)
2676 gtk_tree_model_filter_build_level (filter, NULL, NULL);
2677 level = FILTER_LEVEL (filter->priv->root);
2679 for (i = 0; i < gtk_tree_path_get_depth (real_path); i++)
2682 gboolean found_child = FALSE;
2686 gtk_tree_path_free (real_path);
2687 gtk_tree_path_free (retval);
2691 tmp = bsearch_elt_with_offset (level->array, child_indices[i], &j);
2694 gtk_tree_path_append_index (retval, j);
2695 if (!tmp->children && build_levels)
2696 gtk_tree_model_filter_build_level (filter, level, tmp);
2697 level = tmp->children;
2701 if (!found_child && fetch_children)
2703 tmp = gtk_tree_model_filter_fetch_child (filter, level,
2707 /* didn't find the child, let's try to bring it back */
2708 if (!tmp || tmp->offset != child_indices[i])
2711 gtk_tree_path_free (real_path);
2712 gtk_tree_path_free (retval);
2716 gtk_tree_path_append_index (retval, j);
2717 if (!tmp->children && build_levels)
2718 gtk_tree_model_filter_build_level (filter, level, tmp);
2719 level = tmp->children;
2722 else if (!found_child && !fetch_children)
2725 gtk_tree_path_free (real_path);
2726 gtk_tree_path_free (retval);
2731 gtk_tree_path_free (real_path);
2736 * gtk_tree_model_filter_convert_child_path_to_path:
2737 * @filter: A #GtkTreeModelFilter.
2738 * @child_path: A #GtkTreePath to convert.
2740 * Converts @child_path to a path relative to @filter. That is, @child_path
2741 * points to a path in the child model. The rerturned path will point to the
2742 * same row in the filtered model. If @child_path isn't a valid path on the
2743 * child model, then %NULL is returned.
2745 * Return value: A newly allocated #GtkTreePath, or %NULL.
2750 gtk_tree_model_filter_convert_child_path_to_path (GtkTreeModelFilter *filter,
2751 GtkTreePath *child_path)
2753 /* this function does the sanity checks */
2754 return gtk_real_tree_model_filter_convert_child_path_to_path (filter,
2761 * gtk_tree_model_filter_convert_path_to_child_path:
2762 * @filter: A #GtkTreeModelFilter.
2763 * @filter_path: A #GtkTreePath to convert.
2765 * Converts @filter_path to a path on the child model of @filter. That is,
2766 * @filter_path points to a location in @filter. The returned path will
2767 * point to the same location in the model not being filtered. If @filter_path
2768 * does not point to a location in the child model, %NULL is returned.
2770 * Return value: A newly allocated #GtkTreePath, or %NULL.
2775 gtk_tree_model_filter_convert_path_to_child_path (GtkTreeModelFilter *filter,
2776 GtkTreePath *filter_path)
2778 gint *filter_indices;
2779 GtkTreePath *retval;
2783 g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (filter), NULL);
2784 g_return_val_if_fail (filter->priv->child_model != NULL, NULL);
2785 g_return_val_if_fail (filter_path != NULL, NULL);
2788 retval = gtk_tree_path_new ();
2789 filter_indices = gtk_tree_path_get_indices (filter_path);
2790 if (!filter->priv->root)
2791 gtk_tree_model_filter_build_level (filter, NULL, NULL);
2792 level = FILTER_LEVEL (filter->priv->root);
2794 for (i = 0; i < gtk_tree_path_get_depth (filter_path); i++)
2796 gint count = filter_indices[i];
2798 if (!level || level->array->len <= filter_indices[i])
2800 gtk_tree_path_free (retval);
2804 if (g_array_index (level->array, FilterElt, count).children == NULL)
2805 gtk_tree_model_filter_build_level (filter, level, &g_array_index (level->array, FilterElt, count));
2807 if (!level || level->array->len <= filter_indices[i])
2809 gtk_tree_path_free (retval);
2813 gtk_tree_path_append_index (retval, g_array_index (level->array, FilterElt, count).offset);
2814 level = g_array_index (level->array, FilterElt, count).children;
2819 if (filter->priv->virtual_root)
2821 GtkTreePath *real_retval;
2823 real_retval = gtk_tree_model_filter_add_root (retval,
2824 filter->priv->virtual_root);
2825 gtk_tree_path_free (retval);
2834 gtk_tree_model_filter_refilter_helper (GtkTreeModel *model,
2839 /* evil, don't try this at home, but certainly speeds things up */
2840 gtk_tree_model_filter_row_changed (model, path, iter, data);
2846 * gtk_tree_model_filter_refilter:
2847 * @filter: A #GtkTreeModelFilter.
2849 * Emits ::row_changed for each row in the child model, which causes
2850 * the filter to re-evaluate whether a row is visible or not.
2855 gtk_tree_model_filter_refilter (GtkTreeModelFilter *filter)
2857 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
2860 gtk_tree_model_foreach (filter->priv->child_model,
2861 gtk_tree_model_filter_refilter_helper,
2866 * gtk_tree_model_filter_clear_cache:
2867 * @filter: A #GtkTreeModelFilter.
2869 * This function should almost never be called. It clears the @filter
2870 * of any cached iterators that haven't been reffed with
2871 * gtk_tree_model_ref_node(). This might be useful if the child model
2872 * being filtered is static (and doesn't change often) and there has been
2873 * a lot of unreffed access to nodes. As a side effect of this function,
2874 * all unreffed itters will be invalid.
2879 gtk_tree_model_filter_clear_cache (GtkTreeModelFilter *filter)
2881 g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
2883 if (filter->priv->zero_ref_count)
2884 gtk_tree_model_filter_clear_cache_helper (filter,
2885 FILTER_LEVEL (filter->priv->root));
2888 #define __GTK_TREE_MODEL_FILTER_C__
2889 #include "gtkaliasdef.c"