]> Pileus Git - ~andy/gtk/blob - gtk/gtktreemodelfilter.c
7d08fbf6e5e56a0b2371a3c49d05bc9a9f18ea0c
[~andy/gtk] / gtk / gtktreemodelfilter.c
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>
4  *
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.
9  *
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.
14  *
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.
19  */
20
21 #include "gtktreemodelfilter.h"
22 #include "gtkintl.h"
23 #include <string.h>
24
25 /* ITER FORMAT:
26  *
27  * iter->stamp = filter->priv->stamp
28  * iter->user_data = FilterLevel
29  * iter->user_data2 = FilterElt
30  */
31
32 /* all paths, iters, etc prefixed with c_ are paths, iters, etc relative to the
33  * child model.
34  */
35
36 typedef struct _FilterElt FilterElt;
37 typedef struct _FilterLevel FilterLevel;
38
39 struct _FilterElt
40 {
41   GtkTreeIter iter;
42   FilterLevel *children;
43   gint offset;
44   gint ref_count;
45   gint zero_ref_count;
46   gboolean visible;
47 };
48
49 struct _FilterLevel
50 {
51   GArray *array;
52   gint ref_count;
53
54   FilterElt *parent_elt;
55   FilterLevel *parent_level;
56 };
57
58 #define GTK_TREE_MODEL_FILTER_GET_PRIVATE(obj)  (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_TREE_MODEL_FILTER, GtkTreeModelFilterPrivate))
59
60 struct _GtkTreeModelFilterPrivate
61 {
62   gpointer root;
63   gint stamp;
64   guint child_flags;
65   GtkTreeModel *child_model;
66   gint zero_ref_count;
67
68   guint root_level_visible;
69
70   GtkTreePath *virtual_root;
71
72   GtkTreeModelFilterVisibleFunc visible_func;
73   gpointer visible_data;
74   GtkDestroyNotify visible_destroy;
75
76   gint modify_n_columns;
77   GType *modify_types;
78   GtkTreeModelFilterModifyFunc modify_func;
79   gpointer modify_data;
80   gpointer modify_destroy;
81
82   gint visible_column;
83
84   gboolean visible_method_set;
85   gboolean modify_func_set;
86
87   /* signal ids */
88   guint changed_id;
89   guint inserted_id;
90   guint has_child_toggled_id;
91   guint deleted_id;
92   guint reordered_id;
93 };
94
95 /* properties */
96 enum
97 {
98   PROP_0,
99   PROP_CHILD_MODEL,
100   PROP_VIRTUAL_ROOT
101 };
102
103 #define GTK_TREE_MODEL_FILTER_CACHE_CHILD_ITERS(filter) \
104         (((GtkTreeModelFilter *)filter)->priv->child_flags & GTK_TREE_MODEL_ITERS_PERSIST)
105
106 #define FILTER_ELT(filter_elt) ((FilterElt *)filter_elt)
107 #define FILTER_LEVEL(filter_level) ((FilterLevel *)filter_level)
108
109 /* general code (object/interface init, properties, etc) */
110 static void         gtk_tree_model_filter_init                            (GtkTreeModelFilter      *filter);
111 static void         gtk_tree_model_filter_class_init                      (GtkTreeModelFilterClass *filter_class);
112 static void         gtk_tree_model_filter_tree_model_init                 (GtkTreeModelIface       *iface);
113 static void         gtk_tree_model_filter_finalize                        (GObject                 *object);
114 static void         gtk_tree_model_filter_set_property                    (GObject                 *object,
115                                                                            guint                    prop_id,
116                                                                            const GValue            *value,
117                                                                            GParamSpec              *pspec);
118 static void         gtk_tree_model_filter_get_property                    (GObject                 *object,
119                                                                            guint                    prop_id,
120                                                                            GValue                 *value,
121                                                                            GParamSpec             *pspec);
122
123 /* signal handlers */
124 static void         gtk_tree_model_filter_row_changed                     (GtkTreeModel           *c_model,
125                                                                            GtkTreePath            *c_path,
126                                                                            GtkTreeIter            *c_iter,
127                                                                            gpointer                data);
128 static void         gtk_tree_model_filter_row_inserted                    (GtkTreeModel           *c_model,
129                                                                            GtkTreePath            *c_path,
130                                                                            GtkTreeIter            *c_iter,
131                                                                            gpointer                data);
132 static void         gtk_tree_model_filter_row_has_child_toggled           (GtkTreeModel           *c_model,
133                                                                            GtkTreePath            *c_path,
134                                                                            GtkTreeIter            *c_iter,
135                                                                            gpointer                data);
136 static void         gtk_tree_model_filter_row_deleted                     (GtkTreeModel           *c_model,
137                                                                            GtkTreePath            *c_path,
138                                                                            gpointer                data);
139 static void         gtk_tree_model_filter_rows_reordered                  (GtkTreeModel           *c_model,
140                                                                            GtkTreePath            *c_path,
141                                                                            GtkTreeIter            *c_iter,
142                                                                            gint                   *new_order,
143                                                                            gpointer                data);
144
145 /* GtkTreeModel interface */
146 static guint        gtk_tree_model_filter_get_flags                       (GtkTreeModel           *model);
147 static gint         gtk_tree_model_filter_get_n_columns                   (GtkTreeModel           *model);
148 static GType        gtk_tree_model_filter_get_column_type                 (GtkTreeModel           *model,
149                                                                            gint                    index);
150 static gboolean     gtk_tree_model_filter_get_iter                        (GtkTreeModel           *model,
151                                                                            GtkTreeIter            *iter,
152                                                                            GtkTreePath            *path);
153 static GtkTreePath *gtk_tree_model_filter_get_path                        (GtkTreeModel           *model,
154                                                                            GtkTreeIter            *iter);
155 static void         gtk_tree_model_filter_get_value                       (GtkTreeModel           *model,
156                                                                            GtkTreeIter            *iter,
157                                                                            gint                    column,
158                                                                            GValue                 *value);
159 static gboolean     gtk_tree_model_filter_iter_next                       (GtkTreeModel           *model,
160                                                                            GtkTreeIter            *iter);
161 static gboolean     gtk_tree_model_filter_iter_children                   (GtkTreeModel           *model,
162                                                                            GtkTreeIter            *iter,
163                                                                            GtkTreeIter            *parent);
164 static gboolean     gtk_tree_model_filter_iter_has_child                  (GtkTreeModel           *model,
165                                                                            GtkTreeIter            *iter);
166 static gint         gtk_tree_model_filter_iter_n_children                 (GtkTreeModel           *model,
167                                                                            GtkTreeIter            *iter);
168 static gboolean     gtk_tree_model_filter_iter_nth_child                  (GtkTreeModel           *model,
169                                                                            GtkTreeIter            *iter,
170                                                                            GtkTreeIter            *parent,
171                                                                            gint                    n);
172 static gboolean     gtk_tree_model_filter_iter_parent                     (GtkTreeModel           *model,
173                                                                            GtkTreeIter            *iter,
174                                                                            GtkTreeIter            *child);
175 static void         gtk_tree_model_filter_ref_node                        (GtkTreeModel           *model,
176                                                                            GtkTreeIter            *iter);
177 static void         gtk_tree_model_filter_unref_node                      (GtkTreeModel           *model,
178                                                                            GtkTreeIter            *iter);
179
180
181 /* private functions */
182 static void        gtk_tree_model_filter_build_level                      (GtkTreeModelFilter     *filter,
183                                                                            FilterLevel            *parent_level,
184                                                                            FilterElt              *parent_elt);
185 static void        gtk_tree_model_filter_free_level                       (GtkTreeModelFilter     *filter,
186                                                                            FilterLevel            *filter_level);
187
188 static GtkTreePath *gtk_tree_model_filter_elt_get_path                    (FilterLevel            *level,
189                                                                            FilterElt              *elt,
190                                                                            GtkTreePath            *root);
191
192 static GtkTreePath *gtk_tree_model_filter_add_root                        (GtkTreePath            *src,
193                                                                            GtkTreePath            *root);
194 static GtkTreePath *gtk_tree_model_filter_remove_root                     (GtkTreePath            *src,
195                                                                            GtkTreePath            *root);
196
197 static void         gtk_tree_model_filter_increment_stamp                 (GtkTreeModelFilter     *filter);
198
199 static gboolean     gtk_tree_model_filter_visible                         (GtkTreeModelFilter     *filter,
200                                                                            GtkTreeIter            *child_iter);
201 static void         gtk_tree_model_filter_clear_cache_helper              (GtkTreeModelFilter     *filter,
202                                                                            FilterLevel            *level);
203
204 static void         gtk_tree_model_filter_real_unref_node                 (GtkTreeModel           *model,
205                                                                            GtkTreeIter            *iter,
206                                                                            gboolean                propagate_unref);
207
208 static void         gtk_tree_model_filter_set_model                       (GtkTreeModelFilter     *filter,
209                                                                            GtkTreeModel           *child_model);
210 static void         gtk_tree_model_filter_set_root                        (GtkTreeModelFilter     *filter,
211                                                                            GtkTreePath            *root);
212
213 static GtkTreePath *gtk_real_tree_model_filter_convert_child_path_to_path (GtkTreeModelFilter     *filter,
214                                                                            GtkTreePath            *child_path,
215                                                                            gboolean                build_levels,
216                                                                            gboolean                fetch_childs);
217
218 static FilterElt   *gtk_tree_model_filter_fetch_child                     (GtkTreeModelFilter     *filter,
219                                                                            FilterLevel            *level,
220                                                                            gint                    offset,
221                                                                            gint                   *index);
222 static void         gtk_tree_model_filter_remove_node                     (GtkTreeModelFilter     *filter,
223                                                                            GtkTreeIter            *iter,
224                                                                            gboolean                emit_signal);
225 static void         gtk_tree_model_filter_update_childs                   (GtkTreeModelFilter     *filter,
226                                                                            FilterLevel            *level,
227                                                                            FilterElt              *elt);
228 static FilterElt   *bsearch_elt_with_offset                               (GArray                 *array,
229                                                                            gint                   offset,
230                                                                            gint                  *index);
231
232
233 static GObjectClass *parent_class = NULL;
234
235 GType
236 gtk_tree_model_filter_get_type (void)
237 {
238   static GType tree_model_filter_type = 0;
239
240   if (!tree_model_filter_type)
241     {
242       static const GTypeInfo tree_model_filter_info =
243         {
244           sizeof (GtkTreeModelFilterClass),
245           NULL, /* base_init */
246           NULL, /* base_finalize */
247           (GClassInitFunc) gtk_tree_model_filter_class_init,
248           NULL, /* class_finalize */
249           NULL, /* class_data */
250           sizeof (GtkTreeModelFilter),
251           0, /* n_preallocs */
252           (GInstanceInitFunc) gtk_tree_model_filter_init
253         };
254
255       static const GInterfaceInfo tree_model_info =
256         {
257           (GInterfaceInitFunc) gtk_tree_model_filter_tree_model_init,
258           NULL,
259           NULL
260         };
261
262       tree_model_filter_type = g_type_register_static (G_TYPE_OBJECT,
263                                                        "GtkTreeModelFilter",
264                                                        &tree_model_filter_info, 0);
265
266       g_type_add_interface_static (tree_model_filter_type,
267                                    GTK_TYPE_TREE_MODEL,
268                                    &tree_model_info);
269     }
270
271   return tree_model_filter_type;
272 }
273
274 static void
275 gtk_tree_model_filter_init (GtkTreeModelFilter *filter)
276 {
277   filter->priv = GTK_TREE_MODEL_FILTER_GET_PRIVATE (filter);
278
279   filter->priv->visible_column = -1;
280   filter->priv->zero_ref_count = 0;
281   filter->priv->visible_method_set = FALSE;
282   filter->priv->modify_func_set = FALSE;
283 }
284
285 static void
286 gtk_tree_model_filter_class_init (GtkTreeModelFilterClass *filter_class)
287 {
288   GObjectClass *object_class;
289
290   object_class = (GObjectClass *) filter_class;
291   parent_class = g_type_class_peek_parent (filter_class);
292
293   object_class->set_property = gtk_tree_model_filter_set_property;
294   object_class->get_property = gtk_tree_model_filter_get_property;
295
296   object_class->finalize = gtk_tree_model_filter_finalize;
297
298   /* Properties -- FIXME: disabled translations for now, until I can come up with a
299    * better description
300    */
301   g_object_class_install_property (object_class,
302                                    PROP_CHILD_MODEL,
303                                    g_param_spec_object ("child_model",
304                                                         ("The child model"),
305                                                         ("The model for the filtermodel to filter"),
306                                                         GTK_TYPE_TREE_MODEL,
307                                                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
308
309   g_object_class_install_property (object_class,
310                                    PROP_VIRTUAL_ROOT,
311                                    g_param_spec_boxed ("virtual_root",
312                                                        ("The virtual root"),
313                                                        ("The virtual root (relative to the child model) for this filtermodel"),
314                                                        GTK_TYPE_TREE_PATH,
315                                                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
316
317   g_type_class_add_private (object_class, sizeof (GtkTreeModelFilterPrivate));
318 }
319
320 static void
321 gtk_tree_model_filter_tree_model_init (GtkTreeModelIface *iface)
322 {
323   iface->get_flags = gtk_tree_model_filter_get_flags;
324   iface->get_n_columns = gtk_tree_model_filter_get_n_columns;
325   iface->get_column_type = gtk_tree_model_filter_get_column_type;
326   iface->get_iter = gtk_tree_model_filter_get_iter;
327   iface->get_path = gtk_tree_model_filter_get_path;
328   iface->get_value = gtk_tree_model_filter_get_value;
329   iface->iter_next = gtk_tree_model_filter_iter_next;
330   iface->iter_children = gtk_tree_model_filter_iter_children;
331   iface->iter_has_child = gtk_tree_model_filter_iter_has_child;
332   iface->iter_n_children = gtk_tree_model_filter_iter_n_children;
333   iface->iter_nth_child = gtk_tree_model_filter_iter_nth_child;
334   iface->iter_parent = gtk_tree_model_filter_iter_parent;
335   iface->ref_node = gtk_tree_model_filter_ref_node;
336   iface->unref_node = gtk_tree_model_filter_unref_node;
337 }
338
339
340 static void
341 gtk_tree_model_filter_finalize (GObject *object)
342 {
343   GtkTreeModelFilter *filter = (GtkTreeModelFilter *) object;
344
345   gtk_tree_model_filter_set_model (filter, NULL);
346
347   if (filter->priv->virtual_root)
348     gtk_tree_path_free (filter->priv->virtual_root);
349
350   if (filter->priv->root)
351     gtk_tree_model_filter_free_level (filter, filter->priv->root);
352
353   if (filter->priv->modify_types)
354     g_free (filter->priv->modify_types);
355
356   /* must chain up */
357   parent_class->finalize (object);
358 }
359
360 static void
361 gtk_tree_model_filter_set_property (GObject      *object,
362                                     guint         prop_id,
363                                     const GValue *value,
364                                     GParamSpec   *pspec)
365 {
366   GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (object);
367
368   switch (prop_id)
369     {
370       case PROP_CHILD_MODEL:
371         gtk_tree_model_filter_set_model (filter, g_value_get_object (value));
372         break;
373       case PROP_VIRTUAL_ROOT:
374         gtk_tree_model_filter_set_root (filter, g_value_get_boxed (value));
375         break;
376       default:
377         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
378         break;
379     }
380 }
381
382 static void
383 gtk_tree_model_filter_get_property (GObject    *object,
384                                     guint       prop_id,
385                                     GValue     *value,
386                                     GParamSpec *pspec)
387 {
388   GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (object);
389
390   switch (prop_id)
391     {
392       case PROP_CHILD_MODEL:
393         g_value_set_object (value, filter->priv->child_model);
394         break;
395       case PROP_VIRTUAL_ROOT:
396         g_value_set_boxed (value, filter->priv->virtual_root);
397         break;
398       default:
399         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
400         break;
401     }
402 }
403
404 /* helpers */
405
406 static void
407 gtk_tree_model_filter_build_level (GtkTreeModelFilter *filter,
408                                    FilterLevel        *parent_level,
409                                    FilterElt          *parent_elt)
410 {
411   GtkTreeIter iter;
412   GtkTreeIter root;
413   FilterLevel *new_level;
414   gint length = 0;
415   gint i;
416
417   g_assert (filter->priv->child_model != NULL);
418
419   if (!parent_level)
420     {
421       if (filter->priv->virtual_root)
422         {
423           if (gtk_tree_model_get_iter (filter->priv->child_model, &root, filter->priv->virtual_root) == FALSE)
424             return;
425           length = gtk_tree_model_iter_n_children (filter->priv->child_model, &root);
426
427           if (gtk_tree_model_iter_children (filter->priv->child_model, &iter, &root) == FALSE)
428             return;
429         }
430       else
431         {
432           if (!gtk_tree_model_get_iter_first (filter->priv->child_model, &iter))
433             return;
434           length = gtk_tree_model_iter_n_children (filter->priv->child_model, NULL);
435         }
436     }
437   else
438     {
439       GtkTreeIter parent_iter;
440       GtkTreeIter child_parent_iter;
441
442       parent_iter.stamp = filter->priv->stamp;
443       parent_iter.user_data = parent_level;
444       parent_iter.user_data2 = parent_elt;
445
446       gtk_tree_model_filter_convert_iter_to_child_iter (filter,
447                                                         &child_parent_iter,
448                                                         &parent_iter);
449       if (gtk_tree_model_iter_children (filter->priv->child_model, &iter, &child_parent_iter) == FALSE)
450         return;
451
452       /* stamp may have changed */
453       gtk_tree_model_filter_convert_iter_to_child_iter (filter,
454                                                         &child_parent_iter,
455                                                         &parent_iter);
456       length = gtk_tree_model_iter_n_children (filter->priv->child_model, &child_parent_iter);
457     }
458
459   g_return_if_fail (length > 0);
460
461   new_level = g_new (FilterLevel, 1);
462   new_level->array = g_array_sized_new (FALSE, FALSE,
463                                         sizeof (FilterElt),
464                                         length);
465   new_level->ref_count = 0;
466   new_level->parent_elt = parent_elt;
467   new_level->parent_level = parent_level;
468
469   if (parent_elt)
470     parent_elt->children = new_level;
471   else
472     filter->priv->root = new_level;
473
474   /* increase the count of zero ref_counts */
475   while (parent_level)
476     {
477       parent_elt->zero_ref_count++;
478
479       parent_elt = parent_level->parent_elt;
480       parent_level = parent_level->parent_level;
481     }
482   filter->priv->zero_ref_count++;
483
484   i = 0;
485
486   if (!new_level->parent_level)
487     filter->priv->root_level_visible = 0;
488
489   do
490     {
491       if (gtk_tree_model_filter_visible (filter, &iter))
492         {
493           FilterElt filter_elt;
494
495           filter_elt.offset = i;
496           filter_elt.zero_ref_count = 0;
497           filter_elt.ref_count = 0;
498           filter_elt.children = NULL;
499           filter_elt.visible = TRUE;
500
501           if (GTK_TREE_MODEL_FILTER_CACHE_CHILD_ITERS (filter))
502             filter_elt.iter = iter;
503
504           g_array_append_val (new_level->array, filter_elt);
505
506           if (!new_level->parent_level)
507             filter->priv->root_level_visible++;
508         }
509       i++;
510     }
511   while (gtk_tree_model_iter_next (filter->priv->child_model, &iter));
512 }
513
514 static void
515 gtk_tree_model_filter_free_level (GtkTreeModelFilter *filter,
516                                   FilterLevel        *filter_level)
517 {
518   gint i;
519
520   g_assert (filter_level);
521
522   if (filter_level->ref_count == 0)
523     {
524       FilterLevel *parent_level = filter_level->parent_level;
525       FilterElt *parent_elt = filter_level->parent_elt;
526
527       do
528         {
529           if (parent_elt)
530             parent_elt->zero_ref_count--;
531
532           if (parent_level)
533             {
534               parent_elt = parent_level->parent_elt;
535               parent_level = parent_level->parent_level;
536             }
537         }
538       while (parent_level);
539       filter->priv->zero_ref_count--;
540     }
541
542   for (i = 0; i < filter_level->array->len; i++)
543     {
544       if (g_array_index (filter_level->array, FilterElt, i).children)
545         gtk_tree_model_filter_free_level (filter,
546                                           FILTER_LEVEL (g_array_index (filter_level->array, FilterElt, i).children));
547     }
548
549   if (!filter_level->parent_level)
550     filter->priv->root_level_visible = 0;
551
552   if (filter_level->parent_elt)
553     filter_level->parent_elt->children = NULL;
554   else
555     filter->priv->root = NULL;
556
557   g_array_free (filter_level->array, TRUE);
558   filter_level->array = NULL;
559
560   g_free (filter_level);
561   filter_level = NULL;
562 }
563
564 static GtkTreePath *
565 gtk_tree_model_filter_elt_get_path (FilterLevel *level,
566                                     FilterElt   *elt,
567                                     GtkTreePath *root)
568 {
569   FilterLevel *walker = level;
570   FilterElt *walker2 = elt;
571   GtkTreePath *path;
572   GtkTreePath *real_path;
573
574   g_return_val_if_fail (level != NULL, NULL);
575   g_return_val_if_fail (elt != NULL, NULL);
576
577   path = gtk_tree_path_new ();
578
579   while (walker)
580     {
581       gtk_tree_path_prepend_index (path, walker2->offset);
582
583       walker2 = walker->parent_elt;
584       walker = walker->parent_level;
585     }
586
587   if (root)
588     {
589       real_path = gtk_tree_model_filter_add_root (path, root);
590       gtk_tree_path_free (path);
591       return real_path;
592     }
593
594   return path;
595 }
596
597 static GtkTreePath *
598 gtk_tree_model_filter_add_root (GtkTreePath *src,
599                                 GtkTreePath *root)
600 {
601   GtkTreePath *retval;
602   gint i;
603
604   retval = gtk_tree_path_copy (root);
605
606   for (i = 0; i < gtk_tree_path_get_depth (src); i++)
607     gtk_tree_path_append_index (retval, gtk_tree_path_get_indices (src)[i]);
608
609   return retval;
610 }
611
612 static GtkTreePath *
613 gtk_tree_model_filter_remove_root (GtkTreePath *src,
614                                    GtkTreePath *root)
615 {
616   GtkTreePath *retval;
617   gint i;
618   gint depth;
619   gint *indices;
620
621   if (gtk_tree_path_get_depth (src) <= gtk_tree_path_get_depth (root))
622     return NULL;
623
624   depth = gtk_tree_path_get_depth (src);
625   indices = gtk_tree_path_get_indices (src);
626
627   for (i = 0; i < gtk_tree_path_get_depth (root); i++)
628     if (indices[i] != gtk_tree_path_get_indices (root)[i])
629       return NULL;
630
631   retval = gtk_tree_path_new ();
632
633   for (; i < depth; i++)
634     gtk_tree_path_append_index (retval, indices[i]);
635
636   return retval;
637 }
638
639 static void
640 gtk_tree_model_filter_increment_stamp (GtkTreeModelFilter *filter)
641 {
642   do
643     {
644       filter->priv->stamp++;
645     }
646   while (filter->priv->stamp == 0);
647
648   gtk_tree_model_filter_clear_cache (filter);
649 }
650
651 static gboolean
652 gtk_tree_model_filter_visible (GtkTreeModelFilter *filter,
653                                GtkTreeIter        *child_iter)
654 {
655   if (filter->priv->visible_func)
656     {
657       return (filter->priv->visible_func (filter->priv->child_model,
658                                     child_iter,
659                                     filter->priv->visible_data));
660     }
661   else if (filter->priv->visible_column >= 0)
662    {
663      GValue val = {0, };
664
665      gtk_tree_model_get_value (filter->priv->child_model, child_iter,
666                                filter->priv->visible_column, &val);
667
668      if (g_value_get_boolean (&val))
669        {
670          g_value_unset (&val);
671          return TRUE;
672        }
673
674      g_value_unset (&val);
675      return FALSE;
676    }
677
678   /* no filter thing set, so always visible */
679   return TRUE;
680 }
681
682 static void
683 gtk_tree_model_filter_clear_cache_helper (GtkTreeModelFilter *filter,
684                                           FilterLevel        *level)
685 {
686   gint i;
687
688   g_assert (level);
689
690   for (i = 0; i < level->array->len; i++)
691     {
692       if (g_array_index (level->array, FilterElt, i).zero_ref_count > 0)
693         gtk_tree_model_filter_clear_cache_helper (filter, g_array_index (level->array, FilterElt, i).children);
694      }
695
696   if (level->ref_count == 0 && level != filter->priv->root)
697     {
698       gtk_tree_model_filter_free_level (filter, level);
699       return;
700     }
701 }
702
703 static FilterElt *
704 gtk_tree_model_filter_fetch_child (GtkTreeModelFilter *filter,
705                                    FilterLevel        *level,
706                                    gint                offset,
707                                    gint               *index)
708 {
709   gint i = 0;
710   gint start, middle, end;
711   gint len;
712   GtkTreePath *c_path = NULL;
713   GtkTreeIter c_iter;
714   GtkTreePath *c_parent_path = NULL;
715   GtkTreeIter c_parent_iter;
716   FilterElt elt;
717
718   /* check if child exists and is visible */
719   if (level->parent_elt)
720     {
721       c_parent_path =
722         gtk_tree_model_filter_elt_get_path (level->parent_level,
723                                             level->parent_elt,
724                                             filter->priv->virtual_root);
725       if (!c_parent_path)
726         return NULL;
727     }
728   else
729     {
730       if (filter->priv->virtual_root)
731         c_parent_path = gtk_tree_path_copy (filter->priv->virtual_root);
732       else
733         c_parent_path = NULL;
734     }
735
736   if (c_parent_path)
737     {
738       gtk_tree_model_get_iter (filter->priv->child_model,
739                                &c_parent_iter,
740                                c_parent_path);
741       len = gtk_tree_model_iter_n_children (filter->priv->child_model,
742                                             &c_parent_iter);
743
744       c_path = gtk_tree_path_copy (c_parent_path);
745       gtk_tree_path_free (c_parent_path);
746     }
747   else
748     {
749       len = gtk_tree_model_iter_n_children (filter->priv->child_model, NULL);
750       c_path = gtk_tree_path_new ();
751     }
752
753   gtk_tree_path_append_index (c_path, offset);
754   gtk_tree_model_get_iter (filter->priv->child_model, &c_iter, c_path);
755   gtk_tree_path_free (c_path);
756
757   if (offset >= len || !gtk_tree_model_filter_visible (filter, &c_iter))
758     return NULL;
759
760   /* add child */
761   elt.offset = offset;
762   elt.zero_ref_count = 0;
763   elt.ref_count = 0;
764   elt.children = NULL;
765   /* visibility should be FALSE as we don't emit row_inserted */
766   elt.visible = FALSE;
767
768   if (GTK_TREE_MODEL_FILTER_CACHE_CHILD_ITERS (filter))
769     elt.iter = c_iter;
770
771   /* find index (binary search on offset) */
772   start = 0;
773   end = level->array->len;
774
775   if (start != end)
776     {
777       while (start != end)
778         {
779           middle = (start + end) / 2;
780
781           if (g_array_index (level->array, FilterElt, middle).offset <= offset)
782             start = middle + 1;
783           else
784             end = middle;
785         }
786
787       if (g_array_index (level->array, FilterElt, middle).offset <= offset)
788         i = middle + 1;
789       else
790         i = middle;
791     }
792   else
793     i = 0;
794
795   g_array_insert_val (level->array, i, elt);
796   *index = i;
797
798   for (i = MAX (--i, 0); i < level->array->len; i++)
799     {
800       FilterElt *e = &(g_array_index (level->array, FilterElt, i));
801       if (e->children)
802         e->children->parent_elt = e;
803     }
804
805   return &g_array_index (level->array, FilterElt, *index);
806 }
807
808 static void
809 gtk_tree_model_filter_remove_node (GtkTreeModelFilter *filter,
810                                    GtkTreeIter        *iter,
811                                    gboolean            emit_signal)
812 {
813   FilterElt *elt, *parent;
814   FilterLevel *level, *parent_level;
815   gint offset, i, length, level_refcount;
816
817   /* FIXME: this function is very ugly. I need to rethink and
818    * rewrite it someday.
819    */
820
821   level = FILTER_LEVEL (iter->user_data);
822   elt = FILTER_ELT (iter->user_data2);
823
824   parent = level->parent_elt;
825   parent_level = level->parent_level;
826   length = level->array->len;
827   offset = elt->offset;
828
829   /* ref counting */
830   while (elt->ref_count > 0)
831     gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter),
832                                            iter, FALSE);
833
834   level_refcount = level->ref_count;
835
836   /* do the ref counting first! this touches the stamp */
837   if (emit_signal)
838     {
839       GtkTreePath *path;
840
841       path = gtk_tree_model_get_path (GTK_TREE_MODEL (filter), iter);
842       gtk_tree_model_filter_increment_stamp (filter);
843       gtk_tree_model_row_deleted (GTK_TREE_MODEL (filter), path);
844       gtk_tree_path_free (path);
845     }
846
847   if ((length == 1 || level_refcount == 0) &&
848       emit_signal && iter->user_data != filter->priv->root)
849     {
850       /* above code destroyed the level */
851       goto emit_has_child_toggled;
852     }
853
854   if (length == 1)
855     {
856       /* kill the level */
857       gtk_tree_model_filter_free_level (filter, level);
858
859       if (!filter->priv->root)
860         /* we killed the root */
861         return;
862     }
863   else
864     {
865       FilterElt *tmp;
866
867       /* remove the node */
868       tmp = bsearch_elt_with_offset (level->array, elt->offset, &i);
869
870       if (tmp)
871         {
872           g_array_remove_index (level->array, i);
873
874           for (i = MAX (--i, 0); i < level->array->len; i++)
875             {
876               /* NOTE: here we do *not* decrease offsets, because the node was
877                * not removed from the child model
878                */
879               elt = &g_array_index (level->array, FilterElt, i);
880               if (elt->children)
881                 elt->children->parent_elt = elt;
882             }
883         }
884     }
885
886 emit_has_child_toggled:
887   /* children are being handled first, so we can check it this way
888    *
889    * yes this if-statement is ugly
890    */
891   if ((parent && parent->children && parent->children->array->len <= 1) ||
892       (length == 1 && emit_signal && iter->user_data != filter->priv->root))
893     {
894       /* latest child has been removed, level has been destroyed */
895       GtkTreeIter piter;
896       GtkTreePath *ppath;
897
898       piter.stamp = filter->priv->stamp;
899       piter.user_data = parent_level;
900       piter.user_data2 = parent;
901
902       ppath = gtk_tree_model_get_path (GTK_TREE_MODEL (filter), &piter);
903
904       gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (filter),
905                                             ppath, &piter);
906       gtk_tree_path_free (ppath);
907     }
908 }
909
910 static void
911 gtk_tree_model_filter_update_childs (GtkTreeModelFilter *filter,
912                                      FilterLevel        *level,
913                                      FilterElt          *elt)
914 {
915   GtkTreeIter c_iter;
916   GtkTreeIter iter;
917
918   if (!elt->visible)
919     return;
920
921   iter.stamp = filter->priv->stamp;
922   iter.user_data = level;
923   iter.user_data2 = elt;
924
925   gtk_tree_model_filter_convert_iter_to_child_iter (filter, &c_iter, &iter);
926
927   if (gtk_tree_model_iter_has_child (filter->priv->child_model, &c_iter))
928     {
929       GtkTreePath *path = gtk_tree_model_get_path (GTK_TREE_MODEL (filter),
930                                                    &iter);
931       gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (filter),
932                                             path,
933                                             &iter);
934       if (path)
935         gtk_tree_path_free (path);
936     }
937 }
938
939 static FilterElt *
940 bsearch_elt_with_offset (GArray *array,
941                          gint    offset,
942                          gint   *index)
943 {
944   gint start, middle, end;
945   FilterElt *elt;
946
947   start = 0;
948   end = array->len;
949
950   if (array->len < 1)
951     return NULL;
952
953   if (start == end)
954     {
955       elt = &g_array_index (array, FilterElt, 0);
956
957       if (elt->offset == offset)
958         {
959           *index = 0;
960           return elt;
961         }
962       else
963         return NULL;
964     }
965
966   while (start != end)
967     {
968       middle = (start + end) / 2;
969
970       elt = &g_array_index (array, FilterElt, middle);
971
972       if (elt->offset < offset)
973         start = middle + 1;
974       else if (elt->offset > offset)
975         end = middle;
976       else
977         break;
978     }
979
980   if (elt->offset == offset)
981     {
982       *index = middle;
983       return elt;
984     }
985
986   return NULL;
987 }
988
989 /* TreeModel signals */
990 static void
991 gtk_tree_model_filter_row_changed (GtkTreeModel *c_model,
992                                    GtkTreePath  *c_path,
993                                    GtkTreeIter  *c_iter,
994                                    gpointer      data)
995 {
996   GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (data);
997   GtkTreeIter iter;
998   GtkTreeIter childs;
999   GtkTreeIter real_c_iter;
1000   GtkTreePath *path = NULL;
1001
1002   FilterElt *elt;
1003   FilterLevel *level;
1004
1005   gboolean requested_state;
1006   gboolean current_state;
1007   gboolean free_c_path = FALSE;
1008
1009   g_return_if_fail (c_path != NULL || c_iter != NULL);
1010
1011   if (!c_path)
1012     {
1013       c_path = gtk_tree_model_get_path (c_model, c_iter);
1014       free_c_path = TRUE;
1015     }
1016
1017   if (c_iter)
1018     real_c_iter = *c_iter;
1019   else
1020     gtk_tree_model_get_iter (c_model, &real_c_iter, c_path);
1021
1022   /* is this node above the virtual root? */
1023   if (filter->priv->virtual_root
1024       && (gtk_tree_path_get_depth (filter->priv->virtual_root)
1025           >= gtk_tree_path_get_depth (c_path)))
1026     goto done;
1027
1028   /* what's the requested state? */
1029   requested_state = gtk_tree_model_filter_visible (filter, &real_c_iter);
1030
1031   /* now, let's see whether the item is there */
1032   path = gtk_real_tree_model_filter_convert_child_path_to_path (filter,
1033                                                                 c_path,
1034                                                                 FALSE,
1035                                                                 FALSE);
1036
1037   if (path)
1038     {
1039       gtk_tree_model_get_iter (GTK_TREE_MODEL (filter), &iter, path);
1040       current_state = FILTER_ELT (iter.user_data2)->visible;
1041     }
1042   else
1043     current_state = FALSE;
1044
1045   if (current_state == FALSE && requested_state == FALSE)
1046     /* no changes required */
1047     goto done;
1048
1049   if (current_state == TRUE && requested_state == FALSE)
1050     {
1051       /* get rid of this node */
1052       gtk_tree_model_get_iter (GTK_TREE_MODEL (filter), &iter, path);
1053       gtk_tree_model_filter_remove_node (filter, &iter, TRUE);
1054
1055       level = FILTER_LEVEL (iter.user_data);
1056
1057       if (!level->parent_level)
1058         filter->priv->root_level_visible--;
1059
1060       goto done;
1061     }
1062
1063   if (current_state == TRUE && requested_state == TRUE)
1064     {
1065       /* progate the signal */
1066       gtk_tree_model_get_iter (GTK_TREE_MODEL (filter), &iter, path);
1067       gtk_tree_model_row_changed (GTK_TREE_MODEL (filter), path, &iter);
1068
1069       level = FILTER_LEVEL (iter.user_data);
1070       elt = FILTER_ELT (iter.user_data2);
1071
1072       /* and update the childs */
1073       if (gtk_tree_model_iter_children (c_model, &childs, &real_c_iter))
1074         gtk_tree_model_filter_update_childs (filter, level, elt);
1075
1076       goto done;
1077     }
1078
1079   /* only current == FALSE and requested == TRUE is left,
1080    * pull in the child
1081    */
1082   g_return_if_fail (current_state == FALSE && requested_state == TRUE);
1083
1084   /* make sure the new item has been pulled in */
1085   if (!filter->priv->root)
1086     {
1087       gint i;
1088       FilterLevel *root;
1089
1090       gtk_tree_model_filter_build_level (filter, NULL, NULL);
1091
1092       root = FILTER_LEVEL (filter->priv->root);
1093
1094       if (root)
1095         {
1096           for (i = 0; i < root->array->len; i++)
1097             g_array_index (root->array, FilterElt, i).visible = FALSE;
1098           filter->priv->root_level_visible = 0;
1099         }
1100     }
1101
1102   if (!path)
1103     path = gtk_real_tree_model_filter_convert_child_path_to_path (filter,
1104                                                                   c_path,
1105                                                                   TRUE,
1106                                                                   TRUE);
1107
1108   g_return_if_fail (path != NULL);
1109
1110   gtk_tree_model_filter_increment_stamp (filter);
1111   gtk_tree_model_get_iter (GTK_TREE_MODEL (filter), &iter, path);
1112
1113   level = FILTER_LEVEL (iter.user_data);
1114   elt = FILTER_ELT (iter.user_data2);
1115
1116   elt->visible = TRUE;
1117
1118   if (!level->parent_level)
1119     filter->priv->root_level_visible++;
1120
1121   /* update stamp */
1122   gtk_tree_model_row_inserted (GTK_TREE_MODEL (filter), path, &iter);
1123
1124   if (gtk_tree_model_iter_children (c_model, &childs, c_iter))
1125     gtk_tree_model_filter_update_childs (filter, level, elt);
1126
1127 done:
1128   if (path)
1129     gtk_tree_path_free (path);
1130
1131   if (free_c_path)
1132     gtk_tree_path_free (c_path);
1133 }
1134
1135 static void
1136 gtk_tree_model_filter_row_inserted (GtkTreeModel *c_model,
1137                                     GtkTreePath  *c_path,
1138                                     GtkTreeIter  *c_iter,
1139                                     gpointer      data)
1140 {
1141   GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (data);
1142   GtkTreePath *path = NULL;
1143   GtkTreePath *real_path = NULL;
1144   GtkTreeIter iter;
1145
1146   GtkTreeIter real_c_iter;
1147
1148   FilterElt *elt;
1149   FilterLevel *level;
1150   FilterLevel *parent_level;
1151
1152   gint i = 0, offset, index = -1;
1153
1154   gboolean free_c_path = FALSE;
1155
1156   g_return_if_fail (c_path != NULL || c_iter != NULL);
1157
1158   if (!c_path)
1159     {
1160       c_path = gtk_tree_model_get_path (c_model, c_iter);
1161       free_c_path = TRUE;
1162     }
1163
1164   if (c_iter)
1165     real_c_iter = *c_iter;
1166   else
1167     gtk_tree_model_get_iter (c_model, &real_c_iter, c_path);
1168
1169   /* the row has already been inserted. so we need to fixup the
1170    * virtual root here first
1171    */
1172   if (filter->priv->virtual_root)
1173     {
1174       if (gtk_tree_path_get_depth (filter->priv->virtual_root) >=
1175           gtk_tree_path_get_depth (c_path))
1176         {
1177           gint level;
1178           gint *v_indices, *c_indices;
1179
1180           level = gtk_tree_path_get_depth (c_path) - 1;
1181           v_indices = gtk_tree_path_get_indices (filter->priv->virtual_root);
1182           c_indices = gtk_tree_path_get_indices (c_path);
1183
1184           if (v_indices[level] >= c_indices[level])
1185             (v_indices[level])++;
1186         }
1187     }
1188
1189   if (!filter->priv->root)
1190     {
1191       gtk_tree_model_filter_build_level (filter, NULL, NULL);
1192       /* that already put the inserted iter in the level */
1193
1194       goto done_and_emit;
1195     }
1196
1197   parent_level = level = FILTER_LEVEL (filter->priv->root);
1198
1199   /* subtract virtual root if necessary */
1200   if (filter->priv->virtual_root)
1201     {
1202       real_path = gtk_tree_model_filter_remove_root (c_path,
1203                                                      filter->priv->virtual_root);
1204       /* not our kiddo */
1205       if (!real_path)
1206         goto done;
1207     }
1208   else
1209     real_path = gtk_tree_path_copy (c_path);
1210
1211   if (gtk_tree_path_get_depth (real_path) - 1 >= 1)
1212     {
1213       /* find the parent level */
1214       while (i < gtk_tree_path_get_depth (real_path) - 1)
1215         {
1216           gint j;
1217
1218           if (!level)
1219             /* we don't cover this signal */
1220             goto done;
1221
1222           elt = bsearch_elt_with_offset (level->array,
1223                                          gtk_tree_path_get_indices (real_path)[i],
1224                                          &j);
1225
1226           if (!elt)
1227             /* parent is probably being filtered out */
1228             goto done;
1229
1230           if (!elt->children)
1231             {
1232               GtkTreePath *tmppath;
1233               GtkTreeIter  tmpiter;
1234
1235               tmpiter.stamp = filter->priv->stamp;
1236               tmpiter.user_data = level;
1237               tmpiter.user_data2 = elt;
1238
1239               tmppath = gtk_tree_model_get_path (GTK_TREE_MODEL (data),
1240                                                  &tmpiter);
1241
1242               if (tmppath)
1243                 {
1244                   gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (data),
1245                                                         tmppath, &tmpiter);
1246                   gtk_tree_path_free (tmppath);
1247                 }
1248
1249               /* not covering this signal */
1250               goto done;
1251             }
1252
1253           level = elt->children;
1254           parent_level = level;
1255           i++;
1256         }
1257     }
1258
1259   if (!parent_level)
1260     goto done;
1261
1262   /* let's try to insert the value */
1263   offset = gtk_tree_path_get_indices (real_path)[gtk_tree_path_get_depth (real_path) - 1];
1264
1265   /* update the offsets, yes if we didn't insert the node above, there will
1266    * be a gap here. This will be filled with the node (via fetch_child) when
1267    * it becomes visible
1268    */
1269   for (i = 0; i < level->array->len; i++)
1270     {
1271       FilterElt *e = &g_array_index (level->array, FilterElt, i);
1272       if ((e->offset >= offset))
1273         e->offset++;
1274     }
1275
1276   /* only insert when visible */
1277   if (gtk_tree_model_filter_visible (filter, &real_c_iter))
1278     {
1279       FilterElt felt;
1280
1281       if (GTK_TREE_MODEL_FILTER_CACHE_CHILD_ITERS (filter))
1282         felt.iter = real_c_iter;
1283
1284       felt.offset = offset;
1285       felt.zero_ref_count = 0;
1286       felt.ref_count = 0;
1287       felt.visible = TRUE;
1288       felt.children = NULL;
1289
1290       for (i = 0; i < level->array->len; i++)
1291         if (g_array_index (level->array, FilterElt, i).offset > offset)
1292           break;
1293
1294       g_array_insert_val (level->array, i, felt);
1295       index = i;
1296
1297       if (!level->parent_level)
1298         filter->priv->root_level_visible++;
1299     }
1300
1301   /* another iteration to update the references of childs to parents. */
1302   for (i = 0; i < level->array->len; i++)
1303     {
1304       FilterElt *e = &g_array_index (level->array, FilterElt, i);
1305       if (e->children)
1306         e->children->parent_elt = e;
1307     }
1308
1309   /* don't emit the signal if we aren't visible */
1310   if (!gtk_tree_model_filter_visible (filter, &real_c_iter))
1311     goto done;
1312
1313 done_and_emit:
1314   /* NOTE: pass c_path here and NOT real_path. This function does
1315    * root subtraction itself
1316    */
1317   path = gtk_real_tree_model_filter_convert_child_path_to_path (filter,
1318                                                                 c_path,
1319                                                                 FALSE, TRUE);
1320
1321   if (!path)
1322     goto done;
1323
1324   gtk_tree_model_filter_increment_stamp (filter);
1325
1326   gtk_tree_model_get_iter (GTK_TREE_MODEL (data), &iter, path);
1327   gtk_tree_model_row_inserted (GTK_TREE_MODEL (data), path, &iter);
1328
1329   gtk_tree_path_free (path);
1330
1331 done:
1332   if (real_path)
1333     gtk_tree_path_free (real_path);
1334
1335   if (free_c_path)
1336     gtk_tree_path_free (c_path);
1337 }
1338
1339 static void
1340 gtk_tree_model_filter_row_has_child_toggled (GtkTreeModel *c_model,
1341                                              GtkTreePath  *c_path,
1342                                              GtkTreeIter  *c_iter,
1343                                              gpointer      data)
1344 {
1345   GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (data);
1346   GtkTreePath *path;
1347   GtkTreeIter iter;
1348
1349   g_return_if_fail (c_path != NULL && c_iter != NULL);
1350
1351   /* FIXME: does this code work? */
1352
1353   if (!gtk_tree_model_filter_visible (filter, c_iter))
1354     return;
1355
1356   path = gtk_real_tree_model_filter_convert_child_path_to_path (filter,
1357                                                                 c_path,
1358                                                                 FALSE,
1359                                                                 TRUE);
1360   if (!path)
1361     return;
1362
1363   gtk_tree_model_get_iter (GTK_TREE_MODEL (data), &iter, path);
1364   gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (data), path, &iter);
1365
1366   gtk_tree_path_free (path);
1367 }
1368
1369 static void
1370 gtk_tree_model_filter_row_deleted (GtkTreeModel *c_model,
1371                                    GtkTreePath  *c_path,
1372                                    gpointer      data)
1373 {
1374   GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (data);
1375   GtkTreePath *path;
1376   GtkTreeIter iter;
1377   FilterElt *elt;
1378   FilterLevel *level;
1379   gint offset;
1380   gboolean emit_signal = TRUE;
1381   gint i;
1382
1383   g_return_if_fail (c_path != NULL);
1384
1385   /* special case the deletion of an ancestor of the virtual root */
1386   if (filter->priv->virtual_root &&
1387       (gtk_tree_path_is_ancestor (c_path, filter->priv->virtual_root) ||
1388        !gtk_tree_path_compare (c_path, filter->priv->virtual_root)))
1389     {
1390       gint i;
1391       GtkTreePath *path;
1392       FilterLevel *level = FILTER_LEVEL (filter->priv->root);
1393
1394       if (!level)
1395         return;
1396
1397       /* remove everything in the filter model
1398        *
1399        * For now, we just iterate over the root level and emit a
1400        * row_deleted for each FilterElt. Not sure if this is correct.
1401        */
1402
1403       gtk_tree_model_filter_increment_stamp (filter);
1404       path = gtk_tree_path_new ();
1405       gtk_tree_path_append_index (path, 0);
1406
1407       for (i = 0; i < level->array->len; i++)
1408         gtk_tree_model_row_deleted (GTK_TREE_MODEL (data), path);
1409
1410       gtk_tree_path_free (path);
1411       gtk_tree_model_filter_free_level (filter, filter->priv->root);
1412
1413       return;
1414     }
1415
1416   /* fixup virtual root */
1417   if (filter->priv->virtual_root)
1418     {
1419       if (gtk_tree_path_get_depth (filter->priv->virtual_root) >=
1420           gtk_tree_path_get_depth (c_path))
1421         {
1422           gint level;
1423           gint *v_indices, *c_indices;
1424
1425           level = gtk_tree_path_get_depth (c_path) - 1;
1426           v_indices = gtk_tree_path_get_indices (filter->priv->virtual_root);
1427           c_indices = gtk_tree_path_get_indices (c_path);
1428
1429           if (v_indices[level] > c_indices[level])
1430             (v_indices[level])--;
1431         }
1432     }
1433
1434   path = gtk_real_tree_model_filter_convert_child_path_to_path (filter,
1435                                                                 c_path,
1436                                                                 FALSE,
1437                                                                 FALSE);
1438
1439   if (!path)
1440     {
1441       /* fixup the offsets */
1442       GtkTreePath *real_path;
1443
1444       if (!filter->priv->root)
1445         return;
1446
1447       level = FILTER_LEVEL (filter->priv->root);
1448
1449       /* subtract vroot if necessary */
1450       if (filter->priv->virtual_root)
1451         {
1452           real_path = gtk_tree_model_filter_remove_root (c_path,
1453                                                          filter->priv->virtual_root);
1454           /* we don't handle this */
1455           if (!real_path)
1456             return;
1457         }
1458       else
1459         real_path = gtk_tree_path_copy (c_path);
1460
1461       i = 0;
1462       if (gtk_tree_path_get_depth (real_path) - 1 >= 1)
1463         {
1464           while (i < gtk_tree_path_get_depth (real_path) - 1)
1465             {
1466               gint j;
1467
1468               if (!level)
1469                 {
1470                   /* we don't cover this */
1471                   gtk_tree_path_free (real_path);
1472                   return;
1473                 }
1474
1475               elt = bsearch_elt_with_offset (level->array,
1476                                              gtk_tree_path_get_indices (real_path)[i],
1477                                              &j);
1478
1479               if (!elt || !elt->children)
1480                 {
1481                   /* parent is filtered out, so no level */
1482                   gtk_tree_path_free (real_path);
1483                   return;
1484                 }
1485
1486               level = elt->children;
1487               i++;
1488             }
1489         }
1490
1491       offset = gtk_tree_path_get_indices (real_path)[gtk_tree_path_get_depth (real_path) - 1];
1492       gtk_tree_path_free (real_path);
1493
1494       if (!level)
1495         return;
1496
1497       /* we need:
1498        * - the offset of the removed item
1499        * - the level
1500        */
1501       for (i = 0; i < level->array->len; i++)
1502         {
1503           elt = &g_array_index (level->array, FilterElt, i);
1504           if (elt->offset > offset)
1505             elt->offset--;
1506           if (elt->children)
1507             elt->children->parent_elt = elt;
1508         }
1509
1510       return;
1511     }
1512
1513   gtk_tree_model_get_iter (GTK_TREE_MODEL (data), &iter, path);
1514
1515   level = FILTER_LEVEL (iter.user_data);
1516   elt = FILTER_ELT (iter.user_data2);
1517   offset = elt->offset;
1518
1519   if (!level->parent_level && elt->visible)
1520     filter->priv->root_level_visible--;
1521
1522   if (emit_signal)
1523     {
1524       if (level->ref_count == 0 && level != filter->priv->root)
1525         {
1526           gtk_tree_model_filter_increment_stamp (filter);
1527           gtk_tree_model_row_deleted (GTK_TREE_MODEL (data), path);
1528
1529           gtk_tree_path_free (path);
1530           return;
1531         }
1532
1533       gtk_tree_model_filter_increment_stamp (filter);
1534       gtk_tree_model_row_deleted (GTK_TREE_MODEL (data), path);
1535       iter.stamp = filter->priv->stamp;
1536
1537       while (elt->ref_count > 0)
1538         gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (data), &iter,
1539                                                FALSE);
1540     }
1541
1542   if (level->array->len == 1)
1543     {
1544       /* kill level */
1545       gtk_tree_model_filter_free_level (filter, level);
1546     }
1547   else
1548     {
1549       FilterElt *tmp;
1550
1551       /* remove the row */
1552       tmp = bsearch_elt_with_offset (level->array, elt->offset, &i);
1553
1554       offset = tmp->offset;
1555       g_array_remove_index (level->array, i);
1556
1557       for (i = MAX (--i, 0); i < level->array->len; i++)
1558         {
1559           elt = &g_array_index (level->array, FilterElt, i);
1560           if (elt->offset > offset)
1561             elt->offset--;
1562           if (elt->children)
1563             elt->children->parent_elt = elt;
1564         }
1565     }
1566
1567   gtk_tree_path_free (path);
1568 }
1569
1570 static void
1571 gtk_tree_model_filter_rows_reordered (GtkTreeModel *c_model,
1572                                       GtkTreePath  *c_path,
1573                                       GtkTreeIter  *c_iter,
1574                                       gint         *new_order,
1575                                       gpointer      data)
1576 {
1577   FilterElt *elt;
1578   FilterLevel *level;
1579   GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (data);
1580
1581   GtkTreePath *path;
1582   GtkTreeIter iter;
1583
1584   gint *tmp_array;
1585   gint i, j, elt_count;
1586   gint length;
1587
1588   GArray *new_array;
1589
1590   g_return_if_fail (new_order != NULL);
1591
1592   if (c_path == NULL || gtk_tree_path_get_indices (c_path) == NULL)
1593     {
1594       if (!filter->priv->root)
1595         return;
1596
1597       length = gtk_tree_model_iter_n_children (c_model, NULL);
1598
1599       if (filter->priv->virtual_root)
1600         {
1601           gint new_pos = -1;
1602
1603           /* reorder root level of path */
1604           for (i = 0; i < length; i++)
1605             if (new_order[i] == gtk_tree_path_get_indices (filter->priv->virtual_root)[0])
1606               new_pos = i;
1607
1608           if (new_pos < 0)
1609             return;
1610
1611           gtk_tree_path_get_indices (filter->priv->virtual_root)[0] = new_pos;
1612           return;
1613         }
1614
1615       path = gtk_tree_path_new ();
1616       level = FILTER_LEVEL (filter->priv->root);
1617     }
1618   else
1619     {
1620       GtkTreeIter child_iter;
1621
1622       /* virtual root anchor reordering */
1623       if (filter->priv->virtual_root &&
1624           gtk_tree_path_get_depth (c_path) <
1625           gtk_tree_path_get_depth (filter->priv->virtual_root))
1626         {
1627           gint new_pos = -1;
1628           gint length;
1629           gint level;
1630           GtkTreeIter real_c_iter;
1631
1632           level = gtk_tree_path_get_depth (c_path);
1633
1634           if (c_iter)
1635             real_c_iter = *c_iter;
1636           else
1637             gtk_tree_model_get_iter (c_model, &real_c_iter, c_path);
1638
1639           length = gtk_tree_model_iter_n_children (c_model, &real_c_iter);
1640
1641           for (i = 0; i < length; i++)
1642             if (new_order[i] == gtk_tree_path_get_indices (filter->priv->virtual_root)[level])
1643               new_pos = i;
1644
1645           if (new_pos < 0)
1646             return;
1647
1648           gtk_tree_path_get_indices (filter->priv->virtual_root)[level] = new_pos;
1649           return;
1650         }
1651
1652       path = gtk_real_tree_model_filter_convert_child_path_to_path (filter,
1653                                                                     c_path,
1654                                                                     FALSE,
1655                                                                     FALSE);
1656       if (!path && filter->priv->virtual_root &&
1657           gtk_tree_path_compare (c_path, filter->priv->virtual_root))
1658         return;
1659
1660       if (!path && !filter->priv->virtual_root)
1661         return;
1662
1663       if (!path)
1664         {
1665           /* root level mode */
1666           if (!c_iter)
1667             gtk_tree_model_get_iter (c_model, c_iter, c_path);
1668           length = gtk_tree_model_iter_n_children (c_model, c_iter);
1669           path = gtk_tree_path_new ();
1670           level = FILTER_LEVEL (filter->priv->root);
1671         }
1672       else
1673         {
1674           gtk_tree_model_get_iter (GTK_TREE_MODEL (data), &iter, path);
1675
1676           level = FILTER_LEVEL (iter.user_data);
1677           elt = FILTER_ELT (iter.user_data2);
1678
1679           if (!elt->children)
1680             {
1681               gtk_tree_path_free (path);
1682               return;
1683             }
1684
1685           level = elt->children;
1686
1687           gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (filter), &child_iter, &iter);
1688           length = gtk_tree_model_iter_n_children (c_model, &child_iter);
1689         }
1690     }
1691
1692   if (level->array->len < 1)
1693     return;
1694
1695   /* NOTE: we do not bail out here if level->array->len < 2 like
1696    * GtkTreeModelSort does. This because we do some special tricky
1697    * reordering.
1698    */
1699
1700   /* construct a new array */
1701   new_array = g_array_sized_new (FALSE, FALSE, sizeof (FilterElt),
1702                                  level->array->len);
1703   tmp_array = g_new (gint, level->array->len);
1704
1705   for (i = 0, elt_count = 0; i < length; i++)
1706     {
1707       FilterElt *e = NULL;
1708       gint old_offset = -1;
1709
1710       for (j = 0; j < level->array->len; j++)
1711         if (g_array_index (level->array, FilterElt, j).offset == new_order[i])
1712           {
1713             e = &g_array_index (level->array, FilterElt, j);
1714             old_offset = j;
1715             break;
1716           }
1717
1718       if (!e)
1719         continue;
1720
1721       tmp_array[elt_count] = old_offset;
1722       g_array_append_val (new_array, *e);
1723       g_array_index (new_array, FilterElt, elt_count).offset = i;
1724       elt_count++;
1725     }
1726
1727   g_array_free (level->array, TRUE);
1728   level->array = new_array;
1729
1730   /* fix up stuff */
1731   for (i = 0; i < level->array->len; i++)
1732     {
1733       FilterElt *e = &g_array_index (level->array, FilterElt, i);
1734       if (e->children)
1735         e->children->parent_elt = e;
1736     }
1737
1738   /* emit rows_reordered */
1739   if (!gtk_tree_path_get_indices (path))
1740     gtk_tree_model_rows_reordered (GTK_TREE_MODEL (data), path, NULL,
1741                                    tmp_array);
1742   else
1743     gtk_tree_model_rows_reordered (GTK_TREE_MODEL (data), path, &iter,
1744                                    tmp_array);
1745
1746   /* done */
1747   g_free (tmp_array);
1748   gtk_tree_path_free (path);
1749 }
1750
1751 /* TreeModelIface implementation */
1752 static guint
1753 gtk_tree_model_filter_get_flags (GtkTreeModel *model)
1754 {
1755   GtkTreeModelFlags flags;
1756
1757   g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), 0);
1758   g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL, 0);
1759
1760   flags = gtk_tree_model_get_flags (GTK_TREE_MODEL_FILTER (model)->priv->child_model);
1761
1762   if ((flags & GTK_TREE_MODEL_LIST_ONLY) == GTK_TREE_MODEL_LIST_ONLY)
1763     return GTK_TREE_MODEL_LIST_ONLY;
1764
1765   return 0;
1766 }
1767
1768 static gint
1769 gtk_tree_model_filter_get_n_columns (GtkTreeModel *model)
1770 {
1771   GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
1772
1773   g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), 0);
1774   g_return_val_if_fail (filter->priv->child_model != NULL, 0);
1775
1776   if (filter->priv->child_model == NULL)
1777     return 0;
1778
1779   /* so we can't modify the modify func after this ... */
1780   filter->priv->modify_func_set = TRUE;
1781
1782   if (filter->priv->modify_n_columns > 0)
1783     return filter->priv->modify_n_columns;
1784
1785   return gtk_tree_model_get_n_columns (filter->priv->child_model);
1786 }
1787
1788 static GType
1789 gtk_tree_model_filter_get_column_type (GtkTreeModel *model,
1790                                        gint          index)
1791 {
1792   GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
1793
1794   g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), G_TYPE_INVALID);
1795   g_return_val_if_fail (filter->priv->child_model != NULL, G_TYPE_INVALID);
1796
1797   /* so we can't modify the modify func after this ... */
1798   filter->priv->modify_func_set = TRUE;
1799
1800   if (filter->priv->modify_types)
1801     {
1802       g_return_val_if_fail (index < filter->priv->modify_n_columns, G_TYPE_INVALID);
1803
1804       return filter->priv->modify_types[index];
1805     }
1806
1807   return gtk_tree_model_get_column_type (filter->priv->child_model, index);
1808 }
1809
1810 static gboolean
1811 gtk_tree_model_filter_get_iter (GtkTreeModel *model,
1812                                 GtkTreeIter  *iter,
1813                                 GtkTreePath  *path)
1814 {
1815   GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
1816   gint *indices;
1817   FilterLevel *level;
1818   gint depth, i;
1819
1820   g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
1821   g_return_val_if_fail (filter->priv->child_model != NULL, FALSE);
1822
1823   indices = gtk_tree_path_get_indices (path);
1824
1825   if (filter->priv->root == NULL)
1826     gtk_tree_model_filter_build_level (filter, NULL, NULL);
1827   level = FILTER_LEVEL (filter->priv->root);
1828
1829   depth = gtk_tree_path_get_depth (path);
1830   if (!depth)
1831     {
1832       iter->stamp = 0;
1833       return FALSE;
1834     }
1835
1836   for (i = 0; i < depth - 1; i++)
1837     {
1838       if (!level || indices[i] >= level->array->len)
1839         {
1840           return FALSE;
1841         }
1842
1843       if (!g_array_index (level->array, FilterElt, indices[i]).children)
1844         gtk_tree_model_filter_build_level (filter, level,
1845                                            &g_array_index (level->array,
1846                                                            FilterElt,
1847                                                            indices[i]));
1848       level = g_array_index (level->array, FilterElt, indices[i]).children;
1849     }
1850
1851   if (!level || indices[i] >= level->array->len)
1852     {
1853       iter->stamp = 0;
1854       return FALSE;
1855     }
1856
1857   iter->stamp = filter->priv->stamp;
1858   iter->user_data = level;
1859   iter->user_data2 = &g_array_index (level->array, FilterElt,
1860                                      indices[depth - 1]);
1861
1862   return TRUE;
1863 }
1864
1865 static GtkTreePath *
1866 gtk_tree_model_filter_get_path (GtkTreeModel *model,
1867                                 GtkTreeIter  *iter)
1868 {
1869   GtkTreePath *retval;
1870   FilterLevel *level;
1871   FilterElt *elt;
1872
1873   g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), NULL);
1874   g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL, NULL);
1875   g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->stamp == iter->stamp, NULL);
1876
1877   retval = gtk_tree_path_new ();
1878   level = iter->user_data;
1879   elt = iter->user_data2;
1880
1881   while (level)
1882     {
1883       gtk_tree_path_prepend_index (retval,
1884                                    elt - FILTER_ELT (level->array->data));
1885       elt = level->parent_elt;
1886       level = level->parent_level;
1887     }
1888
1889   return retval;
1890 }
1891
1892 static void
1893 gtk_tree_model_filter_get_value (GtkTreeModel *model,
1894                                  GtkTreeIter  *iter,
1895                                  gint          column,
1896                                  GValue       *value)
1897 {
1898   GtkTreeIter child_iter;
1899   GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (model);
1900
1901   g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (model));
1902   g_return_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL);
1903   g_return_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->stamp == iter->stamp);
1904
1905   if (filter->priv->modify_func)
1906     {
1907       g_return_if_fail (column < filter->priv->modify_n_columns);
1908
1909       g_value_init (value, filter->priv->modify_types[column]);
1910       filter->priv->modify_func (model,
1911                            iter,
1912                            value,
1913                            column,
1914                            filter->priv->modify_data);
1915
1916       return;
1917     }
1918
1919   gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_iter, iter);
1920   gtk_tree_model_get_value (GTK_TREE_MODEL_FILTER (model)->priv->child_model,
1921                             &child_iter, column, value);
1922 }
1923
1924 static gboolean
1925 gtk_tree_model_filter_iter_next (GtkTreeModel *model,
1926                                  GtkTreeIter  *iter)
1927 {
1928   FilterLevel *level;
1929   FilterElt *elt;
1930
1931   g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
1932   g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL, FALSE);
1933   g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->stamp == iter->stamp, FALSE);
1934
1935   level = iter->user_data;
1936   elt = iter->user_data2;
1937
1938   if (elt - FILTER_ELT (level->array->data) >= level->array->len - 1)
1939     {
1940       iter->stamp = 0;
1941       return FALSE;
1942     }
1943
1944   iter->user_data2 = elt + 1;
1945
1946   return TRUE;
1947 }
1948
1949 static gboolean
1950 gtk_tree_model_filter_iter_children (GtkTreeModel *model,
1951                                      GtkTreeIter  *iter,
1952                                      GtkTreeIter  *parent)
1953 {
1954   GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
1955   FilterLevel *level;
1956
1957   iter->stamp = 0;
1958   g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
1959   g_return_val_if_fail (filter->priv->child_model != NULL, FALSE);
1960   if (parent)
1961     g_return_val_if_fail (filter->priv->stamp == parent->stamp, FALSE);
1962
1963   if (!parent)
1964     {
1965       if (!filter->priv->root)
1966         gtk_tree_model_filter_build_level (filter, NULL, NULL);
1967       if (!filter->priv->root)
1968         return FALSE;
1969
1970       level = filter->priv->root;
1971       iter->stamp = filter->priv->stamp;
1972       iter->user_data = level;
1973       iter->user_data2 = level->array->data;
1974     }
1975   else
1976     {
1977       if (FILTER_ELT (parent->user_data2)->children == NULL)
1978         gtk_tree_model_filter_build_level (filter,
1979                                            FILTER_LEVEL (parent->user_data),
1980                                            FILTER_ELT (parent->user_data2));
1981       if (FILTER_ELT (parent->user_data2)->children == NULL)
1982         return FALSE;
1983
1984       /* empty array? */
1985       if (FILTER_ELT (parent->user_data2)->children->array->len <= 0)
1986         return FALSE;
1987
1988       iter->stamp = filter->priv->stamp;
1989       iter->user_data = FILTER_ELT (parent->user_data2)->children;
1990       iter->user_data2 = FILTER_LEVEL (iter->user_data)->array->data;
1991     }
1992
1993   return TRUE;
1994 }
1995
1996 static gboolean
1997 gtk_tree_model_filter_iter_has_child (GtkTreeModel *model,
1998                                       GtkTreeIter  *iter)
1999 {
2000   GtkTreeIter child_iter;
2001   GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
2002   FilterElt *elt;
2003
2004   g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
2005   g_return_val_if_fail (filter->priv->child_model != NULL, FALSE);
2006   g_return_val_if_fail (filter->priv->stamp == iter->stamp, FALSE);
2007
2008   filter = GTK_TREE_MODEL_FILTER (model);
2009
2010   gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_iter, iter);
2011   elt = FILTER_ELT (iter->user_data2);
2012
2013   /* we need to build the level to check if not all children are filtered
2014    * out
2015    */
2016   if (!elt->children
2017       && gtk_tree_model_iter_has_child (filter->priv->child_model, &child_iter))
2018     gtk_tree_model_filter_build_level (filter, FILTER_LEVEL (iter->user_data),
2019                                        elt);
2020
2021   /* FIXME: we should prolly count the visible nodes here, just like in
2022    * _iter_n_children.
2023    */
2024   if (elt->children && elt->children->array->len > 0)
2025     return TRUE;
2026
2027   return FALSE;
2028 }
2029
2030 static gint
2031 gtk_tree_model_filter_iter_n_children (GtkTreeModel *model,
2032                                        GtkTreeIter  *iter)
2033 {
2034   GtkTreeIter child_iter;
2035   GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
2036   FilterElt *elt;
2037
2038   g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), 0);
2039   g_return_val_if_fail (filter->priv->child_model != NULL, 0);
2040   if (iter)
2041     g_return_val_if_fail (filter->priv->stamp == iter->stamp, 0);
2042
2043   if (!iter)
2044     {
2045       if (!filter->priv->root)
2046         gtk_tree_model_filter_build_level (filter, NULL, NULL);
2047
2048       /* count visible nodes */
2049       return filter->priv->root_level_visible;
2050     }
2051
2052   elt = FILTER_ELT (iter->user_data2);
2053   gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_iter, iter);
2054
2055   if (!elt->children &&
2056       gtk_tree_model_iter_has_child (filter->priv->child_model, &child_iter))
2057     gtk_tree_model_filter_build_level (filter,
2058                                        FILTER_LEVEL (iter->user_data),
2059                                        elt);
2060
2061   if (elt->children && elt->children->array->len)
2062     {
2063       int i = 0;
2064       int count = 0;
2065       GArray *a = elt->children->array;
2066
2067       /* count visible nodes */
2068       for (i = 0; i < a->len; i++)
2069         if (g_array_index (a, FilterElt, i).visible)
2070           count++;
2071
2072       return count;
2073     }
2074
2075   return 0;
2076 }
2077
2078 static gboolean
2079 gtk_tree_model_filter_iter_nth_child (GtkTreeModel *model,
2080                                       GtkTreeIter  *iter,
2081                                       GtkTreeIter  *parent,
2082                                       gint          n)
2083 {
2084   FilterLevel *level;
2085   GtkTreeIter children;
2086
2087   g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
2088   if (parent)
2089     g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->stamp == parent->stamp, FALSE);
2090
2091   /* use this instead of has_Child to force us to build the level, if needed */
2092   if (gtk_tree_model_filter_iter_children (model, &children, parent) == FALSE)
2093     {
2094       iter->stamp = 0;
2095       return FALSE;
2096     }
2097
2098   level = children.user_data;
2099   if (n >= level->array->len)
2100     {
2101       iter->stamp = 0;
2102       return FALSE;
2103     }
2104
2105   iter->stamp = GTK_TREE_MODEL_FILTER (model)->priv->stamp;
2106   iter->user_data = level;
2107   iter->user_data2 = &g_array_index (level->array, FilterElt, n);
2108
2109   return TRUE;
2110 }
2111
2112 static gboolean
2113 gtk_tree_model_filter_iter_parent (GtkTreeModel *model,
2114                                    GtkTreeIter  *iter,
2115                                    GtkTreeIter  *child)
2116 {
2117   FilterLevel *level;
2118
2119   iter->stamp = 0;
2120   g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
2121   g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL, FALSE);
2122   g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->stamp == child->stamp, FALSE);
2123
2124   level = child->user_data;
2125
2126   if (level->parent_level)
2127     {
2128       iter->stamp = GTK_TREE_MODEL_FILTER (model)->priv->stamp;
2129       iter->user_data = level->parent_level;
2130       iter->user_data2 = level->parent_elt;
2131
2132       return TRUE;
2133     }
2134
2135   return FALSE;
2136 }
2137
2138 static void
2139 gtk_tree_model_filter_ref_node (GtkTreeModel *model,
2140                                 GtkTreeIter  *iter)
2141 {
2142   GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
2143   GtkTreeIter child_iter;
2144   FilterLevel *level;
2145   FilterElt *elt;
2146
2147   g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (model));
2148   g_return_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL);
2149   g_return_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->stamp == iter->stamp);
2150
2151   gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_iter, iter);
2152
2153   gtk_tree_model_ref_node (filter->priv->child_model, &child_iter);
2154
2155   level = iter->user_data;
2156   elt = iter->user_data2;
2157
2158   elt->ref_count++;
2159   level->ref_count++;
2160   if (level->ref_count == 1)
2161     {
2162       FilterLevel *parent_level = level->parent_level;
2163       FilterElt *parent_elt = level->parent_elt;
2164
2165       /* we were at zero -- time to decrease the zero_ref_count val */
2166       do
2167         {
2168           if (parent_elt)
2169             parent_elt->zero_ref_count--;
2170
2171           if (parent_level)
2172             {
2173               parent_elt = parent_level->parent_elt;
2174               parent_level = parent_level->parent_level;
2175             }
2176         }
2177       while (parent_level);
2178       filter->priv->zero_ref_count--;
2179     }
2180 }
2181
2182 static void
2183 gtk_tree_model_filter_unref_node (GtkTreeModel *model,
2184                                   GtkTreeIter  *iter)
2185 {
2186   gtk_tree_model_filter_real_unref_node (model, iter, TRUE);
2187 }
2188
2189 static void
2190 gtk_tree_model_filter_real_unref_node (GtkTreeModel *model,
2191                                        GtkTreeIter  *iter,
2192                                        gboolean      propagate_unref)
2193 {
2194   GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
2195   FilterLevel *level;
2196   FilterElt *elt;
2197
2198   g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (model));
2199   g_return_if_fail (filter->priv->child_model != NULL);
2200   g_return_if_fail (filter->priv->stamp == iter->stamp);
2201
2202   if (propagate_unref)
2203     {
2204       GtkTreeIter child_iter;
2205       gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_iter, iter);
2206       gtk_tree_model_unref_node (filter->priv->child_model, &child_iter);
2207     }
2208
2209   level = iter->user_data;
2210   elt = iter->user_data2;
2211
2212   g_return_if_fail (elt->ref_count > 0);
2213
2214   elt->ref_count--;
2215   level->ref_count--;
2216   if (level->ref_count == 0)
2217     {
2218       FilterLevel *parent_level = level->parent_level;
2219       FilterElt *parent_elt = level->parent_elt;
2220
2221       /* we are at zero -- time to increase the zero_ref_count val */
2222       while (parent_level)
2223         {
2224           parent_elt->zero_ref_count++;
2225
2226           parent_elt = parent_level->parent_elt;
2227           parent_level = parent_level->parent_level;
2228         }
2229       filter->priv->zero_ref_count++;
2230     }
2231 }
2232
2233 /* bits and pieces */
2234 static void
2235 gtk_tree_model_filter_set_model (GtkTreeModelFilter *filter,
2236                                  GtkTreeModel       *child_model)
2237 {
2238   g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
2239
2240   if (filter->priv->child_model)
2241     {
2242       g_signal_handler_disconnect (G_OBJECT (filter->priv->child_model),
2243                                    filter->priv->changed_id);
2244       g_signal_handler_disconnect (G_OBJECT (filter->priv->child_model),
2245                                    filter->priv->inserted_id);
2246       g_signal_handler_disconnect (G_OBJECT (filter->priv->child_model),
2247                                    filter->priv->has_child_toggled_id);
2248       g_signal_handler_disconnect (G_OBJECT (filter->priv->child_model),
2249                                    filter->priv->deleted_id);
2250       g_signal_handler_disconnect (G_OBJECT (filter->priv->child_model),
2251                                    filter->priv->reordered_id);
2252
2253       /* reset our state */
2254       if (filter->priv->root)
2255         gtk_tree_model_filter_free_level (filter, filter->priv->root);
2256
2257       filter->priv->root = NULL;
2258       g_object_unref (G_OBJECT (filter->priv->child_model));
2259       filter->priv->visible_column = -1;
2260       /* FIXME: destroy more crack here? the funcs? */
2261     }
2262
2263   filter->priv->child_model = child_model;
2264
2265   if (child_model)
2266     {
2267       g_object_ref (G_OBJECT (filter->priv->child_model));
2268       filter->priv->changed_id =
2269         g_signal_connect (child_model, "row_changed",
2270                           G_CALLBACK (gtk_tree_model_filter_row_changed),
2271                           filter);
2272       filter->priv->inserted_id =
2273         g_signal_connect (child_model, "row_inserted",
2274                           G_CALLBACK (gtk_tree_model_filter_row_inserted),
2275                           filter);
2276       filter->priv->has_child_toggled_id =
2277         g_signal_connect (child_model, "row_has_child_toggled",
2278                           G_CALLBACK (gtk_tree_model_filter_row_has_child_toggled),
2279                           filter);
2280       filter->priv->deleted_id =
2281         g_signal_connect (child_model, "row_deleted",
2282                           G_CALLBACK (gtk_tree_model_filter_row_deleted),
2283                           filter);
2284       filter->priv->reordered_id =
2285         g_signal_connect (child_model, "rows_reordered",
2286                           G_CALLBACK (gtk_tree_model_filter_rows_reordered),
2287                           filter);
2288
2289       filter->priv->child_flags = gtk_tree_model_get_flags (child_model);
2290       filter->priv->stamp = g_random_int ();
2291     }
2292 }
2293
2294 static void
2295 gtk_tree_model_filter_set_root (GtkTreeModelFilter *filter,
2296                                 GtkTreePath        *root)
2297 {
2298   g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
2299
2300   if (!root)
2301     filter->priv->virtual_root = NULL;
2302   else
2303     filter->priv->virtual_root = gtk_tree_path_copy (root);
2304 }
2305
2306 /* public API */
2307
2308 /**
2309  * gtk_tree_model_filter_new:
2310  * @child_model: A #GtkTreeModel.
2311  * @root: A #GtkTreePath or %NULL.
2312  *
2313  * Creates a new #GtkTreeModel, with @child_model as the child_model
2314  * and @root as the virtual root.
2315  *
2316  * Return value: A new #GtkTreeModel.
2317  *
2318  * Since: 2.4
2319  */
2320 GtkTreeModel *
2321 gtk_tree_model_filter_new (GtkTreeModel *child_model,
2322                            GtkTreePath  *root)
2323 {
2324   GtkTreeModel *retval;
2325
2326   g_return_val_if_fail (GTK_IS_TREE_MODEL (child_model), NULL);
2327
2328   retval = GTK_TREE_MODEL (g_object_new (gtk_tree_model_filter_get_type (), NULL));
2329
2330   gtk_tree_model_filter_set_model (GTK_TREE_MODEL_FILTER (retval),
2331                                    child_model);
2332   gtk_tree_model_filter_set_root (GTK_TREE_MODEL_FILTER (retval), root);
2333
2334   return retval;
2335 }
2336
2337 /**
2338  * gtk_tree_model_filter_get_model:
2339  * @filter: A #GtkTreeModelFilter.
2340  *
2341  * Returns a pointer to the child model of @filter.
2342  *
2343  * Return value: A pointer to a #GtkTreeModel.
2344  *
2345  * Since: 2.4
2346  */
2347 GtkTreeModel *
2348 gtk_tree_model_filter_get_model (GtkTreeModelFilter *filter)
2349 {
2350   g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (filter), NULL);
2351
2352   return filter->priv->child_model;
2353 }
2354
2355 /**
2356  * gtk_tree_model_filter_set_visible_func:
2357  * @filter: A #GtkTreeModelFilter.
2358  * @func: A #GtkTreeModelFilterVisibleFunc, the visible function.
2359  * @data: User data to pass to the visible function, or %NULL.
2360  * @destroy: Destroy notifier of @data, or %NULL.
2361  *
2362  * Sets the visible function used when filtering the @filter to be @func. The
2363  * function should return %TRUE if the given row should be visible and
2364  * %FALSE otherwise.
2365  *
2366  * Since: 2.4
2367  */
2368 void
2369 gtk_tree_model_filter_set_visible_func (GtkTreeModelFilter            *filter,
2370                                         GtkTreeModelFilterVisibleFunc  func,
2371                                         gpointer                       data,
2372                                         GtkDestroyNotify               destroy)
2373 {
2374   g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
2375   g_return_if_fail (func != NULL);
2376   g_return_if_fail (filter->priv->visible_method_set == FALSE);
2377
2378   if (filter->priv->visible_func)
2379     {
2380       GtkDestroyNotify d = filter->priv->visible_destroy;
2381
2382       filter->priv->visible_destroy = NULL;
2383       d (filter->priv->visible_data);
2384     }
2385
2386   filter->priv->visible_func = func;
2387   filter->priv->visible_data = data;
2388   filter->priv->visible_destroy = destroy;
2389
2390   filter->priv->visible_method_set = TRUE;
2391 }
2392
2393 /**
2394  * gtk_tree_model_filter_set_modify_func:
2395  * @filter: A #GtkTreeModelFilter.
2396  * @n_columns: The number of columns in the filter model.
2397  * @types: The #GType<!-- -->s of the columns.
2398  * @func: A #GtkTreeModelFilterModifyFunc, or %NULL.
2399  * @data: User data to pass to the modify function, or %NULL.
2400  * @destroy: Destroy notifier of @data, or %NULL.
2401  *
2402  * Sets the @filter to have @n_columns columns with @types. If @func
2403  * is not %NULL, it will set @func to be the modify function of @filter.
2404  *
2405  * Since: 2.4
2406  */
2407 void
2408 gtk_tree_model_filter_set_modify_func (GtkTreeModelFilter           *filter,
2409                                        gint                          n_columns,
2410                                        GType                        *types,
2411                                        GtkTreeModelFilterModifyFunc  func,
2412                                        gpointer                      data,
2413                                        GtkDestroyNotify              destroy)
2414 {
2415   g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
2416   g_return_if_fail (func != NULL);
2417   g_return_if_fail (filter->priv->modify_func_set == FALSE);
2418
2419   if (filter->priv->modify_destroy)
2420     {
2421       GtkDestroyNotify d = filter->priv->modify_destroy;
2422
2423       filter->priv->modify_destroy = NULL;
2424       d (filter->priv->modify_data);
2425     }
2426
2427   filter->priv->modify_n_columns = n_columns;
2428   filter->priv->modify_types = g_new0 (GType, n_columns);
2429   memcpy (filter->priv->modify_types, types, sizeof (GType) * n_columns);
2430   filter->priv->modify_func = func;
2431   filter->priv->modify_data = data;
2432   filter->priv->modify_destroy = destroy;
2433
2434   filter->priv->modify_func_set = TRUE;
2435 }
2436
2437 /**
2438  * gtk_tree_model_filter_set_visible_column:
2439  * @filter: A #GtkTreeModelFilter.
2440  * @column: A #gint which is the column containing the visible information.
2441  *
2442  * Sets @column of the child_model to be the column where @filter should
2443  * look for visibility information. @columns should be a column of type
2444  * %G_TYPE_BOOLEAN, where %TRUE means that a row is visible, and %FALSE
2445  * if not.
2446  *
2447  * Since: 2.4
2448  */
2449 void
2450 gtk_tree_model_filter_set_visible_column (GtkTreeModelFilter *filter,
2451                                           gint column)
2452 {
2453   g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
2454   g_return_if_fail (column >= 0);
2455   g_return_if_fail (filter->priv->visible_method_set == FALSE);
2456
2457   filter->priv->visible_column = column;
2458
2459   filter->priv->visible_method_set = TRUE;
2460 }
2461
2462 /* conversion */
2463
2464 /**
2465  * gtk_tree_model_filter_convert_child_iter_to_iter:
2466  * @filter: A #GtkTreeModelFilter.
2467  * @filter_iter: An uninitialized #GtkTreeIter.
2468  * @child_iter: A valid #GtkTreeIter pointing to a row on the child model.
2469  *
2470  * Sets @filter_iter to point to the row in @filter that corresponds to the
2471  * row pointed at by @child_iter.
2472  *
2473  * Since: 2.4
2474  */
2475 void
2476 gtk_tree_model_filter_convert_child_iter_to_iter (GtkTreeModelFilter *filter,
2477                                                   GtkTreeIter        *filter_iter,
2478                                                   GtkTreeIter        *child_iter)
2479 {
2480   GtkTreePath *child_path, *path;
2481
2482   g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
2483   g_return_if_fail (filter->priv->child_model != NULL);
2484   g_return_if_fail (filter_iter != NULL);
2485   g_return_if_fail (child_iter != NULL);
2486
2487   filter_iter->stamp = 0;
2488
2489   child_path = gtk_tree_model_get_path (filter->priv->child_model, child_iter);
2490   g_return_if_fail (child_path != NULL);
2491
2492   path = gtk_tree_model_filter_convert_child_path_to_path (filter,
2493                                                            child_path);
2494   gtk_tree_path_free (child_path);
2495   g_return_if_fail (path != NULL);
2496
2497   gtk_tree_model_get_iter (GTK_TREE_MODEL (filter), filter_iter, path);
2498   gtk_tree_path_free (path);
2499 }
2500
2501 /**
2502  * gtk_tree_model_filter_convert_iter_to_child_iter:
2503  * @filter: A #GtkTreeModelFilter.
2504  * @child_iter: An uninitialized #GtkTreeIter.
2505  * @filter_iter: A valid #GtkTreeIter pointing to a row on @filter.
2506  *
2507  * Sets @child_iter to point to the row pointed to by @filter_iter.
2508  *
2509  * Since: 2.4
2510  */
2511 void
2512 gtk_tree_model_filter_convert_iter_to_child_iter (GtkTreeModelFilter *filter,
2513                                                   GtkTreeIter        *child_iter,
2514                                                   GtkTreeIter        *filter_iter)
2515 {
2516   g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
2517   g_return_if_fail (filter->priv->child_model != NULL);
2518   g_return_if_fail (child_iter != NULL);
2519   g_return_if_fail (filter_iter != NULL);
2520   g_return_if_fail (filter_iter->stamp == filter->priv->stamp);
2521
2522   if (GTK_TREE_MODEL_FILTER_CACHE_CHILD_ITERS (filter))
2523     {
2524       *child_iter = FILTER_ELT (filter_iter->user_data2)->iter;
2525     }
2526   else
2527     {
2528       GtkTreePath *path;
2529
2530       path = gtk_tree_model_filter_elt_get_path (filter_iter->user_data,
2531                                                  filter_iter->user_data2,
2532                                                  filter->priv->virtual_root);
2533       gtk_tree_model_get_iter (filter->priv->child_model, child_iter, path);
2534       gtk_tree_path_free (path);
2535     }
2536 }
2537
2538 static GtkTreePath *
2539 gtk_real_tree_model_filter_convert_child_path_to_path (GtkTreeModelFilter *filter,
2540                                                        GtkTreePath        *child_path,
2541                                                        gboolean            build_levels,
2542                                                        gboolean            fetch_childs)
2543 {
2544   gint *child_indices;
2545   GtkTreePath *retval;
2546   GtkTreePath *real_path;
2547   FilterLevel *level;
2548   FilterElt *tmp;
2549   gint i;
2550
2551   g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (filter), NULL);
2552   g_return_val_if_fail (filter->priv->child_model != NULL, NULL);
2553   g_return_val_if_fail (child_path != NULL, NULL);
2554
2555   if (!filter->priv->virtual_root)
2556     real_path = gtk_tree_path_copy (child_path);
2557   else
2558     real_path = gtk_tree_model_filter_remove_root (child_path,
2559                                                    filter->priv->virtual_root);
2560
2561   if (!real_path)
2562     return NULL;
2563
2564   retval = gtk_tree_path_new ();
2565   child_indices = gtk_tree_path_get_indices (real_path);
2566
2567   if (filter->priv->root == NULL && build_levels)
2568     gtk_tree_model_filter_build_level (filter, NULL, NULL);
2569   level = FILTER_LEVEL (filter->priv->root);
2570
2571   for (i = 0; i < gtk_tree_path_get_depth (real_path); i++)
2572     {
2573       gint j;
2574       gboolean found_child = FALSE;
2575
2576       if (!level)
2577         {
2578           gtk_tree_path_free (real_path);
2579           gtk_tree_path_free (retval);
2580           return NULL;
2581         }
2582
2583       tmp = bsearch_elt_with_offset (level->array, child_indices[i], &j);
2584       if (tmp)
2585         {
2586           gtk_tree_path_append_index (retval, j);
2587           if (!tmp->children && build_levels)
2588             gtk_tree_model_filter_build_level (filter, level, tmp);
2589           level = tmp->children;
2590           found_child = TRUE;
2591         }
2592
2593       if (!found_child && fetch_childs)
2594         {
2595           tmp = gtk_tree_model_filter_fetch_child (filter, level,
2596                                                    child_indices[i],
2597                                                    &j);
2598
2599           /* didn't find the child, let's try to bring it back */
2600           if (!tmp || tmp->offset != child_indices[i])
2601             {
2602               /* not there */
2603               gtk_tree_path_free (real_path);
2604               gtk_tree_path_free (retval);
2605               return NULL;
2606             }
2607
2608           gtk_tree_path_append_index (retval, j);
2609           if (!tmp->children && build_levels)
2610             gtk_tree_model_filter_build_level (filter, level, tmp);
2611           level = tmp->children;
2612           found_child = TRUE;
2613         }
2614       else if (!found_child && !fetch_childs)
2615         {
2616           /* no path */
2617           gtk_tree_path_free (real_path);
2618           gtk_tree_path_free (retval);
2619           return NULL;
2620         }
2621     }
2622
2623   gtk_tree_path_free (real_path);
2624   return retval;
2625 }
2626
2627 /**
2628  * gtk_tree_model_filter_convert_child_path_to_path:
2629  * @filter: A #GtkTreeModelFilter.
2630  * @child_path: A #GtkTreePath to convert.
2631  *
2632  * Converts @child_path to a path relative to @filter. That is, @child_path
2633  * points to a path in the child model. The rerturned path will point to the
2634  * same row in the filtered model. If @child_path isn't a valid path on the
2635  * child model, then %NULL is returned.
2636  *
2637  * Return value: A newly allocated #GtkTreePath, or %NULL.
2638  *
2639  * Since: 2.4
2640  */
2641 GtkTreePath *
2642 gtk_tree_model_filter_convert_child_path_to_path (GtkTreeModelFilter *filter,
2643                                                   GtkTreePath        *child_path)
2644 {
2645   /* this function does the sanity checks */
2646   return gtk_real_tree_model_filter_convert_child_path_to_path (filter,
2647                                                                 child_path,
2648                                                                 TRUE,
2649                                                                 TRUE);
2650 }
2651
2652 /**
2653  * gtk_tree_model_filter_convert_path_to_child_path:
2654  * @filter: A #GtkTreeModelFilter.
2655  * @filter_path: A #GtkTreePath to convert.
2656  *
2657  * Converts @filter_path to a path on the child model of @filter. That is,
2658  * @filter_path points to a location in @filter. The returned path will
2659  * point to the same location in the model not being filtered. If @filter_path
2660  * does not point to a location in the child model, %NULL is returned.
2661  *
2662  * Return value: A newly allocated #GtkTreePath, or %NULL.
2663  *
2664  * Since: 2.4
2665  */
2666 GtkTreePath *
2667 gtk_tree_model_filter_convert_path_to_child_path (GtkTreeModelFilter *filter,
2668                                                   GtkTreePath        *filter_path)
2669 {
2670   gint *filter_indices;
2671   GtkTreePath *retval;
2672   FilterLevel *level;
2673   gint i;
2674
2675   g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (filter), NULL);
2676   g_return_val_if_fail (filter->priv->child_model != NULL, NULL);
2677   g_return_val_if_fail (filter_path != NULL, NULL);
2678
2679   /* convert path */
2680   retval = gtk_tree_path_new ();
2681   filter_indices = gtk_tree_path_get_indices (filter_path);
2682   if (!filter->priv->root)
2683     gtk_tree_model_filter_build_level (filter, NULL, NULL);
2684   level = FILTER_LEVEL (filter->priv->root);
2685
2686   for (i = 0; i < gtk_tree_path_get_depth (filter_path); i++)
2687     {
2688       gint count = filter_indices[i];
2689
2690       if (!level || level->array->len <= filter_indices[i])
2691         {
2692           gtk_tree_path_free (retval);
2693           return NULL;
2694         }
2695
2696       if (g_array_index (level->array, FilterElt, count).children == NULL)
2697         gtk_tree_model_filter_build_level (filter, level, &g_array_index (level->array, FilterElt, count));
2698
2699       if (!level || level->array->len <= filter_indices[i])
2700         {
2701           gtk_tree_path_free (retval);
2702           return NULL;
2703         }
2704
2705       gtk_tree_path_append_index (retval, g_array_index (level->array, FilterElt, count).offset);
2706       level = g_array_index (level->array, FilterElt, count).children;
2707     }
2708
2709   /* apply vroot */
2710
2711   if (filter->priv->virtual_root)
2712     {
2713       GtkTreePath *real_retval;
2714
2715       real_retval = gtk_tree_model_filter_add_root (retval,
2716                                                     filter->priv->virtual_root);
2717       gtk_tree_path_free (retval);
2718
2719       return real_retval;
2720     }
2721
2722   return retval;
2723 }
2724
2725 static gboolean
2726 gtk_tree_model_filter_refilter_helper (GtkTreeModel *model,
2727                                        GtkTreePath  *path,
2728                                        GtkTreeIter  *iter,
2729                                        gpointer      data)
2730 {
2731   /* evil, don't try this at home, but certainly speeds things up */
2732   gtk_tree_model_filter_row_changed (model, path, iter, data);
2733
2734   return FALSE;
2735 }
2736
2737 /**
2738  * gtk_tree_model_filter_refilter:
2739  * @filter: A #GtkTreeModelFilter.
2740  *
2741  * Emits ::row_changed for each row in the child model, which causes
2742  * the filter to re-evaluate whether a row is visible or not.
2743  *
2744  * Since: 2.4
2745  */
2746 void
2747 gtk_tree_model_filter_refilter (GtkTreeModelFilter *filter)
2748 {
2749   g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
2750
2751   /* S L O W */
2752   gtk_tree_model_foreach (filter->priv->child_model,
2753                           gtk_tree_model_filter_refilter_helper,
2754                           filter);
2755 }
2756
2757 /**
2758  * gtk_tree_model_filter_clear_cache:
2759  * @filter: A #GtkTreeModelFilter.
2760  *
2761  * This function should almost never be called. It clears the @filter
2762  * of any cached iterators that haven't been reffed with
2763  * gtk_tree_model_ref_node(). This might be useful if the child model
2764  * being filtered is static (and doesn't change often) and there has been
2765  * a lot of unreffed access to nodes. As a side effect of this function,
2766  * all unreffed itters will be invalid.
2767  *
2768  * Since: 2.4
2769  */
2770 void
2771 gtk_tree_model_filter_clear_cache (GtkTreeModelFilter *filter)
2772 {
2773   g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
2774
2775   if (filter->priv->zero_ref_count)
2776     gtk_tree_model_filter_clear_cache_helper (filter,
2777                                               FILTER_LEVEL (filter->priv->root));
2778 }