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