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