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