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