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