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