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