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