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