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