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