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