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