]> Pileus Git - ~andy/gtk/blob - gtk/tests/filtermodel.c
Remove left-over calls to dump function
[~andy/gtk] / gtk / tests / filtermodel.c
1 /* Extensive GtkTreeModelFilter tests.
2  * Copyright (C) 2009,2011  Kristian Rietveld  <kris@gtk.org>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include <gtk/gtk.h>
21 #include <string.h>
22
23 #include "treemodel.h"
24 #include "gtktreemodelrefcount.h"
25
26 /* Left to do:
27  *   - Proper coverage checking to see if the unit tests cover
28  *     all possible cases.
29  *   - Check if the iterator stamp is incremented at the correct times.
30  *
31  * For more thorough testing:
32  *   - Test with randomized models.
33  *   - Extensively test a filter model wrapping a sort model,
34  *     or a sort model wrapping a filter model by:
35  *       # Checking structure.
36  *       # Checking for correct signals emissions.
37  *       # Checking correct reference counting.
38  *       # Tests should be done with the sort and filter model
39  *         in various filtering and sorting states.
40  */
41
42
43 /*
44  * Model creation
45  */
46
47 #define LEVEL_LENGTH 5
48
49 static void
50 create_tree_store_set_values (GtkTreeStore *store,
51                               GtkTreeIter  *iter,
52                               gboolean      visible)
53 {
54   GtkTreePath *path;
55   gchar *path_string;
56
57   path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), iter);
58   path_string = gtk_tree_path_to_string (path);
59
60   gtk_tree_store_set (store, iter,
61                       0, path_string,
62                       1, visible,
63                       -1);
64
65   gtk_tree_path_free (path);
66   g_free (path_string);
67 }
68
69 static void
70 create_tree_store_recurse (int           depth,
71                            GtkTreeStore *store,
72                            GtkTreeIter  *parent,
73                            gboolean      visible)
74 {
75   int i;
76
77   for (i = 0; i < LEVEL_LENGTH; i++)
78     {
79       GtkTreeIter iter;
80
81       gtk_tree_store_insert (store, &iter, parent, i);
82       create_tree_store_set_values (store, &iter, visible);
83
84       if (depth > 0)
85         create_tree_store_recurse (depth - 1, store, &iter, visible);
86     }
87 }
88
89 static GtkTreeStore *
90 create_tree_store (int      depth,
91                    gboolean visible)
92 {
93   GtkTreeStore *store;
94
95   store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
96
97   create_tree_store_recurse (depth, store, NULL, visible);
98
99   return store;
100 }
101
102 /*
103  * Fixture
104  */
105
106 typedef struct
107 {
108   GtkWidget *tree_view;
109
110   GtkTreeStore *store;
111   GtkTreeModelFilter *filter;
112
113   SignalMonitor *monitor;
114
115   guint block_signals : 1;
116 } FilterTest;
117
118
119 static void
120 filter_test_store_signal (FilterTest *fixture)
121 {
122   if (fixture->block_signals)
123     g_signal_stop_emission_by_name (fixture->store, "row-changed");
124 }
125
126
127 static void
128 filter_test_setup_generic (FilterTest    *fixture,
129                            gconstpointer  test_data,
130                            int            depth,
131                            gboolean       empty,
132                            gboolean       unfiltered)
133 {
134   const GtkTreePath *vroot = test_data;
135   GtkTreeModel *filter;
136
137   fixture->store = create_tree_store (depth, !empty);
138
139   g_signal_connect_swapped (fixture->store, "row-changed",
140                             G_CALLBACK (filter_test_store_signal), fixture);
141
142   /* Please forgive me for casting const away. */
143   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (fixture->store),
144                                       (GtkTreePath *)vroot);
145   fixture->filter = GTK_TREE_MODEL_FILTER (filter);
146
147   if (!unfiltered)
148     gtk_tree_model_filter_set_visible_column (fixture->filter, 1);
149
150   /* We need a tree view that's listening to get ref counting from that
151    * side.
152    */
153   fixture->tree_view = gtk_tree_view_new_with_model (filter);
154
155   fixture->monitor = signal_monitor_new (filter);
156 }
157
158 static void
159 filter_test_setup_expand_root (FilterTest *fixture)
160 {
161   int i;
162   GtkTreePath *path;
163
164   path = gtk_tree_path_new_from_indices (0, -1);
165
166   for (i = 0; i < LEVEL_LENGTH; i++)
167     {
168       gtk_tree_view_expand_row (GTK_TREE_VIEW (fixture->tree_view),
169                                 path, FALSE);
170       gtk_tree_path_next (path);
171     }
172   gtk_tree_path_free (path);
173 }
174
175 static void
176 filter_test_setup (FilterTest    *fixture,
177                    gconstpointer  test_data)
178 {
179   filter_test_setup_generic (fixture, test_data, 3, FALSE, FALSE);
180 }
181
182 static void
183 filter_test_setup_empty (FilterTest    *fixture,
184                          gconstpointer  test_data)
185 {
186   filter_test_setup_generic (fixture, test_data, 3, TRUE, FALSE);
187 }
188
189 static void
190 filter_test_setup_unfiltered (FilterTest    *fixture,
191                               gconstpointer  test_data)
192 {
193   filter_test_setup_generic (fixture, test_data, 3, FALSE, TRUE);
194 }
195
196 static void
197 filter_test_setup_unfiltered_root_expanded (FilterTest    *fixture,
198                                             gconstpointer  test_data)
199 {
200   filter_test_setup_unfiltered (fixture, test_data);
201   filter_test_setup_expand_root (fixture);
202 }
203
204 static void
205 filter_test_setup_empty_unfiltered (FilterTest    *fixture,
206                                     gconstpointer  test_data)
207 {
208   filter_test_setup_generic (fixture, test_data, 3, TRUE, TRUE);
209 }
210
211 static void
212 filter_test_setup_empty_unfiltered_root_expanded (FilterTest    *fixture,
213                                                   gconstpointer  test_data)
214 {
215   filter_test_setup_empty_unfiltered (fixture, test_data);
216   filter_test_setup_expand_root (fixture);
217 }
218
219 static GtkTreePath *
220 strip_virtual_root (GtkTreePath *path,
221                     GtkTreePath *root_path)
222 {
223   GtkTreePath *real_path;
224
225   if (root_path)
226     {
227       int j;
228       int depth = gtk_tree_path_get_depth (path);
229       int root_depth = gtk_tree_path_get_depth (root_path);
230
231       real_path = gtk_tree_path_new ();
232
233       for (j = 0; j < depth - root_depth; j++)
234         gtk_tree_path_append_index (real_path,
235                                     gtk_tree_path_get_indices (path)[root_depth + j]);
236     }
237   else
238     real_path = gtk_tree_path_copy (path);
239
240   return real_path;
241 }
242
243 static int
244 count_visible (FilterTest  *fixture,
245                GtkTreePath *store_path)
246 {
247   int i;
248   int n_visible = 0;
249   GtkTreeIter iter;
250
251   gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->store),
252                            &iter, store_path);
253
254   for (i = 0; i < LEVEL_LENGTH; i++)
255     {
256       gboolean visible;
257
258       gtk_tree_model_get (GTK_TREE_MODEL (fixture->store), &iter,
259                           1, &visible,
260                           -1);
261
262       if (visible)
263         n_visible++;
264     }
265
266   return n_visible;
267 }
268
269 static void
270 filter_test_append_refilter_signals_recurse (FilterTest  *fixture,
271                                              GtkTreePath *store_path,
272                                              GtkTreePath *filter_path,
273                                              int          depth,
274                                              GtkTreePath *root_path)
275 {
276   int i;
277   int rows_deleted = 0;
278   GtkTreeIter iter;
279
280   gtk_tree_path_down (store_path);
281   gtk_tree_path_down (filter_path);
282
283   gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->store),
284                            &iter, store_path);
285
286   for (i = 0; i < LEVEL_LENGTH; i++)
287     {
288       gboolean visible;
289       GtkTreePath *real_path;
290
291       gtk_tree_model_get (GTK_TREE_MODEL (fixture->store), &iter,
292                           1, &visible,
293                           -1);
294
295       if (root_path &&
296           (!gtk_tree_path_is_descendant (store_path, root_path)
297            || !gtk_tree_path_compare (store_path, root_path)))
298         {
299           if (!gtk_tree_path_compare (store_path, root_path))
300             {
301               if (depth > 1
302                   && gtk_tree_model_iter_has_child (GTK_TREE_MODEL (fixture->store),
303                                                     &iter))
304                 {
305                   GtkTreePath *store_copy;
306                   GtkTreePath *filter_copy;
307
308                   store_copy = gtk_tree_path_copy (store_path);
309                   filter_copy = gtk_tree_path_copy (filter_path);
310                   filter_test_append_refilter_signals_recurse (fixture,
311                                                                store_copy,
312                                                                filter_copy,
313                                                                depth - 1,
314                                                                root_path);
315                   gtk_tree_path_free (store_copy);
316                   gtk_tree_path_free (filter_copy);
317                 }
318             }
319
320           gtk_tree_path_next (store_path);
321           gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &iter);
322
323           if (visible)
324             gtk_tree_path_next (filter_path);
325
326           continue;
327         }
328
329       real_path = strip_virtual_root (filter_path, root_path);
330
331       if (visible)
332         {
333           /* This row will be inserted */
334           signal_monitor_append_signal_path (fixture->monitor, ROW_CHANGED,
335                                              real_path);
336
337           if (gtk_tree_model_iter_has_child (GTK_TREE_MODEL (fixture->store),
338                                              &iter))
339             {
340               signal_monitor_append_signal_path (fixture->monitor,
341                                                  ROW_HAS_CHILD_TOGGLED,
342                                                  real_path);
343
344               if (depth > 1)
345                 {
346                   GtkTreePath *store_copy;
347                   GtkTreePath *filter_copy;
348
349                   store_copy = gtk_tree_path_copy (store_path);
350                   filter_copy = gtk_tree_path_copy (filter_path);
351                   filter_test_append_refilter_signals_recurse (fixture,
352                                                                store_copy,
353                                                                filter_copy,
354                                                                depth - 1,
355                                                                root_path);
356                   gtk_tree_path_free (store_copy);
357                   gtk_tree_path_free (filter_copy);
358                 }
359               else if (depth == 1)
360                 {
361                   GtkTreePath *tmp_path;
362
363                   /* If all child rows are invisible, then the last row to
364                    * become invisible will emit row-has-child-toggled on the
365                    * parent.
366                    */
367
368                   tmp_path = gtk_tree_path_copy (store_path);
369                   gtk_tree_path_append_index (tmp_path, 0);
370
371                   if (count_visible (fixture, tmp_path) == 0)
372                     signal_monitor_append_signal_path (fixture->monitor,
373                                                        ROW_HAS_CHILD_TOGGLED,
374                                                        real_path);
375
376                   gtk_tree_path_free (tmp_path);
377                 }
378             }
379
380           gtk_tree_path_next (filter_path);
381         }
382       else
383         {
384           /* This row will be deleted */
385           rows_deleted++;
386           signal_monitor_append_signal_path (fixture->monitor, ROW_DELETED,
387                                              real_path);
388         }
389
390       gtk_tree_path_free (real_path);
391
392       gtk_tree_path_next (store_path);
393       gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &iter);
394     }
395
396   if (rows_deleted == LEVEL_LENGTH
397       && gtk_tree_path_get_depth (filter_path) > 1)
398     {
399       GtkTreePath *real_path;
400
401       gtk_tree_path_up (store_path);
402       gtk_tree_path_up (filter_path);
403
404       /* A row-has-child-toggled will be emitted on the parent */
405       if (!root_path
406           || (root_path
407               && gtk_tree_path_is_descendant (store_path, root_path)
408               && gtk_tree_path_compare (store_path, root_path)))
409         {
410           real_path = strip_virtual_root (filter_path, root_path);
411           signal_monitor_append_signal_path (fixture->monitor,
412                                              ROW_HAS_CHILD_TOGGLED,
413                                              real_path);
414
415           gtk_tree_path_free (real_path);
416         }
417     }
418 }
419
420 static void
421 filter_test_append_refilter_signals (FilterTest *fixture,
422                                      int         depth)
423 {
424   /* A special function that walks the tree store like the
425    * model validation functions below.
426    */
427   GtkTreePath *path;
428   GtkTreePath *filter_path;
429
430   path = gtk_tree_path_new ();
431   filter_path = gtk_tree_path_new ();
432   filter_test_append_refilter_signals_recurse (fixture,
433                                                path,
434                                                filter_path,
435                                                depth,
436                                                NULL);
437   gtk_tree_path_free (path);
438   gtk_tree_path_free (filter_path);
439 }
440
441 static void
442 filter_test_append_refilter_signals_with_vroot (FilterTest  *fixture,
443                                                 int          depth,
444                                                 GtkTreePath *root_path)
445 {
446   /* A special function that walks the tree store like the
447    * model validation functions below.
448    */
449   GtkTreePath *path;
450   GtkTreePath *filter_path;
451
452   path = gtk_tree_path_new ();
453   filter_path = gtk_tree_path_new ();
454   filter_test_append_refilter_signals_recurse (fixture,
455                                                path,
456                                                filter_path,
457                                                depth,
458                                                root_path);
459   gtk_tree_path_free (path);
460   gtk_tree_path_free (filter_path);
461 }
462
463 static void
464 filter_test_enable_filter (FilterTest *fixture)
465 {
466   gtk_tree_model_filter_set_visible_column (fixture->filter, 1);
467   gtk_tree_model_filter_refilter (fixture->filter);
468 }
469
470 static void
471 filter_test_block_signals (FilterTest *fixture)
472 {
473   fixture->block_signals = TRUE;
474 }
475
476 static void
477 filter_test_unblock_signals (FilterTest *fixture)
478 {
479   fixture->block_signals = FALSE;
480 }
481
482 static void
483 filter_test_teardown (FilterTest    *fixture,
484                       gconstpointer  test_data)
485 {
486   signal_monitor_free (fixture->monitor);
487
488   gtk_widget_destroy (fixture->tree_view);
489
490   g_object_unref (fixture->filter);
491   g_object_unref (fixture->store);
492 }
493
494 /*
495  * Model structure validation
496  */
497
498 static void
499 check_filter_model_recurse (FilterTest  *fixture,
500                             GtkTreePath *store_parent_path,
501                             GtkTreePath *filter_parent_path)
502 {
503   int i;
504   GtkTreeIter store_iter;
505   GtkTreeIter filter_iter;
506   gboolean store_has_next, filter_has_next;
507
508   gtk_tree_path_down (store_parent_path);
509   gtk_tree_path_down (filter_parent_path);
510
511   store_has_next = gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->store),
512                                             &store_iter, store_parent_path);
513   filter_has_next = gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->filter),
514                                              &filter_iter, filter_parent_path);
515
516   for (i = 0; i < LEVEL_LENGTH; i++)
517     {
518       gboolean visible;
519
520       g_return_if_fail (store_has_next == TRUE);
521
522       gtk_tree_model_get (GTK_TREE_MODEL (fixture->store),
523                           &store_iter,
524                           1, &visible,
525                           -1);
526
527       if (visible)
528         {
529           GtkTreePath *tmp;
530           gchar *filter_str, *store_str;
531
532           g_return_if_fail (filter_has_next == TRUE);
533
534           /* Verify path */
535           tmp = gtk_tree_model_get_path (GTK_TREE_MODEL (fixture->filter),
536                                          &filter_iter);
537           g_return_if_fail (gtk_tree_path_compare (tmp, filter_parent_path) == 0);
538
539           /* Verify model content */
540           gtk_tree_model_get (GTK_TREE_MODEL (fixture->store),
541                               &store_iter,
542                               0, &store_str,
543                               -1);
544           gtk_tree_model_get (GTK_TREE_MODEL (fixture->filter),
545                               &filter_iter,
546                               0, &filter_str,
547                               -1);
548
549           g_return_if_fail (g_strcmp0 (store_str, filter_str) == 0);
550
551           g_free (store_str);
552           g_free (filter_str);
553
554           if (gtk_tree_model_iter_has_child (GTK_TREE_MODEL (fixture->filter),
555                                              &filter_iter))
556             {
557               g_return_if_fail (gtk_tree_model_iter_has_child (GTK_TREE_MODEL (fixture->store), &store_iter));
558
559               check_filter_model_recurse (fixture,
560                                           gtk_tree_path_copy (store_parent_path),
561                                           tmp);
562             }
563           else
564             /* Only when we do not recurse we need to free tmp */
565             gtk_tree_path_free (tmp);
566
567           gtk_tree_path_next (filter_parent_path);
568           filter_has_next = gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->filter), &filter_iter);
569         }
570
571       gtk_tree_path_next (store_parent_path);
572       store_has_next = gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &store_iter);
573     }
574
575   /* Both models should have no more content! */
576   g_return_if_fail (store_has_next == FALSE);
577   g_return_if_fail (filter_has_next == FALSE);
578
579   gtk_tree_path_free (store_parent_path);
580   gtk_tree_path_free (filter_parent_path);
581 }
582
583 static void
584 check_filter_model (FilterTest *fixture)
585 {
586   GtkTreePath *path;
587
588   if (fixture->monitor)
589     signal_monitor_assert_is_empty (fixture->monitor);
590
591   path = gtk_tree_path_new ();
592
593   check_filter_model_recurse (fixture, path, gtk_tree_path_copy (path));
594 }
595
596 static void
597 check_filter_model_with_root (FilterTest  *fixture,
598                               GtkTreePath *path)
599 {
600   if (fixture->monitor)
601     signal_monitor_assert_is_empty (fixture->monitor);
602
603   check_filter_model_recurse (fixture,
604                               gtk_tree_path_copy (path),
605                               gtk_tree_path_new ());
606 }
607
608 /* Helpers */
609
610 static void
611 check_level_length (GtkTreeModelFilter *filter,
612                     const gchar        *level,
613                     const int           expected_length)
614 {
615   if (!level)
616     {
617       int model_length;
618
619       model_length = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (filter), NULL);
620       g_assert_cmpint (model_length, ==, expected_length);
621     }
622   else
623     {
624       int model_length;
625       gboolean retrieved_iter = FALSE;
626       GtkTreeIter iter;
627
628       retrieved_iter = gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (filter),
629                                                             &iter, level);
630       g_return_if_fail (retrieved_iter);
631       model_length = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (filter), &iter);
632       g_assert_cmpint (model_length, ==, expected_length);
633     }
634 }
635
636 static void
637 set_path_visibility (FilterTest  *fixture,
638                      const gchar *path,
639                      gboolean     visible)
640 {
641   GtkTreeIter store_iter;
642
643   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
644                                        &store_iter, path);
645   gtk_tree_store_set (fixture->store, &store_iter,
646                       1, visible,
647                       -1);
648 }
649
650 #if 0
651 static void
652 insert_path_with_visibility (FilterTest  *fixture,
653                              const gchar *path_string,
654                              gboolean     visible)
655 {
656   int position;
657   GtkTreePath *path;
658   GtkTreeIter parent, iter;
659
660   path = gtk_tree_path_new_from_string (path_string);
661   position = gtk_tree_path_get_indices (path)[gtk_tree_path_get_depth (path)];
662   gtk_tree_path_up (path);
663
664   if (gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->store), &parent, path))
665     {
666       gtk_tree_store_insert (fixture->store, &iter, &parent, position);
667       create_tree_store_set_values (fixture->store, &iter, visible);
668     }
669   gtk_tree_path_free (path);
670 }
671 #endif
672
673 /*
674  * The actual tests.
675  */
676
677 static void
678 verify_test_suite (FilterTest    *fixture,
679                    gconstpointer  user_data)
680 {
681   check_filter_model (fixture);
682 }
683
684 static void
685 verify_test_suite_vroot (FilterTest    *fixture,
686                          gconstpointer  user_data)
687 {
688   check_filter_model_with_root (fixture, (GtkTreePath *)user_data);
689 }
690
691
692 static void
693 filled_hide_root_level (FilterTest    *fixture,
694                         gconstpointer  user_data)
695 {
696   signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "2");
697   set_path_visibility (fixture, "2", FALSE);
698   check_filter_model (fixture);
699   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 1);
700
701   signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
702   set_path_visibility (fixture, "0", FALSE);
703   check_filter_model (fixture);
704   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 2);
705
706   signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "2");
707   set_path_visibility (fixture, "4", FALSE);
708   check_filter_model (fixture);
709   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 3);
710
711
712   /* Hide remaining */
713   signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
714   signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
715
716   set_path_visibility (fixture, "1", FALSE);
717   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 4);
718
719   set_path_visibility (fixture, "3", FALSE);
720   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 5);
721
722   check_filter_model (fixture);
723
724   /* Show some */
725   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
726   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
727   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "1");
728   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "1");
729
730   set_path_visibility (fixture, "1", TRUE);
731   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 4);
732
733   set_path_visibility (fixture, "3", TRUE);
734   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 3);
735
736   check_filter_model (fixture);
737 }
738
739 static void
740 filled_hide_child_levels (FilterTest    *fixture,
741                           gconstpointer  user_data)
742 {
743   set_path_visibility (fixture, "0:2", FALSE);
744   check_filter_model (fixture);
745   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
746   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 1);
747
748   set_path_visibility (fixture, "0:4", FALSE);
749   check_filter_model (fixture);
750   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
751   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
752
753   set_path_visibility (fixture, "0:4:3", FALSE);
754   check_filter_model (fixture);
755   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
756   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
757
758   set_path_visibility (fixture, "0:4:0", FALSE);
759   set_path_visibility (fixture, "0:4:1", FALSE);
760   set_path_visibility (fixture, "0:4:2", FALSE);
761   set_path_visibility (fixture, "0:4:4", FALSE);
762   check_filter_model (fixture);
763   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
764   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
765
766   /* Since "0:2" is hidden, "0:4" must be "0:3" in the filter model */
767   set_path_visibility (fixture, "0:4", TRUE);
768   check_filter_model (fixture);
769   check_level_length (fixture->filter, "0:3", 0);
770
771   set_path_visibility (fixture, "0:2", TRUE);
772   check_filter_model (fixture);
773   check_level_length (fixture->filter, "0:2", LEVEL_LENGTH);
774   check_level_length (fixture->filter, "0:3", LEVEL_LENGTH);
775   check_level_length (fixture->filter, "0:4", 0);
776
777   /* Once 0:4:0 got inserted, 0:4 became a parent.  Because 0:4 is
778    * not visible, not signals are emitted.
779    */
780   set_path_visibility (fixture, "0:4:2", TRUE);
781   set_path_visibility (fixture, "0:4:4", TRUE);
782   signal_monitor_assert_is_empty (fixture->monitor);
783   check_level_length (fixture->filter, "0:4", 2);
784 }
785
786 static void
787 filled_hide_child_levels_root_expanded (FilterTest    *fixture,
788                                         gconstpointer  user_data)
789 {
790   GtkTreePath *path;
791
792   path = gtk_tree_path_new_from_indices (0, -1);
793   gtk_tree_view_expand_row (GTK_TREE_VIEW (fixture->tree_view), path, FALSE);
794   gtk_tree_path_free (path);
795
796   signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0:2");
797   set_path_visibility (fixture, "0:2", FALSE);
798   check_filter_model (fixture);
799   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
800   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 1);
801
802   signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0:3");
803   set_path_visibility (fixture, "0:4", FALSE);
804   check_filter_model (fixture);
805   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
806   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
807
808   set_path_visibility (fixture, "0:4:3", FALSE);
809   check_filter_model (fixture);
810   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
811   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
812
813   set_path_visibility (fixture, "0:4:0", FALSE);
814   set_path_visibility (fixture, "0:4:1", FALSE);
815   set_path_visibility (fixture, "0:4:2", FALSE);
816   set_path_visibility (fixture, "0:4:4", FALSE);
817   check_filter_model (fixture);
818   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
819   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
820
821   /* Since "0:2" is hidden, "0:4" must be "0:3" in the filter model */
822   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0:3");
823   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0:3");
824   set_path_visibility (fixture, "0:4", TRUE);
825   check_filter_model (fixture);
826   check_level_length (fixture->filter, "0:3", 0);
827
828   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0:2");
829   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0:2");
830   set_path_visibility (fixture, "0:2", TRUE);
831   check_filter_model (fixture);
832   check_level_length (fixture->filter, "0:2", LEVEL_LENGTH);
833   check_level_length (fixture->filter, "0:3", LEVEL_LENGTH);
834   check_level_length (fixture->filter, "0:4", 0);
835
836   /* has-child-toggled for 0:4 is required.  */
837   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0:4");
838   set_path_visibility (fixture, "0:4:2", TRUE);
839   set_path_visibility (fixture, "0:4:4", TRUE);
840   signal_monitor_assert_is_empty (fixture->monitor);
841   check_level_length (fixture->filter, "0:4", 2);
842 }
843
844
845 static void
846 filled_vroot_hide_root_level (FilterTest    *fixture,
847                               gconstpointer  user_data)
848 {
849   GtkTreePath *path = (GtkTreePath *)user_data;
850
851   /* These changes do not affect the filter's root level */
852   set_path_visibility (fixture, "0", FALSE);
853   check_filter_model_with_root (fixture, path);
854   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
855   check_level_length (fixture->filter, "0", LEVEL_LENGTH);
856
857   set_path_visibility (fixture, "4", FALSE);
858   check_filter_model_with_root (fixture, path);
859   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
860   check_level_length (fixture->filter, "0", LEVEL_LENGTH);
861
862   /* Even though we set the virtual root parent node to FALSE,
863    * the virtual root contents remain.
864    */
865   set_path_visibility (fixture, "2", FALSE);
866   check_filter_model_with_root (fixture, path);
867   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
868   check_level_length (fixture->filter, "0", LEVEL_LENGTH);
869
870   /* No change */
871   set_path_visibility (fixture, "1", FALSE);
872   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
873   check_level_length (fixture->filter, "0", LEVEL_LENGTH);
874
875   set_path_visibility (fixture, "3", FALSE);
876   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
877   check_level_length (fixture->filter, "0", LEVEL_LENGTH);
878
879   check_filter_model_with_root (fixture, path);
880
881   /* Show some */
882   set_path_visibility (fixture, "2", TRUE);
883   check_filter_model_with_root (fixture, path);
884   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
885   check_level_length (fixture->filter, "0", LEVEL_LENGTH);
886
887   set_path_visibility (fixture, "1", TRUE);
888   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
889   check_level_length (fixture->filter, "0", LEVEL_LENGTH);
890
891   set_path_visibility (fixture, "3", TRUE);
892   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
893   check_level_length (fixture->filter, "0", LEVEL_LENGTH);
894
895   check_filter_model_with_root (fixture, path);
896
897   /* Now test changes in the virtual root level */
898   signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "2");
899   set_path_visibility (fixture, "2:2", FALSE);
900   check_filter_model_with_root (fixture, path);
901   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 1);
902
903   signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "3");
904   set_path_visibility (fixture, "2:4", FALSE);
905   check_filter_model_with_root (fixture, path);
906   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 2);
907
908   set_path_visibility (fixture, "1:4", FALSE);
909   check_filter_model_with_root (fixture, path);
910   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 2);
911
912   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "3");
913   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "3");
914   set_path_visibility (fixture, "2:4", TRUE);
915   check_filter_model_with_root (fixture, path);
916   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 1);
917
918   set_path_visibility (fixture, "2", FALSE);
919   check_filter_model_with_root (fixture, path);
920   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 1);
921
922   signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
923   signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
924   signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
925   signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
926   set_path_visibility (fixture, "2:0", FALSE);
927   set_path_visibility (fixture, "2:1", FALSE);
928   set_path_visibility (fixture, "2:2", FALSE);
929   set_path_visibility (fixture, "2:3", FALSE);
930   set_path_visibility (fixture, "2:4", FALSE);
931   check_filter_model_with_root (fixture, path);
932   check_level_length (fixture->filter, NULL, 0);
933
934   set_path_visibility (fixture, "2", TRUE);
935   check_filter_model_with_root (fixture, path);
936   check_level_length (fixture->filter, NULL, 0);
937
938   set_path_visibility (fixture, "1:4", FALSE);
939   check_filter_model_with_root (fixture, path);
940   check_level_length (fixture->filter, NULL, 0);
941
942   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
943   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
944   set_path_visibility (fixture, "2:4", TRUE);
945   check_filter_model_with_root (fixture, path);
946   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 4);
947
948   signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
949   set_path_visibility (fixture, "2:4", FALSE);
950   check_filter_model_with_root (fixture, path);
951   check_level_length (fixture->filter, NULL, 0);
952
953   set_path_visibility (fixture, "2", FALSE);
954   check_filter_model_with_root (fixture, path);
955   check_level_length (fixture->filter, NULL, 0);
956
957   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
958   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
959   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "1");
960   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "1");
961   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "2");
962   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2");
963   set_path_visibility (fixture, "2:0", TRUE);
964   set_path_visibility (fixture, "2:1", TRUE);
965   set_path_visibility (fixture, "2:2", TRUE);
966   check_filter_model_with_root (fixture, path);
967   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 2);
968
969   set_path_visibility (fixture, "2", TRUE);
970   check_filter_model_with_root (fixture, path);
971   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 2);
972 }
973
974 static void
975 filled_vroot_hide_child_levels (FilterTest    *fixture,
976                                 gconstpointer  user_data)
977 {
978   GtkTreePath *path = (GtkTreePath *)user_data;
979
980   set_path_visibility (fixture, "2:0:2", FALSE);
981   check_filter_model_with_root (fixture, path);
982   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
983   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 1);
984
985   set_path_visibility (fixture, "2:0:4", FALSE);
986   check_filter_model_with_root (fixture, path);
987   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
988   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
989
990   set_path_visibility (fixture, "2:0:4:3", FALSE);
991   check_filter_model_with_root (fixture, path);
992   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
993   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
994
995   set_path_visibility (fixture, "2:0:4:0", FALSE);
996   set_path_visibility (fixture, "2:0:4:1", FALSE);
997   set_path_visibility (fixture, "2:0:4:2", FALSE);
998   set_path_visibility (fixture, "2:0:4:4", FALSE);
999   check_filter_model_with_root (fixture, path);
1000   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1001   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
1002
1003   /* Since "0:2" is hidden, "0:4" must be "0:3" in the filter model */
1004   set_path_visibility (fixture, "2:0:4", TRUE);
1005   check_filter_model_with_root (fixture, path);
1006   check_level_length (fixture->filter, "0:3", 0);
1007
1008   set_path_visibility (fixture, "2:0:2", TRUE);
1009   check_filter_model_with_root (fixture, path);
1010   check_level_length (fixture->filter, "0:2", LEVEL_LENGTH);
1011   check_level_length (fixture->filter, "0:3", LEVEL_LENGTH);
1012   check_level_length (fixture->filter, "0:4", 0);
1013
1014   /* Once 0:4:0 got inserted, 0:4 became a parent. However, 0:4 is not
1015    * visible, so no signal should be emitted.
1016    */
1017   set_path_visibility (fixture, "2:0:4:2", TRUE);
1018   set_path_visibility (fixture, "2:0:4:4", TRUE);
1019   check_level_length (fixture->filter, "0:4", 2);
1020   signal_monitor_assert_is_empty (fixture->monitor);
1021 }
1022
1023 static void
1024 filled_vroot_hide_child_levels_root_expanded (FilterTest    *fixture,
1025                                               gconstpointer  user_data)
1026 {
1027   GtkTreePath *path = (GtkTreePath *)user_data;
1028   GtkTreePath *tmp_path;
1029
1030   tmp_path = gtk_tree_path_new_from_indices (0, -1);
1031   gtk_tree_view_expand_row (GTK_TREE_VIEW (fixture->tree_view), tmp_path, FALSE);
1032   gtk_tree_path_free (tmp_path);
1033
1034   signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0:2");
1035   set_path_visibility (fixture, "2:0:2", FALSE);
1036   check_filter_model_with_root (fixture, path);
1037   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1038   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 1);
1039
1040   signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0:3");
1041   set_path_visibility (fixture, "2:0:4", FALSE);
1042   check_filter_model_with_root (fixture, path);
1043   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1044   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
1045
1046   set_path_visibility (fixture, "2:0:4:3", FALSE);
1047   check_filter_model_with_root (fixture, path);
1048   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1049   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
1050
1051   set_path_visibility (fixture, "2:0:4:0", FALSE);
1052   set_path_visibility (fixture, "2:0:4:1", FALSE);
1053   set_path_visibility (fixture, "2:0:4:2", FALSE);
1054   set_path_visibility (fixture, "2:0:4:4", FALSE);
1055   check_filter_model_with_root (fixture, path);
1056   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1057   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
1058
1059   /* Since "0:2" is hidden, "0:4" must be "0:3" in the filter model */
1060   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0:3");
1061   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0:3");
1062   set_path_visibility (fixture, "2:0:4", TRUE);
1063   check_filter_model_with_root (fixture, path);
1064   check_level_length (fixture->filter, "0:3", 0);
1065
1066   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0:2");
1067   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0:2");
1068   set_path_visibility (fixture, "2:0:2", TRUE);
1069   check_filter_model_with_root (fixture, path);
1070   check_level_length (fixture->filter, "0:2", LEVEL_LENGTH);
1071   check_level_length (fixture->filter, "0:3", LEVEL_LENGTH);
1072   check_level_length (fixture->filter, "0:4", 0);
1073
1074   /* Once 0:4:0 got inserted, 0:4 became a parent */
1075   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0:4");
1076   set_path_visibility (fixture, "2:0:4:2", TRUE);
1077   set_path_visibility (fixture, "2:0:4:4", TRUE);
1078   check_level_length (fixture->filter, "0:4", 2);
1079   signal_monitor_assert_is_empty (fixture->monitor);
1080 }
1081
1082 static void
1083 empty_show_nodes (FilterTest    *fixture,
1084                   gconstpointer  user_data)
1085 {
1086   check_filter_model (fixture);
1087   check_level_length (fixture->filter, NULL, 0);
1088
1089   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1090   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1091   set_path_visibility (fixture, "3", TRUE);
1092   check_filter_model (fixture);
1093   check_level_length (fixture->filter, NULL, 1);
1094   check_level_length (fixture->filter, "0", 0);
1095
1096   set_path_visibility (fixture, "3:2:2", TRUE);
1097   check_filter_model (fixture);
1098   check_level_length (fixture->filter, NULL, 1);
1099   check_level_length (fixture->filter, "0", 0);
1100
1101   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1102   set_path_visibility (fixture, "3:2", TRUE);
1103   check_filter_model (fixture);
1104   check_level_length (fixture->filter, NULL, 1);
1105   check_level_length (fixture->filter, "0", 1);
1106   check_level_length (fixture->filter, "0:0", 1);
1107   check_level_length (fixture->filter, "0:0:0", 0);
1108
1109   signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
1110   set_path_visibility (fixture, "3", FALSE);
1111   check_filter_model (fixture);
1112   check_level_length (fixture->filter, NULL, 0);
1113
1114   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1115   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1116   set_path_visibility (fixture, "3:2:1", TRUE);
1117   set_path_visibility (fixture, "3", TRUE);
1118   check_filter_model (fixture);
1119   check_level_length (fixture->filter, NULL, 1);
1120   check_level_length (fixture->filter, "0", 1);
1121   check_level_length (fixture->filter, "0:0", 2);
1122   check_level_length (fixture->filter, "0:0:0", 0);
1123 }
1124
1125 static void
1126 empty_show_multiple_nodes (FilterTest    *fixture,
1127                            gconstpointer  user_data)
1128 {
1129   GtkTreeIter iter;
1130   GtkTreePath *changed_path;
1131
1132   check_filter_model (fixture);
1133   check_level_length (fixture->filter, NULL, 0);
1134
1135   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1136   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1137   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "1");
1138   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "1");
1139
1140   /* We simulate a change in visible func condition with this.  The
1141    * visibility state of multiple nodes changes at once, we emit row-changed
1142    * for these nodes (and others) after that.
1143    */
1144   filter_test_block_signals (fixture);
1145   set_path_visibility (fixture, "3", TRUE);
1146   set_path_visibility (fixture, "4", TRUE);
1147   filter_test_unblock_signals (fixture);
1148
1149   changed_path = gtk_tree_path_new ();
1150   gtk_tree_path_append_index (changed_path, 2);
1151   gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->store),
1152                            &iter, changed_path);
1153   /* Invisible node - so no signals expected */
1154   gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1155                               changed_path, &iter);
1156
1157   gtk_tree_path_next (changed_path);
1158   gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &iter);
1159   gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1160                               changed_path, &iter);
1161
1162   gtk_tree_path_next (changed_path);
1163   gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &iter);
1164   gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1165                               changed_path, &iter);
1166
1167   gtk_tree_path_free (changed_path);
1168
1169   check_filter_model (fixture);
1170   check_level_length (fixture->filter, NULL, 2);
1171   check_level_length (fixture->filter, "0", 0);
1172
1173   set_path_visibility (fixture, "3:2:2", TRUE);
1174   check_filter_model (fixture);
1175   check_level_length (fixture->filter, NULL, 2);
1176   check_level_length (fixture->filter, "0", 0);
1177
1178   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1179   set_path_visibility (fixture, "3:2", TRUE);
1180   check_filter_model (fixture);
1181   check_level_length (fixture->filter, NULL, 2);
1182   check_level_length (fixture->filter, "0", 1);
1183   check_level_length (fixture->filter, "0:0", 1);
1184   check_level_length (fixture->filter, "0:0:0", 0);
1185
1186   signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
1187   set_path_visibility (fixture, "3", FALSE);
1188   check_filter_model (fixture);
1189   check_level_length (fixture->filter, NULL, 1);
1190
1191   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1192   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1193   set_path_visibility (fixture, "3:2:1", TRUE);
1194   set_path_visibility (fixture, "3", TRUE);
1195   check_filter_model (fixture);
1196   check_level_length (fixture->filter, NULL, 2);
1197   check_level_length (fixture->filter, "0", 1);
1198   check_level_length (fixture->filter, "0:0", 2);
1199   check_level_length (fixture->filter, "0:0:0", 0);
1200 }
1201
1202 static void
1203 empty_vroot_show_nodes (FilterTest    *fixture,
1204                         gconstpointer  user_data)
1205 {
1206   GtkTreePath *path = (GtkTreePath *)user_data;
1207
1208   check_filter_model_with_root (fixture, path);
1209   check_level_length (fixture->filter, NULL, 0);
1210
1211   set_path_visibility (fixture, "2", TRUE);
1212   check_filter_model_with_root (fixture, path);
1213   check_level_length (fixture->filter, NULL, 0);
1214
1215   set_path_visibility (fixture, "2:2:2", TRUE);
1216   check_filter_model_with_root (fixture, path);
1217   check_level_length (fixture->filter, NULL, 0);
1218
1219   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1220   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1221   set_path_visibility (fixture, "2:2", TRUE);
1222   check_filter_model_with_root (fixture, path);
1223   check_level_length (fixture->filter, NULL, 1);
1224   check_level_length (fixture->filter, "0", 1);
1225   check_level_length (fixture->filter, "0:0", 0);
1226
1227   set_path_visibility (fixture, "3", TRUE);
1228   check_filter_model_with_root (fixture, path);
1229   check_level_length (fixture->filter, NULL, 1);
1230
1231   signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
1232   set_path_visibility (fixture, "2:2", FALSE);
1233   check_filter_model_with_root (fixture, path);
1234   check_level_length (fixture->filter, NULL, 0);
1235
1236   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1237   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1238   set_path_visibility (fixture, "2:2:1", TRUE);
1239   set_path_visibility (fixture, "2:2", TRUE);
1240   check_filter_model_with_root (fixture, path);
1241   check_level_length (fixture->filter, NULL, 1);
1242   check_level_length (fixture->filter, "0", 2);
1243   check_level_length (fixture->filter, "0:1", 0);
1244 }
1245
1246 static void
1247 empty_vroot_show_multiple_nodes (FilterTest    *fixture,
1248                                  gconstpointer  user_data)
1249 {
1250   GtkTreeIter iter;
1251   GtkTreePath *changed_path;
1252   GtkTreePath *path = (GtkTreePath *)user_data;
1253
1254   check_filter_model_with_root (fixture, path);
1255   check_level_length (fixture->filter, NULL, 0);
1256
1257   /* We simulate a change in visible func condition with this.  The
1258    * visibility state of multiple nodes changes at once, we emit row-changed
1259    * for these nodes (and others) after that.
1260    */
1261   filter_test_block_signals (fixture);
1262   set_path_visibility (fixture, "2", TRUE);
1263   set_path_visibility (fixture, "3", TRUE);
1264   filter_test_unblock_signals (fixture);
1265
1266   changed_path = gtk_tree_path_new ();
1267   gtk_tree_path_append_index (changed_path, 1);
1268   gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->store),
1269                            &iter, changed_path);
1270   gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1271                               changed_path, &iter);
1272
1273   gtk_tree_path_next (changed_path);
1274   gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &iter);
1275   gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1276                               changed_path, &iter);
1277
1278   gtk_tree_path_next (changed_path);
1279   gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &iter);
1280   gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1281                               changed_path, &iter);
1282
1283   gtk_tree_path_next (changed_path);
1284   gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &iter);
1285   gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1286                               changed_path, &iter);
1287
1288   gtk_tree_path_free (changed_path);
1289
1290   check_filter_model_with_root (fixture, path);
1291   check_level_length (fixture->filter, NULL, 0);
1292
1293   set_path_visibility (fixture, "2:2:2", TRUE);
1294   check_filter_model_with_root (fixture, path);
1295   check_level_length (fixture->filter, NULL, 0);
1296
1297   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1298   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1299   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "1");
1300   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "1");
1301
1302   /* Again, we simulate a call to refilter */
1303   filter_test_block_signals (fixture);
1304   set_path_visibility (fixture, "2:2", TRUE);
1305   set_path_visibility (fixture, "2:3", TRUE);
1306   filter_test_unblock_signals (fixture);
1307
1308   changed_path = gtk_tree_path_new ();
1309   gtk_tree_path_append_index (changed_path, 2);
1310   gtk_tree_path_append_index (changed_path, 1);
1311   gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->store),
1312                            &iter, changed_path);
1313   gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1314                               changed_path, &iter);
1315
1316   gtk_tree_path_next (changed_path);
1317   gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &iter);
1318   gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1319                               changed_path, &iter);
1320
1321   gtk_tree_path_next (changed_path);
1322   gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &iter);
1323   gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1324                               changed_path, &iter);
1325
1326   gtk_tree_path_next (changed_path);
1327   gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &iter);
1328   gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1329                               changed_path, &iter);
1330
1331   gtk_tree_path_free (changed_path);
1332
1333   check_filter_model_with_root (fixture, path);
1334   check_level_length (fixture->filter, NULL, 2);
1335   check_level_length (fixture->filter, "0", 1);
1336   check_level_length (fixture->filter, "0:0", 0);
1337
1338   set_path_visibility (fixture, "3", TRUE);
1339   check_filter_model_with_root (fixture, path);
1340   check_level_length (fixture->filter, NULL, 2);
1341
1342   signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
1343   set_path_visibility (fixture, "2:2", FALSE);
1344   check_filter_model_with_root (fixture, path);
1345   check_level_length (fixture->filter, NULL, 1);
1346
1347   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1348   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1349   set_path_visibility (fixture, "2:2:1", TRUE);
1350   set_path_visibility (fixture, "2:2", TRUE);
1351   check_filter_model_with_root (fixture, path);
1352   check_level_length (fixture->filter, NULL, 2);
1353   check_level_length (fixture->filter, "0", 2);
1354   check_level_length (fixture->filter, "0:1", 0);
1355 }
1356
1357
1358 static void
1359 unfiltered_hide_single (FilterTest    *fixture,
1360                         gconstpointer  user_data)
1361
1362 {
1363   signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2");
1364   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2");
1365   set_path_visibility (fixture, "2", FALSE);
1366
1367   signal_monitor_assert_is_empty (fixture->monitor);
1368   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1369
1370   /* The view only shows the root level, so we only expect signals
1371    * for the root level.
1372    */
1373   filter_test_append_refilter_signals (fixture, 1);
1374   filter_test_enable_filter (fixture);
1375
1376   check_filter_model (fixture);
1377   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 1);
1378 }
1379
1380 static void
1381 unfiltered_hide_single_root_expanded (FilterTest    *fixture,
1382                                       gconstpointer  user_data)
1383
1384 {
1385   signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2");
1386   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2");
1387   set_path_visibility (fixture, "2", FALSE);
1388
1389   signal_monitor_assert_is_empty (fixture->monitor);
1390   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1391
1392   filter_test_append_refilter_signals (fixture, 2);
1393   filter_test_enable_filter (fixture);
1394
1395   check_filter_model (fixture);
1396   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 1);
1397 }
1398
1399 static void
1400 unfiltered_hide_single_child (FilterTest    *fixture,
1401                               gconstpointer  user_data)
1402
1403 {
1404   /* This row is not shown, so its signal is not propagated */
1405   set_path_visibility (fixture, "2:2", FALSE);
1406
1407   signal_monitor_assert_is_empty (fixture->monitor);
1408   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1409   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1410
1411   /* The view only shows the root level, so we only expect signals
1412    * for the root level.
1413    */
1414   filter_test_append_refilter_signals (fixture, 0);
1415   filter_test_enable_filter (fixture);
1416
1417   check_filter_model (fixture);
1418   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1419   check_level_length (fixture->filter, "2", LEVEL_LENGTH - 1);
1420 }
1421
1422 static void
1423 unfiltered_hide_single_child_root_expanded (FilterTest    *fixture,
1424                                             gconstpointer  user_data)
1425
1426 {
1427   signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2:2");
1428   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
1429   set_path_visibility (fixture, "2:2", FALSE);
1430
1431   signal_monitor_assert_is_empty (fixture->monitor);
1432   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1433   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1434
1435   filter_test_append_refilter_signals (fixture, 2);
1436   filter_test_enable_filter (fixture);
1437
1438   check_filter_model (fixture);
1439   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1440   check_level_length (fixture->filter, "2", LEVEL_LENGTH - 1);
1441 }
1442
1443 static void
1444 unfiltered_hide_single_multi_level (FilterTest    *fixture,
1445                                     gconstpointer  user_data)
1446
1447 {
1448   /* This row is not shown, so its signal is not propagated */
1449   set_path_visibility (fixture, "2:2:2", FALSE);
1450
1451   /* This row is not shown, so its signal is not propagated */
1452   set_path_visibility (fixture, "2:2", FALSE);
1453
1454   signal_monitor_assert_is_empty (fixture->monitor);
1455   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1456   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1457   check_level_length (fixture->filter, "2:2", LEVEL_LENGTH);
1458
1459   /* The view only shows the root level, so we only expect signals
1460    * for the root level.
1461    */
1462   filter_test_append_refilter_signals (fixture, 1);
1463   filter_test_enable_filter (fixture);
1464
1465   check_filter_model (fixture);
1466   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1467   check_level_length (fixture->filter, "2", LEVEL_LENGTH - 1);
1468
1469   set_path_visibility (fixture, "2:2", TRUE);
1470
1471   check_filter_model (fixture);
1472   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1473   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1474   check_level_length (fixture->filter, "2:2", LEVEL_LENGTH - 1);
1475 }
1476
1477 static void
1478 unfiltered_hide_single_multi_level_root_expanded (FilterTest    *fixture,
1479                                                   gconstpointer  user_data)
1480
1481 {
1482   /* This row is not shown, so its signal is not propagated */
1483   set_path_visibility (fixture, "2:2:2", FALSE);
1484
1485   signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2:2");
1486   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
1487   set_path_visibility (fixture, "2:2", FALSE);
1488
1489   signal_monitor_assert_is_empty (fixture->monitor);
1490   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1491   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1492   check_level_length (fixture->filter, "2:2", LEVEL_LENGTH);
1493
1494   filter_test_append_refilter_signals (fixture, 2);
1495   filter_test_enable_filter (fixture);
1496
1497   check_filter_model (fixture);
1498   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1499   check_level_length (fixture->filter, "2", LEVEL_LENGTH - 1);
1500
1501   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "2:2");
1502   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
1503   set_path_visibility (fixture, "2:2", TRUE);
1504
1505   check_filter_model (fixture);
1506   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1507   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1508   check_level_length (fixture->filter, "2:2", LEVEL_LENGTH - 1);
1509 }
1510
1511
1512
1513 static void
1514 unfiltered_vroot_hide_single (FilterTest    *fixture,
1515                               gconstpointer  user_data)
1516
1517 {
1518   GtkTreePath *path = (GtkTreePath *)user_data;
1519
1520   signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2");
1521   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2");
1522   set_path_visibility (fixture, "2:2", FALSE);
1523
1524   signal_monitor_assert_is_empty (fixture->monitor);
1525   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1526
1527   /* The view only shows the root level, so we only expect signals
1528    * for the root level.  (Though for the depth argument, we have to
1529    * take the virtual root into account).
1530    */
1531   filter_test_append_refilter_signals_with_vroot (fixture, 2, path);
1532   filter_test_enable_filter (fixture);
1533
1534   check_filter_model_with_root (fixture, path);
1535   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 1);
1536 }
1537
1538 static void
1539 unfiltered_vroot_hide_single_child (FilterTest    *fixture,
1540                                     gconstpointer  user_data)
1541
1542 {
1543   GtkTreePath *path = (GtkTreePath *)user_data;
1544
1545   /* Not visible, so no signal will be received. */
1546   set_path_visibility (fixture, "2:2:2", FALSE);
1547
1548   signal_monitor_assert_is_empty (fixture->monitor);
1549   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1550   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1551
1552   /* The view only shows the root level, so we only expect signals
1553    * for the root level.  (Though for the depth argument, we have to
1554    * take the virtual root into account).
1555    */
1556   filter_test_append_refilter_signals_with_vroot (fixture, 2, path);
1557   filter_test_enable_filter (fixture);
1558
1559   check_filter_model_with_root (fixture, path);
1560   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1561   check_level_length (fixture->filter, "2", LEVEL_LENGTH - 1);
1562 }
1563
1564 static void
1565 unfiltered_vroot_hide_single_child_root_expanded (FilterTest    *fixture,
1566                                                   gconstpointer  user_data)
1567
1568 {
1569   GtkTreePath *path = (GtkTreePath *)user_data;
1570
1571   signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2:2");
1572   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
1573   set_path_visibility (fixture, "2:2:2", FALSE);
1574
1575   signal_monitor_assert_is_empty (fixture->monitor);
1576   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1577   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1578
1579   filter_test_append_refilter_signals_with_vroot (fixture, 3, path);
1580   filter_test_enable_filter (fixture);
1581
1582   check_filter_model_with_root (fixture, path);
1583   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1584   check_level_length (fixture->filter, "2", LEVEL_LENGTH - 1);
1585 }
1586
1587 static void
1588 unfiltered_vroot_hide_single_multi_level (FilterTest    *fixture,
1589                                           gconstpointer  user_data)
1590
1591 {
1592   GtkTreePath *path = (GtkTreePath *)user_data;
1593
1594   /* This row is not shown, so its signal is not propagated */
1595   set_path_visibility (fixture, "2:2:2:2", FALSE);
1596
1597   /* Not shown, so no signal */
1598   set_path_visibility (fixture, "2:2:2", FALSE);
1599
1600   signal_monitor_assert_is_empty (fixture->monitor);
1601   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1602   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1603   check_level_length (fixture->filter, "2:2", LEVEL_LENGTH);
1604
1605   /* We only expect signals for the root level.  The depth is 2
1606    * because we have to take the virtual root into account.
1607    */
1608   filter_test_append_refilter_signals_with_vroot (fixture, 2, path);
1609   filter_test_enable_filter (fixture);
1610
1611   check_filter_model_with_root (fixture, path);
1612   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1613   check_level_length (fixture->filter, "2", LEVEL_LENGTH - 1);
1614
1615   /* Not shown, so no signal */
1616   set_path_visibility (fixture, "2:2:2", TRUE);
1617
1618   check_filter_model_with_root (fixture, path);
1619   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1620   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1621   check_level_length (fixture->filter, "2:2", LEVEL_LENGTH - 1);
1622 }
1623
1624 static void
1625 unfiltered_vroot_hide_single_multi_level_root_expanded (FilterTest    *fixture,
1626                                                         gconstpointer  user_data)
1627
1628 {
1629   GtkTreePath *path = (GtkTreePath *)user_data;
1630
1631   /* This row is not shown, so its signal is not propagated */
1632   set_path_visibility (fixture, "2:2:2:2", FALSE);
1633
1634   signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2:2");
1635   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
1636   set_path_visibility (fixture, "2:2:2", FALSE);
1637
1638   signal_monitor_assert_is_empty (fixture->monitor);
1639   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1640   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1641   check_level_length (fixture->filter, "2:2", LEVEL_LENGTH);
1642
1643   filter_test_append_refilter_signals_with_vroot (fixture, 3, path);
1644   filter_test_enable_filter (fixture);
1645
1646   check_filter_model_with_root (fixture, path);
1647   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1648   check_level_length (fixture->filter, "2", LEVEL_LENGTH - 1);
1649
1650   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "2:2");
1651   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
1652   set_path_visibility (fixture, "2:2:2", TRUE);
1653
1654   check_filter_model_with_root (fixture, path);
1655   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1656   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1657   check_level_length (fixture->filter, "2:2", LEVEL_LENGTH - 1);
1658 }
1659
1660 static void
1661 unfiltered_show_single (FilterTest    *fixture,
1662                         gconstpointer  user_data)
1663
1664 {
1665   signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2");
1666   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2");
1667   set_path_visibility (fixture, "2", TRUE);
1668
1669   signal_monitor_assert_is_empty (fixture->monitor);
1670   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1671
1672   /* We only expect signals for the root level */
1673   filter_test_append_refilter_signals (fixture, 1);
1674   filter_test_enable_filter (fixture);
1675
1676   check_filter_model (fixture);
1677   check_level_length (fixture->filter, NULL, 1);
1678 }
1679
1680 static void
1681 unfiltered_show_single_child (FilterTest    *fixture,
1682                               gconstpointer  user_data)
1683
1684 {
1685   set_path_visibility (fixture, "2:2", TRUE);
1686
1687   signal_monitor_assert_is_empty (fixture->monitor);
1688   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1689   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1690
1691   /* We only expect signals for the root level */
1692   filter_test_append_refilter_signals (fixture, 1);
1693   filter_test_enable_filter (fixture);
1694
1695   check_filter_model (fixture);
1696   check_level_length (fixture->filter, NULL, 0);
1697
1698   /* From here we are filtered, "2" in the real model is "0" in the filter
1699    * model.
1700    */
1701   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1702   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1703   set_path_visibility (fixture, "2", TRUE);
1704   signal_monitor_assert_is_empty (fixture->monitor);
1705   check_level_length (fixture->filter, NULL, 1);
1706   check_level_length (fixture->filter, "0", 1);
1707 }
1708
1709 static void
1710 unfiltered_show_single_child_root_expanded (FilterTest    *fixture,
1711                                             gconstpointer  user_data)
1712
1713 {
1714   signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2:2");
1715   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
1716   set_path_visibility (fixture, "2:2", TRUE);
1717
1718   signal_monitor_assert_is_empty (fixture->monitor);
1719   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1720   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1721
1722   filter_test_append_refilter_signals (fixture, 2);
1723   filter_test_enable_filter (fixture);
1724
1725   check_filter_model (fixture);
1726   check_level_length (fixture->filter, NULL, 0);
1727
1728   /* From here we are filtered, "2" in the real model is "0" in the filter
1729    * model.
1730    */
1731   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1732   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1733   set_path_visibility (fixture, "2", TRUE);
1734   signal_monitor_assert_is_empty (fixture->monitor);
1735   check_level_length (fixture->filter, NULL, 1);
1736   check_level_length (fixture->filter, "0", 1);
1737 }
1738
1739 static void
1740 unfiltered_show_single_multi_level (FilterTest    *fixture,
1741                                     gconstpointer  user_data)
1742
1743 {
1744   /* The view is not showing these rows (collapsed state), so it is not
1745    * referenced.  The signal should not go through.
1746    */
1747   set_path_visibility (fixture, "2:2:2", TRUE);
1748   set_path_visibility (fixture, "2:2", TRUE);
1749
1750   signal_monitor_assert_is_empty (fixture->monitor);
1751   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1752   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1753   check_level_length (fixture->filter, "2:2", LEVEL_LENGTH);
1754
1755   /* We only expect signals for the first level */
1756   filter_test_append_refilter_signals (fixture, 1);
1757   filter_test_enable_filter (fixture);
1758
1759   check_filter_model (fixture);
1760   check_level_length (fixture->filter, NULL, 0);
1761
1762   /* From here we are filtered, "2" in the real model is "0" in the filter
1763    * model.
1764    */
1765   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1766   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1767   set_path_visibility (fixture, "2", TRUE);
1768   check_filter_model (fixture);
1769   check_level_length (fixture->filter, NULL, 1);
1770   check_level_length (fixture->filter, "0", 1);
1771   check_level_length (fixture->filter, "0:0", 1);
1772 }
1773
1774 static void
1775 unfiltered_show_single_multi_level_root_expanded (FilterTest    *fixture,
1776                                                   gconstpointer  user_data)
1777
1778 {
1779   /* The view is not showing this row (collapsed state), so it is not
1780    * referenced.  The signal should not go through.
1781    */
1782   set_path_visibility (fixture, "2:2:2", TRUE);
1783
1784   signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2:2");
1785   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
1786   set_path_visibility (fixture, "2:2", TRUE);
1787
1788   signal_monitor_assert_is_empty (fixture->monitor);
1789   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1790   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1791   check_level_length (fixture->filter, "2:2", LEVEL_LENGTH);
1792
1793   filter_test_append_refilter_signals (fixture, 2);
1794   filter_test_enable_filter (fixture);
1795
1796   check_filter_model (fixture);
1797   check_level_length (fixture->filter, NULL, 0);
1798
1799   /* From here we are filtered, "2" in the real model is "0" in the filter
1800    * model.
1801    */
1802   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1803   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1804   set_path_visibility (fixture, "2", TRUE);
1805   check_filter_model (fixture);
1806   check_level_length (fixture->filter, NULL, 1);
1807   check_level_length (fixture->filter, "0", 1);
1808   check_level_length (fixture->filter, "0:0", 1);
1809 }
1810
1811 static void
1812 unfiltered_vroot_show_single (FilterTest    *fixture,
1813                               gconstpointer  user_data)
1814
1815 {
1816   GtkTreePath *path = (GtkTreePath *)user_data;
1817
1818   signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2");
1819   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2");
1820   set_path_visibility (fixture, "2:2", TRUE);
1821
1822   signal_monitor_assert_is_empty (fixture->monitor);
1823   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1824
1825   /* The view only shows the root level, so the filter model only has
1826    * the first two levels cached.
1827    */
1828   filter_test_append_refilter_signals_with_vroot (fixture, 2, path);
1829   filter_test_enable_filter (fixture);
1830
1831   check_filter_model_with_root (fixture, path);
1832   check_level_length (fixture->filter, NULL, 1);
1833 }
1834
1835 static void
1836 unfiltered_vroot_show_single_child (FilterTest    *fixture,
1837                                     gconstpointer  user_data)
1838
1839 {
1840   GtkTreePath *path = (GtkTreePath *)user_data;
1841
1842   set_path_visibility (fixture, "2:2:2", TRUE);
1843
1844   signal_monitor_assert_is_empty (fixture->monitor);
1845   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1846   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1847
1848   /* The view only shows the root level, so the filter model only has
1849    * the first two levels cached.
1850    */
1851   filter_test_append_refilter_signals_with_vroot (fixture, 2, path);
1852   filter_test_enable_filter (fixture);
1853
1854   check_filter_model_with_root (fixture, path);
1855   check_level_length (fixture->filter, NULL, 0);
1856
1857   /* From here we are filtered, "2" in the real model is "0" in the filter
1858    * model.
1859    */
1860   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1861   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1862   set_path_visibility (fixture, "2:2", TRUE);
1863   signal_monitor_assert_is_empty (fixture->monitor);
1864   check_level_length (fixture->filter, NULL, 1);
1865   check_level_length (fixture->filter, "0", 1);
1866 }
1867
1868 static void
1869 unfiltered_vroot_show_single_child_root_expanded (FilterTest    *fixture,
1870                                                   gconstpointer  user_data)
1871
1872 {
1873   GtkTreePath *path = (GtkTreePath *)user_data;
1874
1875   signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2:2");
1876   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
1877   set_path_visibility (fixture, "2:2:2", TRUE);
1878
1879   signal_monitor_assert_is_empty (fixture->monitor);
1880   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1881   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1882
1883   filter_test_append_refilter_signals_with_vroot (fixture, 3, path);
1884   filter_test_enable_filter (fixture);
1885
1886   check_filter_model_with_root (fixture, path);
1887   check_level_length (fixture->filter, NULL, 0);
1888
1889   /* From here we are filtered, "2" in the real model is "0" in the filter
1890    * model.
1891    */
1892   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1893   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1894   set_path_visibility (fixture, "2:2", TRUE);
1895   signal_monitor_assert_is_empty (fixture->monitor);
1896   check_level_length (fixture->filter, NULL, 1);
1897   check_level_length (fixture->filter, "0", 1);
1898 }
1899
1900
1901 static void
1902 unfiltered_vroot_show_single_multi_level (FilterTest    *fixture,
1903                                           gconstpointer  user_data)
1904
1905 {
1906   GtkTreePath *path = (GtkTreePath *)user_data;
1907
1908   /* The view is not showing this row (collapsed state), so it is not
1909    * referenced.  The signal should not go through.
1910    */
1911   set_path_visibility (fixture, "2:2:2:2", TRUE);
1912
1913   set_path_visibility (fixture, "2:2:2", TRUE);
1914
1915   signal_monitor_assert_is_empty (fixture->monitor);
1916   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1917   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1918   check_level_length (fixture->filter, "2:2", LEVEL_LENGTH);
1919
1920   /* We only expect signals for the root level */
1921   filter_test_append_refilter_signals_with_vroot (fixture, 2, path);
1922   filter_test_enable_filter (fixture);
1923
1924   check_filter_model_with_root (fixture, path);
1925   check_level_length (fixture->filter, NULL, 0);
1926
1927   /* From here we are filtered, "2" in the real model is "0" in the filter
1928    * model.
1929    */
1930   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1931   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1932   set_path_visibility (fixture, "2:2", TRUE);
1933   check_filter_model_with_root (fixture, path);
1934   check_level_length (fixture->filter, NULL, 1);
1935   check_level_length (fixture->filter, "0", 1);
1936   check_level_length (fixture->filter, "0:0", 1);
1937 }
1938
1939 static void
1940 unfiltered_vroot_show_single_multi_level_root_expanded (FilterTest    *fixture,
1941                                                         gconstpointer  user_data)
1942
1943 {
1944   GtkTreePath *path = (GtkTreePath *)user_data;
1945
1946   /* The view is not showing this row (collapsed state), so it is not
1947    * referenced.  The signal should not go through.
1948    */
1949   set_path_visibility (fixture, "2:2:2:2", TRUE);
1950
1951   signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2:2");
1952   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
1953   set_path_visibility (fixture, "2:2:2", TRUE);
1954
1955   signal_monitor_assert_is_empty (fixture->monitor);
1956   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1957   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1958   check_level_length (fixture->filter, "2:2", LEVEL_LENGTH);
1959
1960   filter_test_append_refilter_signals_with_vroot (fixture, 3, path);
1961   filter_test_enable_filter (fixture);
1962
1963   check_filter_model_with_root (fixture, path);
1964   check_level_length (fixture->filter, NULL, 0);
1965
1966   /* From here we are filtered, "2" in the real model is "0" in the filter
1967    * model.
1968    */
1969   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1970   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1971   set_path_visibility (fixture, "2:2", TRUE);
1972   check_filter_model_with_root (fixture, path);
1973   check_level_length (fixture->filter, NULL, 1);
1974   check_level_length (fixture->filter, "0", 1);
1975   check_level_length (fixture->filter, "0:0", 1);
1976 }
1977
1978 static void
1979 unfiltered_rows_reordered_root_level (FilterTest    *fixture,
1980                                       gconstpointer  user_data)
1981 {
1982   int order0[] = { 1, 2, 3, 4, 0 };
1983   int order1[] = { 0, 2, 1, 3, 4 };
1984   int order2[] = { 4, 0, 1, 2, 3 };
1985   GtkTreeIter iter0, iter1, iter2, iter3, iter4;
1986   GtkTreePath *path;
1987
1988   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
1989                                        &iter0, "0");
1990   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
1991                                        &iter1, "1");
1992   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
1993                                        &iter2, "2");
1994   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
1995                                        &iter3, "3");
1996   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
1997                                        &iter4, "4");
1998
1999   path = gtk_tree_path_new ();
2000   signal_monitor_append_signal_reordered (fixture->monitor,
2001                                           ROWS_REORDERED,
2002                                           path, order0, 5);
2003   gtk_tree_store_move_after (fixture->store, &iter0, &iter4);
2004   signal_monitor_assert_is_empty (fixture->monitor);
2005
2006   signal_monitor_append_signal_reordered (fixture->monitor,
2007                                           ROWS_REORDERED,
2008                                           path, order1, 5);
2009   gtk_tree_store_move_after (fixture->store, &iter2, &iter3);
2010   signal_monitor_assert_is_empty (fixture->monitor);
2011
2012   signal_monitor_append_signal_reordered (fixture->monitor,
2013                                           ROWS_REORDERED,
2014                                           path, order2, 5);
2015   gtk_tree_store_move_before (fixture->store, &iter0, &iter1);
2016   signal_monitor_assert_is_empty (fixture->monitor);
2017
2018   gtk_tree_path_free (path);
2019 }
2020
2021 static void
2022 unfiltered_rows_reordered_child_level (FilterTest    *fixture,
2023                                        gconstpointer  user_data)
2024 {
2025   int order0[] = { 1, 2, 3, 4, 0 };
2026   int order1[] = { 0, 2, 1, 3, 4 };
2027   int order2[] = { 4, 0, 1, 2, 3 };
2028   GtkTreeIter iter0, iter1, iter2, iter3, iter4;
2029   GtkTreePath *path;
2030
2031   /* Expand row 0 */
2032   path = gtk_tree_path_new_from_indices (0, -1);
2033   gtk_tree_view_expand_row (GTK_TREE_VIEW (fixture->tree_view), path, FALSE);
2034
2035   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2036                                        &iter0, "0:0");
2037   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2038                                        &iter1, "0:1");
2039   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2040                                        &iter2, "0:2");
2041   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2042                                        &iter3, "0:3");
2043   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2044                                        &iter4, "0:4");
2045
2046   signal_monitor_append_signal_reordered (fixture->monitor,
2047                                           ROWS_REORDERED,
2048                                           path, order0, 5);
2049   gtk_tree_store_move_after (fixture->store, &iter0, &iter4);
2050   signal_monitor_assert_is_empty (fixture->monitor);
2051
2052   signal_monitor_append_signal_reordered (fixture->monitor,
2053                                           ROWS_REORDERED,
2054                                           path, order1, 5);
2055   gtk_tree_store_move_after (fixture->store, &iter2, &iter3);
2056   signal_monitor_assert_is_empty (fixture->monitor);
2057
2058   signal_monitor_append_signal_reordered (fixture->monitor,
2059                                           ROWS_REORDERED,
2060                                           path, order2, 5);
2061   gtk_tree_store_move_before (fixture->store, &iter0, &iter1);
2062   signal_monitor_assert_is_empty (fixture->monitor);
2063
2064   gtk_tree_path_free (path);
2065 }
2066
2067 static void
2068 filtered_rows_reordered_root_level_first_hidden (FilterTest    *fixture,
2069                                                  gconstpointer  user_data)
2070 {
2071   int order0[] = { 1, 2, 3, 0 };
2072   int order1[] = { 0, 2, 1, 3 };
2073   int order2[] = { 3, 0, 1, 2 };
2074   GtkTreeIter iter1, iter2, iter3, iter4;
2075   GtkTreePath *path;
2076
2077   /* Hide middle path */
2078   signal_monitor_append_signal (fixture->monitor,
2079                                 ROW_DELETED, "0");
2080   set_path_visibility (fixture, "0", FALSE);
2081   signal_monitor_assert_is_empty (fixture->monitor);
2082
2083   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2084                                        &iter1, "1");
2085   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2086                                        &iter2, "2");
2087   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2088                                        &iter3, "3");
2089   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2090                                        &iter4, "4");
2091
2092   path = gtk_tree_path_new ();
2093   signal_monitor_append_signal_reordered (fixture->monitor,
2094                                           ROWS_REORDERED,
2095                                           path, order0, 4);
2096   gtk_tree_store_move_after (fixture->store, &iter1, &iter4);
2097   signal_monitor_assert_is_empty (fixture->monitor);
2098
2099   signal_monitor_append_signal_reordered (fixture->monitor,
2100                                           ROWS_REORDERED,
2101                                           path, order1, 4);
2102   gtk_tree_store_move_after (fixture->store, &iter3, &iter4);
2103   signal_monitor_assert_is_empty (fixture->monitor);
2104
2105   signal_monitor_append_signal_reordered (fixture->monitor,
2106                                           ROWS_REORDERED,
2107                                           path, order2, 4);
2108   gtk_tree_store_move_before (fixture->store, &iter1, &iter2);
2109   signal_monitor_assert_is_empty (fixture->monitor);
2110
2111   gtk_tree_path_free (path);
2112 }
2113
2114 static void
2115 filtered_rows_reordered_root_level_middle_hidden (FilterTest    *fixture,
2116                                                   gconstpointer  user_data)
2117 {
2118   int order0[] = { 1, 2, 3, 0 };
2119   int order1[] = { 0, 2, 1, 3 };
2120   int order2[] = { 3, 0, 1, 2 };
2121   GtkTreeIter iter0, iter1, iter3, iter4;
2122   GtkTreePath *path;
2123
2124   /* Hide middle path */
2125   signal_monitor_append_signal (fixture->monitor,
2126                                 ROW_DELETED, "2");
2127   set_path_visibility (fixture, "2", FALSE);
2128   signal_monitor_assert_is_empty (fixture->monitor);
2129
2130   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2131                                        &iter0, "0");
2132   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2133                                        &iter1, "1");
2134   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2135                                        &iter3, "3");
2136   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2137                                        &iter4, "4");
2138
2139   path = gtk_tree_path_new ();
2140   signal_monitor_append_signal_reordered (fixture->monitor,
2141                                           ROWS_REORDERED,
2142                                           path, order0, 4);
2143   gtk_tree_store_move_after (fixture->store, &iter0, &iter4);
2144   signal_monitor_assert_is_empty (fixture->monitor);
2145
2146   signal_monitor_append_signal_reordered (fixture->monitor,
2147                                           ROWS_REORDERED,
2148                                           path, order1, 4);
2149   gtk_tree_store_move_after (fixture->store, &iter3, &iter4);
2150   signal_monitor_assert_is_empty (fixture->monitor);
2151
2152   signal_monitor_append_signal_reordered (fixture->monitor,
2153                                           ROWS_REORDERED,
2154                                           path, order2, 4);
2155   gtk_tree_store_move_before (fixture->store, &iter0, &iter1);
2156   signal_monitor_assert_is_empty (fixture->monitor);
2157
2158   gtk_tree_path_free (path);
2159 }
2160
2161 static void
2162 filtered_rows_reordered_child_level_first_hidden (FilterTest    *fixture,
2163                                                   gconstpointer  user_data)
2164 {
2165   int order0[] = { 1, 2, 3, 0 };
2166   int order1[] = { 0, 2, 1, 3 };
2167   int order2[] = { 3, 0, 1, 2 };
2168   GtkTreeIter iter1, iter2, iter3, iter4;
2169   GtkTreePath *path;
2170
2171   /* Expand row 0 */
2172   path = gtk_tree_path_new_from_indices (0, -1);
2173   gtk_tree_view_expand_row (GTK_TREE_VIEW (fixture->tree_view), path, TRUE);
2174
2175   /* Hide middle path */
2176   signal_monitor_append_signal (fixture->monitor,
2177                                 ROW_DELETED, "0:0");
2178   set_path_visibility (fixture, "0:0", FALSE);
2179   signal_monitor_assert_is_empty (fixture->monitor);
2180
2181   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2182                                        &iter1, "0:1");
2183   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2184                                        &iter2, "0:2");
2185   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2186                                        &iter3, "0:3");
2187   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2188                                        &iter4, "0:4");
2189
2190   signal_monitor_append_signal_reordered (fixture->monitor,
2191                                           ROWS_REORDERED,
2192                                           path, order0, 4);
2193   gtk_tree_store_move_after (fixture->store, &iter1, &iter4);
2194   signal_monitor_assert_is_empty (fixture->monitor);
2195
2196   signal_monitor_append_signal_reordered (fixture->monitor,
2197                                           ROWS_REORDERED,
2198                                           path, order1, 4);
2199   gtk_tree_store_move_after (fixture->store, &iter3, &iter4);
2200   signal_monitor_assert_is_empty (fixture->monitor);
2201
2202   signal_monitor_append_signal_reordered (fixture->monitor,
2203                                           ROWS_REORDERED,
2204                                           path, order2, 4);
2205   gtk_tree_store_move_before (fixture->store, &iter1, &iter2);
2206   signal_monitor_assert_is_empty (fixture->monitor);
2207
2208   gtk_tree_path_free (path);
2209 }
2210
2211 static void
2212 filtered_rows_reordered_child_level_middle_hidden (FilterTest    *fixture,
2213                                                    gconstpointer  user_data)
2214 {
2215   int order0[] = { 1, 2, 3, 0 };
2216   int order1[] = { 0, 2, 1, 3 };
2217   int order2[] = { 3, 0, 1, 2 };
2218   GtkTreeIter iter0, iter1, iter3, iter4;
2219   GtkTreePath *path;
2220
2221   /* Expand row 0 */
2222   path = gtk_tree_path_new_from_indices (0, -1);
2223   gtk_tree_view_expand_row (GTK_TREE_VIEW (fixture->tree_view), path, FALSE);
2224
2225   /* Hide middle path */
2226   signal_monitor_append_signal (fixture->monitor,
2227                                 ROW_DELETED, "0:2");
2228   set_path_visibility (fixture, "0:2", FALSE);
2229   signal_monitor_assert_is_empty (fixture->monitor);
2230
2231   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2232                                        &iter0, "0:0");
2233   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2234                                        &iter1, "0:1");
2235   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2236                                        &iter3, "0:3");
2237   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2238                                        &iter4, "0:4");
2239
2240   signal_monitor_append_signal_reordered (fixture->monitor,
2241                                           ROWS_REORDERED,
2242                                           path, order0, 4);
2243   gtk_tree_store_move_after (fixture->store, &iter0, &iter4);
2244   signal_monitor_assert_is_empty (fixture->monitor);
2245
2246   signal_monitor_append_signal_reordered (fixture->monitor,
2247                                           ROWS_REORDERED,
2248                                           path, order1, 4);
2249   gtk_tree_store_move_after (fixture->store, &iter3, &iter4);
2250   signal_monitor_assert_is_empty (fixture->monitor);
2251
2252   signal_monitor_append_signal_reordered (fixture->monitor,
2253                                           ROWS_REORDERED,
2254                                           path, order2, 4);
2255   gtk_tree_store_move_before (fixture->store, &iter0, &iter1);
2256   signal_monitor_assert_is_empty (fixture->monitor);
2257
2258   gtk_tree_path_free (path);
2259 }
2260
2261 static void
2262 filtered_rows_reordered_child_level_4_hidden (FilterTest    *fixture,
2263                                               gconstpointer  user_data)
2264 {
2265   int order0[] = { 0 };
2266   GtkTreeIter iter1, iter4;
2267   GtkTreePath *path;
2268
2269   /* Expand row 0 */
2270   path = gtk_tree_path_new_from_indices (0, -1);
2271   gtk_tree_view_expand_row (GTK_TREE_VIEW (fixture->tree_view), path, FALSE);
2272
2273   /* Hide last 4 paths */
2274   signal_monitor_append_signal (fixture->monitor,
2275                                 ROW_DELETED, "0:4");
2276   signal_monitor_append_signal (fixture->monitor,
2277                                 ROW_DELETED, "0:3");
2278   signal_monitor_append_signal (fixture->monitor,
2279                                 ROW_DELETED, "0:2");
2280   signal_monitor_append_signal (fixture->monitor,
2281                                 ROW_DELETED, "0:0");
2282   set_path_visibility (fixture, "0:4", FALSE);
2283   set_path_visibility (fixture, "0:3", FALSE);
2284   set_path_visibility (fixture, "0:2", FALSE);
2285   set_path_visibility (fixture, "0:0", FALSE);
2286   signal_monitor_assert_is_empty (fixture->monitor);
2287
2288   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2289                                        &iter1, "0:1");
2290   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2291                                        &iter4, "0:4");
2292
2293   signal_monitor_append_signal_reordered (fixture->monitor,
2294                                           ROWS_REORDERED,
2295                                           path, order0, 1);
2296   gtk_tree_store_move_after (fixture->store, &iter1, &iter4);
2297   signal_monitor_assert_is_empty (fixture->monitor);
2298
2299   gtk_tree_path_free (path);
2300 }
2301
2302 static void
2303 filtered_rows_reordered_child_level_all_hidden (FilterTest    *fixture,
2304                                                 gconstpointer  user_data)
2305 {
2306   GtkTreeIter iter1, iter4;
2307   GtkTreePath *path;
2308
2309   /* Expand row 0 */
2310   path = gtk_tree_path_new_from_indices (0, -1);
2311   gtk_tree_view_expand_row (GTK_TREE_VIEW (fixture->tree_view), path, FALSE);
2312   gtk_tree_path_free (path);
2313
2314   /* Hide last 4 paths */
2315   signal_monitor_append_signal (fixture->monitor,
2316                                 ROW_DELETED, "0:4");
2317   signal_monitor_append_signal (fixture->monitor,
2318                                 ROW_DELETED, "0:3");
2319   signal_monitor_append_signal (fixture->monitor,
2320                                 ROW_DELETED, "0:2");
2321   signal_monitor_append_signal (fixture->monitor,
2322                                 ROW_DELETED, "0:1");
2323   signal_monitor_append_signal (fixture->monitor,
2324                                 ROW_DELETED, "0:0");
2325   signal_monitor_append_signal (fixture->monitor,
2326                                 ROW_HAS_CHILD_TOGGLED, "0");
2327   set_path_visibility (fixture, "0:4", FALSE);
2328   set_path_visibility (fixture, "0:3", FALSE);
2329   set_path_visibility (fixture, "0:2", FALSE);
2330   set_path_visibility (fixture, "0:1", FALSE);
2331   set_path_visibility (fixture, "0:0", FALSE);
2332   signal_monitor_assert_is_empty (fixture->monitor);
2333
2334   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2335                                        &iter1, "0:1");
2336   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2337                                        &iter4, "0:4");
2338
2339   gtk_tree_store_move_after (fixture->store, &iter1, &iter4);
2340   signal_monitor_assert_is_empty (fixture->monitor);
2341 }
2342
2343 static void
2344 insert_before (void)
2345 {
2346   GtkTreeStore *store;
2347   GtkTreeModel *filter;
2348   GtkWidget *tree_view;
2349   SignalMonitor *monitor;
2350   GtkTreeIter iter;
2351   GtkTreeIter last_iter;
2352   GtkTreePath *path;
2353
2354   /* This tests two aspects of the row-inserted handling:
2355    *   1) If the newly inserted node was already handled by building
2356    *      the root level, don't handle it a second time.
2357    *   2) Offsets of existing nodes must be updated when a new
2358    *      node is inserted.
2359    */
2360
2361   store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
2362   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
2363   gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter),
2364                                             1);
2365
2366   tree_view = gtk_tree_view_new_with_model (filter);
2367   monitor = signal_monitor_new (filter);
2368
2369   check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, 0);
2370
2371   /* Insert 0 */
2372   path = gtk_tree_path_new_from_indices (0, -1);
2373   signal_monitor_append_signal_path (monitor, ROW_INSERTED, path);
2374   gtk_tree_path_free (path);
2375
2376   gtk_tree_store_insert_with_values (store, &iter, NULL, 0,
2377                                      0, "Foo", 1, TRUE, -1);
2378
2379   signal_monitor_assert_is_empty (monitor);
2380   check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, 1);
2381
2382   /* Insert 1 */
2383   path = gtk_tree_path_new_from_indices (1, -1);
2384   signal_monitor_append_signal_path (monitor, ROW_INSERTED, path);
2385   gtk_tree_path_free (path);
2386
2387   gtk_tree_store_insert_with_values (store, &iter, NULL, 1,
2388                                      0, "Foo", 1, TRUE, -1);
2389   last_iter = iter;
2390
2391   signal_monitor_assert_is_empty (monitor);
2392   check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, 2);
2393
2394   /* Insert on 1 again -- invisible */
2395   gtk_tree_store_insert_with_values (store, &iter, NULL, 1,
2396                                      0, "Foo", 1, FALSE, -1);
2397
2398   signal_monitor_assert_is_empty (monitor);
2399   check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, 2);
2400
2401   /* Insert on 1 again -- visible */
2402   path = gtk_tree_path_new_from_indices (1, -1);
2403   signal_monitor_append_signal_path (monitor, ROW_INSERTED, path);
2404   gtk_tree_path_free (path);
2405
2406   gtk_tree_store_insert_with_values (store, &iter, NULL, 1,
2407                                      0, "Foo", 1, TRUE, -1);
2408
2409   signal_monitor_assert_is_empty (monitor);
2410   check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, 3);
2411
2412   /* Modify the iter that should be at the last position and check the
2413    * signal we get.
2414    */
2415   path = gtk_tree_path_new_from_indices (2, -1);
2416   signal_monitor_append_signal_path (monitor, ROW_CHANGED, path);
2417   gtk_tree_path_free (path);
2418
2419   gtk_tree_store_set (store, &last_iter, 0, "Foo changed", -1);
2420
2421   signal_monitor_assert_is_empty (monitor);
2422   check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, 3);
2423 }
2424
2425 static void
2426 insert_child (void)
2427 {
2428   GtkTreeStore *store;
2429   GtkTreeModel *filter;
2430   GtkWidget *tree_view;
2431   SignalMonitor *monitor;
2432   GtkTreeIter parent, iter;
2433   GtkTreePath *path;
2434
2435   store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
2436
2437   gtk_tree_store_insert_with_values (store, &parent, NULL, 0,
2438                                      0, "Parent", 1, TRUE, -1);
2439
2440
2441   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
2442   gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter),
2443                                             1);
2444
2445   tree_view = gtk_tree_view_new_with_model (filter);
2446   monitor = signal_monitor_new (filter);
2447
2448   /* Insert child -- invisible */
2449   path = gtk_tree_path_new_from_indices (0, -1);
2450   signal_monitor_append_signal_path (monitor, ROW_HAS_CHILD_TOGGLED, path);
2451   /* The signal is received twice, once a pass through from GtkTreeStore
2452    * and one generated by GtkTreeModelFilter.  Not accurate, but cannot
2453    * hurt.
2454    */
2455   signal_monitor_append_signal_path (monitor, ROW_HAS_CHILD_TOGGLED, path);
2456   gtk_tree_path_free (path);
2457
2458   gtk_tree_store_insert_with_values (store, &iter, &parent, 1,
2459                                      0, "Child", 1, FALSE, -1);
2460
2461   signal_monitor_assert_is_empty (monitor);
2462   check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, 1);
2463
2464   /* Insert child */
2465   path = gtk_tree_path_new_from_indices (0, 0, -1);
2466   gtk_tree_path_up (path); /* 0 */
2467   signal_monitor_append_signal_path (monitor, ROW_HAS_CHILD_TOGGLED, path);
2468   gtk_tree_path_free (path);
2469
2470   gtk_tree_store_insert_with_values (store, &iter, &parent, 0,
2471                                      0, "Child", 1, TRUE, -1);
2472
2473   signal_monitor_assert_is_empty (monitor);
2474   check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, 1);
2475
2476   /* Insert child -- invisible */
2477   gtk_tree_store_insert_with_values (store, &iter, &parent, 1,
2478                                      0, "Child", 1, FALSE, -1);
2479
2480   signal_monitor_assert_is_empty (monitor);
2481   check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, 1);
2482 }
2483
2484
2485
2486 static void
2487 remove_node (void)
2488 {
2489   GtkTreeIter iter, iter1, iter2, iter3;
2490   GtkListStore *list;
2491   GtkTreeModel *filter;
2492   GtkWidget *view G_GNUC_UNUSED;
2493
2494   list = gtk_list_store_new (1, G_TYPE_INT);
2495   gtk_list_store_insert_with_values (list, &iter1, 0, 0, 1, -1);
2496   gtk_list_store_insert_with_values (list, &iter, 1, 0, 2, -1);
2497   gtk_list_store_insert_with_values (list, &iter, 2, 0, 3, -1);
2498   gtk_list_store_insert_with_values (list, &iter, 3, 0, 4, -1);
2499   gtk_list_store_insert_with_values (list, &iter, 4, 0, 5, -1);
2500   gtk_list_store_insert_with_values (list, &iter, 5, 0, 6, -1);
2501   gtk_list_store_insert_with_values (list, &iter2, 6, 0, 7, -1);
2502   gtk_list_store_insert_with_values (list, &iter3, 7, 0, 8, -1);
2503
2504   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (list), NULL);
2505   view = gtk_tree_view_new_with_model (filter);
2506
2507   gtk_list_store_remove (list, &iter1);
2508   gtk_list_store_remove (list, &iter3);
2509   gtk_list_store_remove (list, &iter2);
2510
2511   gtk_widget_destroy (view);
2512   g_object_unref (filter);
2513   g_object_unref (list);
2514 }
2515
2516 static void
2517 remove_node_vroot (void)
2518 {
2519   GtkTreeIter parent, root;
2520   GtkTreeIter iter, iter1, iter2, iter3;
2521   GtkTreeStore *tree;
2522   GtkTreeModel *filter;
2523   GtkTreePath *path;
2524   GtkWidget *view G_GNUC_UNUSED;
2525
2526   tree = gtk_tree_store_new (1, G_TYPE_INT);
2527   gtk_tree_store_insert_with_values (tree, &parent, NULL, 0, 0, 0, -1);
2528   gtk_tree_store_insert_with_values (tree, &root, &parent, 0, 0, 0, -1);
2529
2530   gtk_tree_store_insert_with_values (tree, &iter1, &root, 0, 0, 1, -1);
2531   gtk_tree_store_insert_with_values (tree, &iter, &root, 1, 0, 2, -1);
2532   gtk_tree_store_insert_with_values (tree, &iter, &root, 2, 0, 3, -1);
2533   gtk_tree_store_insert_with_values (tree, &iter, &root, 3, 0, 4, -1);
2534   gtk_tree_store_insert_with_values (tree, &iter, &root, 4, 0, 5, -1);
2535   gtk_tree_store_insert_with_values (tree, &iter, &root, 5, 0, 6, -1);
2536   gtk_tree_store_insert_with_values (tree, &iter2, &root, 6, 0, 7, -1);
2537   gtk_tree_store_insert_with_values (tree, &iter3, &root, 7, 0, 8, -1);
2538
2539   path = gtk_tree_path_new_from_indices (0, 0, -1);
2540   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (tree), path);
2541   gtk_tree_path_free (path);
2542
2543   view = gtk_tree_view_new_with_model (filter);
2544
2545   gtk_tree_store_remove (tree, &iter1);
2546   gtk_tree_store_remove (tree, &iter3);
2547   gtk_tree_store_remove (tree, &iter2);
2548
2549   gtk_widget_destroy (view);
2550   g_object_unref (filter);
2551   g_object_unref (tree);
2552 }
2553
2554 static void
2555 remove_vroot_ancestor (void)
2556 {
2557   GtkTreeIter parent, root;
2558   GtkTreeIter iter, iter1, iter2, iter3;
2559   GtkTreeStore *tree;
2560   GtkTreeModel *filter;
2561   GtkTreePath *path;
2562   GtkWidget *view G_GNUC_UNUSED;
2563
2564   tree = gtk_tree_store_new (1, G_TYPE_INT);
2565   gtk_tree_store_insert_with_values (tree, &parent, NULL, 0, 0, 0, -1);
2566   gtk_tree_store_insert_with_values (tree, &root, &parent, 0, 0, 0, -1);
2567
2568   gtk_tree_store_insert_with_values (tree, &iter1, &root, 0, 0, 1, -1);
2569   gtk_tree_store_insert_with_values (tree, &iter, &root, 1, 0, 2, -1);
2570   gtk_tree_store_insert_with_values (tree, &iter, &root, 2, 0, 3, -1);
2571   gtk_tree_store_insert_with_values (tree, &iter, &root, 3, 0, 4, -1);
2572   gtk_tree_store_insert_with_values (tree, &iter, &root, 4, 0, 5, -1);
2573   gtk_tree_store_insert_with_values (tree, &iter, &root, 5, 0, 6, -1);
2574   gtk_tree_store_insert_with_values (tree, &iter2, &root, 6, 0, 7, -1);
2575   gtk_tree_store_insert_with_values (tree, &iter3, &root, 7, 0, 8, -1);
2576
2577   path = gtk_tree_path_new_from_indices (0, 0, -1);
2578   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (tree), path);
2579   gtk_tree_path_free (path);
2580
2581   view = gtk_tree_view_new_with_model (filter);
2582
2583   gtk_tree_store_remove (tree, &parent);
2584
2585   gtk_widget_destroy (view);
2586   g_object_unref (filter);
2587   g_object_unref (tree);
2588 }
2589
2590 static void
2591 ref_count_single_level (void)
2592 {
2593   GtkTreeIter iter[5];
2594   GtkTreeModel *model;
2595   GtkTreeModelRefCount *ref_model;
2596   GtkTreeModel *filter_model;
2597   GtkWidget *tree_view;
2598
2599   model = gtk_tree_model_ref_count_new ();
2600   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
2601
2602   gtk_tree_store_append (GTK_TREE_STORE (model), &iter[0], NULL);
2603   gtk_tree_store_append (GTK_TREE_STORE (model), &iter[1], NULL);
2604   gtk_tree_store_append (GTK_TREE_STORE (model), &iter[2], NULL);
2605   gtk_tree_store_append (GTK_TREE_STORE (model), &iter[3], NULL);
2606   gtk_tree_store_append (GTK_TREE_STORE (model), &iter[4], NULL);
2607
2608   assert_root_level_unreferenced (ref_model);
2609
2610   filter_model = gtk_tree_model_filter_new (model, NULL);
2611   tree_view = gtk_tree_view_new_with_model (filter_model);
2612
2613   assert_node_ref_count (ref_model, &iter[0], 2);
2614   assert_node_ref_count (ref_model, &iter[1], 1);
2615   assert_node_ref_count (ref_model, &iter[2], 1);
2616   assert_node_ref_count (ref_model, &iter[3], 1);
2617   assert_node_ref_count (ref_model, &iter[4], 1);
2618
2619   gtk_widget_destroy (tree_view);
2620
2621   assert_node_ref_count (ref_model, &iter[0], 1);
2622   assert_node_ref_count (ref_model, &iter[1], 0);
2623   assert_node_ref_count (ref_model, &iter[2], 0);
2624   assert_node_ref_count (ref_model, &iter[3], 0);
2625   assert_node_ref_count (ref_model, &iter[4], 0);
2626
2627   g_object_unref (filter_model);
2628
2629   assert_node_ref_count (ref_model, &iter[0], 0);
2630
2631   g_object_unref (ref_model);
2632 }
2633
2634 static void
2635 ref_count_two_levels (void)
2636 {
2637   GtkTreeIter parent1, parent2, iter, iter_first;
2638   GtkTreeModel *model;
2639   GtkTreeModelRefCount *ref_model;
2640   GtkTreeModel *filter_model;
2641   GtkWidget *tree_view;
2642
2643   model = gtk_tree_model_ref_count_new ();
2644   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
2645
2646   gtk_tree_store_append (GTK_TREE_STORE (model), &parent1, NULL);
2647   gtk_tree_store_append (GTK_TREE_STORE (model), &parent2, NULL);
2648   gtk_tree_store_append (GTK_TREE_STORE (model), &iter_first, &parent2);
2649   gtk_tree_store_append (GTK_TREE_STORE (model), &iter, &parent2);
2650   gtk_tree_store_append (GTK_TREE_STORE (model), &iter, &parent2);
2651
2652   assert_entire_model_unreferenced (ref_model);
2653
2654   filter_model = gtk_tree_model_filter_new (model, NULL);
2655   tree_view = gtk_tree_view_new_with_model (filter_model);
2656
2657   /* This is quite confusing:
2658    *  - node 0 has a ref count of 2 because it is referenced as the
2659    *    first node in a level and by the tree view.
2660    *  - node 1 has a ref count of 2 because it is referenced by its
2661    *    child level and by the tree view.
2662    */
2663   assert_root_level_referenced (ref_model, 2);
2664   assert_node_ref_count (ref_model, &iter_first, 1);
2665   assert_node_ref_count (ref_model, &iter, 0);
2666
2667   gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
2668
2669   assert_node_ref_count (ref_model, &parent1, 2);
2670   assert_node_ref_count (ref_model, &parent2, 2);
2671   assert_node_ref_count (ref_model, &iter_first, 2);
2672   assert_node_ref_count (ref_model, &iter, 1);
2673
2674   gtk_tree_view_collapse_all (GTK_TREE_VIEW (tree_view));
2675
2676   /* The child level is not destroyed because its parent is visible */
2677   assert_node_ref_count (ref_model, &parent1, 2);
2678   assert_node_ref_count (ref_model, &parent2, 2);
2679   assert_node_ref_count (ref_model, &iter_first, 1);
2680   assert_node_ref_count (ref_model, &iter, 0);
2681
2682   gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
2683
2684   assert_node_ref_count (ref_model, &parent1, 2);
2685   assert_node_ref_count (ref_model, &parent2, 2);
2686   assert_node_ref_count (ref_model, &iter_first, 1);
2687   assert_node_ref_count (ref_model, &iter, 0);
2688
2689   gtk_widget_destroy (tree_view);
2690
2691   assert_root_level_referenced (ref_model, 1);
2692   assert_node_ref_count (ref_model, &iter_first, 1);
2693   assert_node_ref_count (ref_model, &iter, 0);
2694
2695   gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
2696
2697   /* The root level and first level remain cached, only the references on the
2698    * first nodes of these levels are kept.
2699    */
2700   assert_node_ref_count (ref_model, &parent1, 1);
2701   assert_node_ref_count (ref_model, &parent2, 1);
2702   assert_node_ref_count (ref_model, &iter_first, 1);
2703   assert_node_ref_count (ref_model, &iter, 0);
2704
2705   g_object_unref (filter_model);
2706   g_object_unref (ref_model);
2707 }
2708
2709 static void
2710 ref_count_three_levels (void)
2711 {
2712   GtkTreeIter grandparent1, grandparent2, parent1, parent2;
2713   GtkTreeIter iter_parent1, iter_parent2, iter_parent2_first;
2714   GtkTreeModel *model;
2715   GtkTreeModelRefCount *ref_model;
2716   GtkTreeModel *filter_model;
2717   GtkTreePath *path;
2718   GtkWidget *tree_view;
2719
2720   model = gtk_tree_model_ref_count_new ();
2721   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
2722
2723   /* + grandparent1
2724    * + grandparent2
2725    *   + parent1
2726    *     + iter_parent1
2727    *   + parent2
2728    *     + iter_parent2_first
2729    *     + iter_parent2
2730    */
2731
2732   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
2733   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent2, NULL);
2734   gtk_tree_store_append (GTK_TREE_STORE (model), &parent1, &grandparent2);
2735   gtk_tree_store_append (GTK_TREE_STORE (model), &iter_parent1, &parent1);
2736   gtk_tree_store_append (GTK_TREE_STORE (model), &parent2, &grandparent2);
2737   gtk_tree_store_append (GTK_TREE_STORE (model), &iter_parent2_first, &parent2);
2738   gtk_tree_store_append (GTK_TREE_STORE (model), &iter_parent2, &parent2);
2739
2740   assert_entire_model_unreferenced (ref_model);
2741
2742   filter_model = gtk_tree_model_filter_new (model, NULL);
2743   tree_view = gtk_tree_view_new_with_model (filter_model);
2744
2745   /* This is quite confusing:
2746    *  - node 0 has a ref count of 2 because it is referenced as the
2747    *    first node in a level and by the tree view.
2748    *  - node 1 has a ref count of 2 because it is referenced by its
2749    *    child level and by the tree view.
2750    */
2751   assert_root_level_referenced (ref_model, 2);
2752   assert_node_ref_count (ref_model, &parent1, 1);
2753   assert_node_ref_count (ref_model, &parent2, 0);
2754   assert_level_unreferenced (ref_model, &parent1);
2755   assert_level_unreferenced (ref_model, &parent2);
2756
2757   path = gtk_tree_path_new_from_indices (1, -1);
2758   gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path, FALSE);
2759
2760   assert_node_ref_count (ref_model, &grandparent1, 2);
2761   assert_node_ref_count (ref_model, &grandparent2, 2);
2762   assert_node_ref_count (ref_model, &parent1, 3);
2763   assert_node_ref_count (ref_model, &parent2, 2);
2764   assert_node_ref_count (ref_model, &iter_parent1, 1);
2765   assert_node_ref_count (ref_model, &iter_parent2_first, 1);
2766   assert_node_ref_count (ref_model, &iter_parent2, 0);
2767
2768   gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path, TRUE);
2769
2770   assert_node_ref_count (ref_model, &grandparent1, 2);
2771   assert_node_ref_count (ref_model, &grandparent2, 2);
2772   assert_node_ref_count (ref_model, &parent1, 3);
2773   assert_node_ref_count (ref_model, &parent2, 2);
2774   assert_node_ref_count (ref_model, &iter_parent1, 2);
2775   assert_node_ref_count (ref_model, &iter_parent2_first, 2);
2776   assert_node_ref_count (ref_model, &iter_parent2, 1);
2777
2778   gtk_tree_view_collapse_all (GTK_TREE_VIEW (tree_view));
2779
2780   assert_node_ref_count (ref_model, &grandparent1, 2);
2781   assert_node_ref_count (ref_model, &grandparent2, 2);
2782   assert_node_ref_count (ref_model, &parent1, 2);
2783   assert_node_ref_count (ref_model, &parent2, 1);
2784   assert_node_ref_count (ref_model, &iter_parent1, 1);
2785   assert_node_ref_count (ref_model, &iter_parent2_first, 1);
2786   assert_node_ref_count (ref_model, &iter_parent2, 0);
2787
2788   gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
2789
2790   assert_node_ref_count (ref_model, &grandparent1, 2);
2791   assert_node_ref_count (ref_model, &grandparent2, 2);
2792   assert_node_ref_count (ref_model, &parent1, 1);
2793   assert_node_ref_count (ref_model, &parent2, 0);
2794   assert_node_ref_count (ref_model, &iter_parent1, 0);
2795   assert_node_ref_count (ref_model, &iter_parent2_first, 0);
2796   assert_node_ref_count (ref_model, &iter_parent2, 0);
2797
2798   gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path, FALSE);
2799
2800   assert_node_ref_count (ref_model, &grandparent1, 2);
2801   assert_node_ref_count (ref_model, &grandparent2, 2);
2802   assert_node_ref_count (ref_model, &parent1, 3);
2803   assert_node_ref_count (ref_model, &parent2, 2);
2804   assert_node_ref_count (ref_model, &iter_parent1, 1);
2805   assert_node_ref_count (ref_model, &iter_parent2_first, 1);
2806   assert_node_ref_count (ref_model, &iter_parent2, 0);
2807
2808   gtk_tree_path_append_index (path, 1);
2809   gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path, FALSE);
2810
2811   assert_node_ref_count (ref_model, &grandparent1, 2);
2812   assert_node_ref_count (ref_model, &grandparent2, 2);
2813   assert_node_ref_count (ref_model, &parent1, 3);
2814   assert_node_ref_count (ref_model, &parent2, 2);
2815   assert_node_ref_count (ref_model, &iter_parent1, 1);
2816   assert_node_ref_count (ref_model, &iter_parent2_first, 2);
2817   assert_node_ref_count (ref_model, &iter_parent2, 1);
2818
2819   gtk_tree_view_collapse_row (GTK_TREE_VIEW (tree_view), path);
2820
2821   assert_node_ref_count (ref_model, &grandparent1, 2);
2822   assert_node_ref_count (ref_model, &grandparent2, 2);
2823   assert_node_ref_count (ref_model, &parent1, 3);
2824   assert_node_ref_count (ref_model, &parent2, 2);
2825   assert_node_ref_count (ref_model, &iter_parent1, 1);
2826   assert_node_ref_count (ref_model, &iter_parent2_first, 1);
2827   assert_node_ref_count (ref_model, &iter_parent2, 0);
2828
2829   gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
2830
2831   assert_node_ref_count (ref_model, &grandparent1, 2);
2832   assert_node_ref_count (ref_model, &grandparent2, 2);
2833   assert_node_ref_count (ref_model, &parent1, 3);
2834   assert_node_ref_count (ref_model, &parent2, 2);
2835   assert_node_ref_count (ref_model, &iter_parent1, 1);
2836   assert_node_ref_count (ref_model, &iter_parent2_first, 1);
2837   assert_node_ref_count (ref_model, &iter_parent2, 0);
2838
2839   gtk_tree_path_up (path);
2840   gtk_tree_view_collapse_row (GTK_TREE_VIEW (tree_view), path);
2841   gtk_tree_path_free (path);
2842
2843   assert_node_ref_count (ref_model, &grandparent1, 2);
2844   assert_node_ref_count (ref_model, &grandparent2, 2);
2845   assert_node_ref_count (ref_model, &parent1, 2);
2846   assert_node_ref_count (ref_model, &parent2, 1);
2847   assert_node_ref_count (ref_model, &iter_parent1, 1);
2848   assert_node_ref_count (ref_model, &iter_parent2_first, 1);
2849   assert_node_ref_count (ref_model, &iter_parent2, 0);
2850
2851   gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
2852
2853   assert_node_ref_count (ref_model, &grandparent1, 2);
2854   assert_node_ref_count (ref_model, &grandparent2, 2);
2855   assert_node_ref_count (ref_model, &parent1, 1);
2856   assert_node_ref_count (ref_model, &parent2, 0);
2857   assert_node_ref_count (ref_model, &iter_parent1, 0);
2858   assert_node_ref_count (ref_model, &iter_parent2_first, 0);
2859   assert_node_ref_count (ref_model, &iter_parent2, 0);
2860
2861   gtk_widget_destroy (tree_view);
2862
2863   gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
2864
2865   /* The root level and first level remain cached, only the references on the
2866    * first nodes of these levels are kept.  Grandparent2 is the parent
2867    * of the first level with parent1, so grandparent2 keeps a reference
2868    * as well.
2869    */
2870   assert_node_ref_count (ref_model, &grandparent1, 1);
2871   assert_node_ref_count (ref_model, &grandparent2, 1);
2872   assert_node_ref_count (ref_model, &parent1, 1);
2873   assert_node_ref_count (ref_model, &parent2, 0);
2874   assert_node_ref_count (ref_model, &iter_parent1, 0);
2875   assert_node_ref_count (ref_model, &iter_parent2_first, 0);
2876   assert_node_ref_count (ref_model, &iter_parent2, 0);
2877
2878   g_object_unref (filter_model);
2879   g_object_unref (ref_model);
2880 }
2881
2882 static void
2883 ref_count_delete_row (void)
2884 {
2885   GtkTreeIter grandparent1, grandparent2, parent1, parent2;
2886   GtkTreeIter iter_parent1, iter_parent2, iter_parent2_first;
2887   GtkTreeModel *model;
2888   GtkTreeModelRefCount *ref_model;
2889   GtkTreeModel *filter_model;
2890   GtkTreePath *path;
2891   GtkWidget *tree_view;
2892
2893   model = gtk_tree_model_ref_count_new ();
2894   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
2895
2896   /* + grandparent1
2897    * + grandparent2
2898    *   + parent1
2899    *     + iter_parent1
2900    *   + parent2
2901    *     + iter_parent2_first
2902    *     + iter_parent2
2903    */
2904
2905   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
2906   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent2, NULL);
2907   gtk_tree_store_append (GTK_TREE_STORE (model), &parent1, &grandparent2);
2908   gtk_tree_store_append (GTK_TREE_STORE (model), &iter_parent1, &parent1);
2909   gtk_tree_store_append (GTK_TREE_STORE (model), &parent2, &grandparent2);
2910   gtk_tree_store_append (GTK_TREE_STORE (model), &iter_parent2_first, &parent2);
2911   gtk_tree_store_append (GTK_TREE_STORE (model), &iter_parent2, &parent2);
2912
2913   assert_entire_model_unreferenced (ref_model);
2914
2915   filter_model = gtk_tree_model_filter_new (model, NULL);
2916   tree_view = gtk_tree_view_new_with_model (filter_model);
2917
2918   assert_root_level_referenced (ref_model, 2);
2919   assert_node_ref_count (ref_model, &parent1, 1);
2920   assert_node_ref_count (ref_model, &parent2, 0);
2921   assert_level_unreferenced (ref_model, &parent1);
2922   assert_level_unreferenced (ref_model, &parent2);
2923
2924   path = gtk_tree_path_new_from_indices (1, -1);
2925   gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path, TRUE);
2926   gtk_tree_path_free (path);
2927
2928   assert_node_ref_count (ref_model, &grandparent1, 2);
2929   assert_node_ref_count (ref_model, &grandparent2, 2);
2930   assert_node_ref_count (ref_model, &parent1, 3);
2931   assert_node_ref_count (ref_model, &parent2, 2);
2932   assert_node_ref_count (ref_model, &iter_parent1, 2);
2933   assert_node_ref_count (ref_model, &iter_parent2_first, 2);
2934   assert_node_ref_count (ref_model, &iter_parent2, 1);
2935
2936   gtk_tree_store_remove (GTK_TREE_STORE (model), &iter_parent2);
2937
2938   assert_node_ref_count (ref_model, &grandparent1, 2);
2939   assert_node_ref_count (ref_model, &grandparent2, 2);
2940   assert_node_ref_count (ref_model, &parent1, 3);
2941   assert_node_ref_count (ref_model, &parent2, 2);
2942   assert_node_ref_count (ref_model, &iter_parent1, 2);
2943   assert_node_ref_count (ref_model, &iter_parent2_first, 2);
2944
2945   gtk_tree_store_remove (GTK_TREE_STORE (model), &parent1);
2946
2947   assert_node_ref_count (ref_model, &grandparent1, 2);
2948   assert_node_ref_count (ref_model, &grandparent2, 2);
2949   assert_node_ref_count (ref_model, &parent2, 3);
2950   assert_level_referenced (ref_model, 2, &parent2);
2951
2952   gtk_tree_store_remove (GTK_TREE_STORE (model), &grandparent2);
2953
2954   assert_node_ref_count (ref_model, &grandparent1, 2);
2955
2956   gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
2957
2958   assert_node_ref_count (ref_model, &grandparent1, 2);
2959
2960   gtk_widget_destroy (tree_view);
2961   gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
2962
2963   assert_node_ref_count (ref_model, &grandparent1, 1);
2964
2965   g_object_unref (filter_model);
2966
2967   assert_node_ref_count (ref_model, &grandparent1, 0);
2968
2969   g_object_unref (ref_model);
2970 }
2971
2972 static void
2973 ref_count_filter_row_length_1 (void)
2974 {
2975   GtkTreeIter level1_1;
2976   GtkTreeIter level2_1;
2977   GtkTreeIter level3_1;
2978   GtkTreeIter level4_1;
2979   GtkTreeModel *model;
2980   GtkTreeModelRefCount *ref_model;
2981   GtkTreeModel *filter_model;
2982   GtkTreePath *path;
2983   GtkWidget *tree_view;
2984   GType column_types[] = { G_TYPE_BOOLEAN };
2985
2986   model = gtk_tree_model_ref_count_new ();
2987   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
2988
2989   gtk_tree_store_set_column_types (GTK_TREE_STORE (model), 1,
2990                                    column_types);
2991
2992
2993   /* + level1_1
2994    *   + level2_1
2995    *     + level3_1
2996    *       + level4_1
2997    *
2998    * Node level1_1 is expanded.  This makes that levels 1 and 2 are
2999    * visible.  Level 3 is cached because its parent is visible.  Level 4
3000    * is not cached.
3001    */
3002
3003   gtk_tree_store_append (GTK_TREE_STORE (model), &level1_1, NULL);
3004   gtk_tree_store_append (GTK_TREE_STORE (model), &level2_1, &level1_1);
3005   gtk_tree_store_append (GTK_TREE_STORE (model), &level3_1, &level2_1);
3006   gtk_tree_store_append (GTK_TREE_STORE (model), &level4_1, &level3_1);
3007
3008   gtk_tree_store_set (GTK_TREE_STORE (model), &level1_1, 0, TRUE, -1);
3009   gtk_tree_store_set (GTK_TREE_STORE (model), &level2_1, 0, TRUE, -1);
3010   gtk_tree_store_set (GTK_TREE_STORE (model), &level3_1, 0, TRUE, -1);
3011   gtk_tree_store_set (GTK_TREE_STORE (model), &level4_1, 0, TRUE, -1);
3012
3013   assert_entire_model_unreferenced (ref_model);
3014
3015   filter_model = gtk_tree_model_filter_new (model, NULL);
3016   gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), 0);
3017   tree_view = gtk_tree_view_new_with_model (filter_model);
3018
3019   assert_node_ref_count (ref_model, &level1_1, 3);
3020   assert_node_ref_count (ref_model, &level2_1, 1);
3021   assert_node_ref_count (ref_model, &level3_1, 0);
3022   assert_node_ref_count (ref_model, &level4_1, 0);
3023
3024   path = gtk_tree_path_new_from_indices (0, -1);
3025   gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path, FALSE);
3026   gtk_tree_path_free (path);
3027
3028   assert_node_ref_count (ref_model, &level1_1, 3);
3029   assert_node_ref_count (ref_model, &level2_1, 3);
3030   assert_node_ref_count (ref_model, &level3_1, 1);
3031   assert_node_ref_count (ref_model, &level4_1, 0);
3032
3033   gtk_tree_store_set (GTK_TREE_STORE (model), &level4_1, 0, FALSE, -1);
3034
3035   assert_node_ref_count (ref_model, &level1_1, 3);
3036   assert_node_ref_count (ref_model, &level2_1, 3);
3037   assert_node_ref_count (ref_model, &level3_1, 1);
3038   assert_node_ref_count (ref_model, &level4_1, 0);
3039
3040   /* level3_1 has a visible parent, so the node is kept in the cache. */
3041   gtk_tree_store_set (GTK_TREE_STORE (model), &level3_1, 0, FALSE, -1);
3042
3043   assert_node_ref_count (ref_model, &level1_1, 3);
3044   assert_node_ref_count (ref_model, &level2_1, 3);
3045   assert_node_ref_count (ref_model, &level3_1, 1);
3046   assert_node_ref_count (ref_model, &level4_1, 0);
3047
3048   /* level2_1 has a visible parent, so is kept in the cache.  However,
3049    * the external reference should be released.
3050    */
3051   gtk_tree_store_set (GTK_TREE_STORE (model), &level2_1, 0, FALSE, -1);
3052
3053   assert_node_ref_count (ref_model, &level1_1, 3);
3054   assert_node_ref_count (ref_model, &level2_1, 1);
3055   assert_node_ref_count (ref_model, &level3_1, 0);
3056   assert_node_ref_count (ref_model, &level4_1, 0);
3057
3058   gtk_tree_store_set (GTK_TREE_STORE (model), &level1_1, 0, FALSE, -1);
3059
3060   assert_node_ref_count (ref_model, &level1_1, 2);
3061   assert_node_ref_count (ref_model, &level2_1, 1);
3062   assert_node_ref_count (ref_model, &level3_1, 0);
3063   assert_node_ref_count (ref_model, &level4_1, 0);
3064
3065   gtk_widget_destroy (tree_view);
3066   gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
3067
3068   assert_node_ref_count (ref_model, &level1_1, 2);
3069   assert_node_ref_count (ref_model, &level2_1, 1);
3070
3071   g_object_unref (filter_model);
3072
3073   assert_node_ref_count (ref_model, &level1_1, 0);
3074
3075   g_object_unref (ref_model);
3076 }
3077
3078 static void
3079 ref_count_filter_row_length_1_remove_in_root_level (void)
3080 {
3081   GtkTreeIter level1_1;
3082   GtkTreeIter level2_1;
3083   GtkTreeIter level3_1;
3084   GtkTreeIter level4_1;
3085   GtkTreeModel *model;
3086   GtkTreeModelRefCount *ref_model;
3087   GtkTreeModel *filter_model;
3088   GtkTreePath *path;
3089   GtkWidget *tree_view;
3090   GType column_types[] = { G_TYPE_BOOLEAN };
3091
3092   model = gtk_tree_model_ref_count_new ();
3093   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
3094
3095   gtk_tree_store_set_column_types (GTK_TREE_STORE (model), 1,
3096                                    column_types);
3097
3098
3099   /* + level1_1
3100    *   + level2_1
3101    *     + level3_1
3102    *       + level4_1
3103    */
3104
3105   gtk_tree_store_append (GTK_TREE_STORE (model), &level1_1, NULL);
3106   gtk_tree_store_append (GTK_TREE_STORE (model), &level2_1, &level1_1);
3107   gtk_tree_store_append (GTK_TREE_STORE (model), &level3_1, &level2_1);
3108   gtk_tree_store_append (GTK_TREE_STORE (model), &level4_1, &level3_1);
3109
3110   gtk_tree_store_set (GTK_TREE_STORE (model), &level1_1, 0, TRUE, -1);
3111   gtk_tree_store_set (GTK_TREE_STORE (model), &level2_1, 0, TRUE, -1);
3112   gtk_tree_store_set (GTK_TREE_STORE (model), &level3_1, 0, TRUE, -1);
3113   gtk_tree_store_set (GTK_TREE_STORE (model), &level4_1, 0, TRUE, -1);
3114
3115   assert_entire_model_unreferenced (ref_model);
3116
3117   filter_model = gtk_tree_model_filter_new (model, NULL);
3118   gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), 0);
3119   tree_view = gtk_tree_view_new_with_model (filter_model);
3120
3121   assert_node_ref_count (ref_model, &level1_1, 3);
3122   assert_node_ref_count (ref_model, &level2_1, 1);
3123   assert_node_ref_count (ref_model, &level3_1, 0);
3124   assert_node_ref_count (ref_model, &level4_1, 0);
3125
3126   path = gtk_tree_path_new_from_indices (0, -1);
3127   gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path, TRUE);
3128   gtk_tree_path_free (path);
3129
3130   assert_node_ref_count (ref_model, &level1_1, 3);
3131   assert_node_ref_count (ref_model, &level2_1, 3);
3132   assert_node_ref_count (ref_model, &level3_1, 3);
3133   assert_node_ref_count (ref_model, &level4_1, 2);
3134
3135   gtk_tree_store_set (GTK_TREE_STORE (model), &level1_1, 0, FALSE, -1);
3136
3137   assert_node_ref_count (ref_model, &level1_1, 2);
3138   assert_node_ref_count (ref_model, &level2_1, 1);
3139   assert_node_ref_count (ref_model, &level3_1, 0);
3140   assert_node_ref_count (ref_model, &level4_1, 0);
3141
3142   gtk_widget_destroy (tree_view);
3143   gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
3144
3145   assert_node_ref_count (ref_model, &level1_1, 2);
3146   assert_node_ref_count (ref_model, &level2_1, 1);
3147   assert_node_ref_count (ref_model, &level3_1, 0);
3148   assert_node_ref_count (ref_model, &level4_1, 0);
3149
3150   g_object_unref (filter_model);
3151
3152   assert_node_ref_count (ref_model, &level1_1, 0);
3153   assert_node_ref_count (ref_model, &level2_1, 0);
3154   assert_node_ref_count (ref_model, &level3_1, 0);
3155   assert_node_ref_count (ref_model, &level4_1, 0);
3156
3157   g_object_unref (ref_model);
3158 }
3159
3160 static void
3161 ref_count_filter_row_length_1_remove_in_child_level (void)
3162 {
3163   GtkTreeIter level1_1;
3164   GtkTreeIter level2_1;
3165   GtkTreeIter level3_1;
3166   GtkTreeIter level4_1;
3167   GtkTreeModel *model;
3168   GtkTreeModelRefCount *ref_model;
3169   GtkTreeModel *filter_model;
3170   GtkTreePath *path;
3171   GtkWidget *tree_view;
3172   GType column_types[] = { G_TYPE_BOOLEAN };
3173
3174   model = gtk_tree_model_ref_count_new ();
3175   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
3176
3177   gtk_tree_store_set_column_types (GTK_TREE_STORE (model), 1,
3178                                    column_types);
3179
3180
3181   /* + level1_1
3182    *   + level2_1
3183    *     + level3_1
3184    *       + level4_1
3185    */
3186
3187   gtk_tree_store_append (GTK_TREE_STORE (model), &level1_1, NULL);
3188   gtk_tree_store_append (GTK_TREE_STORE (model), &level2_1, &level1_1);
3189   gtk_tree_store_append (GTK_TREE_STORE (model), &level3_1, &level2_1);
3190   gtk_tree_store_append (GTK_TREE_STORE (model), &level4_1, &level3_1);
3191
3192   gtk_tree_store_set (GTK_TREE_STORE (model), &level1_1, 0, TRUE, -1);
3193   gtk_tree_store_set (GTK_TREE_STORE (model), &level2_1, 0, TRUE, -1);
3194   gtk_tree_store_set (GTK_TREE_STORE (model), &level3_1, 0, TRUE, -1);
3195   gtk_tree_store_set (GTK_TREE_STORE (model), &level4_1, 0, TRUE, -1);
3196
3197   assert_entire_model_unreferenced (ref_model);
3198
3199   filter_model = gtk_tree_model_filter_new (model, NULL);
3200   gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), 0);
3201   tree_view = gtk_tree_view_new_with_model (filter_model);
3202
3203   assert_node_ref_count (ref_model, &level1_1, 3);
3204   assert_node_ref_count (ref_model, &level2_1, 1);
3205   assert_node_ref_count (ref_model, &level3_1, 0);
3206   assert_node_ref_count (ref_model, &level4_1, 0);
3207
3208   path = gtk_tree_path_new_from_indices (0, -1);
3209   gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path, TRUE);
3210   gtk_tree_path_free (path);
3211
3212   assert_node_ref_count (ref_model, &level1_1, 3);
3213   assert_node_ref_count (ref_model, &level2_1, 3);
3214   assert_node_ref_count (ref_model, &level3_1, 3);
3215   assert_node_ref_count (ref_model, &level4_1, 2);
3216
3217   gtk_tree_store_set (GTK_TREE_STORE (model), &level2_1, 0, FALSE, -1);
3218
3219   assert_node_ref_count (ref_model, &level1_1, 3);
3220   assert_node_ref_count (ref_model, &level2_1, 1);
3221   assert_node_ref_count (ref_model, &level3_1, 0);
3222   assert_node_ref_count (ref_model, &level4_1, 0);
3223
3224   gtk_widget_destroy (tree_view);
3225   gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
3226
3227   assert_node_ref_count (ref_model, &level1_1, 2);
3228   assert_node_ref_count (ref_model, &level2_1, 1);
3229   assert_node_ref_count (ref_model, &level3_1, 0);
3230   assert_node_ref_count (ref_model, &level4_1, 0);
3231
3232   g_object_unref (filter_model);
3233
3234   assert_node_ref_count (ref_model, &level1_1, 0);
3235   assert_node_ref_count (ref_model, &level2_1, 0);
3236   assert_node_ref_count (ref_model, &level3_1, 0);
3237   assert_node_ref_count (ref_model, &level4_1, 0);
3238
3239   g_object_unref (ref_model);
3240 }
3241
3242 static void
3243 ref_count_filter_row_length_gt_1 (void)
3244 {
3245   GtkTreeIter level1_1, level1_2;
3246   GtkTreeIter level2_1, level2_2;
3247   GtkTreeIter level3_1, level3_2;
3248   GtkTreeIter level4_1, level4_2;
3249   GtkTreeModel *model;
3250   GtkTreeModelRefCount *ref_model;
3251   GtkTreeModel *filter_model;
3252   GtkTreePath *path;
3253   GtkWidget *tree_view;
3254   GType column_types[] = { G_TYPE_BOOLEAN };
3255
3256   model = gtk_tree_model_ref_count_new ();
3257   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
3258
3259   gtk_tree_store_set_column_types (GTK_TREE_STORE (model), 1,
3260                                    column_types);
3261
3262
3263   /* + level1_1
3264    * + level1_2
3265    *   + level2_1
3266    *   + level2_2
3267    *     + level3_1
3268    *     + level3_2
3269    *       + level4_1
3270    *       + level4_2
3271    *
3272    * Node level1_2 is expanded.  This makes that levels 1 and 2 are
3273    * visible.  Level 3 is cached because its parent is visible.  Level 4
3274    * is not cached.
3275    */
3276
3277   gtk_tree_store_append (GTK_TREE_STORE (model), &level1_1, NULL);
3278   gtk_tree_store_append (GTK_TREE_STORE (model), &level1_2, NULL);
3279   gtk_tree_store_append (GTK_TREE_STORE (model), &level2_1, &level1_2);
3280   gtk_tree_store_append (GTK_TREE_STORE (model), &level2_2, &level1_2);
3281   gtk_tree_store_append (GTK_TREE_STORE (model), &level3_1, &level2_2);
3282   gtk_tree_store_append (GTK_TREE_STORE (model), &level3_2, &level2_2);
3283   gtk_tree_store_append (GTK_TREE_STORE (model), &level4_1, &level3_2);
3284   gtk_tree_store_append (GTK_TREE_STORE (model), &level4_2, &level3_2);
3285
3286   gtk_tree_store_set (GTK_TREE_STORE (model), &level1_1, 0, TRUE, -1);
3287   gtk_tree_store_set (GTK_TREE_STORE (model), &level1_2, 0, TRUE, -1);
3288   gtk_tree_store_set (GTK_TREE_STORE (model), &level2_1, 0, TRUE, -1);
3289   gtk_tree_store_set (GTK_TREE_STORE (model), &level2_2, 0, TRUE, -1);
3290   gtk_tree_store_set (GTK_TREE_STORE (model), &level3_1, 0, TRUE, -1);
3291   gtk_tree_store_set (GTK_TREE_STORE (model), &level3_2, 0, TRUE, -1);
3292   gtk_tree_store_set (GTK_TREE_STORE (model), &level4_1, 0, TRUE, -1);
3293   gtk_tree_store_set (GTK_TREE_STORE (model), &level4_2, 0, TRUE, -1);
3294
3295   assert_entire_model_unreferenced (ref_model);
3296
3297   filter_model = gtk_tree_model_filter_new (model, NULL);
3298   gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), 0);
3299   tree_view = gtk_tree_view_new_with_model (filter_model);
3300
3301   assert_node_ref_count (ref_model, &level1_1, 2);
3302   assert_node_ref_count (ref_model, &level1_2, 2);
3303   assert_node_ref_count (ref_model, &level2_1, 1);
3304   assert_node_ref_count (ref_model, &level2_2, 0);
3305   assert_node_ref_count (ref_model, &level3_1, 0);
3306   assert_node_ref_count (ref_model, &level3_2, 0);
3307   assert_node_ref_count (ref_model, &level4_1, 0);
3308   assert_node_ref_count (ref_model, &level4_2, 0);
3309
3310   path = gtk_tree_path_new_from_indices (1, -1);
3311   gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path, FALSE);
3312   gtk_tree_path_free (path);
3313
3314   assert_node_ref_count (ref_model, &level1_1, 2);
3315   assert_node_ref_count (ref_model, &level1_2, 2);
3316   assert_node_ref_count (ref_model, &level2_1, 2);
3317   assert_node_ref_count (ref_model, &level2_2, 2);
3318   assert_node_ref_count (ref_model, &level3_1, 1);
3319   assert_node_ref_count (ref_model, &level3_2, 0);
3320   assert_node_ref_count (ref_model, &level4_1, 0);
3321   assert_node_ref_count (ref_model, &level4_2, 0);
3322
3323   gtk_tree_store_set (GTK_TREE_STORE (model), &level4_1, 0, FALSE, -1);
3324
3325   assert_node_ref_count (ref_model, &level1_1, 2);
3326   assert_node_ref_count (ref_model, &level1_2, 2);
3327   assert_node_ref_count (ref_model, &level2_1, 2);
3328   assert_node_ref_count (ref_model, &level2_2, 2);
3329   assert_node_ref_count (ref_model, &level3_1, 1);
3330   assert_node_ref_count (ref_model, &level3_2, 0);
3331   assert_node_ref_count (ref_model, &level4_1, 0);
3332   assert_node_ref_count (ref_model, &level4_2, 0);
3333
3334   gtk_tree_store_set (GTK_TREE_STORE (model), &level3_1, 0, FALSE, -1);
3335
3336   assert_node_ref_count (ref_model, &level1_1, 2);
3337   assert_node_ref_count (ref_model, &level1_2, 2);
3338   assert_node_ref_count (ref_model, &level2_1, 2);
3339   assert_node_ref_count (ref_model, &level2_2, 2);
3340   assert_node_ref_count (ref_model, &level3_1, 0);
3341   assert_node_ref_count (ref_model, &level3_2, 1);
3342   assert_node_ref_count (ref_model, &level4_1, 0);
3343   assert_node_ref_count (ref_model, &level4_2, 0);
3344
3345   gtk_tree_store_set (GTK_TREE_STORE (model), &level2_2, 0, FALSE, -1);
3346
3347   assert_node_ref_count (ref_model, &level1_1, 2);
3348   assert_node_ref_count (ref_model, &level1_2, 2);
3349   assert_node_ref_count (ref_model, &level2_1, 2);
3350   assert_node_ref_count (ref_model, &level2_2, 0);
3351   assert_node_ref_count (ref_model, &level3_1, 0);
3352   assert_node_ref_count (ref_model, &level3_2, 0);
3353   assert_node_ref_count (ref_model, &level4_1, 0);
3354   assert_node_ref_count (ref_model, &level4_2, 0);
3355
3356   gtk_tree_store_set (GTK_TREE_STORE (model), &level1_2, 0, FALSE, -1);
3357
3358   assert_node_ref_count (ref_model, &level1_1, 2);
3359   assert_node_ref_count (ref_model, &level1_2, 0);
3360   assert_node_ref_count (ref_model, &level2_1, 0);
3361   assert_node_ref_count (ref_model, &level2_2, 0);
3362   assert_node_ref_count (ref_model, &level3_1, 0);
3363   assert_node_ref_count (ref_model, &level3_2, 0);
3364   assert_node_ref_count (ref_model, &level4_1, 0);
3365   assert_node_ref_count (ref_model, &level4_2, 0);
3366
3367   gtk_widget_destroy (tree_view);
3368   gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
3369
3370   assert_node_ref_count (ref_model, &level1_1, 1);
3371
3372   g_object_unref (filter_model);
3373
3374   assert_node_ref_count (ref_model, &level1_1, 0);
3375
3376   g_object_unref (ref_model);
3377 }
3378
3379 static void
3380 ref_count_filter_row_length_gt_1_visible_children (void)
3381 {
3382   GtkTreeIter level1_1, level1_2;
3383   GtkTreeIter level2_1, level2_2;
3384   GtkTreeIter level3_1, level3_2;
3385   GtkTreeIter level4_1, level4_2;
3386   GtkTreeModel *model;
3387   GtkTreeModelRefCount *ref_model;
3388   GtkTreeModel *filter_model;
3389   GtkTreePath *path;
3390   GtkWidget *tree_view;
3391   GType column_types[] = { G_TYPE_BOOLEAN };
3392
3393   model = gtk_tree_model_ref_count_new ();
3394   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
3395
3396   gtk_tree_store_set_column_types (GTK_TREE_STORE (model), 1,
3397                                    column_types);
3398
3399
3400   /* + level1_1
3401    * + level1_2
3402    *   + level2_1
3403    *   + level2_2
3404    *     + level3_1
3405    *     + level3_2
3406    *       + level4_1
3407    *       + level4_2
3408    */
3409
3410   gtk_tree_store_append (GTK_TREE_STORE (model), &level1_1, NULL);
3411   gtk_tree_store_append (GTK_TREE_STORE (model), &level1_2, NULL);
3412   gtk_tree_store_append (GTK_TREE_STORE (model), &level2_1, &level1_2);
3413   gtk_tree_store_append (GTK_TREE_STORE (model), &level2_2, &level1_2);
3414   gtk_tree_store_append (GTK_TREE_STORE (model), &level3_1, &level2_2);
3415   gtk_tree_store_append (GTK_TREE_STORE (model), &level3_2, &level2_2);
3416   gtk_tree_store_append (GTK_TREE_STORE (model), &level4_1, &level3_2);
3417   gtk_tree_store_append (GTK_TREE_STORE (model), &level4_2, &level3_2);
3418
3419   gtk_tree_store_set (GTK_TREE_STORE (model), &level1_1, 0, TRUE, -1);
3420   gtk_tree_store_set (GTK_TREE_STORE (model), &level1_2, 0, TRUE, -1);
3421   gtk_tree_store_set (GTK_TREE_STORE (model), &level2_1, 0, TRUE, -1);
3422   gtk_tree_store_set (GTK_TREE_STORE (model), &level2_2, 0, TRUE, -1);
3423   gtk_tree_store_set (GTK_TREE_STORE (model), &level3_1, 0, TRUE, -1);
3424   gtk_tree_store_set (GTK_TREE_STORE (model), &level3_2, 0, TRUE, -1);
3425   gtk_tree_store_set (GTK_TREE_STORE (model), &level4_1, 0, TRUE, -1);
3426   gtk_tree_store_set (GTK_TREE_STORE (model), &level4_2, 0, TRUE, -1);
3427
3428   assert_entire_model_unreferenced (ref_model);
3429
3430   filter_model = gtk_tree_model_filter_new (model, NULL);
3431   gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), 0);
3432   tree_view = gtk_tree_view_new_with_model (filter_model);
3433
3434   assert_node_ref_count (ref_model, &level1_1, 2);
3435   assert_node_ref_count (ref_model, &level1_2, 2);
3436   assert_node_ref_count (ref_model, &level2_1, 1);
3437   assert_node_ref_count (ref_model, &level2_2, 0);
3438   assert_node_ref_count (ref_model, &level3_1, 0);
3439   assert_node_ref_count (ref_model, &level3_2, 0);
3440   assert_node_ref_count (ref_model, &level4_1, 0);
3441   assert_node_ref_count (ref_model, &level4_2, 0);
3442
3443   path = gtk_tree_path_new_from_indices (1, -1);
3444   gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path, TRUE);
3445   gtk_tree_path_free (path);
3446
3447   assert_node_ref_count (ref_model, &level1_1, 2);
3448   assert_node_ref_count (ref_model, &level1_2, 2);
3449   assert_node_ref_count (ref_model, &level2_1, 2);
3450   assert_node_ref_count (ref_model, &level2_2, 2);
3451   assert_node_ref_count (ref_model, &level3_1, 2);
3452   assert_node_ref_count (ref_model, &level3_2, 2);
3453   assert_node_ref_count (ref_model, &level4_1, 2);
3454   assert_node_ref_count (ref_model, &level4_2, 1);
3455
3456   gtk_tree_store_set (GTK_TREE_STORE (model), &level2_2, 0, FALSE, -1);
3457
3458   assert_node_ref_count (ref_model, &level1_1, 2);
3459   assert_node_ref_count (ref_model, &level1_2, 2);
3460   assert_node_ref_count (ref_model, &level2_1, 2);
3461   assert_node_ref_count (ref_model, &level2_2, 0);
3462   assert_node_ref_count (ref_model, &level3_1, 0);
3463   assert_node_ref_count (ref_model, &level3_2, 0);
3464   assert_node_ref_count (ref_model, &level4_1, 0);
3465   assert_node_ref_count (ref_model, &level4_2, 0);
3466
3467   gtk_widget_destroy (tree_view);
3468   gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
3469
3470   assert_node_ref_count (ref_model, &level1_1, 1);
3471   assert_node_ref_count (ref_model, &level1_2, 1);
3472   assert_node_ref_count (ref_model, &level2_1, 1);
3473   assert_node_ref_count (ref_model, &level2_2, 0);
3474   assert_node_ref_count (ref_model, &level3_1, 0);
3475   assert_node_ref_count (ref_model, &level3_2, 0);
3476   assert_node_ref_count (ref_model, &level4_1, 0);
3477   assert_node_ref_count (ref_model, &level4_2, 0);
3478
3479   g_object_unref (filter_model);
3480
3481   assert_node_ref_count (ref_model, &level1_1, 0);
3482   assert_node_ref_count (ref_model, &level1_2, 0);
3483   assert_node_ref_count (ref_model, &level2_1, 0);
3484   assert_node_ref_count (ref_model, &level2_2, 0);
3485   assert_node_ref_count (ref_model, &level3_1, 0);
3486   assert_node_ref_count (ref_model, &level3_2, 0);
3487   assert_node_ref_count (ref_model, &level4_1, 0);
3488   assert_node_ref_count (ref_model, &level4_2, 0);
3489
3490   g_object_unref (ref_model);
3491 }
3492
3493 static void
3494 ref_count_cleanup (void)
3495 {
3496   GtkTreeIter grandparent1, grandparent2, parent1, parent2;
3497   GtkTreeIter iter_parent1, iter_parent2, iter_parent2_first;
3498   GtkTreeModel *model;
3499   GtkTreeModelRefCount *ref_model;
3500   GtkTreeModel *filter_model;
3501   GtkWidget *tree_view;
3502
3503   model = gtk_tree_model_ref_count_new ();
3504   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
3505
3506   /* + grandparent1
3507    * + grandparent2
3508    *   + parent1
3509    *     + iter_parent1
3510    *   + parent2
3511    *     + iter_parent2_first
3512    *     + iter_parent2
3513    */
3514
3515   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
3516   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent2, NULL);
3517   gtk_tree_store_append (GTK_TREE_STORE (model), &parent1, &grandparent2);
3518   gtk_tree_store_append (GTK_TREE_STORE (model), &iter_parent1, &parent1);
3519   gtk_tree_store_append (GTK_TREE_STORE (model), &parent2, &grandparent2);
3520   gtk_tree_store_append (GTK_TREE_STORE (model), &iter_parent2_first, &parent2);
3521   gtk_tree_store_append (GTK_TREE_STORE (model), &iter_parent2, &parent2);
3522
3523   filter_model = gtk_tree_model_filter_new (model, NULL);
3524   tree_view = gtk_tree_view_new_with_model (filter_model);
3525
3526   gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
3527
3528   assert_node_ref_count (ref_model, &grandparent1, 2);
3529   assert_node_ref_count (ref_model, &grandparent2, 2);
3530   assert_node_ref_count (ref_model, &parent1, 3);
3531   assert_node_ref_count (ref_model, &parent2, 2);
3532   assert_node_ref_count (ref_model, &iter_parent1, 2);
3533   assert_node_ref_count (ref_model, &iter_parent2_first, 2);
3534   assert_node_ref_count (ref_model, &iter_parent2, 1);
3535
3536   gtk_widget_destroy (tree_view);
3537
3538   assert_node_ref_count (ref_model, &grandparent1, 1);
3539   assert_node_ref_count (ref_model, &grandparent2, 1);
3540   assert_node_ref_count (ref_model, &parent1, 2);
3541   assert_node_ref_count (ref_model, &parent2, 1);
3542   assert_node_ref_count (ref_model, &iter_parent1, 1);
3543   assert_node_ref_count (ref_model, &iter_parent2_first, 1);
3544   assert_node_ref_count (ref_model, &iter_parent2, 0);
3545
3546   gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
3547
3548   /* The root level and first level remain cached, only the references on the
3549    * first nodes of these levels are kept.  Grandparent2 is the parent
3550    * of the first level with parent1, so grandparent2 keeps a reference
3551    * as well.
3552    */
3553   assert_node_ref_count (ref_model, &grandparent1, 1);
3554   assert_node_ref_count (ref_model, &grandparent2, 1);
3555   assert_node_ref_count (ref_model, &parent1, 1);
3556   assert_node_ref_count (ref_model, &parent2, 0);
3557   assert_node_ref_count (ref_model, &iter_parent1, 0);
3558   assert_node_ref_count (ref_model, &iter_parent2_first, 0);
3559   assert_node_ref_count (ref_model, &iter_parent2, 0);
3560
3561   g_object_unref (filter_model);
3562   g_object_unref (ref_model);
3563 }
3564
3565 static void
3566 ref_count_row_ref (void)
3567 {
3568   GtkTreeIter grandparent1, grandparent2, parent1, parent2;
3569   GtkTreeIter iter_parent1, iter_parent2, iter_parent2_first;
3570   GtkTreeModel *model;
3571   GtkTreeModelRefCount *ref_model;
3572   GtkTreeModel *filter_model;
3573   GtkWidget *tree_view;
3574   GtkTreePath *path;
3575   GtkTreeRowReference *row_ref;
3576
3577   model = gtk_tree_model_ref_count_new ();
3578   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
3579
3580   /* + grandparent1
3581    * + grandparent2
3582    *   + parent1
3583    *     + iter_parent1
3584    *   + parent2
3585    *     + iter_parent2
3586    *     + iter_parent2
3587    */
3588
3589   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
3590   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent2, NULL);
3591   gtk_tree_store_append (GTK_TREE_STORE (model), &parent1, &grandparent2);
3592   gtk_tree_store_append (GTK_TREE_STORE (model), &iter_parent1, &parent1);
3593   gtk_tree_store_append (GTK_TREE_STORE (model), &parent2, &grandparent2);
3594   gtk_tree_store_append (GTK_TREE_STORE (model), &iter_parent2_first, &parent2);
3595   gtk_tree_store_append (GTK_TREE_STORE (model), &iter_parent2, &parent2);
3596
3597   filter_model = gtk_tree_model_filter_new (model, NULL);
3598   tree_view = gtk_tree_view_new_with_model (filter_model);
3599
3600   path = gtk_tree_path_new_from_indices (1, 1, 1, -1);
3601   row_ref = gtk_tree_row_reference_new (filter_model, path);
3602   gtk_tree_path_free (path);
3603
3604   assert_node_ref_count (ref_model, &grandparent1, 2);
3605   assert_node_ref_count (ref_model, &grandparent2, 3);
3606   assert_node_ref_count (ref_model, &parent1, 1);
3607   assert_node_ref_count (ref_model, &parent2, 2);
3608   assert_node_ref_count (ref_model, &iter_parent1, 0);
3609   assert_node_ref_count (ref_model, &iter_parent2_first, 1);
3610   assert_node_ref_count (ref_model, &iter_parent2, 1);
3611
3612   gtk_tree_row_reference_free (row_ref);
3613
3614   assert_node_ref_count (ref_model, &grandparent1, 2);
3615   assert_node_ref_count (ref_model, &grandparent2, 2);
3616   assert_node_ref_count (ref_model, &parent1, 1);
3617   assert_node_ref_count (ref_model, &parent2, 1);
3618   assert_node_ref_count (ref_model, &iter_parent1, 0);
3619   assert_node_ref_count (ref_model, &iter_parent2_first, 1);
3620   assert_node_ref_count (ref_model, &iter_parent2, 0);
3621
3622   path = gtk_tree_path_new_from_indices (1, 1, 1, -1);
3623   row_ref = gtk_tree_row_reference_new (filter_model, path);
3624   gtk_tree_path_free (path);
3625
3626   assert_node_ref_count (ref_model, &grandparent1, 2);
3627   assert_node_ref_count (ref_model, &grandparent2, 3);
3628   assert_node_ref_count (ref_model, &parent1, 1);
3629   assert_node_ref_count (ref_model, &parent2, 2);
3630   assert_node_ref_count (ref_model, &iter_parent1, 0);
3631   assert_node_ref_count (ref_model, &iter_parent2_first, 1);
3632   assert_node_ref_count (ref_model, &iter_parent2, 1);
3633
3634   gtk_tree_store_remove (GTK_TREE_STORE (model), &parent2);
3635
3636   assert_node_ref_count (ref_model, &grandparent1, 2);
3637   assert_node_ref_count (ref_model, &grandparent2, 2);
3638   assert_node_ref_count (ref_model, &parent1, 1);
3639   assert_node_ref_count (ref_model, &iter_parent1, 0);
3640
3641   gtk_tree_row_reference_free (row_ref);
3642
3643   assert_node_ref_count (ref_model, &grandparent1, 2);
3644   assert_node_ref_count (ref_model, &grandparent2, 2);
3645   assert_node_ref_count (ref_model, &parent1, 1);
3646   assert_node_ref_count (ref_model, &iter_parent1, 0);
3647
3648   gtk_widget_destroy (tree_view);
3649
3650   gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
3651
3652   /* The root level and first level remain cached, only the references on the
3653    * first nodes of these levels are kept.  Grandparent2 is the parent
3654    * of the first level with parent1, so grandparent2 keeps a reference
3655    * as well.
3656    */
3657   assert_node_ref_count (ref_model, &grandparent1, 1);
3658   assert_node_ref_count (ref_model, &grandparent2, 1);
3659   assert_node_ref_count (ref_model, &parent1, 1);
3660
3661   g_object_unref (filter_model);
3662   g_object_unref (ref_model);
3663 }
3664
3665 static void
3666 ref_count_transfer_root_level_insert (void)
3667 {
3668   GtkTreeIter grandparent1, grandparent2, grandparent3;
3669   GtkTreeIter new_node;
3670   GtkTreeModel *model;
3671   GtkTreeModelRefCount *ref_model;
3672   GtkTreeModel *filter_model;
3673   GtkWidget *tree_view;
3674
3675   model = gtk_tree_model_ref_count_new ();
3676   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
3677
3678   /* + grandparent1
3679    * + grandparent2
3680    * + grandparent3
3681    */
3682
3683   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
3684   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent2, NULL);
3685   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent3, NULL);
3686
3687   filter_model = gtk_tree_model_filter_new (model, NULL);
3688   tree_view = gtk_tree_view_new_with_model (filter_model);
3689
3690   assert_node_ref_count (ref_model, &grandparent1, 2);
3691   assert_node_ref_count (ref_model, &grandparent2, 1);
3692   assert_node_ref_count (ref_model, &grandparent3, 1);
3693
3694   gtk_tree_store_prepend (GTK_TREE_STORE (model), &new_node, NULL);
3695
3696   assert_node_ref_count (ref_model, &new_node, 2);
3697   assert_node_ref_count (ref_model, &grandparent1, 1);
3698   assert_node_ref_count (ref_model, &grandparent2, 1);
3699   assert_node_ref_count (ref_model, &grandparent3, 1);
3700
3701   gtk_widget_destroy (tree_view);
3702   g_object_unref (filter_model);
3703   g_object_unref (ref_model);
3704 }
3705
3706 static void
3707 ref_count_transfer_root_level_remove (void)
3708 {
3709   GtkTreeIter grandparent1, grandparent2, grandparent3;
3710   GtkTreeModel *model;
3711   GtkTreeModelRefCount *ref_model;
3712   GtkTreeModel *filter_model;
3713   GtkWidget *tree_view;
3714
3715   model = gtk_tree_model_ref_count_new ();
3716   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
3717
3718   /* + grandparent1
3719    * + grandparent2
3720    * + grandparent3
3721    */
3722
3723   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
3724   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent2, NULL);
3725   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent3, NULL);
3726
3727   filter_model = gtk_tree_model_filter_new (model, NULL);
3728   tree_view = gtk_tree_view_new_with_model (filter_model);
3729
3730   assert_node_ref_count (ref_model, &grandparent1, 2);
3731   assert_node_ref_count (ref_model, &grandparent2, 1);
3732   assert_node_ref_count (ref_model, &grandparent3, 1);
3733
3734   gtk_tree_store_remove (GTK_TREE_STORE (model), &grandparent1);
3735
3736   assert_node_ref_count (ref_model, &grandparent2, 2);
3737   assert_node_ref_count (ref_model, &grandparent3, 1);
3738
3739   gtk_tree_store_remove (GTK_TREE_STORE (model), &grandparent2);
3740
3741   assert_node_ref_count (ref_model, &grandparent3, 2);
3742
3743   gtk_widget_destroy (tree_view);
3744   g_object_unref (filter_model);
3745   g_object_unref (ref_model);
3746 }
3747
3748 static void
3749 ref_count_transfer_root_level_remove_filtered (void)
3750 {
3751   GtkTreeIter grandparent1, grandparent2, grandparent3, grandparent4;
3752   GtkTreeModel *model;
3753   GtkTreeModelRefCount *ref_model;
3754   GtkTreeModel *filter_model;
3755   GtkWidget *tree_view;
3756   GType column_types[] = { G_TYPE_BOOLEAN };
3757
3758   model = gtk_tree_model_ref_count_new ();
3759   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
3760
3761   gtk_tree_store_set_column_types (GTK_TREE_STORE (model), 1,
3762                                    column_types);
3763
3764   /* + grandparent1
3765    * + grandparent2
3766    * + grandparent3
3767    * + grandparent4
3768    */
3769
3770   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
3771   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent2, NULL);
3772   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent3, NULL);
3773   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent4, NULL);
3774
3775   /* Filter first node */
3776   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent1, 0, FALSE, -1);
3777   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, TRUE, -1);
3778   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent3, 0, TRUE, -1);
3779   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent4, 0, TRUE, -1);
3780
3781   filter_model = gtk_tree_model_filter_new (model, NULL);
3782   gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), 0);
3783   tree_view = gtk_tree_view_new_with_model (filter_model);
3784
3785   assert_node_ref_count (ref_model, &grandparent1, 0);
3786   assert_node_ref_count (ref_model, &grandparent2, 2);
3787   assert_node_ref_count (ref_model, &grandparent3, 1);
3788   assert_node_ref_count (ref_model, &grandparent4, 1);
3789
3790   gtk_tree_store_remove (GTK_TREE_STORE (model), &grandparent2);
3791
3792   assert_node_ref_count (ref_model, &grandparent1, 0);
3793   assert_node_ref_count (ref_model, &grandparent3, 2);
3794   assert_node_ref_count (ref_model, &grandparent4, 1);
3795
3796   gtk_tree_store_remove (GTK_TREE_STORE (model), &grandparent3);
3797
3798   assert_node_ref_count (ref_model, &grandparent1, 0);
3799   assert_node_ref_count (ref_model, &grandparent4, 2);
3800
3801   gtk_tree_store_remove (GTK_TREE_STORE (model), &grandparent4);
3802
3803   /* Check level length to get root level cached again */
3804   check_level_length (GTK_TREE_MODEL_FILTER (filter_model), NULL, 0);
3805
3806   assert_node_ref_count (ref_model, &grandparent1, 1);
3807
3808   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent2, NULL);
3809
3810   assert_node_ref_count (ref_model, &grandparent1, 1);
3811   assert_node_ref_count (ref_model, &grandparent2, 0);
3812
3813   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, TRUE, -1);
3814
3815   assert_node_ref_count (ref_model, &grandparent1, 1);
3816   assert_node_ref_count (ref_model, &grandparent2, 1);
3817
3818   check_level_length (GTK_TREE_MODEL_FILTER (filter_model), NULL, 1);
3819
3820   gtk_widget_destroy (tree_view);
3821   g_object_unref (filter_model);
3822   g_object_unref (ref_model);
3823 }
3824
3825 static void
3826 ref_count_transfer_root_level_reordered (void)
3827 {
3828   GtkTreeIter grandparent1, grandparent2, grandparent3;
3829   GtkTreeModel *model;
3830   GtkTreeModelRefCount *ref_model;
3831   GtkTreeModel *filter_model;
3832   GtkWidget *tree_view;
3833
3834   model = gtk_tree_model_ref_count_new ();
3835   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
3836
3837   /* + grandparent1
3838    * + grandparent2
3839    * + grandparent3
3840    */
3841
3842   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
3843   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent2, NULL);
3844   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent3, NULL);
3845
3846   filter_model = gtk_tree_model_filter_new (model, NULL);
3847   tree_view = gtk_tree_view_new_with_model (filter_model);
3848
3849   assert_node_ref_count (ref_model, &grandparent1, 2);
3850   assert_node_ref_count (ref_model, &grandparent2, 1);
3851   assert_node_ref_count (ref_model, &grandparent3, 1);
3852
3853   /* gtk_tree_store_move() will emit rows-reordered */
3854   gtk_tree_store_move_after (GTK_TREE_STORE (model),
3855                              &grandparent1, &grandparent3);
3856
3857   assert_node_ref_count (ref_model, &grandparent2, 2);
3858   assert_node_ref_count (ref_model, &grandparent3, 1);
3859   assert_node_ref_count (ref_model, &grandparent1, 1);
3860
3861   gtk_widget_destroy (tree_view);
3862   g_object_unref (filter_model);
3863   g_object_unref (ref_model);
3864 }
3865
3866 static void
3867 ref_count_transfer_root_level_reordered_filtered (void)
3868 {
3869   GtkTreeIter grandparent1, grandparent2, grandparent3;
3870   GtkTreeModel *model;
3871   GtkTreeModelRefCount *ref_model;
3872   GtkTreeModel *filter_model;
3873   GtkWidget *tree_view;
3874   GType column_types[] = { G_TYPE_BOOLEAN };
3875
3876   model = gtk_tree_model_ref_count_new ();
3877   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
3878
3879   gtk_tree_store_set_column_types (GTK_TREE_STORE (model), 1,
3880                                    column_types);
3881
3882   /* + grandparent1
3883    * + grandparent2
3884    * + grandparent3
3885    */
3886
3887   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
3888   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent2, NULL);
3889   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent3, NULL);
3890
3891   /* Test with 1 node filtered */
3892   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, TRUE, -1);
3893   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent3, 0, TRUE, -1);
3894
3895   filter_model = gtk_tree_model_filter_new (model, NULL);
3896   gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), 0);
3897   tree_view = gtk_tree_view_new_with_model (filter_model);
3898
3899   assert_node_ref_count (ref_model, &grandparent1, 0);
3900   assert_node_ref_count (ref_model, &grandparent2, 2);
3901   assert_node_ref_count (ref_model, &grandparent3, 1);
3902
3903   /* Move the invisible node grandparent1 */
3904
3905   /* gtk_tree_store_move() will emit rows-reordered */
3906   gtk_tree_store_move_after (GTK_TREE_STORE (model),
3907                              &grandparent1, &grandparent3);
3908
3909   assert_node_ref_count (ref_model, &grandparent2, 2);
3910   assert_node_ref_count (ref_model, &grandparent3, 1);
3911   assert_node_ref_count (ref_model, &grandparent1, 0);
3912
3913   /* Move the invisible node grandparent1 */
3914
3915   /* gtk_tree_store_move() will emit rows-reordered */
3916   gtk_tree_store_move_before (GTK_TREE_STORE (model),
3917                               &grandparent1, &grandparent2);
3918
3919   assert_node_ref_count (ref_model, &grandparent1, 0);
3920   assert_node_ref_count (ref_model, &grandparent2, 2);
3921   assert_node_ref_count (ref_model, &grandparent3, 1);
3922
3923   /* Now swap grandparent2 and grandparent3, first reference must transfer */
3924   /* gtk_tree_store_swap() will emit rows-reordered */
3925   gtk_tree_store_swap (GTK_TREE_STORE (model),
3926                        &grandparent2, &grandparent3);
3927
3928   assert_node_ref_count (ref_model, &grandparent1, 0);
3929   assert_node_ref_count (ref_model, &grandparent3, 2);
3930   assert_node_ref_count (ref_model, &grandparent2, 1);
3931
3932   /* Swap back */
3933   gtk_tree_store_swap (GTK_TREE_STORE (model),
3934                        &grandparent2, &grandparent3);
3935
3936   assert_node_ref_count (ref_model, &grandparent1, 0);
3937   assert_node_ref_count (ref_model, &grandparent2, 2);
3938   assert_node_ref_count (ref_model, &grandparent3, 1);
3939
3940   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent1, 0, TRUE, -1);
3941
3942   assert_node_ref_count (ref_model, &grandparent1, 2);
3943   assert_node_ref_count (ref_model, &grandparent2, 1);
3944   assert_node_ref_count (ref_model, &grandparent3, 1);
3945
3946   /* Test with two nodes filtered */
3947   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent1, 0, FALSE, -1);
3948   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, FALSE, -1);
3949
3950   assert_node_ref_count (ref_model, &grandparent1, 0);
3951   assert_node_ref_count (ref_model, &grandparent2, 0);
3952   assert_node_ref_count (ref_model, &grandparent3, 2);
3953
3954   /* gtk_tree_store_move() will emit rows-reordered */
3955   gtk_tree_store_move_before (GTK_TREE_STORE (model),
3956                              &grandparent3, &grandparent1);
3957
3958   assert_node_ref_count (ref_model, &grandparent3, 2);
3959   assert_node_ref_count (ref_model, &grandparent2, 0);
3960   assert_node_ref_count (ref_model, &grandparent1, 0);
3961
3962   gtk_widget_destroy (tree_view);
3963   g_object_unref (filter_model);
3964   g_object_unref (ref_model);
3965 }
3966
3967 static void
3968 ref_count_transfer_root_level_filter (void)
3969 {
3970   GtkTreeIter grandparent1, grandparent2, grandparent3, grandparent4;
3971   GtkTreeIter new_node;
3972   GtkTreeModel *model;
3973   GtkTreeModelRefCount *ref_model;
3974   GtkTreeModel *filter_model;
3975   GtkWidget *tree_view;
3976   GType column_types[] = { G_TYPE_BOOLEAN };
3977
3978   model = gtk_tree_model_ref_count_new ();
3979   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
3980
3981   gtk_tree_store_set_column_types (GTK_TREE_STORE (model), 1,
3982                                    column_types);
3983
3984   /* + grandparent1
3985    * + grandparent2
3986    * + grandparent3
3987    * + grandparent4
3988    */
3989
3990   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
3991   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent2, NULL);
3992   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent3, NULL);
3993   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent4, NULL);
3994
3995   /* Filter first node */
3996   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent1, 0, FALSE, -1);
3997   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, TRUE, -1);
3998   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent3, 0, TRUE, -1);
3999   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent4, 0, TRUE, -1);
4000
4001   filter_model = gtk_tree_model_filter_new (model, NULL);
4002   gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), 0);
4003   tree_view = gtk_tree_view_new_with_model (filter_model);
4004
4005   assert_node_ref_count (ref_model, &grandparent1, 0);
4006   assert_node_ref_count (ref_model, &grandparent2, 2);
4007   assert_node_ref_count (ref_model, &grandparent3, 1);
4008   assert_node_ref_count (ref_model, &grandparent4, 1);
4009
4010   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, FALSE, -1);
4011
4012   assert_node_ref_count (ref_model, &grandparent1, 0);
4013   assert_node_ref_count (ref_model, &grandparent2, 0);
4014   assert_node_ref_count (ref_model, &grandparent3, 2);
4015   assert_node_ref_count (ref_model, &grandparent4, 1);
4016
4017   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent3, 0, FALSE, -1);
4018
4019   assert_node_ref_count (ref_model, &grandparent1, 0);
4020   assert_node_ref_count (ref_model, &grandparent2, 0);
4021   assert_node_ref_count (ref_model, &grandparent3, 0);
4022   assert_node_ref_count (ref_model, &grandparent4, 2);
4023
4024   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent4, 0, FALSE, -1);
4025
4026   assert_node_ref_count (ref_model, &grandparent1, 0);
4027   assert_node_ref_count (ref_model, &grandparent2, 0);
4028   assert_node_ref_count (ref_model, &grandparent3, 0);
4029   assert_node_ref_count (ref_model, &grandparent4, 1);
4030
4031   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, TRUE, -1);
4032
4033   assert_node_ref_count (ref_model, &grandparent1, 0);
4034   assert_node_ref_count (ref_model, &grandparent2, 2);
4035   assert_node_ref_count (ref_model, &grandparent3, 0);
4036   assert_node_ref_count (ref_model, &grandparent4, 0);
4037
4038   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, FALSE, -1);
4039
4040   assert_node_ref_count (ref_model, &grandparent1, 0);
4041   assert_node_ref_count (ref_model, &grandparent2, 0);
4042   assert_node_ref_count (ref_model, &grandparent3, 0);
4043   assert_node_ref_count (ref_model, &grandparent4, 1);
4044
4045   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent1, 0, TRUE, -1);
4046
4047   assert_node_ref_count (ref_model, &grandparent1, 2);
4048   assert_node_ref_count (ref_model, &grandparent2, 0);
4049   assert_node_ref_count (ref_model, &grandparent3, 0);
4050   assert_node_ref_count (ref_model, &grandparent4, 0);
4051
4052   gtk_tree_store_prepend (GTK_TREE_STORE (model), &new_node, NULL);
4053
4054   assert_node_ref_count (ref_model, &new_node, 0);
4055   assert_node_ref_count (ref_model, &grandparent1, 2);
4056   assert_node_ref_count (ref_model, &grandparent2, 0);
4057   assert_node_ref_count (ref_model, &grandparent3, 0);
4058   assert_node_ref_count (ref_model, &grandparent4, 0);
4059
4060   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent1, 0, FALSE, -1);
4061
4062   assert_node_ref_count (ref_model, &new_node, 0);
4063   assert_node_ref_count (ref_model, &grandparent1, 0);
4064   assert_node_ref_count (ref_model, &grandparent2, 0);
4065   assert_node_ref_count (ref_model, &grandparent3, 0);
4066   assert_node_ref_count (ref_model, &grandparent4, 1);
4067
4068   gtk_tree_store_remove (GTK_TREE_STORE (model), &new_node);
4069   gtk_tree_store_prepend (GTK_TREE_STORE (model), &new_node, NULL);
4070
4071   assert_node_ref_count (ref_model, &new_node, 0);
4072   assert_node_ref_count (ref_model, &grandparent1, 0);
4073   assert_node_ref_count (ref_model, &grandparent2, 0);
4074   assert_node_ref_count (ref_model, &grandparent3, 0);
4075   assert_node_ref_count (ref_model, &grandparent4, 1);
4076
4077   gtk_tree_store_set (GTK_TREE_STORE (model), &new_node, 0, TRUE, -1);
4078
4079   assert_node_ref_count (ref_model, &new_node, 2);
4080   assert_node_ref_count (ref_model, &grandparent1, 0);
4081   assert_node_ref_count (ref_model, &grandparent2, 0);
4082   assert_node_ref_count (ref_model, &grandparent3, 0);
4083   assert_node_ref_count (ref_model, &grandparent4, 0);
4084
4085   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, TRUE, -1);
4086   gtk_tree_store_remove (GTK_TREE_STORE (model), &new_node);
4087
4088   assert_node_ref_count (ref_model, &grandparent1, 0);
4089   assert_node_ref_count (ref_model, &grandparent2, 2);
4090   assert_node_ref_count (ref_model, &grandparent3, 0);
4091   assert_node_ref_count (ref_model, &grandparent4, 0);
4092
4093   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent4, 0, TRUE, -1);
4094   gtk_tree_store_remove (GTK_TREE_STORE (model), &grandparent2);
4095
4096   gtk_widget_destroy (tree_view);
4097   g_object_unref (filter_model);
4098   g_object_unref (ref_model);
4099 }
4100
4101 static void
4102 ref_count_transfer_child_level_insert (void)
4103 {
4104   GtkTreeIter grandparent1;
4105   GtkTreeIter parent1, parent2, parent3;
4106   GtkTreeIter new_node;
4107   GtkTreeModel *model;
4108   GtkTreeModelRefCount *ref_model;
4109   GtkTreeModel *filter_model;
4110   GtkWidget *tree_view;
4111
4112   model = gtk_tree_model_ref_count_new ();
4113   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
4114
4115   /* + grandparent1
4116    *   + parent1
4117    *   + parent2
4118    *   + parent3
4119    */
4120
4121   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
4122   gtk_tree_store_append (GTK_TREE_STORE (model), &parent1, &grandparent1);
4123   gtk_tree_store_append (GTK_TREE_STORE (model), &parent2, &grandparent1);
4124   gtk_tree_store_append (GTK_TREE_STORE (model), &parent3, &grandparent1);
4125
4126   filter_model = gtk_tree_model_filter_new (model, NULL);
4127   tree_view = gtk_tree_view_new_with_model (filter_model);
4128
4129   assert_node_ref_count (ref_model, &grandparent1, 3);
4130   assert_node_ref_count (ref_model, &parent1, 1);
4131   assert_node_ref_count (ref_model, &parent2, 0);
4132   assert_node_ref_count (ref_model, &parent3, 0);
4133
4134   gtk_tree_store_prepend (GTK_TREE_STORE (model), &new_node, &grandparent1);
4135
4136   assert_node_ref_count (ref_model, &grandparent1, 3);
4137   assert_node_ref_count (ref_model, &new_node, 1);
4138   assert_node_ref_count (ref_model, &parent1, 0);
4139   assert_node_ref_count (ref_model, &parent2, 0);
4140   assert_node_ref_count (ref_model, &parent3, 0);
4141
4142   gtk_widget_destroy (tree_view);
4143   g_object_unref (filter_model);
4144   g_object_unref (ref_model);
4145 }
4146
4147 static void
4148 ref_count_transfer_child_level_remove (void)
4149 {
4150   GtkTreeIter grandparent1;
4151   GtkTreeIter parent1, parent2, parent3;
4152   GtkTreeModel *model;
4153   GtkTreeModelRefCount *ref_model;
4154   GtkTreeModel *filter_model;
4155   GtkWidget *tree_view;
4156
4157   model = gtk_tree_model_ref_count_new ();
4158   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
4159
4160   /* + grandparent1
4161    *   + parent1
4162    *   + parent2
4163    *   + parent3
4164    */
4165
4166   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
4167   gtk_tree_store_append (GTK_TREE_STORE (model), &parent1, &grandparent1);
4168   gtk_tree_store_append (GTK_TREE_STORE (model), &parent2, &grandparent1);
4169   gtk_tree_store_append (GTK_TREE_STORE (model), &parent3, &grandparent1);
4170
4171   filter_model = gtk_tree_model_filter_new (model, NULL);
4172   tree_view = gtk_tree_view_new_with_model (filter_model);
4173
4174   assert_node_ref_count (ref_model, &grandparent1, 3);
4175   assert_node_ref_count (ref_model, &parent1, 1);
4176   assert_node_ref_count (ref_model, &parent2, 0);
4177   assert_node_ref_count (ref_model, &parent3, 0);
4178
4179   gtk_tree_store_remove (GTK_TREE_STORE (model), &parent1);
4180
4181   assert_node_ref_count (ref_model, &grandparent1, 3);
4182   assert_node_ref_count (ref_model, &parent2, 1);
4183   assert_node_ref_count (ref_model, &parent3, 0);
4184
4185   gtk_tree_store_remove (GTK_TREE_STORE (model), &parent2);
4186
4187   assert_node_ref_count (ref_model, &grandparent1, 3);
4188   assert_node_ref_count (ref_model, &parent3, 1);
4189
4190   gtk_widget_destroy (tree_view);
4191   g_object_unref (filter_model);
4192   g_object_unref (ref_model);
4193 }
4194
4195 static void
4196 ref_count_transfer_child_level_remove_filtered (void)
4197 {
4198   GtkTreeIter grandparent1;
4199   GtkTreeIter parent1, parent2, parent3, parent4;
4200   GtkTreeModel *model;
4201   GtkTreeModelRefCount *ref_model;
4202   GtkTreeModel *filter_model;
4203   GtkWidget *tree_view;
4204   GType column_types[] = { G_TYPE_BOOLEAN };
4205
4206   model = gtk_tree_model_ref_count_new ();
4207   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
4208
4209   gtk_tree_store_set_column_types (GTK_TREE_STORE (model), 1,
4210                                    column_types);
4211
4212   /* + grandparent1
4213    *   + parent1
4214    *   + parent2
4215    *   + parent3
4216    *   + parent4
4217    */
4218
4219   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
4220   gtk_tree_store_append (GTK_TREE_STORE (model), &parent1, &grandparent1);
4221   gtk_tree_store_append (GTK_TREE_STORE (model), &parent2, &grandparent1);
4222   gtk_tree_store_append (GTK_TREE_STORE (model), &parent3, &grandparent1);
4223   gtk_tree_store_append (GTK_TREE_STORE (model), &parent4, &grandparent1);
4224
4225   /* Filter first node */
4226   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent1, 0, TRUE, -1);
4227   gtk_tree_store_set (GTK_TREE_STORE (model), &parent1, 0, FALSE, -1);
4228   gtk_tree_store_set (GTK_TREE_STORE (model), &parent2, 0, TRUE, -1);
4229   gtk_tree_store_set (GTK_TREE_STORE (model), &parent3, 0, TRUE, -1);
4230   gtk_tree_store_set (GTK_TREE_STORE (model), &parent4, 0, TRUE, -1);
4231
4232   filter_model = gtk_tree_model_filter_new (model, NULL);
4233   gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), 0);
4234   tree_view = gtk_tree_view_new_with_model (filter_model);
4235
4236   assert_node_ref_count (ref_model, &grandparent1, 3);
4237   assert_node_ref_count (ref_model, &parent1, 0);
4238   assert_node_ref_count (ref_model, &parent2, 1);
4239   assert_node_ref_count (ref_model, &parent3, 0);
4240   assert_node_ref_count (ref_model, &parent4, 0);
4241
4242   gtk_tree_store_remove (GTK_TREE_STORE (model), &parent2);
4243
4244   assert_node_ref_count (ref_model, &grandparent1, 3);
4245   assert_node_ref_count (ref_model, &parent1, 0);
4246   assert_node_ref_count (ref_model, &parent3, 1);
4247   assert_node_ref_count (ref_model, &parent4, 0);
4248
4249   gtk_tree_store_remove (GTK_TREE_STORE (model), &parent3);
4250
4251   assert_node_ref_count (ref_model, &grandparent1, 3);
4252   assert_node_ref_count (ref_model, &parent1, 0);
4253   assert_node_ref_count (ref_model, &parent4, 1);
4254
4255   gtk_tree_store_remove (GTK_TREE_STORE (model), &parent4);
4256
4257   /* Check level length to get level cached again */
4258   check_level_length (GTK_TREE_MODEL_FILTER (filter_model), "0", 0);
4259
4260   assert_node_ref_count (ref_model, &grandparent1, 3);
4261   assert_node_ref_count (ref_model, &parent1, 1);
4262
4263   gtk_tree_store_append (GTK_TREE_STORE (model), &parent2, &grandparent1);
4264
4265   assert_node_ref_count (ref_model, &grandparent1, 3);
4266   assert_node_ref_count (ref_model, &parent1, 1);
4267   assert_node_ref_count (ref_model, &parent2, 0);
4268
4269   gtk_tree_store_set (GTK_TREE_STORE (model), &parent2, 0, TRUE, -1);
4270
4271   assert_node_ref_count (ref_model, &grandparent1, 3);
4272   assert_node_ref_count (ref_model, &parent1, 1);
4273   assert_node_ref_count (ref_model, &parent2, 0);
4274
4275   check_level_length (GTK_TREE_MODEL_FILTER (filter_model), "0", 1);
4276
4277   gtk_widget_destroy (tree_view);
4278   g_object_unref (filter_model);
4279   g_object_unref (ref_model);
4280 }
4281
4282 static void
4283 ref_count_transfer_child_level_reordered (void)
4284 {
4285   GtkTreeIter grandparent1;
4286   GtkTreeIter parent1, parent2, parent3;
4287   GtkTreeModel *model;
4288   GtkTreeModelRefCount *ref_model;
4289   GtkTreeModel *filter_model;
4290   GtkWidget *tree_view;
4291
4292   model = gtk_tree_model_ref_count_new ();
4293   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
4294
4295   /* + grandparent1
4296    *   + parent1
4297    *   + parent2
4298    *   + parent3
4299    */
4300
4301   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
4302   gtk_tree_store_append (GTK_TREE_STORE (model), &parent1, &grandparent1);
4303   gtk_tree_store_append (GTK_TREE_STORE (model), &parent2, &grandparent1);
4304   gtk_tree_store_append (GTK_TREE_STORE (model), &parent3, &grandparent1);
4305
4306   filter_model = gtk_tree_model_filter_new (model, NULL);
4307   tree_view = gtk_tree_view_new_with_model (filter_model);
4308
4309   assert_node_ref_count (ref_model, &grandparent1, 3);
4310   assert_node_ref_count (ref_model, &parent1, 1);
4311   assert_node_ref_count (ref_model, &parent2, 0);
4312   assert_node_ref_count (ref_model, &parent3, 0);
4313
4314   /* gtk_tree_store_move() will emit rows-reordered */
4315   gtk_tree_store_move_after (GTK_TREE_STORE (model),
4316                              &parent1, &parent3);
4317
4318   assert_node_ref_count (ref_model, &grandparent1, 3);
4319   assert_node_ref_count (ref_model, &parent2, 1);
4320   assert_node_ref_count (ref_model, &parent3, 0);
4321   assert_node_ref_count (ref_model, &parent1, 0);
4322
4323   gtk_widget_destroy (tree_view);
4324   g_object_unref (filter_model);
4325   g_object_unref (ref_model);
4326 }
4327
4328 static void
4329 ref_count_transfer_child_level_reordered_filtered (void)
4330 {
4331   GtkTreeIter grandparent1;
4332   GtkTreeIter parent1, parent2, parent3;
4333   GtkTreeModel *model;
4334   GtkTreeModelRefCount *ref_model;
4335   GtkTreeModel *filter_model;
4336   GtkWidget *tree_view;
4337   GType column_types[] = { G_TYPE_BOOLEAN };
4338
4339   model = gtk_tree_model_ref_count_new ();
4340   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
4341
4342   gtk_tree_store_set_column_types (GTK_TREE_STORE (model), 1,
4343                                    column_types);
4344
4345   /* + grandparent1
4346    *   + parent1
4347    *   + parent2
4348    *   + parent3
4349    */
4350
4351   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
4352   gtk_tree_store_append (GTK_TREE_STORE (model), &parent1, &grandparent1);
4353   gtk_tree_store_append (GTK_TREE_STORE (model), &parent2, &grandparent1);
4354   gtk_tree_store_append (GTK_TREE_STORE (model), &parent3, &grandparent1);
4355
4356   /* Test with 1 node filtered (parent1) */
4357   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent1, 0, TRUE, -1);
4358   gtk_tree_store_set (GTK_TREE_STORE (model), &parent2, 0, TRUE, -1);
4359   gtk_tree_store_set (GTK_TREE_STORE (model), &parent3, 0, TRUE, -1);
4360
4361   filter_model = gtk_tree_model_filter_new (model, NULL);
4362   gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), 0);
4363   tree_view = gtk_tree_view_new_with_model (filter_model);
4364
4365   assert_node_ref_count (ref_model, &grandparent1, 3);
4366   assert_node_ref_count (ref_model, &parent1, 0);
4367   assert_node_ref_count (ref_model, &parent2, 1);
4368   assert_node_ref_count (ref_model, &parent3, 0);
4369
4370   /* Move invisible node parent 1 */
4371
4372   /* gtk_tree_store_move() will emit rows-reordered */
4373   gtk_tree_store_move_after (GTK_TREE_STORE (model),
4374                              &parent1, &parent3);
4375
4376   assert_node_ref_count (ref_model, &grandparent1, 3);
4377   assert_node_ref_count (ref_model, &parent2, 1);
4378   assert_node_ref_count (ref_model, &parent3, 0);
4379   assert_node_ref_count (ref_model, &parent1, 0);
4380
4381   /* Move invisible node parent 1 */
4382
4383   /* gtk_tree_store_move() will emit rows-reordered */
4384   gtk_tree_store_move_before (GTK_TREE_STORE (model),
4385                               &parent1, &parent2);
4386
4387   assert_node_ref_count (ref_model, &grandparent1, 3);
4388   assert_node_ref_count (ref_model, &parent1, 0);
4389   assert_node_ref_count (ref_model, &parent2, 1);
4390   assert_node_ref_count (ref_model, &parent3, 0);
4391
4392   /* Now swap parent2 and parent2, first reference must transfer */
4393   /* gtk_tree_store_swap() will emit rows-reordered */
4394   gtk_tree_store_swap (GTK_TREE_STORE (model),
4395                        &parent2, &parent3);
4396
4397   assert_node_ref_count (ref_model, &grandparent1, 3);
4398   assert_node_ref_count (ref_model, &parent1, 0);
4399   assert_node_ref_count (ref_model, &parent3, 1);
4400   assert_node_ref_count (ref_model, &parent2, 0);
4401
4402   /* Swap back */
4403   gtk_tree_store_swap (GTK_TREE_STORE (model),
4404                        &parent2, &parent3);
4405
4406   assert_node_ref_count (ref_model, &grandparent1, 3);
4407   assert_node_ref_count (ref_model, &parent1, 0);
4408   assert_node_ref_count (ref_model, &parent2, 1);
4409   assert_node_ref_count (ref_model, &parent3, 0);
4410
4411   gtk_tree_store_set (GTK_TREE_STORE (model), &parent1, 0, TRUE, -1);
4412
4413   assert_node_ref_count (ref_model, &parent1, 1);
4414   assert_node_ref_count (ref_model, &parent2, 0);
4415   assert_node_ref_count (ref_model, &parent3, 0);
4416
4417   /* Test with two nodes filtered */
4418   gtk_tree_store_set (GTK_TREE_STORE (model), &parent1, 0, FALSE, -1);
4419   gtk_tree_store_set (GTK_TREE_STORE (model), &parent2, 0, FALSE, -1);
4420
4421   assert_node_ref_count (ref_model, &parent1, 0);
4422   assert_node_ref_count (ref_model, &parent2, 0);
4423   assert_node_ref_count (ref_model, &parent3, 1);
4424
4425   /* gtk_tree_store_move() will emit rows-reordered */
4426   gtk_tree_store_move_before (GTK_TREE_STORE (model),
4427                              &parent3, &parent1);
4428
4429   assert_node_ref_count (ref_model, &parent3, 1);
4430   assert_node_ref_count (ref_model, &parent2, 0);
4431   assert_node_ref_count (ref_model, &parent1, 0);
4432
4433   gtk_widget_destroy (tree_view);
4434   g_object_unref (filter_model);
4435   g_object_unref (ref_model);
4436 }
4437
4438 static void
4439 ref_count_transfer_child_level_filter (void)
4440 {
4441   GtkTreeIter root;
4442   GtkTreeIter grandparent1, grandparent2, grandparent3, grandparent4;
4443   GtkTreeIter new_node;
4444   GtkTreeModel *model;
4445   GtkTreeModelRefCount *ref_model;
4446   GtkTreeModel *filter_model;
4447   GtkWidget *tree_view;
4448   GType column_types[] = { G_TYPE_BOOLEAN };
4449
4450   model = gtk_tree_model_ref_count_new ();
4451   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
4452
4453   gtk_tree_store_set_column_types (GTK_TREE_STORE (model), 1,
4454                                    column_types);
4455
4456   /* + root
4457    *    + grandparent1
4458    *    + grandparent2
4459    *    + grandparent3
4460    *    + grandparent4
4461    */
4462
4463   gtk_tree_store_append (GTK_TREE_STORE (model), &root, NULL);
4464   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, &root);
4465   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent2, &root);
4466   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent3, &root);
4467   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent4, &root);
4468
4469   /* Filter first node */
4470   gtk_tree_store_set (GTK_TREE_STORE (model), &root, 0, TRUE, -1);
4471   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent1, 0, FALSE, -1);
4472   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, TRUE, -1);
4473   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent3, 0, TRUE, -1);
4474   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent4, 0, TRUE, -1);
4475
4476   filter_model = gtk_tree_model_filter_new (model, NULL);
4477   gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), 0);
4478   tree_view = gtk_tree_view_new_with_model (filter_model);
4479
4480   assert_node_ref_count (ref_model, &grandparent1, 0);
4481   assert_node_ref_count (ref_model, &grandparent2, 1);
4482   assert_node_ref_count (ref_model, &grandparent3, 0);
4483   assert_node_ref_count (ref_model, &grandparent4, 0);
4484
4485   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, FALSE, -1);
4486
4487   assert_node_ref_count (ref_model, &grandparent1, 0);
4488   assert_node_ref_count (ref_model, &grandparent2, 0);
4489   assert_node_ref_count (ref_model, &grandparent3, 1);
4490   assert_node_ref_count (ref_model, &grandparent4, 0);
4491
4492   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent3, 0, FALSE, -1);
4493
4494   assert_node_ref_count (ref_model, &grandparent1, 0);
4495   assert_node_ref_count (ref_model, &grandparent2, 0);
4496   assert_node_ref_count (ref_model, &grandparent3, 0);
4497   assert_node_ref_count (ref_model, &grandparent4, 1);
4498
4499   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent4, 0, FALSE, -1);
4500
4501   assert_node_ref_count (ref_model, &grandparent1, 0);
4502   assert_node_ref_count (ref_model, &grandparent2, 0);
4503   assert_node_ref_count (ref_model, &grandparent3, 0);
4504   assert_node_ref_count (ref_model, &grandparent4, 1);
4505
4506   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, TRUE, -1);
4507
4508   assert_node_ref_count (ref_model, &grandparent1, 0);
4509   assert_node_ref_count (ref_model, &grandparent2, 1);
4510   assert_node_ref_count (ref_model, &grandparent3, 0);
4511   assert_node_ref_count (ref_model, &grandparent4, 0);
4512
4513   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, FALSE, -1);
4514
4515   assert_node_ref_count (ref_model, &grandparent1, 0);
4516   assert_node_ref_count (ref_model, &grandparent2, 0);
4517   assert_node_ref_count (ref_model, &grandparent3, 0);
4518   assert_node_ref_count (ref_model, &grandparent4, 1);
4519
4520   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent1, 0, TRUE, -1);
4521
4522   assert_node_ref_count (ref_model, &grandparent1, 1);
4523   assert_node_ref_count (ref_model, &grandparent2, 0);
4524   assert_node_ref_count (ref_model, &grandparent3, 0);
4525   assert_node_ref_count (ref_model, &grandparent4, 0);
4526
4527   gtk_tree_store_prepend (GTK_TREE_STORE (model), &new_node, &root);
4528
4529   assert_node_ref_count (ref_model, &new_node, 0);
4530   assert_node_ref_count (ref_model, &grandparent1, 1);
4531   assert_node_ref_count (ref_model, &grandparent2, 0);
4532   assert_node_ref_count (ref_model, &grandparent3, 0);
4533   assert_node_ref_count (ref_model, &grandparent4, 0);
4534
4535   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent1, 0, FALSE, -1);
4536
4537   assert_node_ref_count (ref_model, &new_node, 0);
4538   assert_node_ref_count (ref_model, &grandparent1, 0);
4539   assert_node_ref_count (ref_model, &grandparent2, 0);
4540   assert_node_ref_count (ref_model, &grandparent3, 0);
4541   assert_node_ref_count (ref_model, &grandparent4, 1);
4542
4543   gtk_tree_store_remove (GTK_TREE_STORE (model), &new_node);
4544   gtk_tree_store_prepend (GTK_TREE_STORE (model), &new_node, &root);
4545
4546   assert_node_ref_count (ref_model, &new_node, 0);
4547   assert_node_ref_count (ref_model, &grandparent1, 0);
4548   assert_node_ref_count (ref_model, &grandparent2, 0);
4549   assert_node_ref_count (ref_model, &grandparent3, 0);
4550   assert_node_ref_count (ref_model, &grandparent4, 1);
4551
4552   gtk_tree_store_set (GTK_TREE_STORE (model), &new_node, 0, TRUE, -1);
4553
4554   assert_node_ref_count (ref_model, &new_node, 1);
4555   assert_node_ref_count (ref_model, &grandparent1, 0);
4556   assert_node_ref_count (ref_model, &grandparent2, 0);
4557   assert_node_ref_count (ref_model, &grandparent3, 0);
4558   assert_node_ref_count (ref_model, &grandparent4, 0);
4559
4560   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, TRUE, -1);
4561   gtk_tree_store_remove (GTK_TREE_STORE (model), &new_node);
4562
4563   assert_node_ref_count (ref_model, &grandparent1, 0);
4564   assert_node_ref_count (ref_model, &grandparent2, 1);
4565   assert_node_ref_count (ref_model, &grandparent3, 0);
4566   assert_node_ref_count (ref_model, &grandparent4, 0);
4567
4568   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent4, 0, TRUE, -1);
4569   gtk_tree_store_remove (GTK_TREE_STORE (model), &grandparent2);
4570
4571   gtk_widget_destroy (tree_view);
4572   g_object_unref (filter_model);
4573   g_object_unref (ref_model);
4574 }
4575
4576
4577 static gboolean
4578 specific_path_dependent_filter_func (GtkTreeModel *model,
4579                                      GtkTreeIter  *iter,
4580                                      gpointer      data)
4581 {
4582   GtkTreePath *path;
4583
4584   path = gtk_tree_model_get_path (model, iter);
4585   if (gtk_tree_path_get_indices (path)[0] < 4)
4586     return FALSE;
4587
4588   return TRUE;
4589 }
4590
4591 static void
4592 specific_path_dependent_filter (void)
4593 {
4594   int i;
4595   GtkTreeIter iter;
4596   GtkListStore *list;
4597   GtkTreeModel *sort;
4598   GtkTreeModel *filter;
4599
4600   list = gtk_list_store_new (1, G_TYPE_INT);
4601   gtk_list_store_insert_with_values (list, &iter, 0, 0, 1, -1);
4602   gtk_list_store_insert_with_values (list, &iter, 1, 0, 2, -1);
4603   gtk_list_store_insert_with_values (list, &iter, 2, 0, 3, -1);
4604   gtk_list_store_insert_with_values (list, &iter, 3, 0, 4, -1);
4605   gtk_list_store_insert_with_values (list, &iter, 4, 0, 5, -1);
4606   gtk_list_store_insert_with_values (list, &iter, 5, 0, 6, -1);
4607   gtk_list_store_insert_with_values (list, &iter, 6, 0, 7, -1);
4608   gtk_list_store_insert_with_values (list, &iter, 7, 0, 8, -1);
4609
4610   sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (list));
4611   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (sort), NULL);
4612   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
4613                                           specific_path_dependent_filter_func,
4614                                           NULL, NULL);
4615
4616   gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sort), 0,
4617                                         GTK_SORT_DESCENDING);
4618
4619   for (i = 0; i < 4; i++)
4620     {
4621       if (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (list), &iter,
4622                                          NULL, 1))
4623         gtk_list_store_remove (list, &iter);
4624
4625       if (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (list), &iter,
4626                                          NULL, 2))
4627         gtk_list_store_remove (list, &iter);
4628     }
4629
4630   g_object_unref (filter);
4631   g_object_unref (sort);
4632   g_object_unref (list);
4633 }
4634
4635
4636 static gboolean
4637 specific_append_after_collapse_visible_func (GtkTreeModel *model,
4638                                              GtkTreeIter  *iter,
4639                                              gpointer      data)
4640 {
4641   gint number;
4642   gboolean hide_negative_numbers;
4643
4644   gtk_tree_model_get (model, iter, 1, &number, -1);
4645   hide_negative_numbers = GPOINTER_TO_INT (g_object_get_data (data, "private-hide-negative-numbers"));
4646
4647   return (number >= 0 || !hide_negative_numbers);
4648 }
4649
4650 static void
4651 specific_append_after_collapse (void)
4652 {
4653   /* This test is based on one of the test cases I found in my
4654    * old test cases directory.  I unfortunately do not have a record
4655    * from who this test case originated.  -Kris.
4656    *
4657    * General idea:
4658    * - Construct tree.
4659    * - Show tree, expand, collapse.
4660    * - Add a row.
4661    */
4662
4663   GtkTreeIter iter;
4664   GtkTreeIter child_iter;
4665   GtkTreeIter child_iter2;
4666   GtkTreePath *append_path;
4667   GtkTreeStore *store;
4668   GtkTreeModel *filter;
4669   GtkTreeModel *sort;
4670
4671   GtkWidget *window;
4672   GtkWidget *tree_view;
4673
4674   store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_INT);
4675
4676   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
4677   g_object_set_data (G_OBJECT (filter), "private-hide-negative-numbers",
4678                      GINT_TO_POINTER (FALSE));
4679   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
4680                                           specific_append_after_collapse_visible_func,
4681                                           filter, NULL);
4682
4683   sort = gtk_tree_model_sort_new_with_model (filter);
4684
4685   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4686   tree_view = gtk_tree_view_new_with_model (sort);
4687   gtk_container_add (GTK_CONTAINER (window), tree_view);
4688   gtk_widget_realize (tree_view);
4689
4690   while (gtk_events_pending ())
4691     gtk_main_iteration ();
4692
4693   gtk_tree_store_prepend (store, &iter, NULL);
4694   gtk_tree_store_set (store, &iter,
4695                       0, "hallo", 1, 1, -1);
4696
4697   gtk_tree_store_append (store, &child_iter, &iter);
4698   gtk_tree_store_set (store, &child_iter,
4699                       0, "toemaar", 1, 1, -1);
4700
4701   gtk_tree_store_append (store, &child_iter2, &child_iter);
4702   gtk_tree_store_set (store, &child_iter2,
4703                       0, "very deep", 1, 1, -1);
4704
4705   append_path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &child_iter2);
4706
4707   gtk_tree_store_append (store, &child_iter, &iter);
4708   gtk_tree_store_set (store, &child_iter,
4709                       0, "sja", 1, 1, -1);
4710
4711   gtk_tree_store_append (store, &child_iter, &iter);
4712   gtk_tree_store_set (store, &child_iter,
4713                       0, "some word", 1, -1, -1);
4714
4715   /* Expand and collapse the tree */
4716   gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
4717   while (gtk_events_pending ())
4718     gtk_main_iteration ();
4719
4720   gtk_tree_view_collapse_all (GTK_TREE_VIEW (tree_view));
4721   while (gtk_events_pending ())
4722     gtk_main_iteration ();
4723
4724   /* Add another it */
4725   g_object_set_data (G_OBJECT (filter), "private-hide-negative-numbers",
4726                      GINT_TO_POINTER (TRUE));
4727
4728   if (gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, append_path))
4729     {
4730       gtk_tree_store_append (store, &child_iter, &iter);
4731       gtk_tree_store_set (store, &child_iter,
4732                           0, "new new new !!", 1, 1, -1);
4733     }
4734   gtk_tree_path_free (append_path);
4735
4736   /* Expand */
4737   gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
4738   while (gtk_events_pending ())
4739     gtk_main_iteration ();
4740 }
4741
4742
4743 static gint
4744 specific_sort_filter_remove_node_compare_func (GtkTreeModel  *model,
4745                                                GtkTreeIter   *iter1,
4746                                                GtkTreeIter   *iter2,
4747                                                gpointer       data)
4748 {
4749   return -1;
4750 }
4751
4752 static gboolean
4753 specific_sort_filter_remove_node_visible_func (GtkTreeModel  *model,
4754                                                GtkTreeIter   *iter,
4755                                                gpointer       data)
4756 {
4757   char *item = NULL;
4758
4759   /* Do reference the model */
4760   gtk_tree_model_get (model, iter, 0, &item, -1);
4761   g_free (item);
4762
4763   return FALSE;
4764 }
4765
4766 static void
4767 specific_sort_filter_remove_node (void)
4768 {
4769   /* This test is based on one of the test cases I found in my
4770    * old test cases directory.  I unfortunately do not have a record
4771    * from who this test case originated.  -Kris.
4772    *
4773    * General idea:
4774    *  - Create tree store, sort, filter models.  The sort model has
4775    *    a default sort func that is enabled, filter model a visible func
4776    *    that defaults to returning FALSE.
4777    *  - Remove a node from the tree store.
4778    */
4779
4780   GtkTreeIter iter;
4781   GtkTreeStore *store;
4782   GtkTreeModel *filter;
4783   GtkTreeModel *sort;
4784
4785   GtkWidget *window;
4786   GtkWidget *tree_view;
4787
4788   store = gtk_tree_store_new (1, G_TYPE_STRING);
4789   gtk_tree_store_append (store, &iter, NULL);
4790   gtk_tree_store_set (store, &iter, 0, "Hello1", -1);
4791
4792   gtk_tree_store_append (store, &iter, NULL);
4793   gtk_tree_store_set (store, &iter, 0, "Hello2", -1);
4794
4795   sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (store));
4796   gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (sort),
4797                                            specific_sort_filter_remove_node_compare_func, NULL, NULL);
4798
4799   filter = gtk_tree_model_filter_new (sort, NULL);
4800   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
4801                                           specific_sort_filter_remove_node_visible_func,
4802                                           filter, NULL);
4803
4804
4805   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4806   tree_view = gtk_tree_view_new_with_model (filter);
4807   gtk_container_add (GTK_CONTAINER (window), tree_view);
4808   gtk_widget_realize (tree_view);
4809
4810   while (gtk_events_pending ())
4811     gtk_main_iteration ();
4812
4813   /* Remove a node */
4814   gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter);
4815   gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter);
4816   gtk_tree_store_remove (store, &iter);
4817
4818   while (gtk_events_pending ())
4819     gtk_main_iteration ();
4820 }
4821
4822
4823 static void
4824 specific_sort_filter_remove_root (void)
4825 {
4826   /* This test is based on one of the test cases I found in my
4827    * old test cases directory.  I unfortunately do not have a record
4828    * from who this test case originated.  -Kris.
4829    */
4830
4831   GtkTreeModel *model, *sort, *filter;
4832   GtkTreeIter root, mid, leaf;
4833   GtkTreePath *path;
4834
4835   model = GTK_TREE_MODEL (gtk_tree_store_new (1, G_TYPE_INT));
4836   gtk_tree_store_append (GTK_TREE_STORE (model), &root, NULL);
4837   gtk_tree_store_append (GTK_TREE_STORE (model), &mid, &root);
4838   gtk_tree_store_append (GTK_TREE_STORE (model), &leaf, &mid);
4839
4840   path = gtk_tree_model_get_path (model, &mid);
4841
4842   sort = gtk_tree_model_sort_new_with_model (model);
4843   filter = gtk_tree_model_filter_new (sort, path);
4844
4845   gtk_tree_path_free (path);
4846
4847   gtk_tree_store_remove (GTK_TREE_STORE (model), &root);
4848
4849   g_object_unref (filter);
4850   g_object_unref (sort);
4851   g_object_unref (model);
4852 }
4853
4854
4855 static void
4856 specific_root_mixed_visibility (void)
4857 {
4858   int i;
4859   GtkTreeModel *filter;
4860   /* A bit nasty, apologies */
4861   FilterTest fixture;
4862
4863   fixture.store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
4864
4865   for (i = 0; i < LEVEL_LENGTH; i++)
4866     {
4867       GtkTreeIter iter;
4868
4869       gtk_tree_store_insert (fixture.store, &iter, NULL, i);
4870       if (i % 2 == 0)
4871         create_tree_store_set_values (fixture.store, &iter, TRUE);
4872       else
4873         create_tree_store_set_values (fixture.store, &iter, FALSE);
4874     }
4875
4876   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (fixture.store), NULL);
4877   fixture.filter = GTK_TREE_MODEL_FILTER (filter);
4878   fixture.monitor = NULL;
4879
4880   gtk_tree_model_filter_set_visible_column (fixture.filter, 1);
4881
4882   /* In order to trigger the potential bug, we should not access
4883    * the filter model here (so don't call the check functions).
4884    */
4885
4886   /* Change visibility of an odd row to TRUE */
4887   set_path_visibility (&fixture, "3", TRUE);
4888   check_filter_model (&fixture);
4889   check_level_length (fixture.filter, NULL, 4);
4890 }
4891
4892
4893
4894 static gboolean
4895 specific_has_child_filter_filter_func (GtkTreeModel *model,
4896                                        GtkTreeIter  *iter,
4897                                        gpointer      data)
4898 {
4899   return gtk_tree_model_iter_has_child (model, iter);
4900 }
4901
4902 static void
4903 specific_has_child_filter (void)
4904 {
4905   GtkTreeModel *filter;
4906   GtkTreeIter iter, root;
4907   FilterTest fixture; /* This is not how it should be done */
4908   GtkWidget *tree_view;
4909
4910   fixture.store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
4911   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (fixture.store), NULL);
4912   fixture.filter = GTK_TREE_MODEL_FILTER (filter);
4913   fixture.monitor = signal_monitor_new (filter);
4914
4915   tree_view = gtk_tree_view_new_with_model (filter);
4916
4917   /* We will filter on parent state using a filter function.  We will
4918    * manually keep the boolean column in sync, so that we can use
4919    * check_filter_model() to check the consistency of the model.
4920    */
4921   /* FIXME: We need a check_filter_model() that is not tied to LEVEL_LENGTH
4922    * to be able to check the structure here.  We keep the calls to
4923    * check_filter_model() commented out until then.
4924    */
4925   gtk_tree_model_filter_set_visible_func (fixture.filter,
4926                                           specific_has_child_filter_filter_func,
4927                                           NULL, NULL);
4928
4929   /* The first node will be initially invisible: no signals */
4930   gtk_tree_store_append (fixture.store, &root, NULL);
4931   create_tree_store_set_values (fixture.store, &root, FALSE);
4932
4933   /* check_filter_model (&fixture); */
4934   check_level_length (fixture.filter, NULL, 0);
4935   signal_monitor_assert_is_empty (fixture.monitor);
4936
4937   /* Insert a child node. This will cause the parent to become visible
4938    * since there is a child now.
4939    */
4940   signal_monitor_append_signal (fixture.monitor, ROW_INSERTED, "0");
4941   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
4942   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
4943
4944   gtk_tree_store_append (fixture.store, &iter, &root);
4945   create_tree_store_set_values (fixture.store, &iter, TRUE);
4946
4947   /* Parent must now be visible.  Do the level length check first,
4948    * to avoid modifying the child model triggering a row-changed to
4949    * the filter model.
4950    */
4951   check_level_length (fixture.filter, NULL, 1);
4952   check_level_length (fixture.filter, "0", 0);
4953   signal_monitor_assert_is_empty (fixture.monitor);
4954
4955   /* This should propagate row-changed */
4956   signal_monitor_append_signal (fixture.monitor, ROW_CHANGED, "0");
4957   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
4958
4959   set_path_visibility (&fixture, "0", TRUE);
4960   /* check_filter_model (&fixture); */
4961   signal_monitor_assert_is_empty (fixture.monitor);
4962
4963   /* New root node, no child, so no signal */
4964   gtk_tree_store_append (fixture.store, &root, NULL);
4965   check_level_length (fixture.filter, NULL, 1);
4966   signal_monitor_assert_is_empty (fixture.monitor);
4967
4968   /* When the child comes in, this node will become visible */
4969   signal_monitor_append_signal (fixture.monitor, ROW_INSERTED, "1");
4970   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "1");
4971   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "1");
4972   signal_monitor_append_signal (fixture.monitor, ROW_CHANGED, "1");
4973   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "1");
4974
4975   gtk_tree_store_append (fixture.store, &iter, &root);
4976   check_level_length (fixture.filter, NULL, 2);
4977   check_level_length (fixture.filter, "1", 0);
4978
4979   create_tree_store_set_values (fixture.store, &root, TRUE);
4980   create_tree_store_set_values (fixture.store, &iter, TRUE);
4981
4982   /* check_filter_model (&fixture); */
4983   signal_monitor_assert_is_empty (fixture.monitor);
4984
4985   /* Add another child for 1 */
4986   gtk_tree_store_append (fixture.store, &iter, &root);
4987   create_tree_store_set_values (fixture.store, &iter, TRUE);
4988   check_level_length (fixture.filter, NULL, 2);
4989   check_level_length (fixture.filter, "0", 0);
4990   check_level_length (fixture.filter, "1", 0);
4991   signal_monitor_assert_is_empty (fixture.monitor);
4992
4993   /* Now remove one of the remaining child rows */
4994   signal_monitor_append_signal (fixture.monitor, ROW_DELETED, "0");
4995
4996   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture.store),
4997                                        &iter, "0:0");
4998   gtk_tree_store_remove (fixture.store, &iter);
4999
5000   check_level_length (fixture.filter, NULL, 1);
5001   check_level_length (fixture.filter, "0", 0);
5002
5003   set_path_visibility (&fixture, "0", FALSE);
5004   /* check_filter_model (&fixture); */
5005   signal_monitor_assert_is_empty (fixture.monitor);
5006 }
5007
5008
5009 static gboolean
5010 specific_root_has_child_filter_filter_func (GtkTreeModel *model,
5011                                             GtkTreeIter  *iter,
5012                                             gpointer      data)
5013 {
5014   int depth;
5015   GtkTreePath *path;
5016
5017   path = gtk_tree_model_get_path (model, iter);
5018   depth = gtk_tree_path_get_depth (path);
5019   gtk_tree_path_free (path);
5020
5021   if (depth > 1)
5022     return TRUE;
5023   /* else */
5024   return gtk_tree_model_iter_has_child (model, iter);
5025 }
5026
5027 static void
5028 specific_root_has_child_filter (void)
5029 {
5030   GtkTreeModel *filter;
5031   GtkTreeIter iter, root;
5032   FilterTest fixture; /* This is not how it should be done ... */
5033   GtkWidget *tree_view;
5034
5035   /* This is a variation on the above test case, specific has-child-filter,
5036    * herein the has-child check for visibility only applies to root level
5037    * nodes.  In this test, children are always visible because we
5038    * only filter based on the "has child" criterion.
5039    */
5040
5041   fixture.store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
5042   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (fixture.store), NULL);
5043   fixture.filter = GTK_TREE_MODEL_FILTER (filter);
5044   fixture.monitor = signal_monitor_new (filter);
5045
5046   tree_view = gtk_tree_view_new_with_model (filter);
5047
5048   /* We will filter on parent state using a filter function.  We will
5049    * manually keep the boolean column in sync, so that we can use
5050    * check_filter_model() to check the consistency of the model.
5051    */
5052   /* FIXME: We need a check_filter_model() that is not tied to LEVEL_LENGTH
5053    * to be able to check the structure here.  We keep the calls to
5054    * check_filter_model() commented out until then.
5055    */
5056   gtk_tree_model_filter_set_visible_func (fixture.filter,
5057                                           specific_root_has_child_filter_filter_func,
5058                                           NULL, NULL);
5059
5060   /* Add a first node, this will be invisible initially, so no signal
5061    * should be emitted.
5062    */
5063   gtk_tree_store_append (fixture.store, &root, NULL);
5064   create_tree_store_set_values (fixture.store, &root, FALSE);
5065
5066   signal_monitor_assert_is_empty (fixture.monitor);
5067   /* check_filter_model (&fixture); */
5068   check_level_length (fixture.filter, NULL, 0);
5069
5070   /* Add a child node.  This will cause the parent to become visible,
5071    * so we expect row-inserted signals for both.
5072    */
5073   signal_monitor_append_signal (fixture.monitor, ROW_INSERTED, "0");
5074   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
5075   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
5076
5077   gtk_tree_store_append (fixture.store, &iter, &root);
5078   signal_monitor_assert_is_empty (fixture.monitor);
5079
5080   check_level_length (fixture.filter, NULL, 1);
5081   check_level_length (fixture.filter, "0", 1);
5082
5083   /* Modify the content of iter, no signals because the parent is not
5084    * expanded.
5085    */
5086   create_tree_store_set_values (fixture.store, &iter, TRUE);
5087   signal_monitor_assert_is_empty (fixture.monitor);
5088
5089   /* Parent must now be visible.  Do the level length check first,
5090    * to avoid modifying the child model triggering a row-changed to
5091    * the filter model.
5092    */
5093   check_level_length (fixture.filter, NULL, 1);
5094   check_level_length (fixture.filter, "0", 1);
5095
5096   /* Modify path 0 */
5097   signal_monitor_append_signal (fixture.monitor, ROW_CHANGED, "0");
5098   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
5099
5100   set_path_visibility (&fixture, "0", TRUE);
5101   /* check_filter_model (&fixture); */
5102
5103   signal_monitor_assert_is_empty (fixture.monitor);
5104
5105   /* Insert another node in the root level.  Initially invisible, so
5106    * not expecting any signal.
5107    */
5108   gtk_tree_store_append (fixture.store, &root, NULL);
5109   check_level_length (fixture.filter, NULL, 1);
5110
5111   signal_monitor_assert_is_empty (fixture.monitor);
5112
5113   /* Adding a child node which also makes parent at path 1 visible. */
5114   signal_monitor_append_signal (fixture.monitor, ROW_INSERTED, "1");
5115   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "1");
5116   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "1");
5117
5118   gtk_tree_store_append (fixture.store, &iter, &root);
5119   check_level_length (fixture.filter, NULL, 2);
5120   check_level_length (fixture.filter, "1", 1);
5121
5122   signal_monitor_assert_is_empty (fixture.monitor);
5123
5124   /* Check if row-changed is propagated */
5125   signal_monitor_append_signal (fixture.monitor, ROW_CHANGED, "1");
5126   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "1");
5127
5128   create_tree_store_set_values (fixture.store, &root, TRUE);
5129   create_tree_store_set_values (fixture.store, &iter, TRUE);
5130   /* check_filter_model (&fixture); */
5131   signal_monitor_assert_is_empty (fixture.monitor);
5132
5133   /* Insert another child under node 1 */
5134   gtk_tree_store_append (fixture.store, &iter, &root);
5135   create_tree_store_set_values (fixture.store, &iter, TRUE);
5136   check_level_length (fixture.filter, NULL, 2);
5137   check_level_length (fixture.filter, "0", 1);
5138   check_level_length (fixture.filter, "1", 2);
5139   signal_monitor_assert_is_empty (fixture.monitor);
5140
5141   /* Set a child node to invisible.  This should not yield any
5142    * change, because filtering is only done on whether the root
5143    * node has a child, which it still has.
5144    */
5145   set_path_visibility (&fixture, "0:0", FALSE);
5146   signal_monitor_assert_is_empty (fixture.monitor);
5147
5148   /* Now remove one of the remaining child rows */
5149   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
5150   signal_monitor_append_signal (fixture.monitor, ROW_DELETED, "0");
5151
5152   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture.store),
5153                                        &iter, "0:0");
5154   gtk_tree_store_remove (fixture.store, &iter);
5155
5156   check_level_length (fixture.filter, NULL, 1);
5157   check_level_length (fixture.filter, "0", 2);
5158   signal_monitor_assert_is_empty (fixture.monitor);
5159
5160   /* Set visibility of 0 to FALSE, no-op for filter model since
5161    * the child 0:0 is already gone
5162    */
5163   set_path_visibility (&fixture, "0", FALSE);
5164   /* check_filter_model (&fixture); */
5165   signal_monitor_assert_is_empty (fixture.monitor);
5166 }
5167
5168 static void
5169 specific_has_child_filter_on_sort_model (void)
5170 {
5171   GtkTreeModel *filter;
5172   GtkTreeModel *sort_model;
5173   GtkTreeIter iter, root;
5174   FilterTest fixture; /* This is not how it should be done */
5175   GtkWidget *tree_view;
5176
5177   fixture.store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
5178   sort_model = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (fixture.store));
5179   filter = gtk_tree_model_filter_new (sort_model, NULL);
5180   fixture.filter = GTK_TREE_MODEL_FILTER (filter);
5181   fixture.monitor = signal_monitor_new (filter);
5182
5183   tree_view = gtk_tree_view_new_with_model (filter);
5184
5185   /* We will filter on parent state using a filter function.  We will
5186    * manually keep the boolean column in sync, so that we can use
5187    * check_filter_model() to check the consistency of the model.
5188    */
5189   /* FIXME: We need a check_filter_model() that is not tied to LEVEL_LENGTH
5190    * to be able to check the structure here.  We keep the calls to
5191    * check_filter_model() commented out until then.
5192    */
5193   gtk_tree_model_filter_set_visible_func (fixture.filter,
5194                                           specific_has_child_filter_filter_func,
5195                                           NULL, NULL);
5196
5197   /* The first node will be initially invisible: no signals */
5198   gtk_tree_store_append (fixture.store, &root, NULL);
5199   create_tree_store_set_values (fixture.store, &root, FALSE);
5200
5201   /* check_filter_model (&fixture); */
5202   check_level_length (fixture.filter, NULL, 0);
5203   signal_monitor_assert_is_empty (fixture.monitor);
5204
5205   /* Insert a child node. This will cause the parent to become visible
5206    * since there is a child now.
5207    */
5208   signal_monitor_append_signal (fixture.monitor, ROW_INSERTED, "0");
5209   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
5210
5211   gtk_tree_store_append (fixture.store, &iter, &root);
5212   create_tree_store_set_values (fixture.store, &iter, TRUE);
5213
5214   /* Parent must now be visible.  Do the level length check first,
5215    * to avoid modifying the child model triggering a row-changed to
5216    * the filter model.
5217    */
5218   check_level_length (fixture.filter, NULL, 1);
5219   check_level_length (fixture.filter, "0", 0);
5220   signal_monitor_assert_is_empty (fixture.monitor);
5221
5222   /* This should propagate row-changed */
5223   signal_monitor_append_signal (fixture.monitor, ROW_CHANGED, "0");
5224   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
5225
5226   set_path_visibility (&fixture, "0", TRUE);
5227   /* check_filter_model (&fixture); */
5228   signal_monitor_assert_is_empty (fixture.monitor);
5229
5230   /* New root node, no child, so no signal */
5231   gtk_tree_store_append (fixture.store, &root, NULL);
5232   check_level_length (fixture.filter, NULL, 1);
5233   signal_monitor_assert_is_empty (fixture.monitor);
5234
5235   /* When the child comes in, this node will become visible */
5236   signal_monitor_append_signal (fixture.monitor, ROW_INSERTED, "1");
5237   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "1");
5238   signal_monitor_append_signal (fixture.monitor, ROW_CHANGED, "1");
5239   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "1");
5240
5241   gtk_tree_store_append (fixture.store, &iter, &root);
5242   check_level_length (fixture.filter, NULL, 2);
5243   check_level_length (fixture.filter, "1", 0);
5244
5245   create_tree_store_set_values (fixture.store, &root, TRUE);
5246   create_tree_store_set_values (fixture.store, &iter, TRUE);
5247
5248   /* check_filter_model (&fixture); */
5249   signal_monitor_assert_is_empty (fixture.monitor);
5250
5251   /* Add another child for 1 */
5252   gtk_tree_store_append (fixture.store, &iter, &root);
5253   create_tree_store_set_values (fixture.store, &iter, TRUE);
5254   check_level_length (fixture.filter, NULL, 2);
5255   check_level_length (fixture.filter, "0", 0);
5256   check_level_length (fixture.filter, "1", 0);
5257   signal_monitor_assert_is_empty (fixture.monitor);
5258
5259   /* Now remove one of the remaining child rows */
5260   signal_monitor_append_signal (fixture.monitor, ROW_DELETED, "0");
5261
5262   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture.store),
5263                                        &iter, "0:0");
5264   gtk_tree_store_remove (fixture.store, &iter);
5265
5266   check_level_length (fixture.filter, NULL, 1);
5267   check_level_length (fixture.filter, "0", 0);
5268
5269   set_path_visibility (&fixture, "0", FALSE);
5270   /* check_filter_model (&fixture); */
5271   signal_monitor_assert_is_empty (fixture.monitor);
5272 }
5273
5274 static gboolean
5275 specific_at_least_2_children_filter_filter_func (GtkTreeModel *model,
5276                                                  GtkTreeIter  *iter,
5277                                                  gpointer      data)
5278 {
5279   return gtk_tree_model_iter_n_children (model, iter) >= 2;
5280 }
5281
5282 static void
5283 specific_at_least_2_children_filter (void)
5284 {
5285   GtkTreeModel *filter;
5286   GtkTreeIter iter, root;
5287   FilterTest fixture; /* This is not how it should be done */
5288   GtkWidget *tree_view;
5289
5290   fixture.store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
5291   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (fixture.store), NULL);
5292   fixture.filter = GTK_TREE_MODEL_FILTER (filter);
5293   fixture.monitor = signal_monitor_new (filter);
5294
5295   tree_view = gtk_tree_view_new_with_model (filter);
5296
5297   gtk_tree_model_filter_set_visible_func (fixture.filter,
5298                                           specific_at_least_2_children_filter_filter_func,
5299                                           NULL, NULL);
5300
5301   /* The first node will be initially invisible: no signals */
5302   gtk_tree_store_append (fixture.store, &root, NULL);
5303   create_tree_store_set_values (fixture.store, &root, FALSE);
5304
5305   /* check_filter_model (&fixture); */
5306   check_level_length (fixture.filter, NULL, 0);
5307   signal_monitor_assert_is_empty (fixture.monitor);
5308
5309   /* Insert a child node.  Nothing should happen.
5310    */
5311   gtk_tree_store_append (fixture.store, &iter, &root);
5312   create_tree_store_set_values (fixture.store, &iter, TRUE);
5313
5314   check_level_length (fixture.filter, NULL, 0);
5315   signal_monitor_assert_is_empty (fixture.monitor);
5316
5317   /* Insert a second child node.  This will cause the parent to become
5318    * visible.
5319    */
5320   signal_monitor_append_signal (fixture.monitor, ROW_INSERTED, "0");
5321   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
5322
5323   gtk_tree_store_append (fixture.store, &iter, &root);
5324   create_tree_store_set_values (fixture.store, &iter, TRUE);
5325
5326   /* Parent must now be visible.  Do the level length check first,
5327    * to avoid modifying the child model triggering a row-changed to
5328    * the filter model.
5329    */
5330   check_level_length (fixture.filter, NULL, 1);
5331   check_level_length (fixture.filter, "0", 0);
5332   signal_monitor_assert_is_empty (fixture.monitor);
5333
5334   /* This should propagate row-changed */
5335   signal_monitor_append_signal (fixture.monitor, ROW_CHANGED, "0");
5336   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
5337
5338   set_path_visibility (&fixture, "0", TRUE);
5339   /* check_filter_model (&fixture); */
5340   signal_monitor_assert_is_empty (fixture.monitor);
5341
5342   /* New root node, no child, so no signal */
5343   gtk_tree_store_append (fixture.store, &root, NULL);
5344   check_level_length (fixture.filter, NULL, 1);
5345   signal_monitor_assert_is_empty (fixture.monitor);
5346
5347   /* First child, no signal, no change */
5348   gtk_tree_store_append (fixture.store, &iter, &root);
5349   check_level_length (fixture.filter, NULL, 1);
5350   signal_monitor_assert_is_empty (fixture.monitor);
5351
5352   /* When the second child comes in, this node will become visible */
5353   signal_monitor_append_signal (fixture.monitor, ROW_INSERTED, "1");
5354   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "1");
5355   signal_monitor_append_signal (fixture.monitor, ROW_CHANGED, "1");
5356   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "1");
5357
5358   gtk_tree_store_append (fixture.store, &iter, &root);
5359   check_level_length (fixture.filter, NULL, 2);
5360   check_level_length (fixture.filter, "1", 0);
5361
5362   create_tree_store_set_values (fixture.store, &root, TRUE);
5363   create_tree_store_set_values (fixture.store, &iter, TRUE);
5364
5365   /* check_filter_model (&fixture); */
5366   signal_monitor_assert_is_empty (fixture.monitor);
5367
5368   /* Add another child for 1 */
5369   gtk_tree_store_append (fixture.store, &iter, &root);
5370   create_tree_store_set_values (fixture.store, &iter, TRUE);
5371   check_level_length (fixture.filter, NULL, 2);
5372   check_level_length (fixture.filter, "0", 0);
5373   check_level_length (fixture.filter, "1", 0);
5374   signal_monitor_assert_is_empty (fixture.monitor);
5375
5376   /* Now remove one of the remaining child rows */
5377   signal_monitor_append_signal (fixture.monitor, ROW_DELETED, "0");
5378
5379   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture.store),
5380                                        &iter, "0:0");
5381   gtk_tree_store_remove (fixture.store, &iter);
5382
5383   check_level_length (fixture.filter, NULL, 1);
5384   check_level_length (fixture.filter, "0", 0);
5385
5386   set_path_visibility (&fixture, "0", FALSE);
5387   /* check_filter_model (&fixture); */
5388   signal_monitor_assert_is_empty (fixture.monitor);
5389 }
5390
5391 static void
5392 specific_at_least_2_children_filter_on_sort_model (void)
5393 {
5394   GtkTreeModel *filter;
5395   GtkTreeModel *sort_model;
5396   GtkTreeIter iter, root;
5397   FilterTest fixture; /* This is not how it should be done */
5398   GtkWidget *tree_view;
5399
5400   fixture.store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
5401   sort_model = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (fixture.store));
5402   filter = gtk_tree_model_filter_new (sort_model, NULL);
5403   fixture.filter = GTK_TREE_MODEL_FILTER (filter);
5404   fixture.monitor = signal_monitor_new (filter);
5405
5406   tree_view = gtk_tree_view_new_with_model (filter);
5407
5408   gtk_tree_model_filter_set_visible_func (fixture.filter,
5409                                           specific_at_least_2_children_filter_filter_func,
5410                                           NULL, NULL);
5411
5412   /* The first node will be initially invisible: no signals */
5413   gtk_tree_store_append (fixture.store, &root, NULL);
5414   create_tree_store_set_values (fixture.store, &root, FALSE);
5415
5416   /* check_filter_model (&fixture); */
5417   check_level_length (fixture.filter, NULL, 0);
5418   signal_monitor_assert_is_empty (fixture.monitor);
5419
5420   /* Insert a child node.  Nothing should happen.
5421    */
5422   gtk_tree_store_append (fixture.store, &iter, &root);
5423   create_tree_store_set_values (fixture.store, &iter, TRUE);
5424
5425   check_level_length (fixture.filter, NULL, 0);
5426   signal_monitor_assert_is_empty (fixture.monitor);
5427
5428     {
5429       GtkTreePath *path = gtk_tree_path_new_from_indices (0, 0, -1);
5430       GtkTreeRowReference *ref;
5431
5432       ref = gtk_tree_row_reference_new (sort_model, path);
5433       gtk_tree_path_free (path);
5434     }
5435
5436   /* Insert a second child node.  This will cause the parent to become
5437    * visible.
5438    */
5439   signal_monitor_append_signal (fixture.monitor, ROW_INSERTED, "0");
5440   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
5441
5442   gtk_tree_store_append (fixture.store, &iter, &root);
5443   create_tree_store_set_values (fixture.store, &iter, TRUE);
5444
5445   /* Parent must now be visible.  Do the level length check first,
5446    * to avoid modifying the child model triggering a row-changed to
5447    * the filter model.
5448    */
5449   check_level_length (fixture.filter, NULL, 1);
5450   check_level_length (fixture.filter, "0", 0);
5451   signal_monitor_assert_is_empty (fixture.monitor);
5452
5453   /* This should propagate row-changed */
5454   signal_monitor_append_signal (fixture.monitor, ROW_CHANGED, "0");
5455   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
5456
5457   set_path_visibility (&fixture, "0", TRUE);
5458   /* check_filter_model (&fixture); */
5459   signal_monitor_assert_is_empty (fixture.monitor);
5460
5461   /* New root node, no child, so no signal */
5462   gtk_tree_store_append (fixture.store, &root, NULL);
5463   check_level_length (fixture.filter, NULL, 1);
5464   signal_monitor_assert_is_empty (fixture.monitor);
5465 }
5466
5467
5468 static void
5469 specific_filter_add_child (void)
5470 {
5471   /* This test is based on one of the test cases I found in my
5472    * old test cases directory.  I unfortunately do not have a record
5473    * from who this test case originated.  -Kris.
5474    */
5475
5476   GtkTreeIter iter;
5477   GtkTreeIter iter_first;
5478   GtkTreeIter child;
5479   GtkTreeStore *store;
5480   GtkTreeModel *filter G_GNUC_UNUSED;
5481
5482   store = gtk_tree_store_new (1, G_TYPE_STRING);
5483
5484   gtk_tree_store_append (store, &iter_first, NULL);
5485   gtk_tree_store_set (store, &iter_first, 0, "Hello", -1);
5486
5487   gtk_tree_store_append (store, &iter, NULL);
5488   gtk_tree_store_set (store, &iter, 0, "Hello", -1);
5489
5490   gtk_tree_store_append (store, &iter, NULL);
5491   gtk_tree_store_set (store, &iter, 0, "Hello", -1);
5492
5493   gtk_tree_store_append (store, &iter, NULL);
5494   gtk_tree_store_set (store, &iter, 0, "Hello", -1);
5495
5496   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
5497
5498   gtk_tree_store_set (store, &iter, 0, "Hello", -1);
5499   gtk_tree_store_append (store, &child, &iter_first);
5500   gtk_tree_store_set (store, &child, 0, "Hello", -1);
5501 }
5502
5503 static void
5504 specific_list_store_clear (void)
5505 {
5506   GtkTreeIter iter;
5507   GtkListStore *list;
5508   GtkTreeModel *filter;
5509   GtkWidget *view G_GNUC_UNUSED;
5510
5511   list = gtk_list_store_new (1, G_TYPE_INT);
5512   gtk_list_store_insert_with_values (list, &iter, 0, 0, 1, -1);
5513   gtk_list_store_insert_with_values (list, &iter, 1, 0, 2, -1);
5514   gtk_list_store_insert_with_values (list, &iter, 2, 0, 3, -1);
5515   gtk_list_store_insert_with_values (list, &iter, 3, 0, 4, -1);
5516   gtk_list_store_insert_with_values (list, &iter, 4, 0, 5, -1);
5517   gtk_list_store_insert_with_values (list, &iter, 5, 0, 6, -1);
5518   gtk_list_store_insert_with_values (list, &iter, 6, 0, 7, -1);
5519   gtk_list_store_insert_with_values (list, &iter, 7, 0, 8, -1);
5520
5521   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (list), NULL);
5522   view = gtk_tree_view_new_with_model (filter);
5523
5524   gtk_list_store_clear (list);
5525 }
5526
5527 static void
5528 specific_sort_ref_leaf_and_remove_ancestor (void)
5529 {
5530   GtkTreeIter iter, child, child2, child3;
5531   GtkTreeStore *tree;
5532   GtkTreeModel *sort;
5533   GtkTreePath *path;
5534   GtkTreeRowReference *rowref;
5535   GtkWidget *view G_GNUC_UNUSED;
5536
5537   tree = gtk_tree_store_new (1, G_TYPE_INT);
5538   gtk_tree_store_insert_with_values (tree, &iter, NULL, 0, 0, 1, -1);
5539   gtk_tree_store_insert_with_values (tree, &iter, NULL, 1, 0, 2, -1);
5540   gtk_tree_store_insert_with_values (tree, &iter, NULL, 2, 0, 3, -1);
5541   gtk_tree_store_insert_with_values (tree, &iter, NULL, 3, 0, 4, -1);
5542
5543   gtk_tree_store_insert_with_values (tree, &child, &iter, 0, 0, 50, -1);
5544   gtk_tree_store_insert_with_values (tree, &child2, &child, 0, 0, 6, -1);
5545   gtk_tree_store_insert_with_values (tree, &child3, &child2, 0, 0, 7, -1);
5546
5547   sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (tree));
5548   view = gtk_tree_view_new_with_model (sort);
5549   gtk_tree_view_expand_all (GTK_TREE_VIEW (view));
5550
5551   path = gtk_tree_path_new_from_indices (3, 0, 0, 0, -1);
5552   rowref = gtk_tree_row_reference_new (sort, path);
5553   gtk_tree_path_free (path);
5554
5555   path = gtk_tree_path_new_from_indices (3, 0, 0, 0, -1);
5556   rowref = gtk_tree_row_reference_new (sort, path);
5557   gtk_tree_path_free (path);
5558
5559   path = gtk_tree_path_new_from_indices (3, 0, -1);
5560   rowref = gtk_tree_row_reference_new (sort, path);
5561   gtk_tree_path_free (path);
5562
5563   path = gtk_tree_path_new_from_indices (3, -1);
5564   rowref = gtk_tree_row_reference_new (sort, path);
5565   gtk_tree_path_free (path);
5566
5567   /* Deleting a parent */
5568   path = gtk_tree_path_new_from_indices (3, 0, -1);
5569   gtk_tree_model_get_iter (GTK_TREE_MODEL (tree), &iter, path);
5570   gtk_tree_store_remove (tree, &iter);
5571   gtk_tree_path_free (path);
5572
5573   gtk_tree_row_reference_free (rowref);
5574 }
5575
5576 static void
5577 specific_ref_leaf_and_remove_ancestor (void)
5578 {
5579   GtkTreeIter iter, child, child2, child3;
5580   GtkTreeStore *tree;
5581   GtkTreeModel *filter;
5582   GtkTreePath *path;
5583   GtkTreeRowReference *rowref;
5584   GtkWidget *view G_GNUC_UNUSED;
5585
5586   tree = gtk_tree_store_new (1, G_TYPE_INT);
5587   gtk_tree_store_insert_with_values (tree, &iter, NULL, 0, 0, 1, -1);
5588   gtk_tree_store_insert_with_values (tree, &iter, NULL, 1, 0, 2, -1);
5589   gtk_tree_store_insert_with_values (tree, &iter, NULL, 2, 0, 3, -1);
5590   gtk_tree_store_insert_with_values (tree, &iter, NULL, 3, 0, 4, -1);
5591
5592   gtk_tree_store_insert_with_values (tree, &child, &iter, 0, 0, 50, -1);
5593   gtk_tree_store_insert_with_values (tree, &child2, &child, 0, 0, 6, -1);
5594   gtk_tree_store_insert_with_values (tree, &child3, &child2, 0, 0, 7, -1);
5595
5596   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (tree), NULL);
5597   view = gtk_tree_view_new_with_model (filter);
5598   gtk_tree_view_expand_all (GTK_TREE_VIEW (view));
5599
5600   path = gtk_tree_path_new_from_indices (3, 0, 0, 0, -1);
5601   rowref = gtk_tree_row_reference_new (filter, path);
5602   gtk_tree_path_free (path);
5603
5604   path = gtk_tree_path_new_from_indices (3, 0, 0, 0, -1);
5605   rowref = gtk_tree_row_reference_new (filter, path);
5606   gtk_tree_path_free (path);
5607
5608   path = gtk_tree_path_new_from_indices (3, 0, -1);
5609   rowref = gtk_tree_row_reference_new (filter, path);
5610   gtk_tree_path_free (path);
5611
5612   path = gtk_tree_path_new_from_indices (3, -1);
5613   rowref = gtk_tree_row_reference_new (filter, path);
5614   gtk_tree_path_free (path);
5615
5616   /* Deleting a parent */
5617   path = gtk_tree_path_new_from_indices (3, 0, -1);
5618   gtk_tree_model_get_iter (GTK_TREE_MODEL (tree), &iter, path);
5619   gtk_tree_store_remove (tree, &iter);
5620   gtk_tree_path_free (path);
5621
5622   gtk_tree_row_reference_free (rowref);
5623 }
5624
5625 static void
5626 specific_virtual_ref_leaf_and_remove_ancestor (void)
5627 {
5628   GtkTreeIter iter, child, child2, child3;
5629   GtkTreeStore *tree;
5630   GtkTreeModel *filter;
5631   GtkTreePath *path;
5632   GtkTreeRowReference *rowref;
5633   GtkWidget *view G_GNUC_UNUSED;
5634
5635   tree = gtk_tree_store_new (1, G_TYPE_INT);
5636   gtk_tree_store_insert_with_values (tree, &iter, NULL, 0, 0, 1, -1);
5637   gtk_tree_store_insert_with_values (tree, &iter, NULL, 1, 0, 2, -1);
5638   gtk_tree_store_insert_with_values (tree, &iter, NULL, 2, 0, 3, -1);
5639   gtk_tree_store_insert_with_values (tree, &iter, NULL, 3, 0, 4, -1);
5640
5641   gtk_tree_store_insert_with_values (tree, &child, &iter, 0, 0, 50, -1);
5642   gtk_tree_store_insert_with_values (tree, &child2, &child, 0, 0, 6, -1);
5643   gtk_tree_store_insert_with_values (tree, &child3, &child2, 0, 0, 7, -1);
5644
5645   /* Set a virtual root of 3:0 */
5646   path = gtk_tree_path_new_from_indices (3, 0, -1);
5647   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (tree), path);
5648   gtk_tree_path_free (path);
5649
5650   view = gtk_tree_view_new_with_model (filter);
5651   gtk_tree_view_expand_all (GTK_TREE_VIEW (view));
5652
5653   path = gtk_tree_path_new_from_indices (0, 0, -1);
5654   rowref = gtk_tree_row_reference_new (filter, path);
5655   gtk_tree_path_free (path);
5656
5657   path = gtk_tree_path_new_from_indices (0, 0, -1);
5658   rowref = gtk_tree_row_reference_new (filter, path);
5659   gtk_tree_path_free (path);
5660
5661   path = gtk_tree_path_new_from_indices (0, -1);
5662   rowref = gtk_tree_row_reference_new (filter, path);
5663   gtk_tree_path_free (path);
5664
5665   /* Deleting the virtual root */
5666   path = gtk_tree_path_new_from_indices (3, 0, -1);
5667   gtk_tree_model_get_iter (GTK_TREE_MODEL (tree), &iter, path);
5668   gtk_tree_store_remove (tree, &iter);
5669   gtk_tree_path_free (path);
5670
5671   gtk_tree_row_reference_free (rowref);
5672 }
5673
5674
5675 static int
5676 specific_bug_301558_sort_func (GtkTreeModel *model,
5677                                GtkTreeIter  *a,
5678                                GtkTreeIter  *b,
5679                                gpointer      data)
5680 {
5681   int i, j;
5682
5683   gtk_tree_model_get (model, a, 0, &i, -1);
5684   gtk_tree_model_get (model, b, 0, &j, -1);
5685
5686   return j - i;
5687 }
5688
5689 static void
5690 specific_bug_301558 (void)
5691 {
5692   /* Test case for GNOME Bugzilla bug 301558 provided by
5693    * Markku Vire.
5694    */
5695   GtkTreeStore *tree;
5696   GtkTreeModel *filter;
5697   GtkTreeModel *sort;
5698   GtkTreeIter root, iter, iter2;
5699   GtkWidget *view G_GNUC_UNUSED;
5700   int i;
5701   gboolean add;
5702
5703   g_test_bug ("301558");
5704
5705   tree = gtk_tree_store_new (2, G_TYPE_INT, G_TYPE_BOOLEAN);
5706   gtk_tree_store_append (tree, &iter, NULL);
5707   gtk_tree_store_set (tree, &iter, 0, 123, 1, TRUE, -1);
5708   gtk_tree_store_append (tree, &iter2, &iter);
5709   gtk_tree_store_set (tree, &iter2, 0, 73, 1, TRUE, -1);
5710
5711   sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (tree));
5712   gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (sort),
5713                                            specific_bug_301558_sort_func,
5714                                            NULL, NULL);
5715
5716   filter = gtk_tree_model_filter_new (sort, NULL);
5717   gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter), 1);
5718
5719   view = gtk_tree_view_new_with_model (filter);
5720
5721   while (gtk_events_pending ())
5722     gtk_main_iteration ();
5723
5724   add = TRUE;
5725
5726   for (i = 0; i < 10; i++)
5727     {
5728       if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (tree), &root))
5729         g_assert_not_reached ();
5730
5731       if (add)
5732         {
5733           gtk_tree_store_append (tree, &iter, &root);
5734           gtk_tree_store_set (tree, &iter, 0, 456, 1, TRUE, -1);
5735         }
5736       else
5737         {
5738           int n;
5739           n = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (tree), &root);
5740           gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (tree), &iter,
5741                                          &root, n - 1);
5742           gtk_tree_store_remove (tree, &iter);
5743         }
5744
5745       add = !add;
5746     }
5747 }
5748
5749
5750 static gboolean
5751 specific_bug_311955_filter_func (GtkTreeModel *model,
5752                                  GtkTreeIter  *iter,
5753                                  gpointer      data)
5754 {
5755   int value;
5756
5757   gtk_tree_model_get (model, iter, 0, &value, -1);
5758
5759   return (value != 0);
5760 }
5761
5762 static void
5763 specific_bug_311955 (void)
5764 {
5765   /* This is a test case for GNOME Bugzilla bug 311955.  It was written
5766    * by Markku Vire.
5767    */
5768   GtkTreeIter iter, child, root;
5769   GtkTreeStore *store;
5770   GtkTreeModel *sort;
5771   GtkTreeModel *filter;
5772
5773   GtkWidget *window G_GNUC_UNUSED;
5774   GtkWidget *tree_view;
5775   int i;
5776   int n;
5777   GtkTreePath *path;
5778
5779   g_test_bug ("311955");
5780
5781   store = gtk_tree_store_new (1, G_TYPE_INT);
5782
5783   gtk_tree_store_append (store, &root, NULL);
5784   gtk_tree_store_set (store, &root, 0, 33, -1);
5785
5786   gtk_tree_store_append (store, &iter, &root);
5787   gtk_tree_store_set (store, &iter, 0, 50, -1);
5788
5789   gtk_tree_store_append (store, &iter, NULL);
5790   gtk_tree_store_set (store, &iter, 0, 22, -1);
5791
5792   sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (store));
5793   filter = gtk_tree_model_filter_new (sort, NULL);
5794
5795   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
5796                                           specific_bug_311955_filter_func,
5797                                           NULL, NULL);
5798
5799   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5800   tree_view = gtk_tree_view_new_with_model (filter);
5801   g_object_unref (store);
5802
5803   gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
5804
5805   while (gtk_events_pending ())
5806     gtk_main_iteration ();
5807
5808   check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, 2);
5809   check_level_length (GTK_TREE_MODEL_FILTER (filter), "0", 1);
5810
5811   /* Fill model */
5812   for (i = 0; i < 4; i++)
5813     {
5814       gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &root);
5815
5816       gtk_tree_store_append (store, &iter, &root);
5817
5818       if (i < 3)
5819         gtk_tree_store_set (store, &iter, 0, i, -1);
5820
5821       if (i % 2 == 0)
5822         {
5823           gtk_tree_store_append (store, &child, &iter);
5824           gtk_tree_store_set (store, &child, 0, 10, -1);
5825         }
5826     }
5827
5828   while (gtk_events_pending ())
5829     gtk_main_iteration ();
5830
5831   check_level_length (GTK_TREE_MODEL_FILTER (filter), "0", 3);
5832   check_level_length (GTK_TREE_MODEL_FILTER (filter), "0:2", 1);
5833
5834   /* Remove bottommost child from the tree. */
5835   gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &root);
5836   n = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (store), &root);
5837
5838   if (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (store), &iter, &root, n - 2))
5839     {
5840       if (gtk_tree_model_iter_children (GTK_TREE_MODEL (store), &child, &iter))
5841         gtk_tree_store_remove (store, &child);
5842     }
5843   else
5844     g_assert_not_reached ();
5845
5846   path = gtk_tree_path_new_from_indices (0, 2, -1);
5847   gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path, FALSE);
5848   gtk_tree_path_free (path);
5849
5850   check_level_length (GTK_TREE_MODEL_FILTER (filter), "0", 3);
5851   check_level_length (GTK_TREE_MODEL_FILTER (filter), "0:2", 0);
5852 }
5853
5854 static void
5855 specific_bug_311955_clean (void)
5856 {
5857   /* Cleaned up version of the test case for GNOME Bugzilla bug 311955,
5858    * which is easier to understand.
5859    */
5860   GtkTreeIter iter, child, grandchild;
5861   GtkTreeStore *store;
5862   GtkTreeModel *sort;
5863   GtkTreeModel *filter;
5864
5865   GtkWidget *tree_view;
5866   GtkTreePath *path;
5867
5868   store = gtk_tree_store_new (1, G_TYPE_INT);
5869
5870   gtk_tree_store_append (store, &iter, NULL);
5871   gtk_tree_store_set (store, &iter, 0, 1, -1);
5872
5873   gtk_tree_store_append (store, &child, &iter);
5874   gtk_tree_store_set (store, &child, 0, 1, -1);
5875
5876   sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (store));
5877   filter = gtk_tree_model_filter_new (sort, NULL);
5878
5879   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
5880                                           specific_bug_311955_filter_func,
5881                                           NULL, NULL);
5882
5883   tree_view = gtk_tree_view_new_with_model (filter);
5884   g_object_unref (store);
5885
5886   gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
5887
5888   while (gtk_events_pending ())
5889     gtk_main_iteration ();
5890
5891   check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, 1);
5892   check_level_length (GTK_TREE_MODEL_FILTER (filter), "0", 1);
5893
5894   gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter);
5895
5896   gtk_tree_store_append (store, &child, &iter);
5897   gtk_tree_store_set (store, &child, 0, 0, -1);
5898
5899   gtk_tree_store_append (store, &child, &iter);
5900   gtk_tree_store_set (store, &child, 0, 1, -1);
5901
5902   gtk_tree_store_append (store, &child, &iter);
5903   gtk_tree_store_set (store, &child, 0, 1, -1);
5904
5905   gtk_tree_store_append (store, &grandchild, &child);
5906   gtk_tree_store_set (store, &grandchild, 0, 1, -1);
5907
5908   gtk_tree_store_append (store, &child, &iter);
5909   /* Don't set a value: assume 0 */
5910
5911   /* Remove leaf node, check trigger row-has-child-toggled */
5912   path = gtk_tree_path_new_from_indices (0, 3, 0, -1);
5913   gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, path);
5914   gtk_tree_path_free (path);
5915   gtk_tree_store_remove (store, &iter);
5916
5917   path = gtk_tree_path_new_from_indices (0, 2, -1);
5918   gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path, FALSE);
5919   gtk_tree_path_free (path);
5920
5921   check_level_length (GTK_TREE_MODEL_FILTER (filter), "0", 3);
5922   check_level_length (GTK_TREE_MODEL_FILTER (filter), "0:2", 0);
5923
5924   gtk_widget_destroy (tree_view);
5925 }
5926
5927 static void
5928 specific_bug_346800 (void)
5929 {
5930   /* This is a test case for GNOME Bugzilla bug 346800.  It was written
5931    * by Jonathan Matthew.
5932    */
5933
5934   GtkTreeIter node_iters[50];
5935   GtkTreeIter child_iters[50];
5936   GtkTreeModel *model;
5937   GtkTreeModelFilter *filter;
5938   GtkTreeStore *store;
5939   GType *columns;
5940   int i;
5941   int items = 50;
5942   columns = g_new (GType, 2);
5943   columns[0] = G_TYPE_STRING;
5944   columns[1] = G_TYPE_BOOLEAN;
5945   store = gtk_tree_store_newv (2, columns);
5946   model = GTK_TREE_MODEL (store);
5947
5948   g_test_bug ("346800");
5949
5950   filter = GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (model, NULL));
5951   gtk_tree_model_filter_set_visible_column (filter, 1);
5952
5953   for (i=0; i<items; i++)
5954     {
5955       /* allocate random amounts of junk, otherwise the filter model's arrays can expand without moving */
5956
5957       g_malloc (138);
5958       gtk_tree_store_append (store, &node_iters[i], NULL);
5959       gtk_tree_store_set (store, &node_iters[i],
5960                           0, "something",
5961                           1, ((i%6) == 0) ? FALSE : TRUE,
5962                           -1);
5963
5964       g_malloc (47);
5965       gtk_tree_store_append (store, &child_iters[i], &node_iters[i]);
5966       gtk_tree_store_set (store, &child_iters[i],
5967                           0, "something else",
5968                           1, FALSE,
5969                           -1);
5970       gtk_tree_model_filter_refilter (filter);
5971
5972       if (i > 6)
5973         {
5974           gtk_tree_store_set (GTK_TREE_STORE (model), &child_iters[i-1], 1,
5975                               (i & 1) ? TRUE : FALSE, -1);
5976           gtk_tree_model_filter_refilter (filter);
5977
5978           gtk_tree_store_set (GTK_TREE_STORE (model), &child_iters[i-2], 1,
5979                               (i & 1) ? FALSE: TRUE, -1);
5980           gtk_tree_model_filter_refilter (filter);
5981         }
5982     }
5983 }
5984
5985 static gboolean
5986 specific_bug_464173_visible_func (GtkTreeModel *model,
5987                                   GtkTreeIter  *iter,
5988                                   gpointer      data)
5989 {
5990   gboolean *visible = (gboolean *)data;
5991
5992   return *visible;
5993 }
5994
5995 static void
5996 specific_bug_464173 (void)
5997 {
5998   /* Test case for GNOME Bugzilla bug 464173, test case written
5999    * by Andreas Koehler.
6000    */
6001   GtkTreeStore *model;
6002   GtkTreeModelFilter *f_model;
6003   GtkTreeIter iter1, iter2;
6004   GtkWidget *view G_GNUC_UNUSED;
6005   gboolean visible = TRUE;
6006
6007   g_test_bug ("464173");
6008
6009   model = gtk_tree_store_new (1, G_TYPE_STRING);
6010   gtk_tree_store_append (model, &iter1, NULL);
6011   gtk_tree_store_set (model, &iter1, 0, "Foo", -1);
6012   gtk_tree_store_append (model, &iter2, &iter1);
6013   gtk_tree_store_set (model, &iter2, 0, "Bar", -1);
6014
6015   f_model = GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (GTK_TREE_MODEL(model), NULL));
6016   gtk_tree_model_filter_set_visible_func (f_model,
6017                                           specific_bug_464173_visible_func,
6018                                           &visible, NULL);
6019
6020   view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (f_model));
6021
6022   visible = FALSE;
6023   gtk_tree_model_filter_refilter (f_model);
6024 }
6025
6026
6027 static gboolean
6028 specific_bug_540201_filter_func (GtkTreeModel *model,
6029                                  GtkTreeIter  *iter,
6030                                  gpointer      data)
6031 {
6032   gboolean has_children;
6033
6034   has_children = gtk_tree_model_iter_has_child (model, iter);
6035
6036   return has_children;
6037 }
6038
6039 static void
6040 specific_bug_540201 (void)
6041 {
6042   /* Test case for GNOME Bugzilla bug 540201, steps provided by
6043    * Charles Day.
6044    */
6045   GtkTreeIter iter, root;
6046   GtkTreeStore *store;
6047   GtkTreeModel *filter;
6048
6049   GtkWidget *tree_view G_GNUC_UNUSED;
6050
6051   g_test_bug ("540201");
6052
6053   store = gtk_tree_store_new (1, G_TYPE_INT);
6054
6055   gtk_tree_store_append (store, &root, NULL);
6056   gtk_tree_store_set (store, &root, 0, 33, -1);
6057
6058   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
6059   tree_view = gtk_tree_view_new_with_model (filter);
6060
6061   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
6062                                           specific_bug_540201_filter_func,
6063                                           NULL, NULL);
6064
6065   gtk_tree_store_append (store, &iter, &root);
6066   gtk_tree_store_set (store, &iter, 0, 50, -1);
6067
6068   gtk_tree_store_append (store, &iter, &root);
6069   gtk_tree_store_set (store, &iter, 0, 22, -1);
6070
6071
6072   gtk_tree_store_append (store, &root, NULL);
6073   gtk_tree_store_set (store, &root, 0, 33, -1);
6074
6075   gtk_tree_store_append (store, &iter, &root);
6076   gtk_tree_store_set (store, &iter, 0, 22, -1);
6077 }
6078
6079
6080 static gboolean
6081 specific_bug_549287_visible_func (GtkTreeModel *model,
6082                                   GtkTreeIter  *iter,
6083                                   gpointer      data)
6084 {
6085   gboolean result = FALSE;
6086
6087   result = gtk_tree_model_iter_has_child (model, iter);
6088
6089   return result;
6090 }
6091
6092 static void
6093 specific_bug_549287 (void)
6094 {
6095   /* Test case for GNOME Bugzilla bug 529287, provided by Julient Puydt */
6096
6097   int i;
6098   GtkTreeStore *store;
6099   GtkTreeModel *filtered;
6100   GtkWidget *view G_GNUC_UNUSED;
6101   GtkTreeIter iter;
6102   GtkTreeIter *swap, *parent, *child;
6103
6104   g_test_bug ("529287");
6105
6106   store = gtk_tree_store_new (1, G_TYPE_STRING);
6107   filtered = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
6108   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filtered),
6109                                           specific_bug_549287_visible_func,
6110                                           NULL, NULL);
6111
6112   view = gtk_tree_view_new_with_model (filtered);
6113
6114   for (i = 0; i < 4; i++)
6115     {
6116       if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter))
6117         {
6118           parent = gtk_tree_iter_copy (&iter);
6119           child = gtk_tree_iter_copy (&iter);
6120
6121           while (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (store),
6122                                                 child, parent, 0))
6123             {
6124
6125               swap = parent;
6126               parent = child;
6127               child = swap;
6128             }
6129
6130           gtk_tree_store_append (store, child, parent);
6131           gtk_tree_store_set (store, child,
6132                               0, "Something",
6133                               -1);
6134
6135           gtk_tree_iter_free (parent);
6136           gtk_tree_iter_free (child);
6137         }
6138       else
6139         {
6140           gtk_tree_store_append (store, &iter, NULL);
6141           gtk_tree_store_set (store, &iter,
6142                               0, "Something",
6143                               -1);
6144         }
6145
6146       /* since we inserted something, we changed the visibility conditions: */
6147       gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (filtered));
6148     }
6149 }
6150
6151 static gboolean
6152 specific_bug_621076_visible_func (GtkTreeModel *model,
6153                                   GtkTreeIter  *iter,
6154                                   gpointer      data)
6155 {
6156   gboolean visible = FALSE;
6157   gchar *str = NULL;
6158
6159   gtk_tree_model_get (model, iter, 0, &str, -1);
6160   if (str != NULL && g_str_has_prefix (str, "visible"))
6161     {
6162       visible = TRUE;
6163     }
6164   else
6165     {
6166       GtkTreeIter child_iter;
6167       gboolean valid;
6168
6169       /* Recursively check if we have a visible child */
6170       for (valid = gtk_tree_model_iter_children (model, &child_iter, iter);
6171            valid; valid = gtk_tree_model_iter_next (model, &child_iter))
6172         {
6173           if (specific_bug_621076_visible_func (model, &child_iter, data))
6174             {
6175               visible = TRUE;
6176               break;
6177             }
6178         }
6179     }
6180
6181   if (str)
6182     g_free (str);
6183
6184   return visible;
6185 }
6186
6187 static void
6188 specific_bug_621076 (void)
6189 {
6190   /* Test case for GNOME Bugzilla bug 621076, provided by Xavier Claessens */
6191
6192   /* This test case differs from has-child-filter and root-has-child-filter
6193    * in that the visible function both filters on content and model
6194    * structure.  Also, it is recursive.
6195    */
6196
6197   GtkTreeStore *store;
6198   GtkTreeModel *filter;
6199   GtkWidget *view;
6200   GtkTreeIter group_iter;
6201   GtkTreeIter item_iter;
6202   SignalMonitor *monitor;
6203
6204   g_test_bug ("621076");
6205
6206   store = gtk_tree_store_new (1, G_TYPE_STRING);
6207   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
6208   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
6209                                           specific_bug_621076_visible_func,
6210                                           NULL, NULL);
6211
6212   view = gtk_tree_view_new_with_model (filter);
6213   g_object_ref_sink (view);
6214
6215   monitor = signal_monitor_new (filter);
6216
6217   signal_monitor_append_signal (monitor, ROW_INSERTED, "0");
6218   gtk_tree_store_insert_with_values (store, &item_iter, NULL, -1,
6219                                      0, "visible-group-0",
6220                                      -1);
6221   signal_monitor_assert_is_empty (monitor);
6222
6223   /* visible-group-0 is not expanded, so ROW_INSERTED should not be emitted
6224    * for its children. However, ROW_HAS_CHILD_TOGGLED should be emitted on
6225    * visible-group-0 to tell the view that row can be expanded. */
6226   signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "0");
6227   signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "0");
6228   group_iter = item_iter;
6229   gtk_tree_store_insert_with_values (store, &item_iter, &group_iter, -1,
6230                                      0, "visible-0:0",
6231                                      -1);
6232   signal_monitor_assert_is_empty (monitor);
6233
6234   signal_monitor_append_signal (monitor, ROW_INSERTED, "1");
6235   gtk_tree_store_insert_with_values (store, &item_iter, NULL, -1,
6236                                      0, "visible-group-1",
6237                                      -1);
6238   signal_monitor_assert_is_empty (monitor);
6239
6240   /* We are adding an hidden item inside visible-group-1, so
6241    * ROW_HAS_CHILD_TOGGLED should not be emitted.  It is emitted though,
6242    * because the signal originating at TreeStore will be propagated,
6243    * as well a generated signal because the state of the parent *could*
6244    * change by a change in the model.
6245    */
6246   signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "1");
6247   signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "1");
6248   group_iter = item_iter;
6249   gtk_tree_store_insert_with_values (store, &item_iter, &group_iter, -1,
6250                                      0, "group-1:0",
6251                                      -1);
6252   signal_monitor_assert_is_empty (monitor);
6253
6254   /* This group is invisible and its parent too. Nothing should be emitted */
6255   group_iter = item_iter;
6256   gtk_tree_store_insert_with_values (store, &item_iter, &group_iter, -1,
6257                                      0, "group-1:0:0",
6258                                      -1);
6259   signal_monitor_assert_is_empty (monitor);
6260
6261   /* Adding a visible item in this group hierarchy will make all nodes
6262    * in this path visible.  The first level should simply tell the view
6263    * that it now has a child, and the view will load the tree if needed
6264    * (depends on the expanded state).
6265    */
6266   signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "1");
6267   group_iter = item_iter;
6268   gtk_tree_store_insert_with_values (store, &item_iter, &group_iter, -1,
6269                                      0, "visible-1:0:0:0",
6270                                      -1);
6271   signal_monitor_assert_is_empty (monitor);
6272
6273   check_level_length (GTK_TREE_MODEL_FILTER (filter), "1", 1);
6274
6275   gtk_tree_store_insert_with_values (store, &item_iter, NULL, -1,
6276                                      0, "group-2",
6277                                      -1);
6278   signal_monitor_assert_is_empty (monitor);
6279
6280   /* Parent is invisible, and adding this invisible item won't change that,
6281    * so no signal should be emitted. */
6282   group_iter = item_iter;
6283   gtk_tree_store_insert_with_values (store, NULL, &group_iter, -1,
6284                                      0, "invisible-2:0",
6285                                      -1);
6286   signal_monitor_assert_is_empty (monitor);
6287
6288   /* This makes group-2 visible, so it gets inserted and tells it has
6289    * children.
6290    */
6291   signal_monitor_append_signal (monitor, ROW_INSERTED, "2");
6292   signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "2");
6293   gtk_tree_store_insert_with_values (store, NULL, &group_iter, -1,
6294                                      0, "visible-2:1",
6295                                      -1);
6296   signal_monitor_assert_is_empty (monitor);
6297
6298   /* group-2 is already visible, so this time it is a normal insertion */
6299   gtk_tree_store_insert_with_values (store, NULL, &group_iter, -1,
6300                                      0, "visible-2:2",
6301                                      -1);
6302   signal_monitor_assert_is_empty (monitor);
6303
6304
6305   gtk_tree_store_insert_with_values (store, &item_iter, NULL, -1,
6306                                      0, "group-3",
6307                                      -1);
6308   signal_monitor_assert_is_empty (monitor);
6309
6310   /* Parent is invisible, and adding this invisible item won't change that,
6311    * so no signal should be emitted. */
6312   group_iter = item_iter;
6313   gtk_tree_store_insert_with_values (store, NULL, &group_iter, -1,
6314                                      0, "invisible-3:0",
6315                                      -1);
6316   signal_monitor_assert_is_empty (monitor);
6317
6318   gtk_tree_store_insert_with_values (store, &item_iter, &group_iter, -1,
6319                                      0, "invisible-3:1",
6320                                      -1);
6321   signal_monitor_assert_is_empty (monitor);
6322
6323   /* This will make group 3 visible. */
6324   signal_monitor_append_signal (monitor, ROW_INSERTED, "3");
6325   signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "3");
6326   signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "3");
6327   gtk_tree_store_set (store, &item_iter, 0, "visible-3:1", -1);
6328   signal_monitor_assert_is_empty (monitor);
6329
6330   /* Make sure all groups are expanded, so the filter has the tree cached */
6331   gtk_tree_view_expand_all (GTK_TREE_VIEW (view));
6332   while (gtk_events_pending ())
6333     gtk_main_iteration ();
6334
6335   /* Should only yield a row-changed */
6336   signal_monitor_append_signal (monitor, ROW_CHANGED, "3:0");
6337   gtk_tree_store_set (store, &item_iter, 0, "visible-3:1", -1);
6338   signal_monitor_assert_is_empty (monitor);
6339
6340   /* Now remove/hide some items. If a group loses its last item, the group
6341    * should be deleted instead of the item.
6342    */
6343
6344   signal_monitor_append_signal (monitor, ROW_DELETED, "2:1");
6345   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (store), &item_iter, "2:2");
6346   gtk_tree_store_remove (store, &item_iter);
6347   signal_monitor_assert_is_empty (monitor);
6348
6349   signal_monitor_append_signal (monitor, ROW_DELETED, "2:0");
6350   signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "2");
6351   signal_monitor_append_signal (monitor, ROW_DELETED, "2");
6352   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (store), &item_iter, "2:1");
6353   gtk_tree_store_set (store, &item_iter, 0, "invisible-2:1", -1);
6354   signal_monitor_assert_is_empty (monitor);
6355
6356   signal_monitor_append_signal (monitor, ROW_DELETED, "1:0:0:0");
6357   signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "1:0:0");
6358   signal_monitor_append_signal (monitor, ROW_DELETED, "1:0");
6359   signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "1");
6360   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (store), &item_iter, "1:0:0:0");
6361   gtk_tree_store_remove (store, &item_iter);
6362   signal_monitor_assert_is_empty (monitor);
6363
6364   /* Hide a group using row-changed instead of row-deleted */
6365   /* Caution: group 2 is gone, so offsets of the signals have moved. */
6366   signal_monitor_append_signal (monitor, ROW_DELETED, "2:0");
6367   signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "2");
6368   signal_monitor_append_signal (monitor, ROW_DELETED, "2");
6369   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (store), &item_iter,
6370                                        "3:1");
6371   gtk_tree_store_set (store, &item_iter, 0, "invisible-3:1", -1);
6372   signal_monitor_assert_is_empty (monitor);
6373
6374 #if 0
6375   {
6376     GtkWidget *window;
6377     GtkTreeViewColumn *col;
6378
6379     gtk_tree_view_expand_all (GTK_TREE_VIEW (view));
6380
6381     col = gtk_tree_view_column_new_with_attributes ("foo",
6382         gtk_cell_renderer_text_new (),
6383         "text", 0, NULL);
6384     gtk_tree_view_append_column (GTK_TREE_VIEW (view), col);
6385
6386     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6387     g_signal_connect (window, "delete-event",
6388         G_CALLBACK (gtk_widget_destroy), NULL);
6389     g_signal_connect (window, "destroy",
6390         G_CALLBACK (gtk_main_quit), NULL);
6391
6392     gtk_container_add (GTK_CONTAINER (window), view);
6393
6394     gtk_widget_show (view);
6395     gtk_widget_show (window);
6396
6397     gtk_main ();
6398   }
6399 #endif
6400
6401   /* Cleanup */
6402   signal_monitor_free (monitor);
6403   g_object_unref (view);
6404   g_object_unref (store);
6405   g_object_unref (filter);
6406 }
6407
6408 static void
6409 specific_bug_657353_related (void)
6410 {
6411   GtkTreeIter node1, node2, node3, node4;
6412   GtkTreeModel *model;
6413   GtkTreeModelRefCount *ref_model;
6414   GtkTreeModel *filter_model;
6415   GtkWidget *tree_view;
6416   GType column_types[] = { G_TYPE_BOOLEAN };
6417
6418   /* gtk_tree_model_filter_rows_reordered() used to have a problem to
6419    * not properly transfer the first ref count when the first node in
6420    * the level does not have elt->offset == 0.  This test checks for
6421    * that.  This bug could cause the faulty condition
6422    *   elt->ext_ref_count > elt->ref_count
6423    * to raise.
6424    */
6425
6426   model = gtk_tree_model_ref_count_new ();
6427   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
6428
6429   gtk_tree_store_set_column_types (GTK_TREE_STORE (model), 1,
6430                                    column_types);
6431
6432   gtk_tree_store_append (GTK_TREE_STORE (model), &node1, NULL);
6433   gtk_tree_store_append (GTK_TREE_STORE (model), &node2, NULL);
6434   gtk_tree_store_append (GTK_TREE_STORE (model), &node3, NULL);
6435   gtk_tree_store_append (GTK_TREE_STORE (model), &node4, NULL);
6436
6437   /* Hide the first node */
6438   gtk_tree_store_set (GTK_TREE_STORE (model), &node1, 0, FALSE, -1);
6439   gtk_tree_store_set (GTK_TREE_STORE (model), &node2, 0, TRUE, -1);
6440   gtk_tree_store_set (GTK_TREE_STORE (model), &node3, 0, TRUE, -1);
6441   gtk_tree_store_set (GTK_TREE_STORE (model), &node4, 0, TRUE, -1);
6442
6443   filter_model = gtk_tree_model_filter_new (model, NULL);
6444   gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), 0);
6445   tree_view = gtk_tree_view_new_with_model (filter_model);
6446
6447   assert_node_ref_count (ref_model, &node1, 0);
6448   assert_node_ref_count (ref_model, &node2, 2);
6449   assert_node_ref_count (ref_model, &node3, 1);
6450   assert_node_ref_count (ref_model, &node4, 1);
6451
6452   /* Swap nodes 2 and 3 */
6453
6454   /* gtk_tree_store_swap() will emit rows-reordered */
6455   gtk_tree_store_swap (GTK_TREE_STORE (model),
6456                        &node2, &node3);
6457
6458   assert_node_ref_count (ref_model, &node1, 0);
6459   assert_node_ref_count (ref_model, &node3, 2);
6460   assert_node_ref_count (ref_model, &node2, 1);
6461   assert_node_ref_count (ref_model, &node4, 1);
6462
6463   /* Hide node 3 */
6464   gtk_tree_store_set (GTK_TREE_STORE (model), &node3, 0, FALSE, -1);
6465
6466   assert_node_ref_count (ref_model, &node1, 0);
6467   assert_node_ref_count (ref_model, &node3, 0);
6468   assert_node_ref_count (ref_model, &node2, 2);
6469   assert_node_ref_count (ref_model, &node4, 1);
6470
6471   gtk_widget_destroy (tree_view);
6472   g_object_unref (filter_model);
6473   g_object_unref (ref_model);
6474 }
6475
6476 static gboolean
6477 specific_bug_657353_visible_func (GtkTreeModel *model,
6478                                   GtkTreeIter  *iter,
6479                                   gpointer      data)
6480 {
6481   gchar *str;
6482   gboolean ret = FALSE;
6483
6484   gtk_tree_model_get (model, iter, 0, &str, -1);
6485   ret = strstr (str, "hidden") ? FALSE : TRUE;
6486   g_free (str);
6487
6488   return ret;
6489 }
6490
6491 static void
6492 specific_bug_657353 (void)
6493 {
6494   GtkListStore *store;
6495   GtkTreeModel *sort_model;
6496   GtkTreeModel *filter_model;
6497   GtkTreeIter iter, iter_a, iter_b, iter_c;
6498   GtkWidget *tree_view;
6499
6500   /* This is a very carefully crafted test case that is triggering the
6501    * situation described in bug 657353.
6502    *
6503    *   GtkListStore acts like EphyCompletionModel
6504    *   GtkTreeModelSort acts like the sort model added in
6505    *                      ephy_location_entry_set_completion.
6506    *   GtkTreeModelFilter acts like the filter model in
6507    *                      GtkEntryCompletion.
6508    */
6509
6510   /* Set up a model that's wrapped in a GtkTreeModelSort.  The first item
6511    * will be hidden.
6512    */
6513   store = gtk_list_store_new (1, G_TYPE_STRING);
6514   gtk_list_store_insert_with_values (store, &iter_b, 0, 0, "BBB hidden", -1);
6515   gtk_list_store_insert_with_values (store, &iter, 1, 0, "EEE", -1);
6516   gtk_list_store_insert_with_values (store, &iter, 2, 0, "DDD", -1);
6517   gtk_list_store_insert_with_values (store, &iter_c, 3, 0, "CCC", -1);
6518
6519   sort_model = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (store));
6520
6521   filter_model = gtk_tree_model_filter_new (sort_model, NULL);
6522   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter_model),
6523                                           specific_bug_657353_visible_func,
6524                                           filter_model, NULL);
6525
6526   tree_view = gtk_tree_view_new_with_model (filter_model);
6527
6528   /* This triggers emission of rows-reordered.  The elt with offset == 0
6529    * is hidden, which used to cause misbehavior.  (The first reference should
6530    * have moved to CCC, which did not happen).
6531    */
6532   gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sort_model),
6533                                         0, GTK_SORT_ASCENDING);
6534
6535   /* By inserting another item that will appear at the first position, a
6536    * reference transfer is done from CCC (which failed to get this reference
6537    * earlier) to AAA.  At this point, the rule
6538    * elt->ref_count >= elt->ext_ref_count is broken for CCC.
6539    */
6540   gtk_list_store_insert_with_values (store, &iter_a, 6, 0, "AAA", -1);
6541
6542   /* When we hide CCC, the references cannot be correctly released, because
6543    * CCC failed to get a reference during rows-reordered.  The faulty condition
6544    * only manifests itself here with MODEL_FILTER_DEBUG disabled (as is usual
6545    * in production).
6546    */
6547   gtk_list_store_set (store, &iter_c, 0, "CCC hidden", -1);
6548
6549   gtk_widget_destroy (tree_view);
6550   g_object_unref (filter_model);
6551   g_object_unref (sort_model);
6552   g_object_unref (store);
6553 }
6554
6555 static void
6556 specific_bug_658696 (void)
6557 {
6558   GtkTreeStore *store;
6559   GtkTreeModel *filter;
6560   GtkTreePath *vroot;
6561   GtkTreeIter iter;
6562
6563   store = create_tree_store (4, TRUE);
6564
6565   vroot = gtk_tree_path_new_from_indices (0, 0, -1);
6566   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), vroot);
6567   gtk_tree_path_free (vroot);
6568
6569   /* This used to cause a crash in gtk_tree_model_filter_check_ancestors() */
6570   gtk_tree_store_append (store, &iter, NULL);
6571 }
6572
6573 /* main */
6574
6575 void
6576 register_filter_model_tests (void)
6577 {
6578   g_test_add ("/TreeModelFilter/self/verify-test-suite",
6579               FilterTest, NULL,
6580               filter_test_setup,
6581               verify_test_suite,
6582               filter_test_teardown);
6583
6584   g_test_add ("/TreeModelFilter/self/verify-test-suite/vroot/depth-1",
6585               FilterTest, gtk_tree_path_new_from_indices (2, -1),
6586               filter_test_setup,
6587               verify_test_suite_vroot,
6588               filter_test_teardown);
6589   g_test_add ("/TreeModelFilter/self/verify-test-suite/vroot/depth-2",
6590               FilterTest, gtk_tree_path_new_from_indices (2, 3, -1),
6591               filter_test_setup,
6592               verify_test_suite_vroot,
6593               filter_test_teardown);
6594
6595
6596   g_test_add ("/TreeModelFilter/filled/hide-root-level",
6597               FilterTest, NULL,
6598               filter_test_setup,
6599               filled_hide_root_level,
6600               filter_test_teardown);
6601   g_test_add ("/TreeModelFilter/filled/hide-child-levels",
6602               FilterTest, NULL,
6603               filter_test_setup,
6604               filled_hide_child_levels,
6605               filter_test_teardown);
6606   g_test_add ("/TreeModelFilter/filled/hide-child-levels/root-expanded",
6607               FilterTest, NULL,
6608               filter_test_setup,
6609               filled_hide_child_levels_root_expanded,
6610               filter_test_teardown);
6611
6612   g_test_add ("/TreeModelFilter/filled/hide-root-level/vroot",
6613               FilterTest, gtk_tree_path_new_from_indices (2, -1),
6614               filter_test_setup,
6615               filled_vroot_hide_root_level,
6616               filter_test_teardown);
6617   g_test_add ("/TreeModelFilter/filled/hide-child-levels/vroot",
6618               FilterTest, gtk_tree_path_new_from_indices (2, -1),
6619               filter_test_setup,
6620               filled_vroot_hide_child_levels,
6621               filter_test_teardown);
6622   g_test_add ("/TreeModelFilter/filled/hide-child-levels/vroot-root-expanded",
6623               FilterTest, gtk_tree_path_new_from_indices (2, -1),
6624               filter_test_setup,
6625               filled_vroot_hide_child_levels_root_expanded,
6626               filter_test_teardown);
6627
6628
6629   g_test_add ("/TreeModelFilter/empty/show-nodes",
6630               FilterTest, NULL,
6631               filter_test_setup_empty,
6632               empty_show_nodes,
6633               filter_test_teardown);
6634   g_test_add ("/TreeModelFilter/empty/show-multiple-nodes",
6635               FilterTest, NULL,
6636               filter_test_setup_empty,
6637               empty_show_multiple_nodes,
6638               filter_test_teardown);
6639
6640   g_test_add ("/TreeModelFilter/empty/show-nodes/vroot",
6641               FilterTest, gtk_tree_path_new_from_indices (2, -1),
6642               filter_test_setup_empty,
6643               empty_vroot_show_nodes,
6644               filter_test_teardown);
6645   g_test_add ("/TreeModelFilter/empty/show-multiple-nodes/vroot",
6646               FilterTest, gtk_tree_path_new_from_indices (2, -1),
6647               filter_test_setup_empty,
6648               empty_vroot_show_multiple_nodes,
6649               filter_test_teardown);
6650
6651
6652   g_test_add ("/TreeModelFilter/unfiltered/hide-single",
6653               FilterTest, NULL,
6654               filter_test_setup_unfiltered,
6655               unfiltered_hide_single,
6656               filter_test_teardown);
6657   g_test_add ("/TreeModelFilter/unfiltered/hide-single/root-expanded",
6658               FilterTest, NULL,
6659               filter_test_setup_unfiltered_root_expanded,
6660               unfiltered_hide_single_root_expanded,
6661               filter_test_teardown);
6662   g_test_add ("/TreeModelFilter/unfiltered/hide-single-child",
6663               FilterTest, NULL,
6664               filter_test_setup_unfiltered,
6665               unfiltered_hide_single_child,
6666               filter_test_teardown);
6667   g_test_add ("/TreeModelFilter/unfiltered/hide-single-child/root-expanded",
6668               FilterTest, NULL,
6669               filter_test_setup_unfiltered_root_expanded,
6670               unfiltered_hide_single_child_root_expanded,
6671               filter_test_teardown);
6672   g_test_add ("/TreeModelFilter/unfiltered/hide-single-multi-level",
6673               FilterTest, NULL,
6674               filter_test_setup_unfiltered,
6675               unfiltered_hide_single_multi_level,
6676               filter_test_teardown);
6677   g_test_add ("/TreeModelFilter/unfiltered/hide-single-multi-level/root-expanded",
6678               FilterTest, NULL,
6679               filter_test_setup_unfiltered_root_expanded,
6680               unfiltered_hide_single_multi_level_root_expanded,
6681               filter_test_teardown);
6682
6683   g_test_add ("/TreeModelFilter/unfiltered/hide-single/vroot",
6684               FilterTest, gtk_tree_path_new_from_indices (2, -1),
6685               filter_test_setup_unfiltered,
6686               unfiltered_vroot_hide_single,
6687               filter_test_teardown);
6688   g_test_add ("/TreeModelFilter/unfiltered/hide-single-child/vroot",
6689               FilterTest, gtk_tree_path_new_from_indices (2, -1),
6690               filter_test_setup_unfiltered,
6691               unfiltered_vroot_hide_single_child,
6692               filter_test_teardown);
6693   g_test_add ("/TreeModelFilter/unfiltered/hide-single-child/vroot/root-expanded",
6694               FilterTest, gtk_tree_path_new_from_indices (2, -1),
6695               filter_test_setup_unfiltered_root_expanded,
6696               unfiltered_vroot_hide_single_child_root_expanded,
6697               filter_test_teardown);
6698   g_test_add ("/TreeModelFilter/unfiltered/hide-single-multi-level/vroot",
6699               FilterTest, gtk_tree_path_new_from_indices (2, -1),
6700               filter_test_setup_unfiltered,
6701               unfiltered_vroot_hide_single_multi_level,
6702               filter_test_teardown);
6703   g_test_add ("/TreeModelFilter/unfiltered/hide-single-multi-level/vroot/root-expanded",
6704               FilterTest, gtk_tree_path_new_from_indices (2, -1),
6705               filter_test_setup_unfiltered_root_expanded,
6706               unfiltered_vroot_hide_single_multi_level_root_expanded,
6707               filter_test_teardown);
6708
6709
6710
6711   g_test_add ("/TreeModelFilter/unfiltered/show-single",
6712               FilterTest, NULL,
6713               filter_test_setup_empty_unfiltered,
6714               unfiltered_show_single,
6715               filter_test_teardown);
6716   g_test_add ("/TreeModelFilter/unfiltered/show-single-child",
6717               FilterTest, NULL,
6718               filter_test_setup_empty_unfiltered,
6719               unfiltered_show_single_child,
6720               filter_test_teardown);
6721   g_test_add ("/TreeModelFilter/unfiltered/show-single-child/root-expanded",
6722               FilterTest, NULL,
6723               filter_test_setup_empty_unfiltered_root_expanded,
6724               unfiltered_show_single_child_root_expanded,
6725               filter_test_teardown);
6726   g_test_add ("/TreeModelFilter/unfiltered/show-single-multi-level",
6727               FilterTest, NULL,
6728               filter_test_setup_empty_unfiltered,
6729               unfiltered_show_single_multi_level,
6730               filter_test_teardown);
6731   g_test_add ("/TreeModelFilter/unfiltered/show-single-multi-level/root-expanded",
6732               FilterTest, NULL,
6733               filter_test_setup_empty_unfiltered_root_expanded,
6734               unfiltered_show_single_multi_level_root_expanded,
6735               filter_test_teardown);
6736
6737   g_test_add ("/TreeModelFilter/unfiltered/show-single/vroot",
6738               FilterTest, gtk_tree_path_new_from_indices (2, -1),
6739               filter_test_setup_empty_unfiltered,
6740               unfiltered_vroot_show_single,
6741               filter_test_teardown);
6742   g_test_add ("/TreeModelFilter/unfiltered/show-single-child/vroot",
6743               FilterTest, gtk_tree_path_new_from_indices (2, -1),
6744               filter_test_setup_empty_unfiltered,
6745               unfiltered_vroot_show_single_child,
6746               filter_test_teardown);
6747   g_test_add ("/TreeModelFilter/unfiltered/show-single-child/vroot/root-expanded",
6748               FilterTest, gtk_tree_path_new_from_indices (2, -1),
6749               filter_test_setup_empty_unfiltered_root_expanded,
6750               unfiltered_vroot_show_single_child_root_expanded,
6751               filter_test_teardown);
6752   g_test_add ("/TreeModelFilter/unfiltered/show-single-multi-level/vroot",
6753               FilterTest, gtk_tree_path_new_from_indices (2, -1),
6754               filter_test_setup_empty_unfiltered,
6755               unfiltered_vroot_show_single_multi_level,
6756               filter_test_teardown);
6757   g_test_add ("/TreeModelFilter/unfiltered/show-single-multi-level/vroot/root-expanded",
6758               FilterTest, gtk_tree_path_new_from_indices (2, -1),
6759               filter_test_setup_empty_unfiltered_root_expanded,
6760               unfiltered_vroot_show_single_multi_level_root_expanded,
6761               filter_test_teardown);
6762
6763
6764   g_test_add ("/TreeModelFilter/unfiltered/rows-reordered/root-level",
6765               FilterTest, NULL,
6766               filter_test_setup_unfiltered,
6767               unfiltered_rows_reordered_root_level,
6768               filter_test_teardown);
6769   g_test_add ("/TreeModelFilter/unfiltered/rows-reordered/child-level",
6770               FilterTest, NULL,
6771               filter_test_setup_unfiltered,
6772               unfiltered_rows_reordered_child_level,
6773               filter_test_teardown);
6774
6775   g_test_add ("/TreeModelFilter/filtered/rows-reordered/root-level/first-hidden",
6776               FilterTest, NULL,
6777               filter_test_setup,
6778               filtered_rows_reordered_root_level_first_hidden,
6779               filter_test_teardown);
6780   g_test_add ("/TreeModelFilter/filtered/rows-reordered/root-level/middle-hidden",
6781               FilterTest, NULL,
6782               filter_test_setup,
6783               filtered_rows_reordered_root_level_middle_hidden,
6784               filter_test_teardown);
6785   g_test_add ("/TreeModelFilter/filtered/rows-reordered/child-level/first-hidden",
6786               FilterTest, NULL,
6787               filter_test_setup,
6788               filtered_rows_reordered_child_level_first_hidden,
6789               filter_test_teardown);
6790   g_test_add ("/TreeModelFilter/filtered/rows-reordered/child-level/middle-hidden",
6791               FilterTest, NULL,
6792               filter_test_setup,
6793               filtered_rows_reordered_child_level_middle_hidden,
6794               filter_test_teardown);
6795   g_test_add ("/TreeModelFilter/filtered/rows-reordered/child-level/4-hidden",
6796               FilterTest, NULL,
6797               filter_test_setup,
6798               filtered_rows_reordered_child_level_4_hidden,
6799               filter_test_teardown);
6800   g_test_add ("/TreeModelFilter/filtered/rows-reordered/child-level/all-hidden",
6801               FilterTest, NULL,
6802               filter_test_setup,
6803               filtered_rows_reordered_child_level_all_hidden,
6804               filter_test_teardown);
6805
6806   /* Inserts in child models after creation of filter model */
6807   g_test_add_func ("/TreeModelFilter/insert/before",
6808                    insert_before);
6809   g_test_add_func ("/TreeModelFilter/insert/child",
6810                    insert_child);
6811
6812   /* Removals from child model after creating of filter model */
6813   g_test_add_func ("/TreeModelFilter/remove/node",
6814                    remove_node);
6815   g_test_add_func ("/TreeModelFilter/remove/node-vroot",
6816                    remove_node_vroot);
6817   g_test_add_func ("/TreeModelFilter/remove/vroot-ancestor",
6818                    remove_vroot_ancestor);
6819
6820   /* Reference counting */
6821   g_test_add_func ("/TreeModelFilter/ref-count/single-level",
6822                    ref_count_single_level);
6823   g_test_add_func ("/TreeModelFilter/ref-count/two-levels",
6824                    ref_count_two_levels);
6825   g_test_add_func ("/TreeModelFilter/ref-count/three-levels",
6826                    ref_count_three_levels);
6827   g_test_add_func ("/TreeModelFilter/ref-count/delete-row",
6828                    ref_count_delete_row);
6829   g_test_add_func ("/TreeModelFilter/ref-count/filter-row/length-1",
6830                    ref_count_filter_row_length_1);
6831   g_test_add_func ("/TreeModelFilter/ref-count/filter-row/length-1-remove-in-root-level",
6832                    ref_count_filter_row_length_1_remove_in_root_level);
6833   g_test_add_func ("/TreeModelFilter/ref-count/filter-row/length-1-remove-in-child-level",
6834                    ref_count_filter_row_length_1_remove_in_child_level);
6835   g_test_add_func ("/TreeModelFilter/ref-count/filter-row/length-gt-1",
6836                    ref_count_filter_row_length_gt_1);
6837   g_test_add_func ("/TreeModelFilter/ref-count/filter-row/length-gt-1-visible-children",
6838                    ref_count_filter_row_length_gt_1_visible_children);
6839   g_test_add_func ("/TreeModelFilter/ref-count/cleanup",
6840                    ref_count_cleanup);
6841   g_test_add_func ("/TreeModelFilter/ref-count/row-ref",
6842                    ref_count_row_ref);
6843
6844   /* Reference counting, transfer of first reference on
6845    * first node in level.  This is a GtkTreeModelFilter-specific
6846    * feature.
6847    */
6848   g_test_add_func ("/TreeModelFilter/ref-count/transfer/root-level/insert",
6849                    ref_count_transfer_root_level_insert);
6850   g_test_add_func ("/TreeModelFilter/ref-count/transfer/root-level/remove",
6851                    ref_count_transfer_root_level_remove);
6852   g_test_add_func ("/TreeModelFilter/ref-count/transfer/root-level/remove/filtered",
6853                    ref_count_transfer_root_level_remove_filtered);
6854   g_test_add_func ("/TreeModelFilter/ref-count/transfer/root-level/reordered",
6855                    ref_count_transfer_root_level_reordered);
6856   g_test_add_func ("/TreeModelFilter/ref-count/transfer/root-level/reordered/filtered",
6857                    ref_count_transfer_root_level_reordered_filtered);
6858   g_test_add_func ("/TreeModelFilter/ref-count/transfer/root-level/filter",
6859                    ref_count_transfer_root_level_filter);
6860   g_test_add_func ("/TreeModelFilter/ref-count/transfer/child-level/insert",
6861                    ref_count_transfer_child_level_insert);
6862   g_test_add_func ("/TreeModelFilter/ref-count/transfer/child-level/remove",
6863                    ref_count_transfer_child_level_remove);
6864   g_test_add_func ("/TreeModelFilter/ref-count/transfer/child-level/remove/filtered",
6865                    ref_count_transfer_child_level_remove_filtered);
6866   g_test_add_func ("/TreeModelFilter/ref-count/transfer/child-level/reordered",
6867                    ref_count_transfer_child_level_reordered);
6868   g_test_add_func ("/TreeModelFilter/ref-count/transfer/child-level/reordered/filtered",
6869                    ref_count_transfer_child_level_reordered_filtered);
6870   g_test_add_func ("/TreeModelFilter/ref-count/transfer/child-level/filter",
6871                    ref_count_transfer_child_level_filter);
6872
6873   g_test_add_func ("/TreeModelFilter/specific/path-dependent-filter",
6874                    specific_path_dependent_filter);
6875   g_test_add_func ("/TreeModelFilter/specific/append-after-collapse",
6876                    specific_append_after_collapse);
6877   g_test_add_func ("/TreeModelFilter/specific/sort-filter-remove-node",
6878                    specific_sort_filter_remove_node);
6879   g_test_add_func ("/TreeModelFilter/specific/sort-filter-remove-root",
6880                    specific_sort_filter_remove_root);
6881   g_test_add_func ("/TreeModelFilter/specific/root-mixed-visibility",
6882                    specific_root_mixed_visibility);
6883   g_test_add_func ("/TreeModelFilter/specific/has-child-filter",
6884                    specific_has_child_filter);
6885   g_test_add_func ("/TreeModelFilter/specific/has-child-filter-on-sort-model",
6886                    specific_has_child_filter_on_sort_model);
6887   g_test_add_func ("/TreeModelFilter/specific/at-least-2-children-filter",
6888                    specific_at_least_2_children_filter);
6889   g_test_add_func ("/TreeModelFilter/specific/at-least-2-children-filter-on-sort-model",
6890                    specific_at_least_2_children_filter_on_sort_model);
6891   g_test_add_func ("/TreeModelFilter/specific/root-has-child-filter",
6892                    specific_root_has_child_filter);
6893   g_test_add_func ("/TreeModelFilter/specific/filter-add-child",
6894                    specific_filter_add_child);
6895   g_test_add_func ("/TreeModelFilter/specific/list-store-clear",
6896                    specific_list_store_clear);
6897   g_test_add_func ("/TreeModelFilter/specific/sort-ref-leaf-and-remove-ancestor",
6898                    specific_sort_ref_leaf_and_remove_ancestor);
6899   g_test_add_func ("/TreeModelFilter/specific/ref-leaf-and-remove-ancestor",
6900                    specific_ref_leaf_and_remove_ancestor);
6901   g_test_add_func ("/TreeModelFilter/specific/virtual-ref-leaf-and-remove-ancestor",
6902                    specific_virtual_ref_leaf_and_remove_ancestor);
6903
6904   g_test_add_func ("/TreeModelFilter/specific/bug-301558",
6905                    specific_bug_301558);
6906   g_test_add_func ("/TreeModelFilter/specific/bug-311955",
6907                    specific_bug_311955);
6908   g_test_add_func ("/TreeModelFilter/specific/bug-311955-clean",
6909                    specific_bug_311955_clean);
6910   g_test_add_func ("/TreeModelFilter/specific/bug-346800",
6911                    specific_bug_346800);
6912   g_test_add_func ("/TreeModelFilter/specific/bug-464173",
6913                    specific_bug_464173);
6914   g_test_add_func ("/TreeModelFilter/specific/bug-540201",
6915                    specific_bug_540201);
6916   g_test_add_func ("/TreeModelFilter/specific/bug-549287",
6917                    specific_bug_549287);
6918   g_test_add_func ("/TreeModelFilter/specific/bug-621076",
6919                    specific_bug_621076);
6920   g_test_add_func ("/TreeModelFilter/specific/bug-657353-related",
6921                    specific_bug_657353_related);
6922   g_test_add_func ("/TreeModelFilter/specific/bug-657353",
6923                    specific_bug_657353);
6924   g_test_add_func ("/TreeModelFilter/specific/bug-658696",
6925                    specific_bug_658696);
6926 }