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