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