]> Pileus Git - ~andy/gtk/blob - gtk/tests/filtermodel.c
Add unit test for Bug 657353
[~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   gtk_tree_model_ref_count_dump (ref_model);
3793
3794   assert_node_ref_count (ref_model, &grandparent1, 0);
3795   assert_node_ref_count (ref_model, &grandparent3, 2);
3796   assert_node_ref_count (ref_model, &grandparent4, 1);
3797
3798   gtk_tree_store_remove (GTK_TREE_STORE (model), &grandparent3);
3799
3800   assert_node_ref_count (ref_model, &grandparent1, 0);
3801   assert_node_ref_count (ref_model, &grandparent4, 2);
3802
3803   gtk_tree_store_remove (GTK_TREE_STORE (model), &grandparent4);
3804
3805   /* Check level length to get root level cached again */
3806   check_level_length (GTK_TREE_MODEL_FILTER (filter_model), NULL, 0);
3807
3808   assert_node_ref_count (ref_model, &grandparent1, 1);
3809
3810   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent2, NULL);
3811
3812   assert_node_ref_count (ref_model, &grandparent1, 1);
3813   assert_node_ref_count (ref_model, &grandparent2, 0);
3814
3815   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, TRUE, -1);
3816
3817   assert_node_ref_count (ref_model, &grandparent1, 1);
3818   assert_node_ref_count (ref_model, &grandparent2, 1);
3819
3820   check_level_length (GTK_TREE_MODEL_FILTER (filter_model), NULL, 1);
3821
3822   gtk_widget_destroy (tree_view);
3823   g_object_unref (filter_model);
3824   g_object_unref (ref_model);
3825 }
3826
3827 static void
3828 ref_count_transfer_root_level_reordered (void)
3829 {
3830   GtkTreeIter grandparent1, grandparent2, grandparent3;
3831   GtkTreeModel *model;
3832   GtkTreeModelRefCount *ref_model;
3833   GtkTreeModel *filter_model;
3834   GtkWidget *tree_view;
3835
3836   model = gtk_tree_model_ref_count_new ();
3837   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
3838
3839   /* + grandparent1
3840    * + grandparent2
3841    * + grandparent3
3842    */
3843
3844   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
3845   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent2, NULL);
3846   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent3, NULL);
3847
3848   filter_model = gtk_tree_model_filter_new (model, NULL);
3849   tree_view = gtk_tree_view_new_with_model (filter_model);
3850
3851   assert_node_ref_count (ref_model, &grandparent1, 2);
3852   assert_node_ref_count (ref_model, &grandparent2, 1);
3853   assert_node_ref_count (ref_model, &grandparent3, 1);
3854
3855   /* gtk_tree_store_move() will emit rows-reordered */
3856   gtk_tree_store_move_after (GTK_TREE_STORE (model),
3857                              &grandparent1, &grandparent3);
3858
3859   assert_node_ref_count (ref_model, &grandparent2, 2);
3860   assert_node_ref_count (ref_model, &grandparent3, 1);
3861   assert_node_ref_count (ref_model, &grandparent1, 1);
3862
3863   gtk_widget_destroy (tree_view);
3864   g_object_unref (filter_model);
3865   g_object_unref (ref_model);
3866 }
3867
3868 static void
3869 ref_count_transfer_root_level_reordered_filtered (void)
3870 {
3871   GtkTreeIter grandparent1, grandparent2, grandparent3;
3872   GtkTreeModel *model;
3873   GtkTreeModelRefCount *ref_model;
3874   GtkTreeModel *filter_model;
3875   GtkWidget *tree_view;
3876   GType column_types[] = { G_TYPE_BOOLEAN };
3877
3878   model = gtk_tree_model_ref_count_new ();
3879   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
3880
3881   gtk_tree_store_set_column_types (GTK_TREE_STORE (model), 1,
3882                                    column_types);
3883
3884   /* + grandparent1
3885    * + grandparent2
3886    * + grandparent3
3887    */
3888
3889   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
3890   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent2, NULL);
3891   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent3, NULL);
3892
3893   /* Test with 1 node filtered */
3894   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, TRUE, -1);
3895   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent3, 0, TRUE, -1);
3896
3897   filter_model = gtk_tree_model_filter_new (model, NULL);
3898   gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), 0);
3899   tree_view = gtk_tree_view_new_with_model (filter_model);
3900
3901   assert_node_ref_count (ref_model, &grandparent1, 0);
3902   assert_node_ref_count (ref_model, &grandparent2, 2);
3903   assert_node_ref_count (ref_model, &grandparent3, 1);
3904
3905   /* Move the invisible node grandparent1 */
3906
3907   /* gtk_tree_store_move() will emit rows-reordered */
3908   gtk_tree_store_move_after (GTK_TREE_STORE (model),
3909                              &grandparent1, &grandparent3);
3910
3911   assert_node_ref_count (ref_model, &grandparent2, 2);
3912   assert_node_ref_count (ref_model, &grandparent3, 1);
3913   assert_node_ref_count (ref_model, &grandparent1, 0);
3914
3915   /* Move the invisible node grandparent1 */
3916
3917   /* gtk_tree_store_move() will emit rows-reordered */
3918   gtk_tree_store_move_before (GTK_TREE_STORE (model),
3919                               &grandparent1, &grandparent2);
3920
3921   assert_node_ref_count (ref_model, &grandparent1, 0);
3922   assert_node_ref_count (ref_model, &grandparent2, 2);
3923   assert_node_ref_count (ref_model, &grandparent3, 1);
3924
3925   /* Now swap grandparent2 and grandparent3, first reference must transfer */
3926   /* gtk_tree_store_swap() will emit rows-reordered */
3927   gtk_tree_store_swap (GTK_TREE_STORE (model),
3928                        &grandparent2, &grandparent3);
3929
3930   assert_node_ref_count (ref_model, &grandparent1, 0);
3931   assert_node_ref_count (ref_model, &grandparent3, 2);
3932   assert_node_ref_count (ref_model, &grandparent2, 1);
3933
3934   /* Swap back */
3935   gtk_tree_store_swap (GTK_TREE_STORE (model),
3936                        &grandparent2, &grandparent3);
3937
3938   assert_node_ref_count (ref_model, &grandparent1, 0);
3939   assert_node_ref_count (ref_model, &grandparent2, 2);
3940   assert_node_ref_count (ref_model, &grandparent3, 1);
3941
3942   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent1, 0, TRUE, -1);
3943
3944   assert_node_ref_count (ref_model, &grandparent1, 2);
3945   assert_node_ref_count (ref_model, &grandparent2, 1);
3946   assert_node_ref_count (ref_model, &grandparent3, 1);
3947
3948   /* Test with two nodes filtered */
3949   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent1, 0, FALSE, -1);
3950   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, FALSE, -1);
3951
3952   assert_node_ref_count (ref_model, &grandparent1, 0);
3953   assert_node_ref_count (ref_model, &grandparent2, 0);
3954   assert_node_ref_count (ref_model, &grandparent3, 2);
3955
3956   /* gtk_tree_store_move() will emit rows-reordered */
3957   gtk_tree_store_move_before (GTK_TREE_STORE (model),
3958                              &grandparent3, &grandparent1);
3959
3960   assert_node_ref_count (ref_model, &grandparent3, 2);
3961   assert_node_ref_count (ref_model, &grandparent2, 0);
3962   assert_node_ref_count (ref_model, &grandparent1, 0);
3963
3964   gtk_widget_destroy (tree_view);
3965   g_object_unref (filter_model);
3966   g_object_unref (ref_model);
3967 }
3968
3969 static void
3970 ref_count_transfer_root_level_filter (void)
3971 {
3972   GtkTreeIter grandparent1, grandparent2, grandparent3, grandparent4;
3973   GtkTreeIter new_node;
3974   GtkTreeModel *model;
3975   GtkTreeModelRefCount *ref_model;
3976   GtkTreeModel *filter_model;
3977   GtkWidget *tree_view;
3978   GType column_types[] = { G_TYPE_BOOLEAN };
3979
3980   model = gtk_tree_model_ref_count_new ();
3981   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
3982
3983   gtk_tree_store_set_column_types (GTK_TREE_STORE (model), 1,
3984                                    column_types);
3985
3986   /* + grandparent1
3987    * + grandparent2
3988    * + grandparent3
3989    * + grandparent4
3990    */
3991
3992   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
3993   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent2, NULL);
3994   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent3, NULL);
3995   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent4, NULL);
3996
3997   /* Filter first node */
3998   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent1, 0, FALSE, -1);
3999   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, TRUE, -1);
4000   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent3, 0, TRUE, -1);
4001   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent4, 0, TRUE, -1);
4002
4003   filter_model = gtk_tree_model_filter_new (model, NULL);
4004   gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), 0);
4005   tree_view = gtk_tree_view_new_with_model (filter_model);
4006
4007   assert_node_ref_count (ref_model, &grandparent1, 0);
4008   assert_node_ref_count (ref_model, &grandparent2, 2);
4009   assert_node_ref_count (ref_model, &grandparent3, 1);
4010   assert_node_ref_count (ref_model, &grandparent4, 1);
4011
4012   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, FALSE, -1);
4013
4014   assert_node_ref_count (ref_model, &grandparent1, 0);
4015   assert_node_ref_count (ref_model, &grandparent2, 0);
4016   assert_node_ref_count (ref_model, &grandparent3, 2);
4017   assert_node_ref_count (ref_model, &grandparent4, 1);
4018
4019   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent3, 0, FALSE, -1);
4020
4021   assert_node_ref_count (ref_model, &grandparent1, 0);
4022   assert_node_ref_count (ref_model, &grandparent2, 0);
4023   assert_node_ref_count (ref_model, &grandparent3, 0);
4024   assert_node_ref_count (ref_model, &grandparent4, 2);
4025
4026   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent4, 0, FALSE, -1);
4027
4028   assert_node_ref_count (ref_model, &grandparent1, 0);
4029   assert_node_ref_count (ref_model, &grandparent2, 0);
4030   assert_node_ref_count (ref_model, &grandparent3, 0);
4031   assert_node_ref_count (ref_model, &grandparent4, 1);
4032
4033   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, TRUE, -1);
4034
4035   assert_node_ref_count (ref_model, &grandparent1, 0);
4036   assert_node_ref_count (ref_model, &grandparent2, 2);
4037   assert_node_ref_count (ref_model, &grandparent3, 0);
4038   assert_node_ref_count (ref_model, &grandparent4, 0);
4039
4040   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, FALSE, -1);
4041
4042   assert_node_ref_count (ref_model, &grandparent1, 0);
4043   assert_node_ref_count (ref_model, &grandparent2, 0);
4044   assert_node_ref_count (ref_model, &grandparent3, 0);
4045   assert_node_ref_count (ref_model, &grandparent4, 1);
4046
4047   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent1, 0, TRUE, -1);
4048
4049   assert_node_ref_count (ref_model, &grandparent1, 2);
4050   assert_node_ref_count (ref_model, &grandparent2, 0);
4051   assert_node_ref_count (ref_model, &grandparent3, 0);
4052   assert_node_ref_count (ref_model, &grandparent4, 0);
4053
4054   gtk_tree_store_prepend (GTK_TREE_STORE (model), &new_node, NULL);
4055
4056   assert_node_ref_count (ref_model, &new_node, 0);
4057   assert_node_ref_count (ref_model, &grandparent1, 2);
4058   assert_node_ref_count (ref_model, &grandparent2, 0);
4059   assert_node_ref_count (ref_model, &grandparent3, 0);
4060   assert_node_ref_count (ref_model, &grandparent4, 0);
4061
4062   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent1, 0, FALSE, -1);
4063
4064   assert_node_ref_count (ref_model, &new_node, 0);
4065   assert_node_ref_count (ref_model, &grandparent1, 0);
4066   assert_node_ref_count (ref_model, &grandparent2, 0);
4067   assert_node_ref_count (ref_model, &grandparent3, 0);
4068   assert_node_ref_count (ref_model, &grandparent4, 1);
4069
4070   gtk_tree_store_remove (GTK_TREE_STORE (model), &new_node);
4071   gtk_tree_store_prepend (GTK_TREE_STORE (model), &new_node, NULL);
4072
4073   assert_node_ref_count (ref_model, &new_node, 0);
4074   assert_node_ref_count (ref_model, &grandparent1, 0);
4075   assert_node_ref_count (ref_model, &grandparent2, 0);
4076   assert_node_ref_count (ref_model, &grandparent3, 0);
4077   assert_node_ref_count (ref_model, &grandparent4, 1);
4078
4079   gtk_tree_store_set (GTK_TREE_STORE (model), &new_node, 0, TRUE, -1);
4080
4081   assert_node_ref_count (ref_model, &new_node, 2);
4082   assert_node_ref_count (ref_model, &grandparent1, 0);
4083   assert_node_ref_count (ref_model, &grandparent2, 0);
4084   assert_node_ref_count (ref_model, &grandparent3, 0);
4085   assert_node_ref_count (ref_model, &grandparent4, 0);
4086
4087   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, TRUE, -1);
4088   gtk_tree_store_remove (GTK_TREE_STORE (model), &new_node);
4089
4090   assert_node_ref_count (ref_model, &grandparent1, 0);
4091   assert_node_ref_count (ref_model, &grandparent2, 2);
4092   assert_node_ref_count (ref_model, &grandparent3, 0);
4093   assert_node_ref_count (ref_model, &grandparent4, 0);
4094
4095   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent4, 0, TRUE, -1);
4096   gtk_tree_store_remove (GTK_TREE_STORE (model), &grandparent2);
4097
4098   gtk_widget_destroy (tree_view);
4099   g_object_unref (filter_model);
4100   g_object_unref (ref_model);
4101 }
4102
4103 static void
4104 ref_count_transfer_child_level_insert (void)
4105 {
4106   GtkTreeIter grandparent1;
4107   GtkTreeIter parent1, parent2, parent3;
4108   GtkTreeIter new_node;
4109   GtkTreeModel *model;
4110   GtkTreeModelRefCount *ref_model;
4111   GtkTreeModel *filter_model;
4112   GtkWidget *tree_view;
4113
4114   model = gtk_tree_model_ref_count_new ();
4115   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
4116
4117   /* + grandparent1
4118    *   + parent1
4119    *   + parent2
4120    *   + parent3
4121    */
4122
4123   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
4124   gtk_tree_store_append (GTK_TREE_STORE (model), &parent1, &grandparent1);
4125   gtk_tree_store_append (GTK_TREE_STORE (model), &parent2, &grandparent1);
4126   gtk_tree_store_append (GTK_TREE_STORE (model), &parent3, &grandparent1);
4127
4128   filter_model = gtk_tree_model_filter_new (model, NULL);
4129   tree_view = gtk_tree_view_new_with_model (filter_model);
4130
4131   assert_node_ref_count (ref_model, &grandparent1, 3);
4132   assert_node_ref_count (ref_model, &parent1, 1);
4133   assert_node_ref_count (ref_model, &parent2, 0);
4134   assert_node_ref_count (ref_model, &parent3, 0);
4135
4136   gtk_tree_store_prepend (GTK_TREE_STORE (model), &new_node, &grandparent1);
4137
4138   assert_node_ref_count (ref_model, &grandparent1, 3);
4139   assert_node_ref_count (ref_model, &new_node, 1);
4140   assert_node_ref_count (ref_model, &parent1, 0);
4141   assert_node_ref_count (ref_model, &parent2, 0);
4142   assert_node_ref_count (ref_model, &parent3, 0);
4143
4144   gtk_widget_destroy (tree_view);
4145   g_object_unref (filter_model);
4146   g_object_unref (ref_model);
4147 }
4148
4149 static void
4150 ref_count_transfer_child_level_remove (void)
4151 {
4152   GtkTreeIter grandparent1;
4153   GtkTreeIter parent1, parent2, parent3;
4154   GtkTreeModel *model;
4155   GtkTreeModelRefCount *ref_model;
4156   GtkTreeModel *filter_model;
4157   GtkWidget *tree_view;
4158
4159   model = gtk_tree_model_ref_count_new ();
4160   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
4161
4162   /* + grandparent1
4163    *   + parent1
4164    *   + parent2
4165    *   + parent3
4166    */
4167
4168   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
4169   gtk_tree_store_append (GTK_TREE_STORE (model), &parent1, &grandparent1);
4170   gtk_tree_store_append (GTK_TREE_STORE (model), &parent2, &grandparent1);
4171   gtk_tree_store_append (GTK_TREE_STORE (model), &parent3, &grandparent1);
4172
4173   filter_model = gtk_tree_model_filter_new (model, NULL);
4174   tree_view = gtk_tree_view_new_with_model (filter_model);
4175
4176   assert_node_ref_count (ref_model, &grandparent1, 3);
4177   assert_node_ref_count (ref_model, &parent1, 1);
4178   assert_node_ref_count (ref_model, &parent2, 0);
4179   assert_node_ref_count (ref_model, &parent3, 0);
4180
4181   gtk_tree_store_remove (GTK_TREE_STORE (model), &parent1);
4182
4183   gtk_tree_model_ref_count_dump (ref_model);
4184
4185   assert_node_ref_count (ref_model, &grandparent1, 3);
4186   assert_node_ref_count (ref_model, &parent2, 1);
4187   assert_node_ref_count (ref_model, &parent3, 0);
4188
4189   gtk_tree_store_remove (GTK_TREE_STORE (model), &parent2);
4190
4191   assert_node_ref_count (ref_model, &grandparent1, 3);
4192   assert_node_ref_count (ref_model, &parent3, 1);
4193
4194   gtk_widget_destroy (tree_view);
4195   g_object_unref (filter_model);
4196   g_object_unref (ref_model);
4197 }
4198
4199 static void
4200 ref_count_transfer_child_level_remove_filtered (void)
4201 {
4202   GtkTreeIter grandparent1;
4203   GtkTreeIter parent1, parent2, parent3, parent4;
4204   GtkTreeModel *model;
4205   GtkTreeModelRefCount *ref_model;
4206   GtkTreeModel *filter_model;
4207   GtkWidget *tree_view;
4208   GType column_types[] = { G_TYPE_BOOLEAN };
4209
4210   model = gtk_tree_model_ref_count_new ();
4211   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
4212
4213   gtk_tree_store_set_column_types (GTK_TREE_STORE (model), 1,
4214                                    column_types);
4215
4216   /* + grandparent1
4217    *   + parent1
4218    *   + parent2
4219    *   + parent3
4220    *   + parent4
4221    */
4222
4223   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
4224   gtk_tree_store_append (GTK_TREE_STORE (model), &parent1, &grandparent1);
4225   gtk_tree_store_append (GTK_TREE_STORE (model), &parent2, &grandparent1);
4226   gtk_tree_store_append (GTK_TREE_STORE (model), &parent3, &grandparent1);
4227   gtk_tree_store_append (GTK_TREE_STORE (model), &parent4, &grandparent1);
4228
4229   /* Filter first node */
4230   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent1, 0, TRUE, -1);
4231   gtk_tree_store_set (GTK_TREE_STORE (model), &parent1, 0, FALSE, -1);
4232   gtk_tree_store_set (GTK_TREE_STORE (model), &parent2, 0, TRUE, -1);
4233   gtk_tree_store_set (GTK_TREE_STORE (model), &parent3, 0, TRUE, -1);
4234   gtk_tree_store_set (GTK_TREE_STORE (model), &parent4, 0, TRUE, -1);
4235
4236   filter_model = gtk_tree_model_filter_new (model, NULL);
4237   gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), 0);
4238   tree_view = gtk_tree_view_new_with_model (filter_model);
4239
4240   assert_node_ref_count (ref_model, &grandparent1, 3);
4241   assert_node_ref_count (ref_model, &parent1, 0);
4242   assert_node_ref_count (ref_model, &parent2, 1);
4243   assert_node_ref_count (ref_model, &parent3, 0);
4244   assert_node_ref_count (ref_model, &parent4, 0);
4245
4246   gtk_tree_store_remove (GTK_TREE_STORE (model), &parent2);
4247
4248   assert_node_ref_count (ref_model, &grandparent1, 3);
4249   assert_node_ref_count (ref_model, &parent1, 0);
4250   assert_node_ref_count (ref_model, &parent3, 1);
4251   assert_node_ref_count (ref_model, &parent4, 0);
4252
4253   gtk_tree_store_remove (GTK_TREE_STORE (model), &parent3);
4254
4255   assert_node_ref_count (ref_model, &grandparent1, 3);
4256   assert_node_ref_count (ref_model, &parent1, 0);
4257   assert_node_ref_count (ref_model, &parent4, 1);
4258
4259   gtk_tree_store_remove (GTK_TREE_STORE (model), &parent4);
4260
4261   /* Check level length to get level cached again */
4262   check_level_length (GTK_TREE_MODEL_FILTER (filter_model), "0", 0);
4263
4264   assert_node_ref_count (ref_model, &grandparent1, 3);
4265   assert_node_ref_count (ref_model, &parent1, 1);
4266
4267   gtk_tree_store_append (GTK_TREE_STORE (model), &parent2, &grandparent1);
4268
4269   assert_node_ref_count (ref_model, &grandparent1, 3);
4270   assert_node_ref_count (ref_model, &parent1, 1);
4271   assert_node_ref_count (ref_model, &parent2, 0);
4272
4273   gtk_tree_store_set (GTK_TREE_STORE (model), &parent2, 0, TRUE, -1);
4274
4275   assert_node_ref_count (ref_model, &grandparent1, 3);
4276   assert_node_ref_count (ref_model, &parent1, 1);
4277   assert_node_ref_count (ref_model, &parent2, 0);
4278
4279   check_level_length (GTK_TREE_MODEL_FILTER (filter_model), "0", 1);
4280
4281   gtk_widget_destroy (tree_view);
4282   g_object_unref (filter_model);
4283   g_object_unref (ref_model);
4284 }
4285
4286 static void
4287 ref_count_transfer_child_level_reordered (void)
4288 {
4289   GtkTreeIter grandparent1;
4290   GtkTreeIter parent1, parent2, parent3;
4291   GtkTreeModel *model;
4292   GtkTreeModelRefCount *ref_model;
4293   GtkTreeModel *filter_model;
4294   GtkWidget *tree_view;
4295
4296   model = gtk_tree_model_ref_count_new ();
4297   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
4298
4299   /* + grandparent1
4300    *   + parent1
4301    *   + parent2
4302    *   + parent3
4303    */
4304
4305   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
4306   gtk_tree_store_append (GTK_TREE_STORE (model), &parent1, &grandparent1);
4307   gtk_tree_store_append (GTK_TREE_STORE (model), &parent2, &grandparent1);
4308   gtk_tree_store_append (GTK_TREE_STORE (model), &parent3, &grandparent1);
4309
4310   filter_model = gtk_tree_model_filter_new (model, NULL);
4311   tree_view = gtk_tree_view_new_with_model (filter_model);
4312
4313   assert_node_ref_count (ref_model, &grandparent1, 3);
4314   assert_node_ref_count (ref_model, &parent1, 1);
4315   assert_node_ref_count (ref_model, &parent2, 0);
4316   assert_node_ref_count (ref_model, &parent3, 0);
4317
4318   /* gtk_tree_store_move() will emit rows-reordered */
4319   gtk_tree_store_move_after (GTK_TREE_STORE (model),
4320                              &parent1, &parent3);
4321
4322   assert_node_ref_count (ref_model, &grandparent1, 3);
4323   assert_node_ref_count (ref_model, &parent2, 1);
4324   assert_node_ref_count (ref_model, &parent3, 0);
4325   assert_node_ref_count (ref_model, &parent1, 0);
4326
4327   gtk_widget_destroy (tree_view);
4328   g_object_unref (filter_model);
4329   g_object_unref (ref_model);
4330 }
4331
4332 static void
4333 ref_count_transfer_child_level_reordered_filtered (void)
4334 {
4335   GtkTreeIter grandparent1;
4336   GtkTreeIter parent1, parent2, parent3;
4337   GtkTreeModel *model;
4338   GtkTreeModelRefCount *ref_model;
4339   GtkTreeModel *filter_model;
4340   GtkWidget *tree_view;
4341   GType column_types[] = { G_TYPE_BOOLEAN };
4342
4343   model = gtk_tree_model_ref_count_new ();
4344   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
4345
4346   gtk_tree_store_set_column_types (GTK_TREE_STORE (model), 1,
4347                                    column_types);
4348
4349   /* + grandparent1
4350    *   + parent1
4351    *   + parent2
4352    *   + parent3
4353    */
4354
4355   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
4356   gtk_tree_store_append (GTK_TREE_STORE (model), &parent1, &grandparent1);
4357   gtk_tree_store_append (GTK_TREE_STORE (model), &parent2, &grandparent1);
4358   gtk_tree_store_append (GTK_TREE_STORE (model), &parent3, &grandparent1);
4359
4360   /* Test with 1 node filtered (parent1) */
4361   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent1, 0, TRUE, -1);
4362   gtk_tree_store_set (GTK_TREE_STORE (model), &parent2, 0, TRUE, -1);
4363   gtk_tree_store_set (GTK_TREE_STORE (model), &parent3, 0, TRUE, -1);
4364
4365   filter_model = gtk_tree_model_filter_new (model, NULL);
4366   gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), 0);
4367   tree_view = gtk_tree_view_new_with_model (filter_model);
4368
4369   assert_node_ref_count (ref_model, &grandparent1, 3);
4370   assert_node_ref_count (ref_model, &parent1, 0);
4371   assert_node_ref_count (ref_model, &parent2, 1);
4372   assert_node_ref_count (ref_model, &parent3, 0);
4373
4374   /* Move invisible node parent 1 */
4375
4376   /* gtk_tree_store_move() will emit rows-reordered */
4377   gtk_tree_store_move_after (GTK_TREE_STORE (model),
4378                              &parent1, &parent3);
4379
4380   assert_node_ref_count (ref_model, &grandparent1, 3);
4381   assert_node_ref_count (ref_model, &parent2, 1);
4382   assert_node_ref_count (ref_model, &parent3, 0);
4383   assert_node_ref_count (ref_model, &parent1, 0);
4384
4385   /* Move invisible node parent 1 */
4386
4387   /* gtk_tree_store_move() will emit rows-reordered */
4388   gtk_tree_store_move_before (GTK_TREE_STORE (model),
4389                               &parent1, &parent2);
4390
4391   assert_node_ref_count (ref_model, &grandparent1, 3);
4392   assert_node_ref_count (ref_model, &parent1, 0);
4393   assert_node_ref_count (ref_model, &parent2, 1);
4394   assert_node_ref_count (ref_model, &parent3, 0);
4395
4396   /* Now swap parent2 and parent2, first reference must transfer */
4397   /* gtk_tree_store_swap() will emit rows-reordered */
4398   gtk_tree_store_swap (GTK_TREE_STORE (model),
4399                        &parent2, &parent3);
4400
4401   assert_node_ref_count (ref_model, &grandparent1, 3);
4402   assert_node_ref_count (ref_model, &parent1, 0);
4403   assert_node_ref_count (ref_model, &parent3, 1);
4404   assert_node_ref_count (ref_model, &parent2, 0);
4405
4406   /* Swap back */
4407   gtk_tree_store_swap (GTK_TREE_STORE (model),
4408                        &parent2, &parent3);
4409
4410   assert_node_ref_count (ref_model, &grandparent1, 3);
4411   assert_node_ref_count (ref_model, &parent1, 0);
4412   assert_node_ref_count (ref_model, &parent2, 1);
4413   assert_node_ref_count (ref_model, &parent3, 0);
4414
4415   gtk_tree_store_set (GTK_TREE_STORE (model), &parent1, 0, TRUE, -1);
4416
4417   assert_node_ref_count (ref_model, &parent1, 1);
4418   assert_node_ref_count (ref_model, &parent2, 0);
4419   assert_node_ref_count (ref_model, &parent3, 0);
4420
4421   /* Test with two nodes filtered */
4422   gtk_tree_store_set (GTK_TREE_STORE (model), &parent1, 0, FALSE, -1);
4423   gtk_tree_store_set (GTK_TREE_STORE (model), &parent2, 0, FALSE, -1);
4424
4425   assert_node_ref_count (ref_model, &parent1, 0);
4426   assert_node_ref_count (ref_model, &parent2, 0);
4427   assert_node_ref_count (ref_model, &parent3, 1);
4428
4429   /* gtk_tree_store_move() will emit rows-reordered */
4430   gtk_tree_store_move_before (GTK_TREE_STORE (model),
4431                              &parent3, &parent1);
4432
4433   assert_node_ref_count (ref_model, &parent3, 1);
4434   assert_node_ref_count (ref_model, &parent2, 0);
4435   assert_node_ref_count (ref_model, &parent1, 0);
4436
4437   gtk_widget_destroy (tree_view);
4438   g_object_unref (filter_model);
4439   g_object_unref (ref_model);
4440 }
4441
4442 static void
4443 ref_count_transfer_child_level_filter (void)
4444 {
4445   GtkTreeIter root;
4446   GtkTreeIter grandparent1, grandparent2, grandparent3, grandparent4;
4447   GtkTreeIter new_node;
4448   GtkTreeModel *model;
4449   GtkTreeModelRefCount *ref_model;
4450   GtkTreeModel *filter_model;
4451   GtkWidget *tree_view;
4452   GType column_types[] = { G_TYPE_BOOLEAN };
4453
4454   model = gtk_tree_model_ref_count_new ();
4455   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
4456
4457   gtk_tree_store_set_column_types (GTK_TREE_STORE (model), 1,
4458                                    column_types);
4459
4460   /* + root
4461    *    + grandparent1
4462    *    + grandparent2
4463    *    + grandparent3
4464    *    + grandparent4
4465    */
4466
4467   gtk_tree_store_append (GTK_TREE_STORE (model), &root, NULL);
4468   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, &root);
4469   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent2, &root);
4470   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent3, &root);
4471   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent4, &root);
4472
4473   /* Filter first node */
4474   gtk_tree_store_set (GTK_TREE_STORE (model), &root, 0, TRUE, -1);
4475   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent1, 0, FALSE, -1);
4476   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, TRUE, -1);
4477   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent3, 0, TRUE, -1);
4478   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent4, 0, TRUE, -1);
4479
4480   filter_model = gtk_tree_model_filter_new (model, NULL);
4481   gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), 0);
4482   tree_view = gtk_tree_view_new_with_model (filter_model);
4483
4484   assert_node_ref_count (ref_model, &grandparent1, 0);
4485   assert_node_ref_count (ref_model, &grandparent2, 1);
4486   assert_node_ref_count (ref_model, &grandparent3, 0);
4487   assert_node_ref_count (ref_model, &grandparent4, 0);
4488
4489   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, FALSE, -1);
4490
4491   assert_node_ref_count (ref_model, &grandparent1, 0);
4492   assert_node_ref_count (ref_model, &grandparent2, 0);
4493   assert_node_ref_count (ref_model, &grandparent3, 1);
4494   assert_node_ref_count (ref_model, &grandparent4, 0);
4495
4496   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent3, 0, FALSE, -1);
4497
4498   assert_node_ref_count (ref_model, &grandparent1, 0);
4499   assert_node_ref_count (ref_model, &grandparent2, 0);
4500   assert_node_ref_count (ref_model, &grandparent3, 0);
4501   assert_node_ref_count (ref_model, &grandparent4, 1);
4502
4503   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent4, 0, FALSE, -1);
4504
4505   assert_node_ref_count (ref_model, &grandparent1, 0);
4506   assert_node_ref_count (ref_model, &grandparent2, 0);
4507   assert_node_ref_count (ref_model, &grandparent3, 0);
4508   assert_node_ref_count (ref_model, &grandparent4, 1);
4509
4510   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, TRUE, -1);
4511
4512   assert_node_ref_count (ref_model, &grandparent1, 0);
4513   assert_node_ref_count (ref_model, &grandparent2, 1);
4514   assert_node_ref_count (ref_model, &grandparent3, 0);
4515   assert_node_ref_count (ref_model, &grandparent4, 0);
4516
4517   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, FALSE, -1);
4518
4519   assert_node_ref_count (ref_model, &grandparent1, 0);
4520   assert_node_ref_count (ref_model, &grandparent2, 0);
4521   assert_node_ref_count (ref_model, &grandparent3, 0);
4522   assert_node_ref_count (ref_model, &grandparent4, 1);
4523
4524   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent1, 0, TRUE, -1);
4525
4526   assert_node_ref_count (ref_model, &grandparent1, 1);
4527   assert_node_ref_count (ref_model, &grandparent2, 0);
4528   assert_node_ref_count (ref_model, &grandparent3, 0);
4529   assert_node_ref_count (ref_model, &grandparent4, 0);
4530
4531   gtk_tree_store_prepend (GTK_TREE_STORE (model), &new_node, &root);
4532
4533   assert_node_ref_count (ref_model, &new_node, 0);
4534   assert_node_ref_count (ref_model, &grandparent1, 1);
4535   assert_node_ref_count (ref_model, &grandparent2, 0);
4536   assert_node_ref_count (ref_model, &grandparent3, 0);
4537   assert_node_ref_count (ref_model, &grandparent4, 0);
4538
4539   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent1, 0, FALSE, -1);
4540
4541   assert_node_ref_count (ref_model, &new_node, 0);
4542   assert_node_ref_count (ref_model, &grandparent1, 0);
4543   assert_node_ref_count (ref_model, &grandparent2, 0);
4544   assert_node_ref_count (ref_model, &grandparent3, 0);
4545   assert_node_ref_count (ref_model, &grandparent4, 1);
4546
4547   gtk_tree_store_remove (GTK_TREE_STORE (model), &new_node);
4548   gtk_tree_store_prepend (GTK_TREE_STORE (model), &new_node, &root);
4549
4550   assert_node_ref_count (ref_model, &new_node, 0);
4551   assert_node_ref_count (ref_model, &grandparent1, 0);
4552   assert_node_ref_count (ref_model, &grandparent2, 0);
4553   assert_node_ref_count (ref_model, &grandparent3, 0);
4554   assert_node_ref_count (ref_model, &grandparent4, 1);
4555
4556   gtk_tree_store_set (GTK_TREE_STORE (model), &new_node, 0, TRUE, -1);
4557
4558   assert_node_ref_count (ref_model, &new_node, 1);
4559   assert_node_ref_count (ref_model, &grandparent1, 0);
4560   assert_node_ref_count (ref_model, &grandparent2, 0);
4561   assert_node_ref_count (ref_model, &grandparent3, 0);
4562   assert_node_ref_count (ref_model, &grandparent4, 0);
4563
4564   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, TRUE, -1);
4565   gtk_tree_store_remove (GTK_TREE_STORE (model), &new_node);
4566
4567   assert_node_ref_count (ref_model, &grandparent1, 0);
4568   assert_node_ref_count (ref_model, &grandparent2, 1);
4569   assert_node_ref_count (ref_model, &grandparent3, 0);
4570   assert_node_ref_count (ref_model, &grandparent4, 0);
4571
4572   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent4, 0, TRUE, -1);
4573   gtk_tree_store_remove (GTK_TREE_STORE (model), &grandparent2);
4574
4575   gtk_widget_destroy (tree_view);
4576   g_object_unref (filter_model);
4577   g_object_unref (ref_model);
4578 }
4579
4580
4581 static gboolean
4582 specific_path_dependent_filter_func (GtkTreeModel *model,
4583                                      GtkTreeIter  *iter,
4584                                      gpointer      data)
4585 {
4586   GtkTreePath *path;
4587
4588   path = gtk_tree_model_get_path (model, iter);
4589   if (gtk_tree_path_get_indices (path)[0] < 4)
4590     return FALSE;
4591
4592   return TRUE;
4593 }
4594
4595 static void
4596 specific_path_dependent_filter (void)
4597 {
4598   int i;
4599   GtkTreeIter iter;
4600   GtkListStore *list;
4601   GtkTreeModel *sort;
4602   GtkTreeModel *filter;
4603
4604   list = gtk_list_store_new (1, G_TYPE_INT);
4605   gtk_list_store_insert_with_values (list, &iter, 0, 0, 1, -1);
4606   gtk_list_store_insert_with_values (list, &iter, 1, 0, 2, -1);
4607   gtk_list_store_insert_with_values (list, &iter, 2, 0, 3, -1);
4608   gtk_list_store_insert_with_values (list, &iter, 3, 0, 4, -1);
4609   gtk_list_store_insert_with_values (list, &iter, 4, 0, 5, -1);
4610   gtk_list_store_insert_with_values (list, &iter, 5, 0, 6, -1);
4611   gtk_list_store_insert_with_values (list, &iter, 6, 0, 7, -1);
4612   gtk_list_store_insert_with_values (list, &iter, 7, 0, 8, -1);
4613
4614   sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (list));
4615   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (sort), NULL);
4616   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
4617                                           specific_path_dependent_filter_func,
4618                                           NULL, NULL);
4619
4620   gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sort), 0,
4621                                         GTK_SORT_DESCENDING);
4622
4623   for (i = 0; i < 4; i++)
4624     {
4625       if (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (list), &iter,
4626                                          NULL, 1))
4627         gtk_list_store_remove (list, &iter);
4628
4629       if (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (list), &iter,
4630                                          NULL, 2))
4631         gtk_list_store_remove (list, &iter);
4632     }
4633
4634   g_object_unref (filter);
4635   g_object_unref (sort);
4636   g_object_unref (list);
4637 }
4638
4639
4640 static gboolean
4641 specific_append_after_collapse_visible_func (GtkTreeModel *model,
4642                                              GtkTreeIter  *iter,
4643                                              gpointer      data)
4644 {
4645   gint number;
4646   gboolean hide_negative_numbers;
4647
4648   gtk_tree_model_get (model, iter, 1, &number, -1);
4649   hide_negative_numbers = GPOINTER_TO_INT (g_object_get_data (data, "private-hide-negative-numbers"));
4650
4651   return (number >= 0 || !hide_negative_numbers);
4652 }
4653
4654 static void
4655 specific_append_after_collapse (void)
4656 {
4657   /* This test is based on one of the test cases I found in my
4658    * old test cases directory.  I unfortunately do not have a record
4659    * from who this test case originated.  -Kris.
4660    *
4661    * General idea:
4662    * - Construct tree.
4663    * - Show tree, expand, collapse.
4664    * - Add a row.
4665    */
4666
4667   GtkTreeIter iter;
4668   GtkTreeIter child_iter;
4669   GtkTreeIter child_iter2;
4670   GtkTreePath *append_path;
4671   GtkTreeStore *store;
4672   GtkTreeModel *filter;
4673   GtkTreeModel *sort;
4674
4675   GtkWidget *window;
4676   GtkWidget *tree_view;
4677
4678   store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_INT);
4679
4680   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
4681   g_object_set_data (G_OBJECT (filter), "private-hide-negative-numbers",
4682                      GINT_TO_POINTER (FALSE));
4683   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
4684                                           specific_append_after_collapse_visible_func,
4685                                           filter, NULL);
4686
4687   sort = gtk_tree_model_sort_new_with_model (filter);
4688
4689   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4690   tree_view = gtk_tree_view_new_with_model (sort);
4691   gtk_container_add (GTK_CONTAINER (window), tree_view);
4692   gtk_widget_realize (tree_view);
4693
4694   while (gtk_events_pending ())
4695     gtk_main_iteration ();
4696
4697   gtk_tree_store_prepend (store, &iter, NULL);
4698   gtk_tree_store_set (store, &iter,
4699                       0, "hallo", 1, 1, -1);
4700
4701   gtk_tree_store_append (store, &child_iter, &iter);
4702   gtk_tree_store_set (store, &child_iter,
4703                       0, "toemaar", 1, 1, -1);
4704
4705   gtk_tree_store_append (store, &child_iter2, &child_iter);
4706   gtk_tree_store_set (store, &child_iter2,
4707                       0, "very deep", 1, 1, -1);
4708
4709   append_path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &child_iter2);
4710
4711   gtk_tree_store_append (store, &child_iter, &iter);
4712   gtk_tree_store_set (store, &child_iter,
4713                       0, "sja", 1, 1, -1);
4714
4715   gtk_tree_store_append (store, &child_iter, &iter);
4716   gtk_tree_store_set (store, &child_iter,
4717                       0, "some word", 1, -1, -1);
4718
4719   /* Expand and collapse the tree */
4720   gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
4721   while (gtk_events_pending ())
4722     gtk_main_iteration ();
4723
4724   gtk_tree_view_collapse_all (GTK_TREE_VIEW (tree_view));
4725   while (gtk_events_pending ())
4726     gtk_main_iteration ();
4727
4728   /* Add another it */
4729   g_object_set_data (G_OBJECT (filter), "private-hide-negative-numbers",
4730                      GINT_TO_POINTER (TRUE));
4731
4732   if (gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, append_path))
4733     {
4734       gtk_tree_store_append (store, &child_iter, &iter);
4735       gtk_tree_store_set (store, &child_iter,
4736                           0, "new new new !!", 1, 1, -1);
4737     }
4738   gtk_tree_path_free (append_path);
4739
4740   /* Expand */
4741   gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
4742   while (gtk_events_pending ())
4743     gtk_main_iteration ();
4744 }
4745
4746
4747 static gint
4748 specific_sort_filter_remove_node_compare_func (GtkTreeModel  *model,
4749                                                GtkTreeIter   *iter1,
4750                                                GtkTreeIter   *iter2,
4751                                                gpointer       data)
4752 {
4753   return -1;
4754 }
4755
4756 static gboolean
4757 specific_sort_filter_remove_node_visible_func (GtkTreeModel  *model,
4758                                                GtkTreeIter   *iter,
4759                                                gpointer       data)
4760 {
4761   char *item = NULL;
4762
4763   /* Do reference the model */
4764   gtk_tree_model_get (model, iter, 0, &item, -1);
4765   g_free (item);
4766
4767   return FALSE;
4768 }
4769
4770 static void
4771 specific_sort_filter_remove_node (void)
4772 {
4773   /* This test is based on one of the test cases I found in my
4774    * old test cases directory.  I unfortunately do not have a record
4775    * from who this test case originated.  -Kris.
4776    *
4777    * General idea:
4778    *  - Create tree store, sort, filter models.  The sort model has
4779    *    a default sort func that is enabled, filter model a visible func
4780    *    that defaults to returning FALSE.
4781    *  - Remove a node from the tree store.
4782    */
4783
4784   GtkTreeIter iter;
4785   GtkTreeStore *store;
4786   GtkTreeModel *filter;
4787   GtkTreeModel *sort;
4788
4789   GtkWidget *window;
4790   GtkWidget *tree_view;
4791
4792   store = gtk_tree_store_new (1, G_TYPE_STRING);
4793   gtk_tree_store_append (store, &iter, NULL);
4794   gtk_tree_store_set (store, &iter, 0, "Hello1", -1);
4795
4796   gtk_tree_store_append (store, &iter, NULL);
4797   gtk_tree_store_set (store, &iter, 0, "Hello2", -1);
4798
4799   sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (store));
4800   gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (sort),
4801                                            specific_sort_filter_remove_node_compare_func, NULL, NULL);
4802
4803   filter = gtk_tree_model_filter_new (sort, NULL);
4804   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
4805                                           specific_sort_filter_remove_node_visible_func,
4806                                           filter, NULL);
4807
4808
4809   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4810   tree_view = gtk_tree_view_new_with_model (filter);
4811   gtk_container_add (GTK_CONTAINER (window), tree_view);
4812   gtk_widget_realize (tree_view);
4813
4814   while (gtk_events_pending ())
4815     gtk_main_iteration ();
4816
4817   /* Remove a node */
4818   gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter);
4819   gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter);
4820   gtk_tree_store_remove (store, &iter);
4821
4822   while (gtk_events_pending ())
4823     gtk_main_iteration ();
4824 }
4825
4826
4827 static void
4828 specific_sort_filter_remove_root (void)
4829 {
4830   /* This test is based on one of the test cases I found in my
4831    * old test cases directory.  I unfortunately do not have a record
4832    * from who this test case originated.  -Kris.
4833    */
4834
4835   GtkTreeModel *model, *sort, *filter;
4836   GtkTreeIter root, mid, leaf;
4837   GtkTreePath *path;
4838
4839   model = GTK_TREE_MODEL (gtk_tree_store_new (1, G_TYPE_INT));
4840   gtk_tree_store_append (GTK_TREE_STORE (model), &root, NULL);
4841   gtk_tree_store_append (GTK_TREE_STORE (model), &mid, &root);
4842   gtk_tree_store_append (GTK_TREE_STORE (model), &leaf, &mid);
4843
4844   path = gtk_tree_model_get_path (model, &mid);
4845
4846   sort = gtk_tree_model_sort_new_with_model (model);
4847   filter = gtk_tree_model_filter_new (sort, path);
4848
4849   gtk_tree_path_free (path);
4850
4851   gtk_tree_store_remove (GTK_TREE_STORE (model), &root);
4852
4853   g_object_unref (filter);
4854   g_object_unref (sort);
4855   g_object_unref (model);
4856 }
4857
4858
4859 static void
4860 specific_root_mixed_visibility (void)
4861 {
4862   int i;
4863   GtkTreeModel *filter;
4864   /* A bit nasty, apologies */
4865   FilterTest fixture;
4866
4867   fixture.store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
4868
4869   for (i = 0; i < LEVEL_LENGTH; i++)
4870     {
4871       GtkTreeIter iter;
4872
4873       gtk_tree_store_insert (fixture.store, &iter, NULL, i);
4874       if (i % 2 == 0)
4875         create_tree_store_set_values (fixture.store, &iter, TRUE);
4876       else
4877         create_tree_store_set_values (fixture.store, &iter, FALSE);
4878     }
4879
4880   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (fixture.store), NULL);
4881   fixture.filter = GTK_TREE_MODEL_FILTER (filter);
4882   fixture.monitor = NULL;
4883
4884   gtk_tree_model_filter_set_visible_column (fixture.filter, 1);
4885
4886   /* In order to trigger the potential bug, we should not access
4887    * the filter model here (so don't call the check functions).
4888    */
4889
4890   /* Change visibility of an odd row to TRUE */
4891   set_path_visibility (&fixture, "3", TRUE);
4892   check_filter_model (&fixture);
4893   check_level_length (fixture.filter, NULL, 4);
4894 }
4895
4896
4897
4898 static gboolean
4899 specific_has_child_filter_filter_func (GtkTreeModel *model,
4900                                        GtkTreeIter  *iter,
4901                                        gpointer      data)
4902 {
4903   return gtk_tree_model_iter_has_child (model, iter);
4904 }
4905
4906 static void
4907 specific_has_child_filter (void)
4908 {
4909   GtkTreeModel *filter;
4910   GtkTreeIter iter, root;
4911   FilterTest fixture; /* This is not how it should be done */
4912   GtkWidget *tree_view;
4913
4914   fixture.store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
4915   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (fixture.store), NULL);
4916   fixture.filter = GTK_TREE_MODEL_FILTER (filter);
4917   fixture.monitor = signal_monitor_new (filter);
4918
4919   tree_view = gtk_tree_view_new_with_model (filter);
4920
4921   /* We will filter on parent state using a filter function.  We will
4922    * manually keep the boolean column in sync, so that we can use
4923    * check_filter_model() to check the consistency of the model.
4924    */
4925   /* FIXME: We need a check_filter_model() that is not tied to LEVEL_LENGTH
4926    * to be able to check the structure here.  We keep the calls to
4927    * check_filter_model() commented out until then.
4928    */
4929   gtk_tree_model_filter_set_visible_func (fixture.filter,
4930                                           specific_has_child_filter_filter_func,
4931                                           NULL, NULL);
4932
4933   /* The first node will be initially invisible: no signals */
4934   gtk_tree_store_append (fixture.store, &root, NULL);
4935   create_tree_store_set_values (fixture.store, &root, FALSE);
4936
4937   /* check_filter_model (&fixture); */
4938   check_level_length (fixture.filter, NULL, 0);
4939   signal_monitor_assert_is_empty (fixture.monitor);
4940
4941   /* Insert a child node. This will cause the parent to become visible
4942    * since there is a child now.
4943    */
4944   signal_monitor_append_signal (fixture.monitor, ROW_INSERTED, "0");
4945   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
4946   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
4947
4948   gtk_tree_store_append (fixture.store, &iter, &root);
4949   create_tree_store_set_values (fixture.store, &iter, TRUE);
4950
4951   /* Parent must now be visible.  Do the level length check first,
4952    * to avoid modifying the child model triggering a row-changed to
4953    * the filter model.
4954    */
4955   check_level_length (fixture.filter, NULL, 1);
4956   check_level_length (fixture.filter, "0", 0);
4957   signal_monitor_assert_is_empty (fixture.monitor);
4958
4959   /* This should propagate row-changed */
4960   signal_monitor_append_signal (fixture.monitor, ROW_CHANGED, "0");
4961   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
4962
4963   set_path_visibility (&fixture, "0", TRUE);
4964   /* check_filter_model (&fixture); */
4965   signal_monitor_assert_is_empty (fixture.monitor);
4966
4967   /* New root node, no child, so no signal */
4968   gtk_tree_store_append (fixture.store, &root, NULL);
4969   check_level_length (fixture.filter, NULL, 1);
4970   signal_monitor_assert_is_empty (fixture.monitor);
4971
4972   /* When the child comes in, this node will become visible */
4973   signal_monitor_append_signal (fixture.monitor, ROW_INSERTED, "1");
4974   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "1");
4975   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "1");
4976   signal_monitor_append_signal (fixture.monitor, ROW_CHANGED, "1");
4977   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "1");
4978
4979   gtk_tree_store_append (fixture.store, &iter, &root);
4980   check_level_length (fixture.filter, NULL, 2);
4981   check_level_length (fixture.filter, "1", 0);
4982
4983   create_tree_store_set_values (fixture.store, &root, TRUE);
4984   create_tree_store_set_values (fixture.store, &iter, TRUE);
4985
4986   /* check_filter_model (&fixture); */
4987   signal_monitor_assert_is_empty (fixture.monitor);
4988
4989   /* Add another child for 1 */
4990   gtk_tree_store_append (fixture.store, &iter, &root);
4991   create_tree_store_set_values (fixture.store, &iter, TRUE);
4992   check_level_length (fixture.filter, NULL, 2);
4993   check_level_length (fixture.filter, "0", 0);
4994   check_level_length (fixture.filter, "1", 0);
4995   signal_monitor_assert_is_empty (fixture.monitor);
4996
4997   /* Now remove one of the remaining child rows */
4998   signal_monitor_append_signal (fixture.monitor, ROW_DELETED, "0");
4999
5000   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture.store),
5001                                        &iter, "0:0");
5002   gtk_tree_store_remove (fixture.store, &iter);
5003
5004   check_level_length (fixture.filter, NULL, 1);
5005   check_level_length (fixture.filter, "0", 0);
5006
5007   set_path_visibility (&fixture, "0", FALSE);
5008   /* check_filter_model (&fixture); */
5009   signal_monitor_assert_is_empty (fixture.monitor);
5010 }
5011
5012
5013 static gboolean
5014 specific_root_has_child_filter_filter_func (GtkTreeModel *model,
5015                                             GtkTreeIter  *iter,
5016                                             gpointer      data)
5017 {
5018   int depth;
5019   GtkTreePath *path;
5020
5021   path = gtk_tree_model_get_path (model, iter);
5022   depth = gtk_tree_path_get_depth (path);
5023   gtk_tree_path_free (path);
5024
5025   if (depth > 1)
5026     return TRUE;
5027   /* else */
5028   return gtk_tree_model_iter_has_child (model, iter);
5029 }
5030
5031 static void
5032 specific_root_has_child_filter (void)
5033 {
5034   GtkTreeModel *filter;
5035   GtkTreeIter iter, root;
5036   FilterTest fixture; /* This is not how it should be done ... */
5037   GtkWidget *tree_view;
5038
5039   /* This is a variation on the above test case, specific has-child-filter,
5040    * herein the has-child check for visibility only applies to root level
5041    * nodes.  In this test, children are always visible because we
5042    * only filter based on the "has child" criterion.
5043    */
5044
5045   fixture.store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
5046   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (fixture.store), NULL);
5047   fixture.filter = GTK_TREE_MODEL_FILTER (filter);
5048   fixture.monitor = signal_monitor_new (filter);
5049
5050   tree_view = gtk_tree_view_new_with_model (filter);
5051
5052   /* We will filter on parent state using a filter function.  We will
5053    * manually keep the boolean column in sync, so that we can use
5054    * check_filter_model() to check the consistency of the model.
5055    */
5056   /* FIXME: We need a check_filter_model() that is not tied to LEVEL_LENGTH
5057    * to be able to check the structure here.  We keep the calls to
5058    * check_filter_model() commented out until then.
5059    */
5060   gtk_tree_model_filter_set_visible_func (fixture.filter,
5061                                           specific_root_has_child_filter_filter_func,
5062                                           NULL, NULL);
5063
5064   /* Add a first node, this will be invisible initially, so no signal
5065    * should be emitted.
5066    */
5067   gtk_tree_store_append (fixture.store, &root, NULL);
5068   create_tree_store_set_values (fixture.store, &root, FALSE);
5069
5070   signal_monitor_assert_is_empty (fixture.monitor);
5071   /* check_filter_model (&fixture); */
5072   check_level_length (fixture.filter, NULL, 0);
5073
5074   /* Add a child node.  This will cause the parent to become visible,
5075    * so we expect row-inserted signals for both.
5076    */
5077   signal_monitor_append_signal (fixture.monitor, ROW_INSERTED, "0");
5078   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
5079   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
5080
5081   gtk_tree_store_append (fixture.store, &iter, &root);
5082   signal_monitor_assert_is_empty (fixture.monitor);
5083
5084   check_level_length (fixture.filter, NULL, 1);
5085   check_level_length (fixture.filter, "0", 1);
5086
5087   /* Modify the content of iter, no signals because the parent is not
5088    * expanded.
5089    */
5090   create_tree_store_set_values (fixture.store, &iter, TRUE);
5091   signal_monitor_assert_is_empty (fixture.monitor);
5092
5093   /* Parent must now be visible.  Do the level length check first,
5094    * to avoid modifying the child model triggering a row-changed to
5095    * the filter model.
5096    */
5097   check_level_length (fixture.filter, NULL, 1);
5098   check_level_length (fixture.filter, "0", 1);
5099
5100   /* Modify path 0 */
5101   signal_monitor_append_signal (fixture.monitor, ROW_CHANGED, "0");
5102   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
5103
5104   set_path_visibility (&fixture, "0", TRUE);
5105   /* check_filter_model (&fixture); */
5106
5107   signal_monitor_assert_is_empty (fixture.monitor);
5108
5109   /* Insert another node in the root level.  Initially invisible, so
5110    * not expecting any signal.
5111    */
5112   gtk_tree_store_append (fixture.store, &root, NULL);
5113   check_level_length (fixture.filter, NULL, 1);
5114
5115   signal_monitor_assert_is_empty (fixture.monitor);
5116
5117   /* Adding a child node which also makes parent at path 1 visible. */
5118   signal_monitor_append_signal (fixture.monitor, ROW_INSERTED, "1");
5119   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "1");
5120   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "1");
5121
5122   gtk_tree_store_append (fixture.store, &iter, &root);
5123   check_level_length (fixture.filter, NULL, 2);
5124   check_level_length (fixture.filter, "1", 1);
5125
5126   signal_monitor_assert_is_empty (fixture.monitor);
5127
5128   /* Check if row-changed is propagated */
5129   signal_monitor_append_signal (fixture.monitor, ROW_CHANGED, "1");
5130   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "1");
5131
5132   create_tree_store_set_values (fixture.store, &root, TRUE);
5133   create_tree_store_set_values (fixture.store, &iter, TRUE);
5134   /* check_filter_model (&fixture); */
5135   signal_monitor_assert_is_empty (fixture.monitor);
5136
5137   /* Insert another child under node 1 */
5138   gtk_tree_store_append (fixture.store, &iter, &root);
5139   create_tree_store_set_values (fixture.store, &iter, TRUE);
5140   check_level_length (fixture.filter, NULL, 2);
5141   check_level_length (fixture.filter, "0", 1);
5142   check_level_length (fixture.filter, "1", 2);
5143   signal_monitor_assert_is_empty (fixture.monitor);
5144
5145   /* Set a child node to invisible.  This should not yield any
5146    * change, because filtering is only done on whether the root
5147    * node has a child, which it still has.
5148    */
5149   set_path_visibility (&fixture, "0:0", FALSE);
5150   signal_monitor_assert_is_empty (fixture.monitor);
5151
5152   /* Now remove one of the remaining child rows */
5153   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
5154   signal_monitor_append_signal (fixture.monitor, ROW_DELETED, "0");
5155
5156   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture.store),
5157                                        &iter, "0:0");
5158   gtk_tree_store_remove (fixture.store, &iter);
5159
5160   check_level_length (fixture.filter, NULL, 1);
5161   check_level_length (fixture.filter, "0", 2);
5162   signal_monitor_assert_is_empty (fixture.monitor);
5163
5164   /* Set visibility of 0 to FALSE, no-op for filter model since
5165    * the child 0:0 is already gone
5166    */
5167   set_path_visibility (&fixture, "0", FALSE);
5168   /* check_filter_model (&fixture); */
5169   signal_monitor_assert_is_empty (fixture.monitor);
5170 }
5171
5172 static void
5173 specific_has_child_filter_on_sort_model (void)
5174 {
5175   GtkTreeModel *filter;
5176   GtkTreeModel *sort_model;
5177   GtkTreeIter iter, root;
5178   FilterTest fixture; /* This is not how it should be done */
5179   GtkWidget *tree_view;
5180
5181   fixture.store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
5182   sort_model = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (fixture.store));
5183   filter = gtk_tree_model_filter_new (sort_model, NULL);
5184   fixture.filter = GTK_TREE_MODEL_FILTER (filter);
5185   fixture.monitor = signal_monitor_new (filter);
5186
5187   tree_view = gtk_tree_view_new_with_model (filter);
5188
5189   /* We will filter on parent state using a filter function.  We will
5190    * manually keep the boolean column in sync, so that we can use
5191    * check_filter_model() to check the consistency of the model.
5192    */
5193   /* FIXME: We need a check_filter_model() that is not tied to LEVEL_LENGTH
5194    * to be able to check the structure here.  We keep the calls to
5195    * check_filter_model() commented out until then.
5196    */
5197   gtk_tree_model_filter_set_visible_func (fixture.filter,
5198                                           specific_has_child_filter_filter_func,
5199                                           NULL, NULL);
5200
5201   /* The first node will be initially invisible: no signals */
5202   gtk_tree_store_append (fixture.store, &root, NULL);
5203   create_tree_store_set_values (fixture.store, &root, FALSE);
5204
5205   /* check_filter_model (&fixture); */
5206   check_level_length (fixture.filter, NULL, 0);
5207   signal_monitor_assert_is_empty (fixture.monitor);
5208
5209   /* Insert a child node. This will cause the parent to become visible
5210    * since there is a child now.
5211    */
5212   signal_monitor_append_signal (fixture.monitor, ROW_INSERTED, "0");
5213   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
5214
5215   gtk_tree_store_append (fixture.store, &iter, &root);
5216   create_tree_store_set_values (fixture.store, &iter, TRUE);
5217
5218   /* Parent must now be visible.  Do the level length check first,
5219    * to avoid modifying the child model triggering a row-changed to
5220    * the filter model.
5221    */
5222   check_level_length (fixture.filter, NULL, 1);
5223   check_level_length (fixture.filter, "0", 0);
5224   signal_monitor_assert_is_empty (fixture.monitor);
5225
5226   /* This should propagate row-changed */
5227   signal_monitor_append_signal (fixture.monitor, ROW_CHANGED, "0");
5228   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
5229
5230   set_path_visibility (&fixture, "0", TRUE);
5231   /* check_filter_model (&fixture); */
5232   signal_monitor_assert_is_empty (fixture.monitor);
5233
5234   /* New root node, no child, so no signal */
5235   gtk_tree_store_append (fixture.store, &root, NULL);
5236   check_level_length (fixture.filter, NULL, 1);
5237   signal_monitor_assert_is_empty (fixture.monitor);
5238
5239   /* When the child comes in, this node will become visible */
5240   signal_monitor_append_signal (fixture.monitor, ROW_INSERTED, "1");
5241   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "1");
5242   signal_monitor_append_signal (fixture.monitor, ROW_CHANGED, "1");
5243   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "1");
5244
5245   gtk_tree_store_append (fixture.store, &iter, &root);
5246   check_level_length (fixture.filter, NULL, 2);
5247   check_level_length (fixture.filter, "1", 0);
5248
5249   create_tree_store_set_values (fixture.store, &root, TRUE);
5250   create_tree_store_set_values (fixture.store, &iter, TRUE);
5251
5252   /* check_filter_model (&fixture); */
5253   signal_monitor_assert_is_empty (fixture.monitor);
5254
5255   /* Add another child for 1 */
5256   gtk_tree_store_append (fixture.store, &iter, &root);
5257   create_tree_store_set_values (fixture.store, &iter, TRUE);
5258   check_level_length (fixture.filter, NULL, 2);
5259   check_level_length (fixture.filter, "0", 0);
5260   check_level_length (fixture.filter, "1", 0);
5261   signal_monitor_assert_is_empty (fixture.monitor);
5262
5263   /* Now remove one of the remaining child rows */
5264   signal_monitor_append_signal (fixture.monitor, ROW_DELETED, "0");
5265
5266   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture.store),
5267                                        &iter, "0:0");
5268   gtk_tree_store_remove (fixture.store, &iter);
5269
5270   check_level_length (fixture.filter, NULL, 1);
5271   check_level_length (fixture.filter, "0", 0);
5272
5273   set_path_visibility (&fixture, "0", FALSE);
5274   /* check_filter_model (&fixture); */
5275   signal_monitor_assert_is_empty (fixture.monitor);
5276 }
5277
5278 static gboolean
5279 specific_at_least_2_children_filter_filter_func (GtkTreeModel *model,
5280                                                  GtkTreeIter  *iter,
5281                                                  gpointer      data)
5282 {
5283   return gtk_tree_model_iter_n_children (model, iter) >= 2;
5284 }
5285
5286 static void
5287 specific_at_least_2_children_filter (void)
5288 {
5289   GtkTreeModel *filter;
5290   GtkTreeIter iter, root;
5291   FilterTest fixture; /* This is not how it should be done */
5292   GtkWidget *tree_view;
5293
5294   fixture.store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
5295   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (fixture.store), NULL);
5296   fixture.filter = GTK_TREE_MODEL_FILTER (filter);
5297   fixture.monitor = signal_monitor_new (filter);
5298
5299   tree_view = gtk_tree_view_new_with_model (filter);
5300
5301   gtk_tree_model_filter_set_visible_func (fixture.filter,
5302                                           specific_at_least_2_children_filter_filter_func,
5303                                           NULL, NULL);
5304
5305   /* The first node will be initially invisible: no signals */
5306   gtk_tree_store_append (fixture.store, &root, NULL);
5307   create_tree_store_set_values (fixture.store, &root, FALSE);
5308
5309   /* check_filter_model (&fixture); */
5310   check_level_length (fixture.filter, NULL, 0);
5311   signal_monitor_assert_is_empty (fixture.monitor);
5312
5313   /* Insert a child node.  Nothing should happen.
5314    */
5315   gtk_tree_store_append (fixture.store, &iter, &root);
5316   create_tree_store_set_values (fixture.store, &iter, TRUE);
5317
5318   check_level_length (fixture.filter, NULL, 0);
5319   signal_monitor_assert_is_empty (fixture.monitor);
5320
5321   /* Insert a second child node.  This will cause the parent to become
5322    * visible.
5323    */
5324   signal_monitor_append_signal (fixture.monitor, ROW_INSERTED, "0");
5325   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
5326
5327   gtk_tree_store_append (fixture.store, &iter, &root);
5328   create_tree_store_set_values (fixture.store, &iter, TRUE);
5329
5330   /* Parent must now be visible.  Do the level length check first,
5331    * to avoid modifying the child model triggering a row-changed to
5332    * the filter model.
5333    */
5334   check_level_length (fixture.filter, NULL, 1);
5335   check_level_length (fixture.filter, "0", 0);
5336   signal_monitor_assert_is_empty (fixture.monitor);
5337
5338   /* This should propagate row-changed */
5339   signal_monitor_append_signal (fixture.monitor, ROW_CHANGED, "0");
5340   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
5341
5342   set_path_visibility (&fixture, "0", TRUE);
5343   /* check_filter_model (&fixture); */
5344   signal_monitor_assert_is_empty (fixture.monitor);
5345
5346   /* New root node, no child, so no signal */
5347   gtk_tree_store_append (fixture.store, &root, NULL);
5348   check_level_length (fixture.filter, NULL, 1);
5349   signal_monitor_assert_is_empty (fixture.monitor);
5350
5351   /* First child, no signal, no change */
5352   gtk_tree_store_append (fixture.store, &iter, &root);
5353   check_level_length (fixture.filter, NULL, 1);
5354   signal_monitor_assert_is_empty (fixture.monitor);
5355
5356   /* When the second child comes in, this node will become visible */
5357   signal_monitor_append_signal (fixture.monitor, ROW_INSERTED, "1");
5358   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "1");
5359   signal_monitor_append_signal (fixture.monitor, ROW_CHANGED, "1");
5360   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "1");
5361
5362   gtk_tree_store_append (fixture.store, &iter, &root);
5363   check_level_length (fixture.filter, NULL, 2);
5364   check_level_length (fixture.filter, "1", 0);
5365
5366   create_tree_store_set_values (fixture.store, &root, TRUE);
5367   create_tree_store_set_values (fixture.store, &iter, TRUE);
5368
5369   /* check_filter_model (&fixture); */
5370   signal_monitor_assert_is_empty (fixture.monitor);
5371
5372   /* Add another child for 1 */
5373   gtk_tree_store_append (fixture.store, &iter, &root);
5374   create_tree_store_set_values (fixture.store, &iter, TRUE);
5375   check_level_length (fixture.filter, NULL, 2);
5376   check_level_length (fixture.filter, "0", 0);
5377   check_level_length (fixture.filter, "1", 0);
5378   signal_monitor_assert_is_empty (fixture.monitor);
5379
5380   /* Now remove one of the remaining child rows */
5381   signal_monitor_append_signal (fixture.monitor, ROW_DELETED, "0");
5382
5383   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture.store),
5384                                        &iter, "0:0");
5385   gtk_tree_store_remove (fixture.store, &iter);
5386
5387   check_level_length (fixture.filter, NULL, 1);
5388   check_level_length (fixture.filter, "0", 0);
5389
5390   set_path_visibility (&fixture, "0", FALSE);
5391   /* check_filter_model (&fixture); */
5392   signal_monitor_assert_is_empty (fixture.monitor);
5393 }
5394
5395 static void
5396 specific_at_least_2_children_filter_on_sort_model (void)
5397 {
5398   GtkTreeModel *filter;
5399   GtkTreeModel *sort_model;
5400   GtkTreeIter iter, root;
5401   FilterTest fixture; /* This is not how it should be done */
5402   GtkWidget *tree_view;
5403
5404   fixture.store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
5405   sort_model = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (fixture.store));
5406   filter = gtk_tree_model_filter_new (sort_model, NULL);
5407   fixture.filter = GTK_TREE_MODEL_FILTER (filter);
5408   fixture.monitor = signal_monitor_new (filter);
5409
5410   tree_view = gtk_tree_view_new_with_model (filter);
5411
5412   gtk_tree_model_filter_set_visible_func (fixture.filter,
5413                                           specific_at_least_2_children_filter_filter_func,
5414                                           NULL, NULL);
5415
5416   /* The first node will be initially invisible: no signals */
5417   gtk_tree_store_append (fixture.store, &root, NULL);
5418   create_tree_store_set_values (fixture.store, &root, FALSE);
5419
5420   /* check_filter_model (&fixture); */
5421   check_level_length (fixture.filter, NULL, 0);
5422   signal_monitor_assert_is_empty (fixture.monitor);
5423
5424   /* Insert a child node.  Nothing should happen.
5425    */
5426   gtk_tree_store_append (fixture.store, &iter, &root);
5427   create_tree_store_set_values (fixture.store, &iter, TRUE);
5428
5429   check_level_length (fixture.filter, NULL, 0);
5430   signal_monitor_assert_is_empty (fixture.monitor);
5431
5432     {
5433       GtkTreePath *path = gtk_tree_path_new_from_indices (0, 0, -1);
5434       GtkTreeRowReference *ref;
5435
5436       ref = gtk_tree_row_reference_new (sort_model, path);
5437       gtk_tree_path_free (path);
5438     }
5439
5440   /* Insert a second child node.  This will cause the parent to become
5441    * visible.
5442    */
5443   signal_monitor_append_signal (fixture.monitor, ROW_INSERTED, "0");
5444   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
5445
5446   gtk_tree_store_append (fixture.store, &iter, &root);
5447   create_tree_store_set_values (fixture.store, &iter, TRUE);
5448
5449   /* Parent must now be visible.  Do the level length check first,
5450    * to avoid modifying the child model triggering a row-changed to
5451    * the filter model.
5452    */
5453   check_level_length (fixture.filter, NULL, 1);
5454   check_level_length (fixture.filter, "0", 0);
5455   signal_monitor_assert_is_empty (fixture.monitor);
5456
5457   /* This should propagate row-changed */
5458   signal_monitor_append_signal (fixture.monitor, ROW_CHANGED, "0");
5459   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
5460
5461   set_path_visibility (&fixture, "0", TRUE);
5462   /* check_filter_model (&fixture); */
5463   signal_monitor_assert_is_empty (fixture.monitor);
5464
5465   /* New root node, no child, so no signal */
5466   gtk_tree_store_append (fixture.store, &root, NULL);
5467   check_level_length (fixture.filter, NULL, 1);
5468   signal_monitor_assert_is_empty (fixture.monitor);
5469 }
5470
5471
5472 static void
5473 specific_filter_add_child (void)
5474 {
5475   /* This test is based on one of the test cases I found in my
5476    * old test cases directory.  I unfortunately do not have a record
5477    * from who this test case originated.  -Kris.
5478    */
5479
5480   GtkTreeIter iter;
5481   GtkTreeIter iter_first;
5482   GtkTreeIter child;
5483   GtkTreeStore *store;
5484   GtkTreeModel *filter G_GNUC_UNUSED;
5485
5486   store = gtk_tree_store_new (1, G_TYPE_STRING);
5487
5488   gtk_tree_store_append (store, &iter_first, NULL);
5489   gtk_tree_store_set (store, &iter_first, 0, "Hello", -1);
5490
5491   gtk_tree_store_append (store, &iter, NULL);
5492   gtk_tree_store_set (store, &iter, 0, "Hello", -1);
5493
5494   gtk_tree_store_append (store, &iter, NULL);
5495   gtk_tree_store_set (store, &iter, 0, "Hello", -1);
5496
5497   gtk_tree_store_append (store, &iter, NULL);
5498   gtk_tree_store_set (store, &iter, 0, "Hello", -1);
5499
5500   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
5501
5502   gtk_tree_store_set (store, &iter, 0, "Hello", -1);
5503   gtk_tree_store_append (store, &child, &iter_first);
5504   gtk_tree_store_set (store, &child, 0, "Hello", -1);
5505 }
5506
5507 static void
5508 specific_list_store_clear (void)
5509 {
5510   GtkTreeIter iter;
5511   GtkListStore *list;
5512   GtkTreeModel *filter;
5513   GtkWidget *view G_GNUC_UNUSED;
5514
5515   list = gtk_list_store_new (1, G_TYPE_INT);
5516   gtk_list_store_insert_with_values (list, &iter, 0, 0, 1, -1);
5517   gtk_list_store_insert_with_values (list, &iter, 1, 0, 2, -1);
5518   gtk_list_store_insert_with_values (list, &iter, 2, 0, 3, -1);
5519   gtk_list_store_insert_with_values (list, &iter, 3, 0, 4, -1);
5520   gtk_list_store_insert_with_values (list, &iter, 4, 0, 5, -1);
5521   gtk_list_store_insert_with_values (list, &iter, 5, 0, 6, -1);
5522   gtk_list_store_insert_with_values (list, &iter, 6, 0, 7, -1);
5523   gtk_list_store_insert_with_values (list, &iter, 7, 0, 8, -1);
5524
5525   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (list), NULL);
5526   view = gtk_tree_view_new_with_model (filter);
5527
5528   gtk_list_store_clear (list);
5529 }
5530
5531 static void
5532 specific_sort_ref_leaf_and_remove_ancestor (void)
5533 {
5534   GtkTreeIter iter, child, child2, child3;
5535   GtkTreeStore *tree;
5536   GtkTreeModel *sort;
5537   GtkTreePath *path;
5538   GtkTreeRowReference *rowref;
5539   GtkWidget *view G_GNUC_UNUSED;
5540
5541   tree = gtk_tree_store_new (1, G_TYPE_INT);
5542   gtk_tree_store_insert_with_values (tree, &iter, NULL, 0, 0, 1, -1);
5543   gtk_tree_store_insert_with_values (tree, &iter, NULL, 1, 0, 2, -1);
5544   gtk_tree_store_insert_with_values (tree, &iter, NULL, 2, 0, 3, -1);
5545   gtk_tree_store_insert_with_values (tree, &iter, NULL, 3, 0, 4, -1);
5546
5547   gtk_tree_store_insert_with_values (tree, &child, &iter, 0, 0, 50, -1);
5548   gtk_tree_store_insert_with_values (tree, &child2, &child, 0, 0, 6, -1);
5549   gtk_tree_store_insert_with_values (tree, &child3, &child2, 0, 0, 7, -1);
5550
5551   sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (tree));
5552   view = gtk_tree_view_new_with_model (sort);
5553   gtk_tree_view_expand_all (GTK_TREE_VIEW (view));
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, 0, 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, 0, -1);
5564   rowref = gtk_tree_row_reference_new (sort, path);
5565   gtk_tree_path_free (path);
5566
5567   path = gtk_tree_path_new_from_indices (3, -1);
5568   rowref = gtk_tree_row_reference_new (sort, path);
5569   gtk_tree_path_free (path);
5570
5571   /* Deleting a parent */
5572   path = gtk_tree_path_new_from_indices (3, 0, -1);
5573   gtk_tree_model_get_iter (GTK_TREE_MODEL (tree), &iter, path);
5574   gtk_tree_store_remove (tree, &iter);
5575   gtk_tree_path_free (path);
5576
5577   gtk_tree_row_reference_free (rowref);
5578 }
5579
5580 static void
5581 specific_ref_leaf_and_remove_ancestor (void)
5582 {
5583   GtkTreeIter iter, child, child2, child3;
5584   GtkTreeStore *tree;
5585   GtkTreeModel *filter;
5586   GtkTreePath *path;
5587   GtkTreeRowReference *rowref;
5588   GtkWidget *view G_GNUC_UNUSED;
5589
5590   tree = gtk_tree_store_new (1, G_TYPE_INT);
5591   gtk_tree_store_insert_with_values (tree, &iter, NULL, 0, 0, 1, -1);
5592   gtk_tree_store_insert_with_values (tree, &iter, NULL, 1, 0, 2, -1);
5593   gtk_tree_store_insert_with_values (tree, &iter, NULL, 2, 0, 3, -1);
5594   gtk_tree_store_insert_with_values (tree, &iter, NULL, 3, 0, 4, -1);
5595
5596   gtk_tree_store_insert_with_values (tree, &child, &iter, 0, 0, 50, -1);
5597   gtk_tree_store_insert_with_values (tree, &child2, &child, 0, 0, 6, -1);
5598   gtk_tree_store_insert_with_values (tree, &child3, &child2, 0, 0, 7, -1);
5599
5600   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (tree), NULL);
5601   view = gtk_tree_view_new_with_model (filter);
5602   gtk_tree_view_expand_all (GTK_TREE_VIEW (view));
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, 0, 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, 0, -1);
5613   rowref = gtk_tree_row_reference_new (filter, path);
5614   gtk_tree_path_free (path);
5615
5616   path = gtk_tree_path_new_from_indices (3, -1);
5617   rowref = gtk_tree_row_reference_new (filter, path);
5618   gtk_tree_path_free (path);
5619
5620   /* Deleting a parent */
5621   path = gtk_tree_path_new_from_indices (3, 0, -1);
5622   gtk_tree_model_get_iter (GTK_TREE_MODEL (tree), &iter, path);
5623   gtk_tree_store_remove (tree, &iter);
5624   gtk_tree_path_free (path);
5625
5626   gtk_tree_row_reference_free (rowref);
5627 }
5628
5629 static void
5630 specific_virtual_ref_leaf_and_remove_ancestor (void)
5631 {
5632   GtkTreeIter iter, child, child2, child3;
5633   GtkTreeStore *tree;
5634   GtkTreeModel *filter;
5635   GtkTreePath *path;
5636   GtkTreeRowReference *rowref;
5637   GtkWidget *view G_GNUC_UNUSED;
5638
5639   tree = gtk_tree_store_new (1, G_TYPE_INT);
5640   gtk_tree_store_insert_with_values (tree, &iter, NULL, 0, 0, 1, -1);
5641   gtk_tree_store_insert_with_values (tree, &iter, NULL, 1, 0, 2, -1);
5642   gtk_tree_store_insert_with_values (tree, &iter, NULL, 2, 0, 3, -1);
5643   gtk_tree_store_insert_with_values (tree, &iter, NULL, 3, 0, 4, -1);
5644
5645   gtk_tree_store_insert_with_values (tree, &child, &iter, 0, 0, 50, -1);
5646   gtk_tree_store_insert_with_values (tree, &child2, &child, 0, 0, 6, -1);
5647   gtk_tree_store_insert_with_values (tree, &child3, &child2, 0, 0, 7, -1);
5648
5649   /* Set a virtual root of 3:0 */
5650   path = gtk_tree_path_new_from_indices (3, 0, -1);
5651   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (tree), path);
5652   gtk_tree_path_free (path);
5653
5654   view = gtk_tree_view_new_with_model (filter);
5655   gtk_tree_view_expand_all (GTK_TREE_VIEW (view));
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, 0, -1);
5662   rowref = gtk_tree_row_reference_new (filter, path);
5663   gtk_tree_path_free (path);
5664
5665   path = gtk_tree_path_new_from_indices (0, -1);
5666   rowref = gtk_tree_row_reference_new (filter, path);
5667   gtk_tree_path_free (path);
5668
5669   /* Deleting the virtual root */
5670   path = gtk_tree_path_new_from_indices (3, 0, -1);
5671   gtk_tree_model_get_iter (GTK_TREE_MODEL (tree), &iter, path);
5672   gtk_tree_store_remove (tree, &iter);
5673   gtk_tree_path_free (path);
5674
5675   gtk_tree_row_reference_free (rowref);
5676 }
5677
5678
5679 static int
5680 specific_bug_301558_sort_func (GtkTreeModel *model,
5681                                GtkTreeIter  *a,
5682                                GtkTreeIter  *b,
5683                                gpointer      data)
5684 {
5685   int i, j;
5686
5687   gtk_tree_model_get (model, a, 0, &i, -1);
5688   gtk_tree_model_get (model, b, 0, &j, -1);
5689
5690   return j - i;
5691 }
5692
5693 static void
5694 specific_bug_301558 (void)
5695 {
5696   /* Test case for GNOME Bugzilla bug 301558 provided by
5697    * Markku Vire.
5698    */
5699   GtkTreeStore *tree;
5700   GtkTreeModel *filter;
5701   GtkTreeModel *sort;
5702   GtkTreeIter root, iter, iter2;
5703   GtkWidget *view G_GNUC_UNUSED;
5704   int i;
5705   gboolean add;
5706
5707   g_test_bug ("301558");
5708
5709   tree = gtk_tree_store_new (2, G_TYPE_INT, G_TYPE_BOOLEAN);
5710   gtk_tree_store_append (tree, &iter, NULL);
5711   gtk_tree_store_set (tree, &iter, 0, 123, 1, TRUE, -1);
5712   gtk_tree_store_append (tree, &iter2, &iter);
5713   gtk_tree_store_set (tree, &iter2, 0, 73, 1, TRUE, -1);
5714
5715   sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (tree));
5716   gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (sort),
5717                                            specific_bug_301558_sort_func,
5718                                            NULL, NULL);
5719
5720   filter = gtk_tree_model_filter_new (sort, NULL);
5721   gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter), 1);
5722
5723   view = gtk_tree_view_new_with_model (filter);
5724
5725   while (gtk_events_pending ())
5726     gtk_main_iteration ();
5727
5728   add = TRUE;
5729
5730   for (i = 0; i < 10; i++)
5731     {
5732       if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (tree), &root))
5733         g_assert_not_reached ();
5734
5735       if (add)
5736         {
5737           gtk_tree_store_append (tree, &iter, &root);
5738           gtk_tree_store_set (tree, &iter, 0, 456, 1, TRUE, -1);
5739         }
5740       else
5741         {
5742           int n;
5743           n = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (tree), &root);
5744           gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (tree), &iter,
5745                                          &root, n - 1);
5746           gtk_tree_store_remove (tree, &iter);
5747         }
5748
5749       add = !add;
5750     }
5751 }
5752
5753
5754 static gboolean
5755 specific_bug_311955_filter_func (GtkTreeModel *model,
5756                                  GtkTreeIter  *iter,
5757                                  gpointer      data)
5758 {
5759   int value;
5760
5761   gtk_tree_model_get (model, iter, 0, &value, -1);
5762
5763   return (value != 0);
5764 }
5765
5766 static void
5767 specific_bug_311955 (void)
5768 {
5769   /* This is a test case for GNOME Bugzilla bug 311955.  It was written
5770    * by Markku Vire.
5771    */
5772   GtkTreeIter iter, child, root;
5773   GtkTreeStore *store;
5774   GtkTreeModel *sort;
5775   GtkTreeModel *filter;
5776
5777   GtkWidget *window G_GNUC_UNUSED;
5778   GtkWidget *tree_view;
5779   int i;
5780   int n;
5781   GtkTreePath *path;
5782
5783   g_test_bug ("311955");
5784
5785   store = gtk_tree_store_new (1, G_TYPE_INT);
5786
5787   gtk_tree_store_append (store, &root, NULL);
5788   gtk_tree_store_set (store, &root, 0, 33, -1);
5789
5790   gtk_tree_store_append (store, &iter, &root);
5791   gtk_tree_store_set (store, &iter, 0, 50, -1);
5792
5793   gtk_tree_store_append (store, &iter, NULL);
5794   gtk_tree_store_set (store, &iter, 0, 22, -1);
5795
5796   sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (store));
5797   filter = gtk_tree_model_filter_new (sort, NULL);
5798
5799   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
5800                                           specific_bug_311955_filter_func,
5801                                           NULL, NULL);
5802
5803   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5804   tree_view = gtk_tree_view_new_with_model (filter);
5805   g_object_unref (store);
5806
5807   gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
5808
5809   while (gtk_events_pending ())
5810     gtk_main_iteration ();
5811
5812   check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, 2);
5813   check_level_length (GTK_TREE_MODEL_FILTER (filter), "0", 1);
5814
5815   /* Fill model */
5816   for (i = 0; i < 4; i++)
5817     {
5818       gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &root);
5819
5820       gtk_tree_store_append (store, &iter, &root);
5821
5822       if (i < 3)
5823         gtk_tree_store_set (store, &iter, 0, i, -1);
5824
5825       if (i % 2 == 0)
5826         {
5827           gtk_tree_store_append (store, &child, &iter);
5828           gtk_tree_store_set (store, &child, 0, 10, -1);
5829         }
5830     }
5831
5832   while (gtk_events_pending ())
5833     gtk_main_iteration ();
5834
5835   check_level_length (GTK_TREE_MODEL_FILTER (filter), "0", 3);
5836   check_level_length (GTK_TREE_MODEL_FILTER (filter), "0:2", 1);
5837
5838   /* Remove bottommost child from the tree. */
5839   gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &root);
5840   n = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (store), &root);
5841
5842   if (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (store), &iter, &root, n - 2))
5843     {
5844       if (gtk_tree_model_iter_children (GTK_TREE_MODEL (store), &child, &iter))
5845         gtk_tree_store_remove (store, &child);
5846     }
5847   else
5848     g_assert_not_reached ();
5849
5850   path = gtk_tree_path_new_from_indices (0, 2, -1);
5851   gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path, FALSE);
5852   gtk_tree_path_free (path);
5853
5854   check_level_length (GTK_TREE_MODEL_FILTER (filter), "0", 3);
5855   check_level_length (GTK_TREE_MODEL_FILTER (filter), "0:2", 0);
5856 }
5857
5858 static void
5859 specific_bug_311955_clean (void)
5860 {
5861   /* Cleaned up version of the test case for GNOME Bugzilla bug 311955,
5862    * which is easier to understand.
5863    */
5864   GtkTreeIter iter, child, grandchild;
5865   GtkTreeStore *store;
5866   GtkTreeModel *sort;
5867   GtkTreeModel *filter;
5868
5869   GtkWidget *tree_view;
5870   GtkTreePath *path;
5871
5872   store = gtk_tree_store_new (1, G_TYPE_INT);
5873
5874   gtk_tree_store_append (store, &iter, NULL);
5875   gtk_tree_store_set (store, &iter, 0, 1, -1);
5876
5877   gtk_tree_store_append (store, &child, &iter);
5878   gtk_tree_store_set (store, &child, 0, 1, -1);
5879
5880   sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (store));
5881   filter = gtk_tree_model_filter_new (sort, NULL);
5882
5883   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
5884                                           specific_bug_311955_filter_func,
5885                                           NULL, NULL);
5886
5887   tree_view = gtk_tree_view_new_with_model (filter);
5888   g_object_unref (store);
5889
5890   gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
5891
5892   while (gtk_events_pending ())
5893     gtk_main_iteration ();
5894
5895   check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, 1);
5896   check_level_length (GTK_TREE_MODEL_FILTER (filter), "0", 1);
5897
5898   gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter);
5899
5900   gtk_tree_store_append (store, &child, &iter);
5901   gtk_tree_store_set (store, &child, 0, 0, -1);
5902
5903   gtk_tree_store_append (store, &child, &iter);
5904   gtk_tree_store_set (store, &child, 0, 1, -1);
5905
5906   gtk_tree_store_append (store, &child, &iter);
5907   gtk_tree_store_set (store, &child, 0, 1, -1);
5908
5909   gtk_tree_store_append (store, &grandchild, &child);
5910   gtk_tree_store_set (store, &grandchild, 0, 1, -1);
5911
5912   gtk_tree_store_append (store, &child, &iter);
5913   /* Don't set a value: assume 0 */
5914
5915   /* Remove leaf node, check trigger row-has-child-toggled */
5916   path = gtk_tree_path_new_from_indices (0, 3, 0, -1);
5917   gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, path);
5918   gtk_tree_path_free (path);
5919   gtk_tree_store_remove (store, &iter);
5920
5921   path = gtk_tree_path_new_from_indices (0, 2, -1);
5922   gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path, FALSE);
5923   gtk_tree_path_free (path);
5924
5925   check_level_length (GTK_TREE_MODEL_FILTER (filter), "0", 3);
5926   check_level_length (GTK_TREE_MODEL_FILTER (filter), "0:2", 0);
5927
5928   gtk_widget_destroy (tree_view);
5929 }
5930
5931 static void
5932 specific_bug_346800 (void)
5933 {
5934   /* This is a test case for GNOME Bugzilla bug 346800.  It was written
5935    * by Jonathan Matthew.
5936    */
5937
5938   GtkTreeIter node_iters[50];
5939   GtkTreeIter child_iters[50];
5940   GtkTreeModel *model;
5941   GtkTreeModelFilter *filter;
5942   GtkTreeStore *store;
5943   GType *columns;
5944   int i;
5945   int items = 50;
5946   columns = g_new (GType, 2);
5947   columns[0] = G_TYPE_STRING;
5948   columns[1] = G_TYPE_BOOLEAN;
5949   store = gtk_tree_store_newv (2, columns);
5950   model = GTK_TREE_MODEL (store);
5951
5952   g_test_bug ("346800");
5953
5954   filter = GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (model, NULL));
5955   gtk_tree_model_filter_set_visible_column (filter, 1);
5956
5957   for (i=0; i<items; i++)
5958     {
5959       /* allocate random amounts of junk, otherwise the filter model's arrays can expand without moving */
5960
5961       g_malloc (138);
5962       gtk_tree_store_append (store, &node_iters[i], NULL);
5963       gtk_tree_store_set (store, &node_iters[i],
5964                           0, "something",
5965                           1, ((i%6) == 0) ? FALSE : TRUE,
5966                           -1);
5967
5968       g_malloc (47);
5969       gtk_tree_store_append (store, &child_iters[i], &node_iters[i]);
5970       gtk_tree_store_set (store, &child_iters[i],
5971                           0, "something else",
5972                           1, FALSE,
5973                           -1);
5974       gtk_tree_model_filter_refilter (filter);
5975
5976       if (i > 6)
5977         {
5978           gtk_tree_store_set (GTK_TREE_STORE (model), &child_iters[i-1], 1,
5979                               (i & 1) ? TRUE : FALSE, -1);
5980           gtk_tree_model_filter_refilter (filter);
5981
5982           gtk_tree_store_set (GTK_TREE_STORE (model), &child_iters[i-2], 1,
5983                               (i & 1) ? FALSE: TRUE, -1);
5984           gtk_tree_model_filter_refilter (filter);
5985         }
5986     }
5987 }
5988
5989 static gboolean
5990 specific_bug_464173_visible_func (GtkTreeModel *model,
5991                                   GtkTreeIter  *iter,
5992                                   gpointer      data)
5993 {
5994   gboolean *visible = (gboolean *)data;
5995
5996   return *visible;
5997 }
5998
5999 static void
6000 specific_bug_464173 (void)
6001 {
6002   /* Test case for GNOME Bugzilla bug 464173, test case written
6003    * by Andreas Koehler.
6004    */
6005   GtkTreeStore *model;
6006   GtkTreeModelFilter *f_model;
6007   GtkTreeIter iter1, iter2;
6008   GtkWidget *view G_GNUC_UNUSED;
6009   gboolean visible = TRUE;
6010
6011   g_test_bug ("464173");
6012
6013   model = gtk_tree_store_new (1, G_TYPE_STRING);
6014   gtk_tree_store_append (model, &iter1, NULL);
6015   gtk_tree_store_set (model, &iter1, 0, "Foo", -1);
6016   gtk_tree_store_append (model, &iter2, &iter1);
6017   gtk_tree_store_set (model, &iter2, 0, "Bar", -1);
6018
6019   f_model = GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (GTK_TREE_MODEL(model), NULL));
6020   gtk_tree_model_filter_set_visible_func (f_model,
6021                                           specific_bug_464173_visible_func,
6022                                           &visible, NULL);
6023
6024   view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (f_model));
6025
6026   visible = FALSE;
6027   gtk_tree_model_filter_refilter (f_model);
6028 }
6029
6030
6031 static gboolean
6032 specific_bug_540201_filter_func (GtkTreeModel *model,
6033                                  GtkTreeIter  *iter,
6034                                  gpointer      data)
6035 {
6036   gboolean has_children;
6037
6038   has_children = gtk_tree_model_iter_has_child (model, iter);
6039
6040   return has_children;
6041 }
6042
6043 static void
6044 specific_bug_540201 (void)
6045 {
6046   /* Test case for GNOME Bugzilla bug 540201, steps provided by
6047    * Charles Day.
6048    */
6049   GtkTreeIter iter, root;
6050   GtkTreeStore *store;
6051   GtkTreeModel *filter;
6052
6053   GtkWidget *tree_view G_GNUC_UNUSED;
6054
6055   g_test_bug ("540201");
6056
6057   store = gtk_tree_store_new (1, G_TYPE_INT);
6058
6059   gtk_tree_store_append (store, &root, NULL);
6060   gtk_tree_store_set (store, &root, 0, 33, -1);
6061
6062   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
6063   tree_view = gtk_tree_view_new_with_model (filter);
6064
6065   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
6066                                           specific_bug_540201_filter_func,
6067                                           NULL, NULL);
6068
6069   gtk_tree_store_append (store, &iter, &root);
6070   gtk_tree_store_set (store, &iter, 0, 50, -1);
6071
6072   gtk_tree_store_append (store, &iter, &root);
6073   gtk_tree_store_set (store, &iter, 0, 22, -1);
6074
6075
6076   gtk_tree_store_append (store, &root, NULL);
6077   gtk_tree_store_set (store, &root, 0, 33, -1);
6078
6079   gtk_tree_store_append (store, &iter, &root);
6080   gtk_tree_store_set (store, &iter, 0, 22, -1);
6081 }
6082
6083
6084 static gboolean
6085 specific_bug_549287_visible_func (GtkTreeModel *model,
6086                                   GtkTreeIter  *iter,
6087                                   gpointer      data)
6088 {
6089   gboolean result = FALSE;
6090
6091   result = gtk_tree_model_iter_has_child (model, iter);
6092
6093   return result;
6094 }
6095
6096 static void
6097 specific_bug_549287 (void)
6098 {
6099   /* Test case for GNOME Bugzilla bug 529287, provided by Julient Puydt */
6100
6101   int i;
6102   GtkTreeStore *store;
6103   GtkTreeModel *filtered;
6104   GtkWidget *view G_GNUC_UNUSED;
6105   GtkTreeIter iter;
6106   GtkTreeIter *swap, *parent, *child;
6107
6108   g_test_bug ("529287");
6109
6110   store = gtk_tree_store_new (1, G_TYPE_STRING);
6111   filtered = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
6112   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filtered),
6113                                           specific_bug_549287_visible_func,
6114                                           NULL, NULL);
6115
6116   view = gtk_tree_view_new_with_model (filtered);
6117
6118   for (i = 0; i < 4; i++)
6119     {
6120       if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter))
6121         {
6122           parent = gtk_tree_iter_copy (&iter);
6123           child = gtk_tree_iter_copy (&iter);
6124
6125           while (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (store),
6126                                                 child, parent, 0))
6127             {
6128
6129               swap = parent;
6130               parent = child;
6131               child = swap;
6132             }
6133
6134           gtk_tree_store_append (store, child, parent);
6135           gtk_tree_store_set (store, child,
6136                               0, "Something",
6137                               -1);
6138
6139           gtk_tree_iter_free (parent);
6140           gtk_tree_iter_free (child);
6141         }
6142       else
6143         {
6144           gtk_tree_store_append (store, &iter, NULL);
6145           gtk_tree_store_set (store, &iter,
6146                               0, "Something",
6147                               -1);
6148         }
6149
6150       /* since we inserted something, we changed the visibility conditions: */
6151       gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (filtered));
6152     }
6153 }
6154
6155 static gboolean
6156 specific_bug_621076_visible_func (GtkTreeModel *model,
6157                                   GtkTreeIter  *iter,
6158                                   gpointer      data)
6159 {
6160   gboolean visible = FALSE;
6161   gchar *str = NULL;
6162
6163   gtk_tree_model_get (model, iter, 0, &str, -1);
6164   if (str != NULL && g_str_has_prefix (str, "visible"))
6165     {
6166       visible = TRUE;
6167     }
6168   else
6169     {
6170       GtkTreeIter child_iter;
6171       gboolean valid;
6172
6173       /* Recursively check if we have a visible child */
6174       for (valid = gtk_tree_model_iter_children (model, &child_iter, iter);
6175            valid; valid = gtk_tree_model_iter_next (model, &child_iter))
6176         {
6177           if (specific_bug_621076_visible_func (model, &child_iter, data))
6178             {
6179               visible = TRUE;
6180               break;
6181             }
6182         }
6183     }
6184
6185   if (str)
6186     g_free (str);
6187
6188   return visible;
6189 }
6190
6191 static void
6192 specific_bug_621076 (void)
6193 {
6194   /* Test case for GNOME Bugzilla bug 621076, provided by Xavier Claessens */
6195
6196   /* This test case differs from has-child-filter and root-has-child-filter
6197    * in that the visible function both filters on content and model
6198    * structure.  Also, it is recursive.
6199    */
6200
6201   GtkTreeStore *store;
6202   GtkTreeModel *filter;
6203   GtkWidget *view;
6204   GtkTreeIter group_iter;
6205   GtkTreeIter item_iter;
6206   SignalMonitor *monitor;
6207
6208   g_test_bug ("621076");
6209
6210   store = gtk_tree_store_new (1, G_TYPE_STRING);
6211   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
6212   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
6213                                           specific_bug_621076_visible_func,
6214                                           NULL, NULL);
6215
6216   view = gtk_tree_view_new_with_model (filter);
6217   g_object_ref_sink (view);
6218
6219   monitor = signal_monitor_new (filter);
6220
6221   signal_monitor_append_signal (monitor, ROW_INSERTED, "0");
6222   gtk_tree_store_insert_with_values (store, &item_iter, NULL, -1,
6223                                      0, "visible-group-0",
6224                                      -1);
6225   signal_monitor_assert_is_empty (monitor);
6226
6227   /* visible-group-0 is not expanded, so ROW_INSERTED should not be emitted
6228    * for its children. However, ROW_HAS_CHILD_TOGGLED should be emitted on
6229    * visible-group-0 to tell the view that row can be expanded. */
6230   signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "0");
6231   signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "0");
6232   group_iter = item_iter;
6233   gtk_tree_store_insert_with_values (store, &item_iter, &group_iter, -1,
6234                                      0, "visible-0:0",
6235                                      -1);
6236   signal_monitor_assert_is_empty (monitor);
6237
6238   signal_monitor_append_signal (monitor, ROW_INSERTED, "1");
6239   gtk_tree_store_insert_with_values (store, &item_iter, NULL, -1,
6240                                      0, "visible-group-1",
6241                                      -1);
6242   signal_monitor_assert_is_empty (monitor);
6243
6244   /* We are adding an hidden item inside visible-group-1, so
6245    * ROW_HAS_CHILD_TOGGLED should not be emitted.  It is emitted though,
6246    * because the signal originating at TreeStore will be propagated,
6247    * as well a generated signal because the state of the parent *could*
6248    * change by a change in the model.
6249    */
6250   signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "1");
6251   signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "1");
6252   group_iter = item_iter;
6253   gtk_tree_store_insert_with_values (store, &item_iter, &group_iter, -1,
6254                                      0, "group-1:0",
6255                                      -1);
6256   signal_monitor_assert_is_empty (monitor);
6257
6258   /* This group is invisible and its parent too. Nothing should be emitted */
6259   group_iter = item_iter;
6260   gtk_tree_store_insert_with_values (store, &item_iter, &group_iter, -1,
6261                                      0, "group-1:0:0",
6262                                      -1);
6263   signal_monitor_assert_is_empty (monitor);
6264
6265   /* Adding a visible item in this group hierarchy will make all nodes
6266    * in this path visible.  The first level should simply tell the view
6267    * that it now has a child, and the view will load the tree if needed
6268    * (depends on the expanded state).
6269    */
6270   signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "1");
6271   group_iter = item_iter;
6272   gtk_tree_store_insert_with_values (store, &item_iter, &group_iter, -1,
6273                                      0, "visible-1:0:0:0",
6274                                      -1);
6275   signal_monitor_assert_is_empty (monitor);
6276
6277   check_level_length (GTK_TREE_MODEL_FILTER (filter), "1", 1);
6278
6279   gtk_tree_store_insert_with_values (store, &item_iter, NULL, -1,
6280                                      0, "group-2",
6281                                      -1);
6282   signal_monitor_assert_is_empty (monitor);
6283
6284   /* Parent is invisible, and adding this invisible item won't change that,
6285    * so no signal should be emitted. */
6286   group_iter = item_iter;
6287   gtk_tree_store_insert_with_values (store, NULL, &group_iter, -1,
6288                                      0, "invisible-2:0",
6289                                      -1);
6290   signal_monitor_assert_is_empty (monitor);
6291
6292   /* This makes group-2 visible, so it gets inserted and tells it has
6293    * children.
6294    */
6295   signal_monitor_append_signal (monitor, ROW_INSERTED, "2");
6296   signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "2");
6297   gtk_tree_store_insert_with_values (store, NULL, &group_iter, -1,
6298                                      0, "visible-2:1",
6299                                      -1);
6300   signal_monitor_assert_is_empty (monitor);
6301
6302   /* group-2 is already visible, so this time it is a normal insertion */
6303   gtk_tree_store_insert_with_values (store, NULL, &group_iter, -1,
6304                                      0, "visible-2:2",
6305                                      -1);
6306   signal_monitor_assert_is_empty (monitor);
6307
6308
6309   gtk_tree_store_insert_with_values (store, &item_iter, NULL, -1,
6310                                      0, "group-3",
6311                                      -1);
6312   signal_monitor_assert_is_empty (monitor);
6313
6314   /* Parent is invisible, and adding this invisible item won't change that,
6315    * so no signal should be emitted. */
6316   group_iter = item_iter;
6317   gtk_tree_store_insert_with_values (store, NULL, &group_iter, -1,
6318                                      0, "invisible-3:0",
6319                                      -1);
6320   signal_monitor_assert_is_empty (monitor);
6321
6322   gtk_tree_store_insert_with_values (store, &item_iter, &group_iter, -1,
6323                                      0, "invisible-3:1",
6324                                      -1);
6325   signal_monitor_assert_is_empty (monitor);
6326
6327   /* This will make group 3 visible. */
6328   signal_monitor_append_signal (monitor, ROW_INSERTED, "3");
6329   signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "3");
6330   signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "3");
6331   gtk_tree_store_set (store, &item_iter, 0, "visible-3:1", -1);
6332   signal_monitor_assert_is_empty (monitor);
6333
6334   /* Make sure all groups are expanded, so the filter has the tree cached */
6335   gtk_tree_view_expand_all (GTK_TREE_VIEW (view));
6336   while (gtk_events_pending ())
6337     gtk_main_iteration ();
6338
6339   /* Should only yield a row-changed */
6340   signal_monitor_append_signal (monitor, ROW_CHANGED, "3:0");
6341   gtk_tree_store_set (store, &item_iter, 0, "visible-3:1", -1);
6342   signal_monitor_assert_is_empty (monitor);
6343
6344   /* Now remove/hide some items. If a group loses its last item, the group
6345    * should be deleted instead of the item.
6346    */
6347
6348   signal_monitor_append_signal (monitor, ROW_DELETED, "2:1");
6349   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (store), &item_iter, "2:2");
6350   gtk_tree_store_remove (store, &item_iter);
6351   signal_monitor_assert_is_empty (monitor);
6352
6353   signal_monitor_append_signal (monitor, ROW_DELETED, "2:0");
6354   signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "2");
6355   signal_monitor_append_signal (monitor, ROW_DELETED, "2");
6356   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (store), &item_iter, "2:1");
6357   gtk_tree_store_set (store, &item_iter, 0, "invisible-2:1", -1);
6358   signal_monitor_assert_is_empty (monitor);
6359
6360   signal_monitor_append_signal (monitor, ROW_DELETED, "1:0:0:0");
6361   signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "1:0:0");
6362   signal_monitor_append_signal (monitor, ROW_DELETED, "1:0");
6363   signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "1");
6364   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (store), &item_iter, "1:0:0:0");
6365   gtk_tree_store_remove (store, &item_iter);
6366   signal_monitor_assert_is_empty (monitor);
6367
6368   /* Hide a group using row-changed instead of row-deleted */
6369   /* Caution: group 2 is gone, so offsets of the signals have moved. */
6370   signal_monitor_append_signal (monitor, ROW_DELETED, "2:0");
6371   signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "2");
6372   signal_monitor_append_signal (monitor, ROW_DELETED, "2");
6373   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (store), &item_iter,
6374                                        "3:1");
6375   gtk_tree_store_set (store, &item_iter, 0, "invisible-3:1", -1);
6376   signal_monitor_assert_is_empty (monitor);
6377
6378 #if 0
6379   {
6380     GtkWidget *window;
6381     GtkTreeViewColumn *col;
6382
6383     gtk_tree_view_expand_all (GTK_TREE_VIEW (view));
6384
6385     col = gtk_tree_view_column_new_with_attributes ("foo",
6386         gtk_cell_renderer_text_new (),
6387         "text", 0, NULL);
6388     gtk_tree_view_append_column (GTK_TREE_VIEW (view), col);
6389
6390     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6391     g_signal_connect (window, "delete-event",
6392         G_CALLBACK (gtk_widget_destroy), NULL);
6393     g_signal_connect (window, "destroy",
6394         G_CALLBACK (gtk_main_quit), NULL);
6395
6396     gtk_container_add (GTK_CONTAINER (window), view);
6397
6398     gtk_widget_show (view);
6399     gtk_widget_show (window);
6400
6401     gtk_main ();
6402   }
6403 #endif
6404
6405   /* Cleanup */
6406   signal_monitor_free (monitor);
6407   g_object_unref (view);
6408   g_object_unref (store);
6409   g_object_unref (filter);
6410 }
6411
6412 static void
6413 specific_bug_657353_related (void)
6414 {
6415   GtkTreeIter node1, node2, node3, node4;
6416   GtkTreeModel *model;
6417   GtkTreeModelRefCount *ref_model;
6418   GtkTreeModel *filter_model;
6419   GtkWidget *tree_view;
6420   GType column_types[] = { G_TYPE_BOOLEAN };
6421
6422   /* gtk_tree_model_filter_rows_reordered() used to have a problem to
6423    * not properly transfer the first ref count when the first node in
6424    * the level does not have elt->offset == 0.  This test checks for
6425    * that.  This bug could cause the faulty condition
6426    *   elt->ext_ref_count > elt->ref_count
6427    * to raise.
6428    */
6429
6430   model = gtk_tree_model_ref_count_new ();
6431   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
6432
6433   gtk_tree_store_set_column_types (GTK_TREE_STORE (model), 1,
6434                                    column_types);
6435
6436   gtk_tree_store_append (GTK_TREE_STORE (model), &node1, NULL);
6437   gtk_tree_store_append (GTK_TREE_STORE (model), &node2, NULL);
6438   gtk_tree_store_append (GTK_TREE_STORE (model), &node3, NULL);
6439   gtk_tree_store_append (GTK_TREE_STORE (model), &node4, NULL);
6440
6441   /* Hide the first node */
6442   gtk_tree_store_set (GTK_TREE_STORE (model), &node1, 0, FALSE, -1);
6443   gtk_tree_store_set (GTK_TREE_STORE (model), &node2, 0, TRUE, -1);
6444   gtk_tree_store_set (GTK_TREE_STORE (model), &node3, 0, TRUE, -1);
6445   gtk_tree_store_set (GTK_TREE_STORE (model), &node4, 0, TRUE, -1);
6446
6447   filter_model = gtk_tree_model_filter_new (model, NULL);
6448   gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), 0);
6449   tree_view = gtk_tree_view_new_with_model (filter_model);
6450
6451   assert_node_ref_count (ref_model, &node1, 0);
6452   assert_node_ref_count (ref_model, &node2, 2);
6453   assert_node_ref_count (ref_model, &node3, 1);
6454   assert_node_ref_count (ref_model, &node4, 1);
6455
6456   /* Swap nodes 2 and 3 */
6457
6458   /* gtk_tree_store_swap() will emit rows-reordered */
6459   gtk_tree_store_swap (GTK_TREE_STORE (model),
6460                        &node2, &node3);
6461
6462   assert_node_ref_count (ref_model, &node1, 0);
6463   assert_node_ref_count (ref_model, &node3, 2);
6464   assert_node_ref_count (ref_model, &node2, 1);
6465   assert_node_ref_count (ref_model, &node4, 1);
6466
6467   /* Hide node 3 */
6468   gtk_tree_store_set (GTK_TREE_STORE (model), &node3, 0, FALSE, -1);
6469
6470   assert_node_ref_count (ref_model, &node1, 0);
6471   assert_node_ref_count (ref_model, &node3, 0);
6472   assert_node_ref_count (ref_model, &node2, 2);
6473   assert_node_ref_count (ref_model, &node4, 1);
6474
6475   gtk_widget_destroy (tree_view);
6476   g_object_unref (filter_model);
6477   g_object_unref (ref_model);
6478 }
6479
6480 static gboolean
6481 specific_bug_657353_visible_func (GtkTreeModel *model,
6482                                   GtkTreeIter  *iter,
6483                                   gpointer      data)
6484 {
6485   gchar *str;
6486   gboolean ret = FALSE;
6487
6488   gtk_tree_model_get (model, iter, 0, &str, -1);
6489   ret = strstr (str, "hidden") ? FALSE : TRUE;
6490   g_free (str);
6491
6492   return ret;
6493 }
6494
6495 static void
6496 specific_bug_657353 (void)
6497 {
6498   GtkListStore *store;
6499   GtkTreeModel *sort_model;
6500   GtkTreeModel *filter_model;
6501   GtkTreeIter iter, iter_a, iter_b, iter_c;
6502   GtkWidget *tree_view;
6503
6504   /* This is a very carefully crafted test case that is triggering the
6505    * situation described in bug 657353.
6506    *
6507    *   GtkListStore acts like EphyCompletionModel
6508    *   GtkTreeModelSort acts like the sort model added in
6509    *                      ephy_location_entry_set_completion.
6510    *   GtkTreeModelFilter acts like the filter model in
6511    *                      GtkEntryCompletion.
6512    */
6513
6514   /* Set up a model that's wrapped in a GtkTreeModelSort.  The first item
6515    * will be hidden.
6516    */
6517   store = gtk_list_store_new (1, G_TYPE_STRING);
6518   gtk_list_store_insert_with_values (store, &iter_b, 0, 0, "BBB hidden", -1);
6519   gtk_list_store_insert_with_values (store, &iter, 1, 0, "EEE", -1);
6520   gtk_list_store_insert_with_values (store, &iter, 2, 0, "DDD", -1);
6521   gtk_list_store_insert_with_values (store, &iter_c, 3, 0, "CCC", -1);
6522
6523   sort_model = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (store));
6524
6525   filter_model = gtk_tree_model_filter_new (sort_model, NULL);
6526   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter_model),
6527                                           specific_bug_657353_visible_func,
6528                                           filter_model, NULL);
6529
6530   tree_view = gtk_tree_view_new_with_model (filter_model);
6531
6532   /* This triggers emission of rows-reordered.  The elt with offset == 0
6533    * is hidden, which used to cause misbehavior.  (The first reference should
6534    * have moved to CCC, which did not happen).
6535    */
6536   gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sort_model),
6537                                         0, GTK_SORT_ASCENDING);
6538
6539   /* By inserting another item that will appear at the first position, a
6540    * reference transfer is done from CCC (which failed to get this reference
6541    * earlier) to AAA.  At this point, the rule
6542    * elt->ref_count >= elt->ext_ref_count is broken for CCC.
6543    */
6544   gtk_list_store_insert_with_values (store, &iter_a, 6, 0, "AAA", -1);
6545
6546   /* When we hide CCC, the references cannot be correctly released, because
6547    * CCC failed to get a reference during rows-reordered.  The faulty condition
6548    * only manifests itself here with MODEL_FILTER_DEBUG disabled (as is usual
6549    * in production).
6550    */
6551   gtk_list_store_set (store, &iter_c, 0, "CCC hidden", -1);
6552
6553   gtk_widget_destroy (tree_view);
6554   g_object_unref (filter_model);
6555   g_object_unref (sort_model);
6556   g_object_unref (store);
6557 }
6558
6559 static void
6560 specific_bug_658696 (void)
6561 {
6562   GtkTreeStore *store;
6563   GtkTreeModel *filter;
6564   GtkTreePath *vroot;
6565   GtkTreeIter iter;
6566
6567   store = create_tree_store (4, TRUE);
6568
6569   vroot = gtk_tree_path_new_from_indices (0, 0, -1);
6570   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), vroot);
6571   gtk_tree_path_free (vroot);
6572
6573   /* This used to cause a crash in gtk_tree_model_filter_check_ancestors() */
6574   gtk_tree_store_append (store, &iter, NULL);
6575 }
6576
6577 /* main */
6578
6579 void
6580 register_filter_model_tests (void)
6581 {
6582   g_test_add ("/TreeModelFilter/self/verify-test-suite",
6583               FilterTest, NULL,
6584               filter_test_setup,
6585               verify_test_suite,
6586               filter_test_teardown);
6587
6588   g_test_add ("/TreeModelFilter/self/verify-test-suite/vroot/depth-1",
6589               FilterTest, gtk_tree_path_new_from_indices (2, -1),
6590               filter_test_setup,
6591               verify_test_suite_vroot,
6592               filter_test_teardown);
6593   g_test_add ("/TreeModelFilter/self/verify-test-suite/vroot/depth-2",
6594               FilterTest, gtk_tree_path_new_from_indices (2, 3, -1),
6595               filter_test_setup,
6596               verify_test_suite_vroot,
6597               filter_test_teardown);
6598
6599
6600   g_test_add ("/TreeModelFilter/filled/hide-root-level",
6601               FilterTest, NULL,
6602               filter_test_setup,
6603               filled_hide_root_level,
6604               filter_test_teardown);
6605   g_test_add ("/TreeModelFilter/filled/hide-child-levels",
6606               FilterTest, NULL,
6607               filter_test_setup,
6608               filled_hide_child_levels,
6609               filter_test_teardown);
6610   g_test_add ("/TreeModelFilter/filled/hide-child-levels/root-expanded",
6611               FilterTest, NULL,
6612               filter_test_setup,
6613               filled_hide_child_levels_root_expanded,
6614               filter_test_teardown);
6615
6616   g_test_add ("/TreeModelFilter/filled/hide-root-level/vroot",
6617               FilterTest, gtk_tree_path_new_from_indices (2, -1),
6618               filter_test_setup,
6619               filled_vroot_hide_root_level,
6620               filter_test_teardown);
6621   g_test_add ("/TreeModelFilter/filled/hide-child-levels/vroot",
6622               FilterTest, gtk_tree_path_new_from_indices (2, -1),
6623               filter_test_setup,
6624               filled_vroot_hide_child_levels,
6625               filter_test_teardown);
6626   g_test_add ("/TreeModelFilter/filled/hide-child-levels/vroot-root-expanded",
6627               FilterTest, gtk_tree_path_new_from_indices (2, -1),
6628               filter_test_setup,
6629               filled_vroot_hide_child_levels_root_expanded,
6630               filter_test_teardown);
6631
6632
6633   g_test_add ("/TreeModelFilter/empty/show-nodes",
6634               FilterTest, NULL,
6635               filter_test_setup_empty,
6636               empty_show_nodes,
6637               filter_test_teardown);
6638   g_test_add ("/TreeModelFilter/empty/show-multiple-nodes",
6639               FilterTest, NULL,
6640               filter_test_setup_empty,
6641               empty_show_multiple_nodes,
6642               filter_test_teardown);
6643
6644   g_test_add ("/TreeModelFilter/empty/show-nodes/vroot",
6645               FilterTest, gtk_tree_path_new_from_indices (2, -1),
6646               filter_test_setup_empty,
6647               empty_vroot_show_nodes,
6648               filter_test_teardown);
6649   g_test_add ("/TreeModelFilter/empty/show-multiple-nodes/vroot",
6650               FilterTest, gtk_tree_path_new_from_indices (2, -1),
6651               filter_test_setup_empty,
6652               empty_vroot_show_multiple_nodes,
6653               filter_test_teardown);
6654
6655
6656   g_test_add ("/TreeModelFilter/unfiltered/hide-single",
6657               FilterTest, NULL,
6658               filter_test_setup_unfiltered,
6659               unfiltered_hide_single,
6660               filter_test_teardown);
6661   g_test_add ("/TreeModelFilter/unfiltered/hide-single/root-expanded",
6662               FilterTest, NULL,
6663               filter_test_setup_unfiltered_root_expanded,
6664               unfiltered_hide_single_root_expanded,
6665               filter_test_teardown);
6666   g_test_add ("/TreeModelFilter/unfiltered/hide-single-child",
6667               FilterTest, NULL,
6668               filter_test_setup_unfiltered,
6669               unfiltered_hide_single_child,
6670               filter_test_teardown);
6671   g_test_add ("/TreeModelFilter/unfiltered/hide-single-child/root-expanded",
6672               FilterTest, NULL,
6673               filter_test_setup_unfiltered_root_expanded,
6674               unfiltered_hide_single_child_root_expanded,
6675               filter_test_teardown);
6676   g_test_add ("/TreeModelFilter/unfiltered/hide-single-multi-level",
6677               FilterTest, NULL,
6678               filter_test_setup_unfiltered,
6679               unfiltered_hide_single_multi_level,
6680               filter_test_teardown);
6681   g_test_add ("/TreeModelFilter/unfiltered/hide-single-multi-level/root-expanded",
6682               FilterTest, NULL,
6683               filter_test_setup_unfiltered_root_expanded,
6684               unfiltered_hide_single_multi_level_root_expanded,
6685               filter_test_teardown);
6686
6687   g_test_add ("/TreeModelFilter/unfiltered/hide-single/vroot",
6688               FilterTest, gtk_tree_path_new_from_indices (2, -1),
6689               filter_test_setup_unfiltered,
6690               unfiltered_vroot_hide_single,
6691               filter_test_teardown);
6692   g_test_add ("/TreeModelFilter/unfiltered/hide-single-child/vroot",
6693               FilterTest, gtk_tree_path_new_from_indices (2, -1),
6694               filter_test_setup_unfiltered,
6695               unfiltered_vroot_hide_single_child,
6696               filter_test_teardown);
6697   g_test_add ("/TreeModelFilter/unfiltered/hide-single-child/vroot/root-expanded",
6698               FilterTest, gtk_tree_path_new_from_indices (2, -1),
6699               filter_test_setup_unfiltered_root_expanded,
6700               unfiltered_vroot_hide_single_child_root_expanded,
6701               filter_test_teardown);
6702   g_test_add ("/TreeModelFilter/unfiltered/hide-single-multi-level/vroot",
6703               FilterTest, gtk_tree_path_new_from_indices (2, -1),
6704               filter_test_setup_unfiltered,
6705               unfiltered_vroot_hide_single_multi_level,
6706               filter_test_teardown);
6707   g_test_add ("/TreeModelFilter/unfiltered/hide-single-multi-level/vroot/root-expanded",
6708               FilterTest, gtk_tree_path_new_from_indices (2, -1),
6709               filter_test_setup_unfiltered_root_expanded,
6710               unfiltered_vroot_hide_single_multi_level_root_expanded,
6711               filter_test_teardown);
6712
6713
6714
6715   g_test_add ("/TreeModelFilter/unfiltered/show-single",
6716               FilterTest, NULL,
6717               filter_test_setup_empty_unfiltered,
6718               unfiltered_show_single,
6719               filter_test_teardown);
6720   g_test_add ("/TreeModelFilter/unfiltered/show-single-child",
6721               FilterTest, NULL,
6722               filter_test_setup_empty_unfiltered,
6723               unfiltered_show_single_child,
6724               filter_test_teardown);
6725   g_test_add ("/TreeModelFilter/unfiltered/show-single-child/root-expanded",
6726               FilterTest, NULL,
6727               filter_test_setup_empty_unfiltered_root_expanded,
6728               unfiltered_show_single_child_root_expanded,
6729               filter_test_teardown);
6730   g_test_add ("/TreeModelFilter/unfiltered/show-single-multi-level",
6731               FilterTest, NULL,
6732               filter_test_setup_empty_unfiltered,
6733               unfiltered_show_single_multi_level,
6734               filter_test_teardown);
6735   g_test_add ("/TreeModelFilter/unfiltered/show-single-multi-level/root-expanded",
6736               FilterTest, NULL,
6737               filter_test_setup_empty_unfiltered_root_expanded,
6738               unfiltered_show_single_multi_level_root_expanded,
6739               filter_test_teardown);
6740
6741   g_test_add ("/TreeModelFilter/unfiltered/show-single/vroot",
6742               FilterTest, gtk_tree_path_new_from_indices (2, -1),
6743               filter_test_setup_empty_unfiltered,
6744               unfiltered_vroot_show_single,
6745               filter_test_teardown);
6746   g_test_add ("/TreeModelFilter/unfiltered/show-single-child/vroot",
6747               FilterTest, gtk_tree_path_new_from_indices (2, -1),
6748               filter_test_setup_empty_unfiltered,
6749               unfiltered_vroot_show_single_child,
6750               filter_test_teardown);
6751   g_test_add ("/TreeModelFilter/unfiltered/show-single-child/vroot/root-expanded",
6752               FilterTest, gtk_tree_path_new_from_indices (2, -1),
6753               filter_test_setup_empty_unfiltered_root_expanded,
6754               unfiltered_vroot_show_single_child_root_expanded,
6755               filter_test_teardown);
6756   g_test_add ("/TreeModelFilter/unfiltered/show-single-multi-level/vroot",
6757               FilterTest, gtk_tree_path_new_from_indices (2, -1),
6758               filter_test_setup_empty_unfiltered,
6759               unfiltered_vroot_show_single_multi_level,
6760               filter_test_teardown);
6761   g_test_add ("/TreeModelFilter/unfiltered/show-single-multi-level/vroot/root-expanded",
6762               FilterTest, gtk_tree_path_new_from_indices (2, -1),
6763               filter_test_setup_empty_unfiltered_root_expanded,
6764               unfiltered_vroot_show_single_multi_level_root_expanded,
6765               filter_test_teardown);
6766
6767
6768   g_test_add ("/TreeModelFilter/unfiltered/rows-reordered/root-level",
6769               FilterTest, NULL,
6770               filter_test_setup_unfiltered,
6771               unfiltered_rows_reordered_root_level,
6772               filter_test_teardown);
6773   g_test_add ("/TreeModelFilter/unfiltered/rows-reordered/child-level",
6774               FilterTest, NULL,
6775               filter_test_setup_unfiltered,
6776               unfiltered_rows_reordered_child_level,
6777               filter_test_teardown);
6778
6779   g_test_add ("/TreeModelFilter/filtered/rows-reordered/root-level/first-hidden",
6780               FilterTest, NULL,
6781               filter_test_setup,
6782               filtered_rows_reordered_root_level_first_hidden,
6783               filter_test_teardown);
6784   g_test_add ("/TreeModelFilter/filtered/rows-reordered/root-level/middle-hidden",
6785               FilterTest, NULL,
6786               filter_test_setup,
6787               filtered_rows_reordered_root_level_middle_hidden,
6788               filter_test_teardown);
6789   g_test_add ("/TreeModelFilter/filtered/rows-reordered/child-level/first-hidden",
6790               FilterTest, NULL,
6791               filter_test_setup,
6792               filtered_rows_reordered_child_level_first_hidden,
6793               filter_test_teardown);
6794   g_test_add ("/TreeModelFilter/filtered/rows-reordered/child-level/middle-hidden",
6795               FilterTest, NULL,
6796               filter_test_setup,
6797               filtered_rows_reordered_child_level_middle_hidden,
6798               filter_test_teardown);
6799   g_test_add ("/TreeModelFilter/filtered/rows-reordered/child-level/4-hidden",
6800               FilterTest, NULL,
6801               filter_test_setup,
6802               filtered_rows_reordered_child_level_4_hidden,
6803               filter_test_teardown);
6804   g_test_add ("/TreeModelFilter/filtered/rows-reordered/child-level/all-hidden",
6805               FilterTest, NULL,
6806               filter_test_setup,
6807               filtered_rows_reordered_child_level_all_hidden,
6808               filter_test_teardown);
6809
6810   /* Inserts in child models after creation of filter model */
6811   g_test_add_func ("/TreeModelFilter/insert/before",
6812                    insert_before);
6813   g_test_add_func ("/TreeModelFilter/insert/child",
6814                    insert_child);
6815
6816   /* Removals from child model after creating of filter model */
6817   g_test_add_func ("/TreeModelFilter/remove/node",
6818                    remove_node);
6819   g_test_add_func ("/TreeModelFilter/remove/node-vroot",
6820                    remove_node_vroot);
6821   g_test_add_func ("/TreeModelFilter/remove/vroot-ancestor",
6822                    remove_vroot_ancestor);
6823
6824   /* Reference counting */
6825   g_test_add_func ("/TreeModelFilter/ref-count/single-level",
6826                    ref_count_single_level);
6827   g_test_add_func ("/TreeModelFilter/ref-count/two-levels",
6828                    ref_count_two_levels);
6829   g_test_add_func ("/TreeModelFilter/ref-count/three-levels",
6830                    ref_count_three_levels);
6831   g_test_add_func ("/TreeModelFilter/ref-count/delete-row",
6832                    ref_count_delete_row);
6833   g_test_add_func ("/TreeModelFilter/ref-count/filter-row/length-1",
6834                    ref_count_filter_row_length_1);
6835   g_test_add_func ("/TreeModelFilter/ref-count/filter-row/length-1-remove-in-root-level",
6836                    ref_count_filter_row_length_1_remove_in_root_level);
6837   g_test_add_func ("/TreeModelFilter/ref-count/filter-row/length-1-remove-in-child-level",
6838                    ref_count_filter_row_length_1_remove_in_child_level);
6839   g_test_add_func ("/TreeModelFilter/ref-count/filter-row/length-gt-1",
6840                    ref_count_filter_row_length_gt_1);
6841   g_test_add_func ("/TreeModelFilter/ref-count/filter-row/length-gt-1-visible-children",
6842                    ref_count_filter_row_length_gt_1_visible_children);
6843   g_test_add_func ("/TreeModelFilter/ref-count/cleanup",
6844                    ref_count_cleanup);
6845   g_test_add_func ("/TreeModelFilter/ref-count/row-ref",
6846                    ref_count_row_ref);
6847
6848   /* Reference counting, transfer of first reference on
6849    * first node in level.  This is a GtkTreeModelFilter-specific
6850    * feature.
6851    */
6852   g_test_add_func ("/TreeModelFilter/ref-count/transfer/root-level/insert",
6853                    ref_count_transfer_root_level_insert);
6854   g_test_add_func ("/TreeModelFilter/ref-count/transfer/root-level/remove",
6855                    ref_count_transfer_root_level_remove);
6856   g_test_add_func ("/TreeModelFilter/ref-count/transfer/root-level/remove/filtered",
6857                    ref_count_transfer_root_level_remove_filtered);
6858   g_test_add_func ("/TreeModelFilter/ref-count/transfer/root-level/reordered",
6859                    ref_count_transfer_root_level_reordered);
6860   g_test_add_func ("/TreeModelFilter/ref-count/transfer/root-level/reordered/filtered",
6861                    ref_count_transfer_root_level_reordered_filtered);
6862   g_test_add_func ("/TreeModelFilter/ref-count/transfer/root-level/filter",
6863                    ref_count_transfer_root_level_filter);
6864   g_test_add_func ("/TreeModelFilter/ref-count/transfer/child-level/insert",
6865                    ref_count_transfer_child_level_insert);
6866   g_test_add_func ("/TreeModelFilter/ref-count/transfer/child-level/remove",
6867                    ref_count_transfer_child_level_remove);
6868   g_test_add_func ("/TreeModelFilter/ref-count/transfer/child-level/remove/filtered",
6869                    ref_count_transfer_child_level_remove_filtered);
6870   g_test_add_func ("/TreeModelFilter/ref-count/transfer/child-level/reordered",
6871                    ref_count_transfer_child_level_reordered);
6872   g_test_add_func ("/TreeModelFilter/ref-count/transfer/child-level/reordered/filtered",
6873                    ref_count_transfer_child_level_reordered_filtered);
6874   g_test_add_func ("/TreeModelFilter/ref-count/transfer/child-level/filter",
6875                    ref_count_transfer_child_level_filter);
6876
6877   g_test_add_func ("/TreeModelFilter/specific/path-dependent-filter",
6878                    specific_path_dependent_filter);
6879   g_test_add_func ("/TreeModelFilter/specific/append-after-collapse",
6880                    specific_append_after_collapse);
6881   g_test_add_func ("/TreeModelFilter/specific/sort-filter-remove-node",
6882                    specific_sort_filter_remove_node);
6883   g_test_add_func ("/TreeModelFilter/specific/sort-filter-remove-root",
6884                    specific_sort_filter_remove_root);
6885   g_test_add_func ("/TreeModelFilter/specific/root-mixed-visibility",
6886                    specific_root_mixed_visibility);
6887   g_test_add_func ("/TreeModelFilter/specific/has-child-filter",
6888                    specific_has_child_filter);
6889   g_test_add_func ("/TreeModelFilter/specific/has-child-filter-on-sort-model",
6890                    specific_has_child_filter_on_sort_model);
6891   g_test_add_func ("/TreeModelFilter/specific/at-least-2-children-filter",
6892                    specific_at_least_2_children_filter);
6893   g_test_add_func ("/TreeModelFilter/specific/at-least-2-children-filter-on-sort-model",
6894                    specific_at_least_2_children_filter_on_sort_model);
6895   g_test_add_func ("/TreeModelFilter/specific/root-has-child-filter",
6896                    specific_root_has_child_filter);
6897   g_test_add_func ("/TreeModelFilter/specific/filter-add-child",
6898                    specific_filter_add_child);
6899   g_test_add_func ("/TreeModelFilter/specific/list-store-clear",
6900                    specific_list_store_clear);
6901   g_test_add_func ("/TreeModelFilter/specific/sort-ref-leaf-and-remove-ancestor",
6902                    specific_sort_ref_leaf_and_remove_ancestor);
6903   g_test_add_func ("/TreeModelFilter/specific/ref-leaf-and-remove-ancestor",
6904                    specific_ref_leaf_and_remove_ancestor);
6905   g_test_add_func ("/TreeModelFilter/specific/virtual-ref-leaf-and-remove-ancestor",
6906                    specific_virtual_ref_leaf_and_remove_ancestor);
6907
6908   g_test_add_func ("/TreeModelFilter/specific/bug-301558",
6909                    specific_bug_301558);
6910   g_test_add_func ("/TreeModelFilter/specific/bug-311955",
6911                    specific_bug_311955);
6912   g_test_add_func ("/TreeModelFilter/specific/bug-311955-clean",
6913                    specific_bug_311955_clean);
6914   g_test_add_func ("/TreeModelFilter/specific/bug-346800",
6915                    specific_bug_346800);
6916   g_test_add_func ("/TreeModelFilter/specific/bug-464173",
6917                    specific_bug_464173);
6918   g_test_add_func ("/TreeModelFilter/specific/bug-540201",
6919                    specific_bug_540201);
6920   g_test_add_func ("/TreeModelFilter/specific/bug-549287",
6921                    specific_bug_549287);
6922   g_test_add_func ("/TreeModelFilter/specific/bug-621076",
6923                    specific_bug_621076);
6924   g_test_add_func ("/TreeModelFilter/specific/bug-657353-related",
6925                    specific_bug_657353_related);
6926   g_test_add_func ("/TreeModelFilter/specific/bug-657353",
6927                    specific_bug_657353);
6928   g_test_add_func ("/TreeModelFilter/specific/bug-658696",
6929                    specific_bug_658696);
6930 }