]> Pileus Git - ~andy/gtk/blob - gtk/gtktreemodelfilter.c
Fix includes.
[~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 program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation; either version 2 of the
8  * License, or (at your option) any later version.
9  *
10  * This program 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  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public
16  * License along with this program; 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;
1143   GtkTreePath *real_path;
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     return;
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 done:
1330   if (free_c_path)
1331     gtk_tree_path_free (c_path);
1332 }
1333
1334 static void
1335 gtk_tree_model_filter_row_has_child_toggled (GtkTreeModel *c_model,
1336                                              GtkTreePath  *c_path,
1337                                              GtkTreeIter  *c_iter,
1338                                              gpointer      data)
1339 {
1340   GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (data);
1341   GtkTreePath *path;
1342   GtkTreeIter iter;
1343
1344   g_return_if_fail (c_path != NULL && c_iter != NULL);
1345
1346   /* FIXME: does this code work? */
1347
1348   if (!gtk_tree_model_filter_visible (filter, c_iter))
1349     return;
1350
1351   path = gtk_real_tree_model_filter_convert_child_path_to_path (filter,
1352                                                                 c_path,
1353                                                                 FALSE,
1354                                                                 TRUE);
1355   if (!path)
1356     return;
1357
1358   gtk_tree_model_get_iter (GTK_TREE_MODEL (data), &iter, path);
1359   gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (data), path, &iter);
1360
1361   gtk_tree_path_free (path);
1362 }
1363
1364 static void
1365 gtk_tree_model_filter_row_deleted (GtkTreeModel *c_model,
1366                                    GtkTreePath  *c_path,
1367                                    gpointer      data)
1368 {
1369   GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (data);
1370   GtkTreePath *path;
1371   GtkTreeIter iter;
1372   FilterElt *elt;
1373   FilterLevel *level;
1374   gint offset;
1375   gboolean emit_signal = TRUE;
1376   gint i;
1377
1378   g_return_if_fail (c_path != NULL);
1379
1380   /* special case the deletion of an ancestor of the virtual root */
1381   if (filter->priv->virtual_root &&
1382       (gtk_tree_path_is_ancestor (c_path, filter->priv->virtual_root) ||
1383        !gtk_tree_path_compare (c_path, filter->priv->virtual_root)))
1384     {
1385       gint i;
1386       GtkTreePath *path;
1387       FilterLevel *level = FILTER_LEVEL (filter->priv->root);
1388
1389       if (!level)
1390         return;
1391
1392       /* remove everything in the filter model
1393        *
1394        * For now, we just iterate over the root level and emit a
1395        * row_deleted for each FilterElt. Not sure if this is correct.
1396        */
1397
1398       gtk_tree_model_filter_increment_stamp (filter);
1399       path = gtk_tree_path_new ();
1400       gtk_tree_path_append_index (path, 0);
1401
1402       for (i = 0; i < level->array->len; i++)
1403         gtk_tree_model_row_deleted (GTK_TREE_MODEL (data), path);
1404
1405       gtk_tree_path_free (path);
1406       gtk_tree_model_filter_free_level (filter, filter->priv->root);
1407
1408       return;
1409     }
1410
1411   /* fixup virtual root */
1412   if (filter->priv->virtual_root)
1413     {
1414       if (gtk_tree_path_get_depth (filter->priv->virtual_root) >=
1415           gtk_tree_path_get_depth (c_path))
1416         {
1417           gint level;
1418           gint *v_indices, *c_indices;
1419
1420           level = gtk_tree_path_get_depth (c_path) - 1;
1421           v_indices = gtk_tree_path_get_indices (filter->priv->virtual_root);
1422           c_indices = gtk_tree_path_get_indices (c_path);
1423
1424           if (v_indices[level] > c_indices[level])
1425             (v_indices[level])--;
1426         }
1427     }
1428
1429   path = gtk_real_tree_model_filter_convert_child_path_to_path (filter,
1430                                                                 c_path,
1431                                                                 FALSE,
1432                                                                 FALSE);
1433   if (!path)
1434     {
1435       path = gtk_real_tree_model_filter_convert_child_path_to_path (filter,
1436                                                                     c_path,
1437                                                                     FALSE,
1438                                                                     TRUE);
1439
1440       if (!path)
1441         {
1442           /* fixup the offsets */
1443           GtkTreePath *real_path;
1444
1445           if (!filter->priv->root)
1446             return;
1447
1448           level = FILTER_LEVEL (filter->priv->root);
1449
1450           /* subtract vroot if necessary */
1451           if (filter->priv->virtual_root)
1452             {
1453               real_path = gtk_tree_model_filter_remove_root (c_path,
1454                                                              filter->priv->virtual_root);
1455               /* we don't handle this */
1456               if (!real_path)
1457                 return;
1458             }
1459           else
1460             real_path = gtk_tree_path_copy (c_path);
1461
1462           i = 0;
1463           if (gtk_tree_path_get_depth (real_path) - 1 >= 1)
1464             {
1465               while (i < gtk_tree_path_get_depth (real_path) - 1)
1466                 {
1467                   gint j;
1468
1469                   if (!level)
1470                     {
1471                       /* we don't cover this */
1472                       gtk_tree_path_free (real_path);
1473                       return;
1474                     }
1475
1476                   elt = bsearch_elt_with_offset (level->array,
1477                                                  gtk_tree_path_get_indices (real_path)[i],
1478                                                  &j);
1479
1480                   if (!elt || !elt->children)
1481                     {
1482                       /* parent is filtered out, so no level */
1483                       gtk_tree_path_free (real_path);
1484                       return;
1485                     }
1486
1487                   level = elt->children;
1488                   i++;
1489                 }
1490             }
1491
1492           offset = gtk_tree_path_get_indices (real_path)[gtk_tree_path_get_depth (real_path) - 1];
1493           gtk_tree_path_free (real_path);
1494
1495           if (!level)
1496             return;
1497
1498           /* we need:
1499            * - the offset of the removed item
1500            * - the level
1501            */
1502           for (i = 0; i < level->array->len; i++)
1503             {
1504               elt = &g_array_index (level->array, FilterElt, i);
1505               if (elt->offset > offset)
1506                 elt->offset--;
1507               if (elt->children)
1508                 elt->children->parent_elt = elt;
1509             }
1510
1511           return;
1512         }
1513
1514       emit_signal = FALSE;
1515     }
1516
1517   gtk_tree_model_get_iter (GTK_TREE_MODEL (data), &iter, path);
1518
1519   level = FILTER_LEVEL (iter.user_data);
1520   elt = FILTER_ELT (iter.user_data2);
1521   offset = elt->offset;
1522
1523   if (!level->parent_level && elt->visible)
1524     filter->priv->root_level_visible--;
1525
1526   if (emit_signal)
1527     {
1528       if (level->ref_count == 0 && level != filter->priv->root)
1529         {
1530           gtk_tree_model_filter_increment_stamp (filter);
1531           gtk_tree_model_row_deleted (GTK_TREE_MODEL (data), path);
1532
1533           gtk_tree_path_free (path);
1534           return;
1535         }
1536
1537       gtk_tree_model_filter_increment_stamp (filter);
1538       gtk_tree_model_row_deleted (GTK_TREE_MODEL (data), path);
1539       iter.stamp = filter->priv->stamp;
1540
1541       while (elt->ref_count > 0)
1542         gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (data), &iter,
1543                                                FALSE);
1544     }
1545
1546   if (level->array->len == 1)
1547     {
1548       /* kill level */
1549       gtk_tree_model_filter_free_level (filter, level);
1550     }
1551   else
1552     {
1553       FilterElt *tmp;
1554
1555       /* remove the row */
1556       tmp = bsearch_elt_with_offset (level->array, elt->offset, &i);
1557
1558       offset = tmp->offset;
1559       g_array_remove_index (level->array, i);
1560
1561       for (i = MAX (--i, 0); i < level->array->len; i++)
1562         {
1563           elt = &g_array_index (level->array, FilterElt, i);
1564           if (elt->offset > offset)
1565             elt->offset--;
1566           if (elt->children)
1567             elt->children->parent_elt = elt;
1568         }
1569     }
1570
1571   gtk_tree_path_free (path);
1572 }
1573
1574 static void
1575 gtk_tree_model_filter_rows_reordered (GtkTreeModel *c_model,
1576                                       GtkTreePath  *c_path,
1577                                       GtkTreeIter  *c_iter,
1578                                       gint         *new_order,
1579                                       gpointer      data)
1580 {
1581   FilterElt *elt;
1582   FilterLevel *level;
1583   GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (data);
1584
1585   GtkTreePath *path;
1586   GtkTreeIter iter;
1587
1588   gint *tmp_array;
1589   gint i, j, elt_count;
1590   gint length;
1591
1592   GArray *new_array;
1593
1594   g_return_if_fail (new_order != NULL);
1595
1596   if (c_path == NULL || gtk_tree_path_get_indices (c_path) == NULL)
1597     {
1598       if (!filter->priv->root)
1599         return;
1600
1601       length = gtk_tree_model_iter_n_children (c_model, NULL);
1602
1603       if (filter->priv->virtual_root)
1604         {
1605           gint new_pos = -1;
1606
1607           /* reorder root level of path */
1608           for (i = 0; i < length; i++)
1609             if (new_order[i] == gtk_tree_path_get_indices (filter->priv->virtual_root)[0])
1610               new_pos = i;
1611
1612           if (new_pos < 0)
1613             return;
1614
1615           gtk_tree_path_get_indices (filter->priv->virtual_root)[0] = new_pos;
1616           return;
1617         }
1618
1619       path = gtk_tree_path_new ();
1620       level = FILTER_LEVEL (filter->priv->root);
1621     }
1622   else
1623     {
1624       GtkTreeIter child_iter;
1625
1626       /* virtual root anchor reordering */
1627       if (filter->priv->virtual_root &&
1628           gtk_tree_path_get_depth (c_path) <
1629           gtk_tree_path_get_depth (filter->priv->virtual_root))
1630         {
1631           gint new_pos = -1;
1632           gint length;
1633           gint level;
1634           GtkTreeIter real_c_iter;
1635
1636           level = gtk_tree_path_get_depth (c_path);
1637
1638           if (c_iter)
1639             real_c_iter = *c_iter;
1640           else
1641             gtk_tree_model_get_iter (c_model, &real_c_iter, c_path);
1642
1643           length = gtk_tree_model_iter_n_children (c_model, &real_c_iter);
1644
1645           for (i = 0; i < length; i++)
1646             if (new_order[i] == gtk_tree_path_get_indices (filter->priv->virtual_root)[level])
1647               new_pos = i;
1648
1649           if (new_pos < 0)
1650             return;
1651
1652           gtk_tree_path_get_indices (filter->priv->virtual_root)[level] = new_pos;
1653           return;
1654         }
1655
1656       path = gtk_real_tree_model_filter_convert_child_path_to_path (filter,
1657                                                                     c_path,
1658                                                                     FALSE,
1659                                                                     FALSE);
1660       if (!path && filter->priv->virtual_root &&
1661           gtk_tree_path_compare (c_path, filter->priv->virtual_root))
1662         return;
1663
1664       if (!path && !filter->priv->virtual_root)
1665         return;
1666
1667       if (!path)
1668         {
1669           /* root level mode */
1670           if (!c_iter)
1671             gtk_tree_model_get_iter (c_model, c_iter, c_path);
1672           length = gtk_tree_model_iter_n_children (c_model, c_iter);
1673           path = gtk_tree_path_new ();
1674           level = FILTER_LEVEL (filter->priv->root);
1675         }
1676       else
1677         {
1678           gtk_tree_model_get_iter (GTK_TREE_MODEL (data), &iter, path);
1679
1680           level = FILTER_LEVEL (iter.user_data);
1681           elt = FILTER_ELT (iter.user_data2);
1682
1683           if (!elt->children)
1684             {
1685               gtk_tree_path_free (path);
1686               return;
1687             }
1688
1689           level = elt->children;
1690
1691           gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (filter), &child_iter, &iter);
1692           length = gtk_tree_model_iter_n_children (c_model, &child_iter);
1693         }
1694     }
1695
1696   if (level->array->len < 1)
1697     return;
1698
1699   /* NOTE: we do not bail out here if level->array->len < 2 like
1700    * GtkTreeModelSort does. This because we do some special tricky
1701    * reordering.
1702    */
1703
1704   /* construct a new array */
1705   new_array = g_array_sized_new (FALSE, FALSE, sizeof (FilterElt),
1706                                  level->array->len);
1707   tmp_array = g_new (gint, level->array->len);
1708
1709   for (i = 0, elt_count = 0; i < length; i++)
1710     {
1711       FilterElt *e = NULL;
1712       gint old_offset = -1;
1713
1714       for (j = 0; j < level->array->len; j++)
1715         if (g_array_index (level->array, FilterElt, j).offset == new_order[i])
1716           {
1717             e = &g_array_index (level->array, FilterElt, j);
1718             old_offset = j;
1719             break;
1720           }
1721
1722       if (!e)
1723         continue;
1724
1725       tmp_array[elt_count] = old_offset;
1726       g_array_append_val (new_array, *e);
1727       g_array_index (new_array, FilterElt, elt_count).offset = i;
1728       elt_count++;
1729     }
1730
1731   g_array_free (level->array, TRUE);
1732   level->array = new_array;
1733
1734   /* fix up stuff */
1735   for (i = 0; i < level->array->len; i++)
1736     {
1737       FilterElt *e = &g_array_index (level->array, FilterElt, i);
1738       if (e->children)
1739         e->children->parent_elt = e;
1740     }
1741
1742   /* emit rows_reordered */
1743   if (!gtk_tree_path_get_indices (path))
1744     gtk_tree_model_rows_reordered (GTK_TREE_MODEL (data), path, NULL,
1745                                    tmp_array);
1746   else
1747     gtk_tree_model_rows_reordered (GTK_TREE_MODEL (data), path, &iter,
1748                                    tmp_array);
1749
1750   /* done */
1751   g_free (tmp_array);
1752   gtk_tree_path_free (path);
1753 }
1754
1755 /* TreeModelIface implementation */
1756 static guint
1757 gtk_tree_model_filter_get_flags (GtkTreeModel *model)
1758 {
1759   g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), 0);
1760
1761   return 0;
1762 }
1763
1764 static gint
1765 gtk_tree_model_filter_get_n_columns (GtkTreeModel *model)
1766 {
1767   GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
1768
1769   g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), 0);
1770   g_return_val_if_fail (filter->priv->child_model != NULL, 0);
1771
1772   if (filter->priv->child_model == NULL)
1773     return 0;
1774
1775   /* so we can't modify the modify func after this ... */
1776   filter->priv->modify_func_set = TRUE;
1777
1778   if (filter->priv->modify_n_columns > 0)
1779     return filter->priv->modify_n_columns;
1780
1781   return gtk_tree_model_get_n_columns (filter->priv->child_model);
1782 }
1783
1784 static GType
1785 gtk_tree_model_filter_get_column_type (GtkTreeModel *model,
1786                                        gint          index)
1787 {
1788   GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
1789
1790   g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), G_TYPE_INVALID);
1791   g_return_val_if_fail (filter->priv->child_model != NULL, G_TYPE_INVALID);
1792
1793   /* so we can't modify the modify func after this ... */
1794   filter->priv->modify_func_set = TRUE;
1795
1796   if (filter->priv->modify_types)
1797     {
1798       g_return_val_if_fail (index < filter->priv->modify_n_columns, G_TYPE_INVALID);
1799
1800       return filter->priv->modify_types[index];
1801     }
1802
1803   return gtk_tree_model_get_column_type (filter->priv->child_model, index);
1804 }
1805
1806 static gboolean
1807 gtk_tree_model_filter_get_iter (GtkTreeModel *model,
1808                                 GtkTreeIter  *iter,
1809                                 GtkTreePath  *path)
1810 {
1811   GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
1812   gint *indices;
1813   FilterLevel *level;
1814   gint depth, i;
1815
1816   g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
1817   g_return_val_if_fail (filter->priv->child_model != NULL, FALSE);
1818
1819   indices = gtk_tree_path_get_indices (path);
1820
1821   if (filter->priv->root == NULL)
1822     gtk_tree_model_filter_build_level (filter, NULL, NULL);
1823   level = FILTER_LEVEL (filter->priv->root);
1824
1825   depth = gtk_tree_path_get_depth (path);
1826   if (!depth)
1827     {
1828       iter->stamp = 0;
1829       return FALSE;
1830     }
1831
1832   for (i = 0; i < depth - 1; i++)
1833     {
1834       if (!level || indices[i] >= level->array->len)
1835         {
1836           return FALSE;
1837         }
1838
1839       if (!g_array_index (level->array, FilterElt, indices[i]).children)
1840         gtk_tree_model_filter_build_level (filter, level,
1841                                            &g_array_index (level->array,
1842                                                            FilterElt,
1843                                                            indices[i]));
1844       level = g_array_index (level->array, FilterElt, indices[i]).children;
1845     }
1846
1847   if (!level || indices[i] >= level->array->len)
1848     {
1849       iter->stamp = 0;
1850       return FALSE;
1851     }
1852
1853   iter->stamp = filter->priv->stamp;
1854   iter->user_data = level;
1855   iter->user_data2 = &g_array_index (level->array, FilterElt,
1856                                      indices[depth - 1]);
1857
1858   return TRUE;
1859 }
1860
1861 static GtkTreePath *
1862 gtk_tree_model_filter_get_path (GtkTreeModel *model,
1863                                 GtkTreeIter  *iter)
1864 {
1865   GtkTreePath *retval;
1866   FilterLevel *level;
1867   FilterElt *elt;
1868
1869   g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), NULL);
1870   g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL, NULL);
1871   g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->stamp == iter->stamp, NULL);
1872
1873   retval = gtk_tree_path_new ();
1874   level = iter->user_data;
1875   elt = iter->user_data2;
1876
1877   while (level)
1878     {
1879       gtk_tree_path_prepend_index (retval,
1880                                    elt - FILTER_ELT (level->array->data));
1881       elt = level->parent_elt;
1882       level = level->parent_level;
1883     }
1884
1885   return retval;
1886 }
1887
1888 static void
1889 gtk_tree_model_filter_get_value (GtkTreeModel *model,
1890                                  GtkTreeIter  *iter,
1891                                  gint          column,
1892                                  GValue       *value)
1893 {
1894   GtkTreeIter child_iter;
1895   GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (model);
1896
1897   g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (model));
1898   g_return_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL);
1899   g_return_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->stamp == iter->stamp);
1900
1901   if (filter->priv->modify_func)
1902     {
1903       g_return_if_fail (column < filter->priv->modify_n_columns);
1904
1905       g_value_init (value, filter->priv->modify_types[column]);
1906       filter->priv->modify_func (model,
1907                            iter,
1908                            value,
1909                            column,
1910                            filter->priv->modify_data);
1911
1912       return;
1913     }
1914
1915   gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_iter, iter);
1916   gtk_tree_model_get_value (GTK_TREE_MODEL_FILTER (model)->priv->child_model,
1917                             &child_iter, column, value);
1918 }
1919
1920 static gboolean
1921 gtk_tree_model_filter_iter_next (GtkTreeModel *model,
1922                                  GtkTreeIter  *iter)
1923 {
1924   FilterLevel *level;
1925   FilterElt *elt;
1926
1927   g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
1928   g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL, FALSE);
1929   g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->stamp == iter->stamp, FALSE);
1930
1931   level = iter->user_data;
1932   elt = iter->user_data2;
1933
1934   if (elt - FILTER_ELT (level->array->data) >= level->array->len - 1)
1935     {
1936       iter->stamp = 0;
1937       return FALSE;
1938     }
1939
1940   iter->user_data2 = elt + 1;
1941
1942   return TRUE;
1943 }
1944
1945 static gboolean
1946 gtk_tree_model_filter_iter_children (GtkTreeModel *model,
1947                                      GtkTreeIter  *iter,
1948                                      GtkTreeIter  *parent)
1949 {
1950   GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
1951   FilterLevel *level;
1952
1953   iter->stamp = 0;
1954   g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
1955   g_return_val_if_fail (filter->priv->child_model != NULL, FALSE);
1956   if (parent)
1957     g_return_val_if_fail (filter->priv->stamp == parent->stamp, FALSE);
1958
1959   if (!parent)
1960     {
1961       if (!filter->priv->root)
1962         gtk_tree_model_filter_build_level (filter, NULL, NULL);
1963       if (!filter->priv->root)
1964         return FALSE;
1965
1966       level = filter->priv->root;
1967       iter->stamp = filter->priv->stamp;
1968       iter->user_data = level;
1969       iter->user_data2 = level->array->data;
1970     }
1971   else
1972     {
1973       if (FILTER_ELT (parent->user_data2)->children == NULL)
1974         gtk_tree_model_filter_build_level (filter,
1975                                            FILTER_LEVEL (parent->user_data),
1976                                            FILTER_ELT (parent->user_data2));
1977       if (FILTER_ELT (parent->user_data2)->children == NULL)
1978         return FALSE;
1979
1980       /* empty array? */
1981       if (FILTER_ELT (parent->user_data2)->children->array->len <= 0)
1982         return FALSE;
1983
1984       iter->stamp = filter->priv->stamp;
1985       iter->user_data = FILTER_ELT (parent->user_data2)->children;
1986       iter->user_data2 = FILTER_LEVEL (iter->user_data)->array->data;
1987     }
1988
1989   return TRUE;
1990 }
1991
1992 static gboolean
1993 gtk_tree_model_filter_iter_has_child (GtkTreeModel *model,
1994                                       GtkTreeIter  *iter)
1995 {
1996   GtkTreeIter child_iter;
1997   GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
1998   FilterElt *elt;
1999
2000   g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
2001   g_return_val_if_fail (filter->priv->child_model != NULL, FALSE);
2002   g_return_val_if_fail (filter->priv->stamp == iter->stamp, FALSE);
2003
2004   filter = GTK_TREE_MODEL_FILTER (model);
2005
2006   gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_iter, iter);
2007   elt = FILTER_ELT (iter->user_data2);
2008
2009   /* we need to build the level to check if not all children are filtered
2010    * out
2011    */
2012   if (!elt->children
2013       && gtk_tree_model_iter_has_child (filter->priv->child_model, &child_iter))
2014     gtk_tree_model_filter_build_level (filter, FILTER_LEVEL (iter->user_data),
2015                                        elt);
2016
2017   /* FIXME: we should prolly count the visible nodes here, just like in
2018    * _iter_n_children.
2019    */
2020   if (elt->children && elt->children->array->len > 0)
2021     return TRUE;
2022
2023   return FALSE;
2024 }
2025
2026 static gint
2027 gtk_tree_model_filter_iter_n_children (GtkTreeModel *model,
2028                                        GtkTreeIter  *iter)
2029 {
2030   GtkTreeIter child_iter;
2031   GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
2032   FilterElt *elt;
2033
2034   g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), 0);
2035   g_return_val_if_fail (filter->priv->child_model != NULL, 0);
2036   if (iter)
2037     g_return_val_if_fail (filter->priv->stamp == iter->stamp, 0);
2038
2039   if (!iter)
2040     {
2041       if (!filter->priv->root)
2042         gtk_tree_model_filter_build_level (filter, NULL, NULL);
2043
2044       /* count visible nodes */
2045       return filter->priv->root_level_visible;
2046     }
2047
2048   elt = FILTER_ELT (iter->user_data2);
2049   gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_iter, iter);
2050
2051   if (!elt->children &&
2052       gtk_tree_model_iter_has_child (filter->priv->child_model, &child_iter))
2053     gtk_tree_model_filter_build_level (filter,
2054                                        FILTER_LEVEL (iter->user_data),
2055                                        elt);
2056
2057   if (elt->children && elt->children->array->len)
2058     {
2059       int i = 0;
2060       int count = 0;
2061       GArray *a = elt->children->array;
2062
2063       /* count visible nodes */
2064       for (i = 0; i < a->len; i++)
2065         if (g_array_index (a, FilterElt, i).visible)
2066           count++;
2067
2068       return count;
2069     }
2070
2071   return 0;
2072 }
2073
2074 static gboolean
2075 gtk_tree_model_filter_iter_nth_child (GtkTreeModel *model,
2076                                       GtkTreeIter  *iter,
2077                                       GtkTreeIter  *parent,
2078                                       gint          n)
2079 {
2080   FilterLevel *level;
2081   GtkTreeIter children;
2082
2083   g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
2084   if (parent)
2085     g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->stamp == parent->stamp, FALSE);
2086
2087   /* use this instead of has_Child to force us to build the level, if needed */
2088   if (gtk_tree_model_filter_iter_children (model, &children, parent) == FALSE)
2089     {
2090       iter->stamp = 0;
2091       return FALSE;
2092     }
2093
2094   level = children.user_data;
2095   if (n >= level->array->len)
2096     {
2097       iter->stamp = 0;
2098       return FALSE;
2099     }
2100
2101   iter->stamp = GTK_TREE_MODEL_FILTER (model)->priv->stamp;
2102   iter->user_data = level;
2103   iter->user_data2 = &g_array_index (level->array, FilterElt, n);
2104
2105   return TRUE;
2106 }
2107
2108 static gboolean
2109 gtk_tree_model_filter_iter_parent (GtkTreeModel *model,
2110                                    GtkTreeIter  *iter,
2111                                    GtkTreeIter  *child)
2112 {
2113   FilterLevel *level;
2114
2115   iter->stamp = 0;
2116   g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), FALSE);
2117   g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL, FALSE);
2118   g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->stamp == child->stamp, FALSE);
2119
2120   level = child->user_data;
2121
2122   if (level->parent_level)
2123     {
2124       iter->stamp = GTK_TREE_MODEL_FILTER (model)->priv->stamp;
2125       iter->user_data = level->parent_level;
2126       iter->user_data2 = level->parent_elt;
2127
2128       return TRUE;
2129     }
2130
2131   return FALSE;
2132 }
2133
2134 static void
2135 gtk_tree_model_filter_ref_node (GtkTreeModel *model,
2136                                 GtkTreeIter  *iter)
2137 {
2138   GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
2139   GtkTreeIter child_iter;
2140   FilterLevel *level;
2141   FilterElt *elt;
2142
2143   g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (model));
2144   g_return_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL);
2145   g_return_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->stamp == iter->stamp);
2146
2147   gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_iter, iter);
2148
2149   gtk_tree_model_ref_node (filter->priv->child_model, &child_iter);
2150
2151   level = iter->user_data;
2152   elt = iter->user_data2;
2153
2154   elt->ref_count++;
2155   level->ref_count++;
2156   if (level->ref_count == 1)
2157     {
2158       FilterLevel *parent_level = level->parent_level;
2159       FilterElt *parent_elt = level->parent_elt;
2160
2161       /* we were at zero -- time to decrease the zero_ref_count val */
2162       do
2163         {
2164           if (parent_elt)
2165             parent_elt->zero_ref_count--;
2166
2167           if (parent_level)
2168             {
2169               parent_elt = parent_level->parent_elt;
2170               parent_level = parent_level->parent_level;
2171             }
2172         }
2173       while (parent_level);
2174       filter->priv->zero_ref_count--;
2175     }
2176 }
2177
2178 static void
2179 gtk_tree_model_filter_unref_node (GtkTreeModel *model,
2180                                   GtkTreeIter  *iter)
2181 {
2182   gtk_tree_model_filter_real_unref_node (model, iter, TRUE);
2183 }
2184
2185 static void
2186 gtk_tree_model_filter_real_unref_node (GtkTreeModel *model,
2187                                        GtkTreeIter  *iter,
2188                                        gboolean      propagate_unref)
2189 {
2190   GtkTreeModelFilter *filter = (GtkTreeModelFilter *)model;
2191   FilterLevel *level;
2192   FilterElt *elt;
2193
2194   g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (model));
2195   g_return_if_fail (filter->priv->child_model != NULL);
2196   g_return_if_fail (filter->priv->stamp == iter->stamp);
2197
2198   if (propagate_unref)
2199     {
2200       GtkTreeIter child_iter;
2201       gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_iter, iter);
2202       gtk_tree_model_unref_node (filter->priv->child_model, &child_iter);
2203     }
2204
2205   level = iter->user_data;
2206   elt = iter->user_data2;
2207
2208   g_return_if_fail (elt->ref_count > 0);
2209
2210   elt->ref_count--;
2211   level->ref_count--;
2212   if (level->ref_count == 0)
2213     {
2214       FilterLevel *parent_level = level->parent_level;
2215       FilterElt *parent_elt = level->parent_elt;
2216
2217       /* we are at zero -- time to increase the zero_ref_count val */
2218       while (parent_level)
2219         {
2220           parent_elt->zero_ref_count++;
2221
2222           parent_elt = parent_level->parent_elt;
2223           parent_level = parent_level->parent_level;
2224         }
2225       filter->priv->zero_ref_count++;
2226     }
2227 }
2228
2229 /* bits and pieces */
2230 static void
2231 gtk_tree_model_filter_set_model (GtkTreeModelFilter *filter,
2232                                  GtkTreeModel       *child_model)
2233 {
2234   g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
2235
2236   if (filter->priv->child_model)
2237     {
2238       g_signal_handler_disconnect (G_OBJECT (filter->priv->child_model),
2239                                    filter->priv->changed_id);
2240       g_signal_handler_disconnect (G_OBJECT (filter->priv->child_model),
2241                                    filter->priv->inserted_id);
2242       g_signal_handler_disconnect (G_OBJECT (filter->priv->child_model),
2243                                    filter->priv->has_child_toggled_id);
2244       g_signal_handler_disconnect (G_OBJECT (filter->priv->child_model),
2245                                    filter->priv->deleted_id);
2246       g_signal_handler_disconnect (G_OBJECT (filter->priv->child_model),
2247                                    filter->priv->reordered_id);
2248
2249       /* reset our state */
2250       if (filter->priv->root)
2251         gtk_tree_model_filter_free_level (filter, filter->priv->root);
2252
2253       filter->priv->root = NULL;
2254       g_object_unref (G_OBJECT (filter->priv->child_model));
2255       filter->priv->visible_column = -1;
2256       /* FIXME: destroy more crack here? the funcs? */
2257     }
2258
2259   filter->priv->child_model = child_model;
2260
2261   if (child_model)
2262     {
2263       g_object_ref (G_OBJECT (filter->priv->child_model));
2264       filter->priv->changed_id =
2265         g_signal_connect (child_model, "row_changed",
2266                           G_CALLBACK (gtk_tree_model_filter_row_changed),
2267                           filter);
2268       filter->priv->inserted_id =
2269         g_signal_connect (child_model, "row_inserted",
2270                           G_CALLBACK (gtk_tree_model_filter_row_inserted),
2271                           filter);
2272       filter->priv->has_child_toggled_id =
2273         g_signal_connect (child_model, "row_has_child_toggled",
2274                           G_CALLBACK (gtk_tree_model_filter_row_has_child_toggled),
2275                           filter);
2276       filter->priv->deleted_id =
2277         g_signal_connect (child_model, "row_deleted",
2278                           G_CALLBACK (gtk_tree_model_filter_row_deleted),
2279                           filter);
2280       filter->priv->reordered_id =
2281         g_signal_connect (child_model, "rows_reordered",
2282                           G_CALLBACK (gtk_tree_model_filter_rows_reordered),
2283                           filter);
2284
2285       filter->priv->child_flags = gtk_tree_model_get_flags (child_model);
2286       filter->priv->stamp = g_random_int ();
2287     }
2288 }
2289
2290 static void
2291 gtk_tree_model_filter_set_root (GtkTreeModelFilter *filter,
2292                                 GtkTreePath        *root)
2293 {
2294   g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
2295
2296   if (!root)
2297     filter->priv->virtual_root = NULL;
2298   else
2299     filter->priv->virtual_root = gtk_tree_path_copy (root);
2300 }
2301
2302 /* public API */
2303
2304 /**
2305  * gtk_tree_model_filter_new:
2306  * @child_model: A #GtkTreeModel.
2307  * @root: A #GtkTreePath or %NULL.
2308  *
2309  * Creates a new #GtkTreeModel, with @child_model as the child_model
2310  * and @root as the virtual root.
2311  *
2312  * Return value: A new #GtkTreeModel.
2313  *
2314  * Since: 2.4
2315  */
2316 GtkTreeModel *
2317 gtk_tree_model_filter_new (GtkTreeModel *child_model,
2318                            GtkTreePath  *root)
2319 {
2320   GtkTreeModel *retval;
2321
2322   g_return_val_if_fail (GTK_IS_TREE_MODEL (child_model), NULL);
2323
2324   retval = GTK_TREE_MODEL (g_object_new (gtk_tree_model_filter_get_type (), NULL));
2325
2326   gtk_tree_model_filter_set_model (GTK_TREE_MODEL_FILTER (retval),
2327                                    child_model);
2328   gtk_tree_model_filter_set_root (GTK_TREE_MODEL_FILTER (retval), root);
2329
2330   return retval;
2331 }
2332
2333 /**
2334  * gtk_tree_model_filter_get_model:
2335  * @filter: A #GtkTreeModelFilter.
2336  *
2337  * Returns a pointer to the child model of @filter.
2338  *
2339  * Return value: A pointer to a #GtkTreeModel.
2340  *
2341  * Since: 2.4
2342  */
2343 GtkTreeModel *
2344 gtk_tree_model_filter_get_model (GtkTreeModelFilter *filter)
2345 {
2346   g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (filter), NULL);
2347
2348   return filter->priv->child_model;
2349 }
2350
2351 /**
2352  * gtk_tree_model_filter_set_visible_func:
2353  * @filter: A #GtkTreeModelFilter.
2354  * @func: A #GtkTreeModelFilterVisibleFunc, the visible function.
2355  * @data: User data to pass to the visible function, or %NULL.
2356  * @destroy: Destroy notifier of @data, or %NULL.
2357  *
2358  * Sets the visible function used when filtering the @filter to be @func. The
2359  * function should return %TRUE if the given row should be visible and
2360  * %FALSE otherwise.
2361  *
2362  * Since: 2.4
2363  */
2364 void
2365 gtk_tree_model_filter_set_visible_func (GtkTreeModelFilter            *filter,
2366                                         GtkTreeModelFilterVisibleFunc  func,
2367                                         gpointer                       data,
2368                                         GtkDestroyNotify               destroy)
2369 {
2370   g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
2371   g_return_if_fail (func != NULL);
2372   g_return_if_fail (filter->priv->visible_method_set == FALSE);
2373
2374   if (filter->priv->visible_func)
2375     {
2376       GtkDestroyNotify d = filter->priv->visible_destroy;
2377
2378       filter->priv->visible_destroy = NULL;
2379       d (filter->priv->visible_data);
2380     }
2381
2382   filter->priv->visible_func = func;
2383   filter->priv->visible_data = data;
2384   filter->priv->visible_destroy = destroy;
2385
2386   filter->priv->visible_method_set = TRUE;
2387 }
2388
2389 /**
2390  * gtk_tree_model_filter_set_modify_func:
2391  * @filter: A #GtkTreeModelFilter.
2392  * @n_columns: The number of columns in the filter model.
2393  * @types: The #GType<!-- -->s of the columns.
2394  * @func: A #GtkTreeModelFilterModifyFunc, or %NULL.
2395  * @data: User data to pass to the modify function, or %NULL.
2396  * @destroy: Destroy notifier of @data, or %NULL.
2397  *
2398  * Sets the @filter to have @n_columns columns with @types. If @func
2399  * is not %NULL, it will set @func to be the modify function of @filter.
2400  *
2401  * Since: 2.4
2402  */
2403 void
2404 gtk_tree_model_filter_set_modify_func (GtkTreeModelFilter           *filter,
2405                                        gint                          n_columns,
2406                                        GType                        *types,
2407                                        GtkTreeModelFilterModifyFunc  func,
2408                                        gpointer                      data,
2409                                        GtkDestroyNotify              destroy)
2410 {
2411   g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
2412   g_return_if_fail (func != NULL);
2413   g_return_if_fail (filter->priv->modify_func_set == FALSE);
2414
2415   if (filter->priv->modify_destroy)
2416     {
2417       GtkDestroyNotify d = filter->priv->modify_destroy;
2418
2419       filter->priv->modify_destroy = NULL;
2420       d (filter->priv->modify_data);
2421     }
2422
2423   filter->priv->modify_n_columns = n_columns;
2424   filter->priv->modify_types = g_new0 (GType, n_columns);
2425   memcpy (filter->priv->modify_types, types, sizeof (GType) * n_columns);
2426   filter->priv->modify_func = func;
2427   filter->priv->modify_data = data;
2428   filter->priv->modify_destroy = destroy;
2429
2430   filter->priv->modify_func_set = TRUE;
2431 }
2432
2433 /**
2434  * gtk_tree_model_filter_set_visible_column:
2435  * @filter: A #GtkTreeModelFilter.
2436  * @column: A #gint which is the column containing the visible information.
2437  *
2438  * Sets @column of the child_model to be the column where @filter should
2439  * look for visibility information. @columns should be a column of type
2440  * %G_TYPE_BOOLEAN, where %TRUE means that a row is visible, and %FALSE
2441  * if not.
2442  *
2443  * Since: 2.4
2444  */
2445 void
2446 gtk_tree_model_filter_set_visible_column (GtkTreeModelFilter *filter,
2447                                           gint column)
2448 {
2449   g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
2450   g_return_if_fail (column >= 0);
2451   g_return_if_fail (filter->priv->visible_method_set == FALSE);
2452
2453   filter->priv->visible_column = column;
2454
2455   filter->priv->visible_method_set = TRUE;
2456 }
2457
2458 /* conversion */
2459
2460 /**
2461  * gtk_tree_model_filter_convert_child_iter_to_iter:
2462  * @filter: A #GtkTreeModelFilter.
2463  * @filter_iter: An uninitialized #GtkTreeIter.
2464  * @child_iter: A valid #GtkTreeIter pointing to a row on the child model.
2465  *
2466  * Sets @filter_iter to point to the row in @filter that corresponds to the
2467  * row pointed at by @child_iter.
2468  *
2469  * Since: 2.4
2470  */
2471 void
2472 gtk_tree_model_filter_convert_child_iter_to_iter (GtkTreeModelFilter *filter,
2473                                                   GtkTreeIter        *filter_iter,
2474                                                   GtkTreeIter        *child_iter)
2475 {
2476   GtkTreePath *child_path, *path;
2477
2478   g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
2479   g_return_if_fail (filter->priv->child_model != NULL);
2480   g_return_if_fail (filter_iter != NULL);
2481   g_return_if_fail (child_iter != NULL);
2482
2483   filter_iter->stamp = 0;
2484
2485   child_path = gtk_tree_model_get_path (filter->priv->child_model, child_iter);
2486   g_return_if_fail (child_path != NULL);
2487
2488   path = gtk_tree_model_filter_convert_child_path_to_path (filter,
2489                                                            child_path);
2490   gtk_tree_path_free (child_path);
2491   g_return_if_fail (path != NULL);
2492
2493   gtk_tree_model_get_iter (GTK_TREE_MODEL (filter), filter_iter, path);
2494   gtk_tree_path_free (path);
2495 }
2496
2497 /**
2498  * gtk_tree_model_filter_convert_iter_to_child_iter:
2499  * @filter: A #GtkTreeModelFilter.
2500  * @child_iter: An uninitialized #GtkTreeIter.
2501  * @filter_iter: A valid #GtkTreeIter pointing to a row on @filter.
2502  *
2503  * Sets @child_iter to point to the row pointed to by @filter_iter.
2504  *
2505  * Since: 2.4
2506  */
2507 void
2508 gtk_tree_model_filter_convert_iter_to_child_iter (GtkTreeModelFilter *filter,
2509                                                   GtkTreeIter        *child_iter,
2510                                                   GtkTreeIter        *filter_iter)
2511 {
2512   g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
2513   g_return_if_fail (filter->priv->child_model != NULL);
2514   g_return_if_fail (child_iter != NULL);
2515   g_return_if_fail (filter_iter != NULL);
2516   g_return_if_fail (filter_iter->stamp == filter->priv->stamp);
2517
2518   if (GTK_TREE_MODEL_FILTER_CACHE_CHILD_ITERS (filter))
2519     {
2520       *child_iter = FILTER_ELT (filter_iter->user_data2)->iter;
2521     }
2522   else
2523     {
2524       GtkTreePath *path;
2525
2526       path = gtk_tree_model_filter_elt_get_path (filter_iter->user_data,
2527                                                  filter_iter->user_data2,
2528                                                  filter->priv->virtual_root);
2529       gtk_tree_model_get_iter (filter->priv->child_model, child_iter, path);
2530       gtk_tree_path_free (path);
2531     }
2532 }
2533
2534 static GtkTreePath *
2535 gtk_real_tree_model_filter_convert_child_path_to_path (GtkTreeModelFilter *filter,
2536                                                        GtkTreePath        *child_path,
2537                                                        gboolean            build_levels,
2538                                                        gboolean            fetch_childs)
2539 {
2540   gint *child_indices;
2541   GtkTreePath *retval;
2542   GtkTreePath *real_path;
2543   FilterLevel *level;
2544   FilterElt *tmp;
2545   gint i;
2546
2547   g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (filter), NULL);
2548   g_return_val_if_fail (filter->priv->child_model != NULL, NULL);
2549   g_return_val_if_fail (child_path != NULL, NULL);
2550
2551   if (!filter->priv->virtual_root)
2552     real_path = gtk_tree_path_copy (child_path);
2553   else
2554     real_path = gtk_tree_model_filter_remove_root (child_path,
2555                                                    filter->priv->virtual_root);
2556
2557   if (!real_path)
2558     return NULL;
2559
2560   retval = gtk_tree_path_new ();
2561   child_indices = gtk_tree_path_get_indices (real_path);
2562
2563   if (filter->priv->root == NULL && build_levels)
2564     gtk_tree_model_filter_build_level (filter, NULL, NULL);
2565   level = FILTER_LEVEL (filter->priv->root);
2566
2567   for (i = 0; i < gtk_tree_path_get_depth (real_path); i++)
2568     {
2569       gint j;
2570       gboolean found_child = FALSE;
2571
2572       if (!level)
2573         {
2574           gtk_tree_path_free (real_path);
2575           gtk_tree_path_free (retval);
2576           return NULL;
2577         }
2578
2579       tmp = bsearch_elt_with_offset (level->array, child_indices[i], &j);
2580       if (tmp)
2581         {
2582           gtk_tree_path_append_index (retval, j);
2583           if (!tmp->children && build_levels)
2584             gtk_tree_model_filter_build_level (filter, level, tmp);
2585           level = tmp->children;
2586           found_child = TRUE;
2587         }
2588
2589       if (!found_child && fetch_childs)
2590         {
2591           tmp = gtk_tree_model_filter_fetch_child (filter, level,
2592                                                    child_indices[i],
2593                                                    &j);
2594
2595           /* didn't find the child, let's try to bring it back */
2596           if (!tmp || tmp->offset != child_indices[i])
2597             {
2598               /* not there */
2599               gtk_tree_path_free (real_path);
2600               gtk_tree_path_free (retval);
2601               return NULL;
2602             }
2603
2604           gtk_tree_path_append_index (retval, j);
2605           if (!tmp->children && build_levels)
2606             gtk_tree_model_filter_build_level (filter, level, tmp);
2607           level = tmp->children;
2608           found_child = TRUE;
2609         }
2610       else if (!found_child && !fetch_childs)
2611         {
2612           /* no path */
2613           gtk_tree_path_free (real_path);
2614           gtk_tree_path_free (retval);
2615           return NULL;
2616         }
2617     }
2618
2619   gtk_tree_path_free (real_path);
2620   return retval;
2621 }
2622
2623 /**
2624  * gtk_tree_model_filter_convert_child_path_to_path:
2625  * @filter: A #GtkTreeModelFilter.
2626  * @child_path: A #GtkTreePath to convert.
2627  *
2628  * Converts @child_path to a path relative to @filter. That is, @child_path
2629  * points to a path in the child model. The rerturned path will point to the
2630  * same row in the filtered model. If @child_path isn't a valid path on the
2631  * child model, then %NULL is returned.
2632  *
2633  * Return value: A newly allocated #GtkTreePath, or %NULL.
2634  *
2635  * Since: 2.4
2636  */
2637 GtkTreePath *
2638 gtk_tree_model_filter_convert_child_path_to_path (GtkTreeModelFilter *filter,
2639                                                   GtkTreePath        *child_path)
2640 {
2641   /* this function does the sanity checks */
2642   return gtk_real_tree_model_filter_convert_child_path_to_path (filter,
2643                                                                 child_path,
2644                                                                 TRUE,
2645                                                                 TRUE);
2646 }
2647
2648 /**
2649  * gtk_tree_model_filter_convert_path_to_child_path:
2650  * @filter: A #GtkTreeModelFilter.
2651  * @filter_path: A #GtkTreePath to convert.
2652  *
2653  * Converts @filter_path to a path on the child model of @filter. That is,
2654  * @filter_path points to a location in @filter. The returned path will
2655  * point to the same location in the model not being filtered. If @filter_path
2656  * does not point to a location in the child model, %NULL is returned.
2657  *
2658  * Return value: A newly allocated #GtkTreePath, or %NULL.
2659  *
2660  * Since: 2.4
2661  */
2662 GtkTreePath *
2663 gtk_tree_model_filter_convert_path_to_child_path (GtkTreeModelFilter *filter,
2664                                                   GtkTreePath        *filter_path)
2665 {
2666   gint *filter_indices;
2667   GtkTreePath *retval;
2668   FilterLevel *level;
2669   gint i;
2670
2671   g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (filter), NULL);
2672   g_return_val_if_fail (filter->priv->child_model != NULL, NULL);
2673   g_return_val_if_fail (filter_path != NULL, NULL);
2674
2675   /* convert path */
2676   retval = gtk_tree_path_new ();
2677   filter_indices = gtk_tree_path_get_indices (filter_path);
2678   if (!filter->priv->root)
2679     gtk_tree_model_filter_build_level (filter, NULL, NULL);
2680   level = FILTER_LEVEL (filter->priv->root);
2681
2682   for (i = 0; i < gtk_tree_path_get_depth (filter_path); i++)
2683     {
2684       gint count = filter_indices[i];
2685
2686       if (!level || level->array->len <= filter_indices[i])
2687         {
2688           gtk_tree_path_free (retval);
2689           return NULL;
2690         }
2691
2692       if (g_array_index (level->array, FilterElt, count).children == NULL)
2693         gtk_tree_model_filter_build_level (filter, level, &g_array_index (level->array, FilterElt, count));
2694
2695       if (!level || level->array->len <= filter_indices[i])
2696         {
2697           gtk_tree_path_free (retval);
2698           return NULL;
2699         }
2700
2701       gtk_tree_path_append_index (retval, g_array_index (level->array, FilterElt, count).offset);
2702       level = g_array_index (level->array, FilterElt, count).children;
2703     }
2704
2705   /* apply vroot */
2706
2707   if (filter->priv->virtual_root)
2708     {
2709       GtkTreePath *real_retval;
2710
2711       real_retval = gtk_tree_model_filter_add_root (retval,
2712                                                     filter->priv->virtual_root);
2713       gtk_tree_path_free (retval);
2714
2715       return real_retval;
2716     }
2717
2718   return retval;
2719 }
2720
2721 static gboolean
2722 gtk_tree_model_filter_refilter_helper (GtkTreeModel *model,
2723                                        GtkTreePath  *path,
2724                                        GtkTreeIter  *iter,
2725                                        gpointer      data)
2726 {
2727   /* evil, don't try this at home, but certainly speeds things up */
2728   gtk_tree_model_filter_row_changed (model, path, iter, data);
2729
2730   return FALSE;
2731 }
2732
2733 /**
2734  * gtk_tree_model_filter_refilter:
2735  * @filter: A #GtkTreeModelFilter.
2736  *
2737  * Emits ::row_changed for each row in the child model, which causes
2738  * the filter to re-evaluate whether a row is visible or not.
2739  *
2740  * Since: 2.4
2741  */
2742 void
2743 gtk_tree_model_filter_refilter (GtkTreeModelFilter *filter)
2744 {
2745   g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
2746
2747   /* S L O W */
2748   gtk_tree_model_foreach (filter->priv->child_model,
2749                           gtk_tree_model_filter_refilter_helper,
2750                           filter);
2751 }
2752
2753 /**
2754  * gtk_tree_model_filter_clear_cache:
2755  * @filter: A #GtkTreeModelFilter.
2756  *
2757  * This function should almost never be called. It clears the @filter
2758  * of any cached iterators that haven't been reffed with
2759  * gtk_tree_model_ref_node(). This might be useful if the child model
2760  * being filtered is static (and doesn't change often) and there has been
2761  * a lot of unreffed access to nodes. As a side effect of this function,
2762  * all unreffed itters will be invalid.
2763  *
2764  * Since: 2.4
2765  */
2766 void
2767 gtk_tree_model_filter_clear_cache (GtkTreeModelFilter *filter)
2768 {
2769   g_return_if_fail (GTK_IS_TREE_MODEL_FILTER (filter));
2770
2771   if (filter->priv->zero_ref_count)
2772     gtk_tree_model_filter_clear_cache_helper (filter,
2773                                               FILTER_LEVEL (filter->priv->root));
2774 }