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