]> Pileus Git - ~andy/gtk/blob - gtk/tests/filtermodel.c
Extend filter model unit test with row-has-child-toggled testers
[~andy/gtk] / gtk / tests / filtermodel.c
1 /* Extensive GtkTreeModelFilter tests.
2  * Copyright (C) 2009  Kristian Rietveld  <kris@gtk.org>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include <gtk/gtk.h>
21
22
23 /*
24  * Model creation
25  */
26
27 #define LEVEL_LENGTH 5
28
29 static void
30 create_tree_store_set_values (GtkTreeStore *store,
31                               GtkTreeIter  *iter,
32                               gboolean      visible)
33 {
34   GtkTreePath *path;
35
36   path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), iter);
37   gtk_tree_store_set (store, iter,
38                       0, gtk_tree_path_to_string (path),
39                       1, visible,
40                       -1);
41   gtk_tree_path_free (path);
42 }
43
44 static void
45 create_tree_store_recurse (int           depth,
46                            GtkTreeStore *store,
47                            GtkTreeIter  *parent,
48                            gboolean      visible)
49 {
50   int i;
51
52   for (i = 0; i < LEVEL_LENGTH; i++)
53     {
54       GtkTreeIter iter;
55
56       gtk_tree_store_insert (store, &iter, parent, i);
57       create_tree_store_set_values (store, &iter, visible);
58
59       if (depth > 0)
60         create_tree_store_recurse (depth - 1, store, &iter, visible);
61     }
62 }
63
64 static GtkTreeStore *
65 create_tree_store (int      depth,
66                    gboolean visible)
67 {
68   GtkTreeStore *store;
69
70   store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
71
72   create_tree_store_recurse (depth, store, NULL, visible);
73
74   return store;
75 }
76
77
78 /*
79  * Fixture
80  */
81
82 typedef struct
83 {
84   GtkWidget *tree_view;
85
86   GtkTreeStore *store;
87   GtkTreeModelFilter *filter;
88 } FilterTest;
89
90 static void
91 filter_test_setup_generic (FilterTest    *fixture,
92                            gconstpointer  test_data,
93                            int            depth,
94                            gboolean       empty,
95                            gboolean       unfiltered)
96 {
97   const GtkTreePath *vroot = test_data;
98   GtkTreeModel *filter;
99
100   fixture->store = create_tree_store (depth, !empty);
101
102   /* Please forgive me for casting const away. */
103   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (fixture->store),
104                                       (GtkTreePath *)vroot);
105   fixture->filter = GTK_TREE_MODEL_FILTER (filter);
106
107   if (!unfiltered)
108     gtk_tree_model_filter_set_visible_column (fixture->filter, 1);
109
110   /* We need a tree view that's listening to get ref counting from that
111    * side.
112    */
113   fixture->tree_view = gtk_tree_view_new_with_model (filter);
114 }
115
116 static void
117 filter_test_setup (FilterTest    *fixture,
118                    gconstpointer  test_data)
119 {
120   filter_test_setup_generic (fixture, test_data, 3, FALSE, FALSE);
121 }
122
123 static void
124 filter_test_setup_empty (FilterTest    *fixture,
125                          gconstpointer  test_data)
126 {
127   filter_test_setup_generic (fixture, test_data, 3, TRUE, FALSE);
128 }
129
130 static void
131 filter_test_setup_unfiltered (FilterTest    *fixture,
132                               gconstpointer  test_data)
133 {
134   filter_test_setup_generic (fixture, test_data, 3, FALSE, TRUE);
135 }
136
137 static void
138 filter_test_setup_empty_unfiltered (FilterTest    *fixture,
139                                     gconstpointer  test_data)
140 {
141   filter_test_setup_generic (fixture, test_data, 3, TRUE, TRUE);
142 }
143
144 static void
145 filter_test_enable_filter (FilterTest *fixture)
146 {
147   gtk_tree_model_filter_set_visible_column (fixture->filter, 1);
148   gtk_tree_model_filter_refilter (fixture->filter);
149 }
150
151 static void
152 filter_test_teardown (FilterTest    *fixture,
153                       gconstpointer  test_data)
154 {
155   g_object_unref (fixture->filter);
156   g_object_unref (fixture->store);
157 }
158
159 /*
160  * Model structure validation
161  */
162
163 static void
164 check_filter_model_recurse (FilterTest  *fixture,
165                             GtkTreePath *store_parent_path,
166                             GtkTreePath *filter_parent_path)
167 {
168   int i;
169   GtkTreeIter store_iter;
170   GtkTreeIter filter_iter;
171   gboolean store_has_next, filter_has_next;
172
173   gtk_tree_path_down (store_parent_path);
174   gtk_tree_path_down (filter_parent_path);
175
176   store_has_next = gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->store),
177                                             &store_iter, store_parent_path);
178   filter_has_next = gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->filter),
179                                              &filter_iter, filter_parent_path);
180
181   for (i = 0; i < LEVEL_LENGTH; i++)
182     {
183       gboolean visible;
184
185       g_return_if_fail (store_has_next == TRUE);
186
187       gtk_tree_model_get (GTK_TREE_MODEL (fixture->store),
188                           &store_iter,
189                           1, &visible,
190                           -1);
191
192       if (visible)
193         {
194           GtkTreePath *tmp;
195           gchar *filter_str, *store_str;
196
197           g_return_if_fail (filter_has_next == TRUE);
198
199           /* Verify path */
200           tmp = gtk_tree_model_get_path (GTK_TREE_MODEL (fixture->filter),
201                                          &filter_iter);
202           g_return_if_fail (gtk_tree_path_compare (tmp, filter_parent_path) == 0);
203
204           /* Verify model content */
205           gtk_tree_model_get (GTK_TREE_MODEL (fixture->store),
206                               &store_iter,
207                               0, &store_str,
208                               -1);
209           gtk_tree_model_get (GTK_TREE_MODEL (fixture->filter),
210                               &filter_iter,
211                               0, &filter_str,
212                               -1);
213
214           g_return_if_fail (g_strcmp0 (store_str, filter_str) == 0);
215
216           g_free (store_str);
217           g_free (filter_str);
218
219           if (gtk_tree_model_iter_has_child (GTK_TREE_MODEL (fixture->filter),
220                                              &filter_iter))
221             {
222               g_return_if_fail (gtk_tree_model_iter_has_child (GTK_TREE_MODEL (fixture->store), &store_iter));
223
224               check_filter_model_recurse (fixture,
225                                           gtk_tree_path_copy (store_parent_path),
226                                           tmp);
227             }
228
229           gtk_tree_path_next (filter_parent_path);
230           filter_has_next = gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->filter), &filter_iter);
231         }
232
233       gtk_tree_path_next (store_parent_path);
234       store_has_next = gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &store_iter);
235     }
236
237   /* Both models should have no more content! */
238   g_return_if_fail (store_has_next == FALSE);
239   g_return_if_fail (filter_has_next == FALSE);
240
241   gtk_tree_path_free (store_parent_path);
242   gtk_tree_path_free (filter_parent_path);
243 }
244
245 static void
246 check_filter_model (FilterTest *fixture)
247 {
248   GtkTreePath *path;
249
250   path = gtk_tree_path_new ();
251
252   check_filter_model_recurse (fixture, path, gtk_tree_path_copy (path));
253 }
254
255 static void
256 check_filter_model_with_root (FilterTest  *fixture,
257                               GtkTreePath *path)
258 {
259   check_filter_model_recurse (fixture,
260                               gtk_tree_path_copy (path),
261                               gtk_tree_path_new ());
262 }
263
264 /* Helpers */
265
266 static void
267 check_level_length (GtkTreeModelFilter *filter,
268                     const gchar        *level,
269                     const int           length)
270 {
271   if (!level)
272     {
273       int l = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (filter), NULL);
274       g_return_if_fail (l == length);
275     }
276   else
277     {
278       int l;
279       gboolean retrieved_iter = FALSE;
280       GtkTreeIter iter;
281
282       retrieved_iter = gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (filter),
283                                                             &iter, level);
284       g_return_if_fail (retrieved_iter);
285       l = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (filter), &iter);
286       g_return_if_fail (l == length);
287     }
288 }
289
290 static void
291 set_path_visibility (FilterTest  *fixture,
292                      const gchar *path,
293                      gboolean     visible)
294 {
295   GtkTreeIter store_iter;
296
297   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
298                                        &store_iter, path);
299   gtk_tree_store_set (fixture->store, &store_iter,
300                       1, visible,
301                       -1);
302 }
303
304 static void
305 insert_path_with_visibility (FilterTest  *fixture,
306                              const gchar *path_string,
307                              gboolean     visible)
308 {
309   int position;
310   GtkTreePath *path;
311   GtkTreeIter parent, iter;
312
313   path = gtk_tree_path_new_from_string (path_string);
314   position = gtk_tree_path_get_indices (path)[gtk_tree_path_get_depth (path)];
315   gtk_tree_path_up (path);
316
317   if (gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->store), &parent, path))
318     {
319       gtk_tree_store_insert (fixture->store, &iter, &parent, position);
320       create_tree_store_set_values (fixture->store, &iter, visible);
321     }
322   gtk_tree_path_free (path);
323 }
324
325 /*
326  * The actual tests.
327  */
328
329 static void
330 verify_test_suite (FilterTest    *fixture,
331                    gconstpointer  user_data)
332 {
333   check_filter_model (fixture);
334 }
335
336 static void
337 verify_test_suite_vroot (FilterTest    *fixture,
338                          gconstpointer  user_data)
339 {
340   check_filter_model_with_root (fixture, (GtkTreePath *)user_data);
341 }
342
343
344 static void
345 filled_hide_root_level (FilterTest    *fixture,
346                         gconstpointer  user_data)
347 {
348   set_path_visibility (fixture, "2", FALSE);
349   check_filter_model (fixture);
350   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 1);
351
352   set_path_visibility (fixture, "0", FALSE);
353   check_filter_model (fixture);
354   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 2);
355
356   set_path_visibility (fixture, "4", FALSE);
357   check_filter_model (fixture);
358   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 3);
359
360
361   /* Hide remaining */
362   set_path_visibility (fixture, "1", FALSE);
363   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 4);
364
365   set_path_visibility (fixture, "3", FALSE);
366   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 5);
367
368   check_filter_model (fixture);
369
370   /* Show some */
371   set_path_visibility (fixture, "1", TRUE);
372   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 4);
373
374   set_path_visibility (fixture, "3", TRUE);
375   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 3);
376
377   check_filter_model (fixture);
378 }
379
380 static void
381 filled_hide_child_levels (FilterTest    *fixture,
382                           gconstpointer  user_data)
383 {
384   set_path_visibility (fixture, "0:2", FALSE);
385   check_filter_model (fixture);
386   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
387   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 1);
388
389   set_path_visibility (fixture, "0:4", FALSE);
390   check_filter_model (fixture);
391   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
392   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
393
394   set_path_visibility (fixture, "0:4:3", FALSE);
395   check_filter_model (fixture);
396   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
397   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
398
399   set_path_visibility (fixture, "0:4:0", FALSE);
400   set_path_visibility (fixture, "0:4:1", FALSE);
401   set_path_visibility (fixture, "0:4:2", FALSE);
402   set_path_visibility (fixture, "0:4:4", FALSE);
403   check_filter_model (fixture);
404   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
405   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
406
407   set_path_visibility (fixture, "0:4", TRUE);
408   /* Since "0:2" is hidden, "0:4" must be "0:3" in the filter model */
409   check_filter_model (fixture);
410   check_level_length (fixture->filter, "0:3", 0);
411
412   set_path_visibility (fixture, "0:2", TRUE);
413   check_filter_model (fixture);
414   check_level_length (fixture->filter, "0:2", LEVEL_LENGTH);
415   check_level_length (fixture->filter, "0:3", LEVEL_LENGTH);
416   check_level_length (fixture->filter, "0:4", 0);
417
418   set_path_visibility (fixture, "0:4:2", TRUE);
419   set_path_visibility (fixture, "0:4:4", TRUE);
420   check_level_length (fixture->filter, "0:4", 2);
421 }
422
423
424 static void
425 filled_vroot_hide_root_level (FilterTest    *fixture,
426                               gconstpointer  user_data)
427 {
428   GtkTreePath *path = (GtkTreePath *)user_data;
429
430   /* These changes do not affect the filter's root level */
431   set_path_visibility (fixture, "0", FALSE);
432   check_filter_model_with_root (fixture, path);
433   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
434   check_level_length (fixture->filter, "0", LEVEL_LENGTH);
435
436   set_path_visibility (fixture, "4", FALSE);
437   check_filter_model_with_root (fixture, path);
438   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
439   check_level_length (fixture->filter, "0", LEVEL_LENGTH);
440
441   /* Even though we set the virtual root parent node to FALSE,
442    * the virtual root contents remain.
443    */
444   set_path_visibility (fixture, "2", FALSE);
445   check_filter_model_with_root (fixture, path);
446   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
447   check_level_length (fixture->filter, "0", LEVEL_LENGTH);
448
449   /* No change */
450   set_path_visibility (fixture, "1", FALSE);
451   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
452   check_level_length (fixture->filter, "0", LEVEL_LENGTH);
453
454   set_path_visibility (fixture, "3", FALSE);
455   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
456   check_level_length (fixture->filter, "0", LEVEL_LENGTH);
457
458   check_filter_model_with_root (fixture, path);
459
460   /* Show some */
461   set_path_visibility (fixture, "2", TRUE);
462   check_filter_model_with_root (fixture, path);
463   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
464   check_level_length (fixture->filter, "0", LEVEL_LENGTH);
465
466   set_path_visibility (fixture, "1", TRUE);
467   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
468   check_level_length (fixture->filter, "0", LEVEL_LENGTH);
469
470   set_path_visibility (fixture, "3", TRUE);
471   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
472   check_level_length (fixture->filter, "0", LEVEL_LENGTH);
473
474   check_filter_model_with_root (fixture, path);
475
476   /* Now test changes in the virtual root level */
477   set_path_visibility (fixture, "2:2", FALSE);
478   check_filter_model_with_root (fixture, path);
479   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 1);
480
481   set_path_visibility (fixture, "2:4", FALSE);
482   check_filter_model_with_root (fixture, path);
483   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 2);
484
485   set_path_visibility (fixture, "1:4", FALSE);
486   check_filter_model_with_root (fixture, path);
487   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 2);
488
489   set_path_visibility (fixture, "2:4", TRUE);
490   check_filter_model_with_root (fixture, path);
491   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 1);
492
493   set_path_visibility (fixture, "2", FALSE);
494   check_filter_model_with_root (fixture, path);
495   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 1);
496
497   set_path_visibility (fixture, "2:0", FALSE);
498   set_path_visibility (fixture, "2:1", FALSE);
499   set_path_visibility (fixture, "2:2", FALSE);
500   set_path_visibility (fixture, "2:3", FALSE);
501   set_path_visibility (fixture, "2:4", FALSE);
502   check_filter_model_with_root (fixture, path);
503   check_level_length (fixture->filter, NULL, 0);
504
505   set_path_visibility (fixture, "2", TRUE);
506   check_filter_model_with_root (fixture, path);
507   check_level_length (fixture->filter, NULL, 0);
508
509   set_path_visibility (fixture, "1:4", FALSE);
510   check_filter_model_with_root (fixture, path);
511   check_level_length (fixture->filter, NULL, 0);
512
513   set_path_visibility (fixture, "2:4", TRUE);
514   check_filter_model_with_root (fixture, path);
515   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 4);
516
517   set_path_visibility (fixture, "2:4", FALSE);
518   check_filter_model_with_root (fixture, path);
519   check_level_length (fixture->filter, NULL, 0);
520
521   set_path_visibility (fixture, "2", FALSE);
522   check_filter_model_with_root (fixture, path);
523   check_level_length (fixture->filter, NULL, 0);
524
525   set_path_visibility (fixture, "2:0", TRUE);
526   set_path_visibility (fixture, "2:1", TRUE);
527   set_path_visibility (fixture, "2:2", TRUE);
528   check_filter_model_with_root (fixture, path);
529   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 2);
530
531   set_path_visibility (fixture, "2", TRUE);
532   check_filter_model_with_root (fixture, path);
533   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 2);
534 }
535
536 static void
537 filled_vroot_hide_child_levels (FilterTest    *fixture,
538                                 gconstpointer  user_data)
539 {
540   GtkTreePath *path = (GtkTreePath *)user_data;
541
542   set_path_visibility (fixture, "2:0:2", FALSE);
543   check_filter_model_with_root (fixture, path);
544   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
545   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 1);
546
547   set_path_visibility (fixture, "2:0:4", FALSE);
548   check_filter_model_with_root (fixture, path);
549   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
550   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
551
552   set_path_visibility (fixture, "2:0:4:3", FALSE);
553   check_filter_model_with_root (fixture, path);
554   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
555   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
556
557   set_path_visibility (fixture, "2:0:4:0", FALSE);
558   set_path_visibility (fixture, "2:0:4:1", FALSE);
559   set_path_visibility (fixture, "2:0:4:2", FALSE);
560   set_path_visibility (fixture, "2:0:4:4", FALSE);
561   check_filter_model_with_root (fixture, path);
562   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
563   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
564
565   set_path_visibility (fixture, "2:0:4", TRUE);
566   /* Since "0:2" is hidden, "0:4" must be "0:3" in the filter model */
567   check_filter_model_with_root (fixture, path);
568   check_level_length (fixture->filter, "0:3", 0);
569
570   set_path_visibility (fixture, "2:0:2", TRUE);
571   check_filter_model_with_root (fixture, path);
572   check_level_length (fixture->filter, "0:2", LEVEL_LENGTH);
573   check_level_length (fixture->filter, "0:3", LEVEL_LENGTH);
574   check_level_length (fixture->filter, "0:4", 0);
575
576   set_path_visibility (fixture, "2:0:4:2", TRUE);
577   set_path_visibility (fixture, "2:0:4:4", TRUE);
578   check_level_length (fixture->filter, "0:4", 2);
579 }
580
581
582 static void
583 empty_show_nodes (FilterTest    *fixture,
584                   gconstpointer  user_data)
585 {
586   check_filter_model (fixture);
587   check_level_length (fixture->filter, NULL, 0);
588
589   set_path_visibility (fixture, "3", TRUE);
590   check_filter_model (fixture);
591   check_level_length (fixture->filter, NULL, 1);
592   check_level_length (fixture->filter, "0", 0);
593
594   set_path_visibility (fixture, "3:2:2", TRUE);
595   check_filter_model (fixture);
596   check_level_length (fixture->filter, NULL, 1);
597   check_level_length (fixture->filter, "0", 0);
598
599   set_path_visibility (fixture, "3:2", TRUE);
600   check_filter_model (fixture);
601   check_level_length (fixture->filter, NULL, 1);
602   check_level_length (fixture->filter, "0", 1);
603   check_level_length (fixture->filter, "0:0", 1);
604   check_level_length (fixture->filter, "0:0:0", 0);
605
606   set_path_visibility (fixture, "3", FALSE);
607   check_filter_model (fixture);
608   check_level_length (fixture->filter, NULL, 0);
609
610   set_path_visibility (fixture, "3:2:1", TRUE);
611   set_path_visibility (fixture, "3", TRUE);
612   check_filter_model (fixture);
613   check_level_length (fixture->filter, NULL, 1);
614   check_level_length (fixture->filter, "0", 1);
615   check_level_length (fixture->filter, "0:0", 2);
616   check_level_length (fixture->filter, "0:0:0", 0);
617 }
618
619 static void
620 empty_vroot_show_nodes (FilterTest    *fixture,
621                         gconstpointer  user_data)
622 {
623   GtkTreePath *path = (GtkTreePath *)user_data;
624
625   check_filter_model_with_root (fixture, path);
626   check_level_length (fixture->filter, NULL, 0);
627
628   set_path_visibility (fixture, "2", TRUE);
629   check_filter_model_with_root (fixture, path);
630   check_level_length (fixture->filter, NULL, 0);
631
632   set_path_visibility (fixture, "2:2:2", TRUE);
633   check_filter_model_with_root (fixture, path);
634   check_level_length (fixture->filter, NULL, 0);
635
636   set_path_visibility (fixture, "2:2", TRUE);
637   check_filter_model_with_root (fixture, path);
638   check_level_length (fixture->filter, NULL, 1);
639   check_level_length (fixture->filter, "0", 1);
640   check_level_length (fixture->filter, "0:0", 0);
641
642   set_path_visibility (fixture, "3", TRUE);
643   check_filter_model_with_root (fixture, path);
644   check_level_length (fixture->filter, NULL, 1);
645
646   set_path_visibility (fixture, "2:2", FALSE);
647   check_filter_model_with_root (fixture, path);
648   check_level_length (fixture->filter, NULL, 0);
649
650   set_path_visibility (fixture, "2:2:1", TRUE);
651   set_path_visibility (fixture, "2:2", TRUE);
652   check_filter_model_with_root (fixture, path);
653   check_level_length (fixture->filter, NULL, 1);
654   check_level_length (fixture->filter, "0", 2);
655   check_level_length (fixture->filter, "0:1", 0);
656 }
657
658
659 static void
660 unfiltered_hide_single (FilterTest    *fixture,
661                         gconstpointer  user_data)
662
663 {
664   set_path_visibility (fixture, "2", FALSE);
665
666   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
667
668   filter_test_enable_filter (fixture);
669
670   check_filter_model (fixture);
671   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 1);
672 }
673
674 static void
675 unfiltered_hide_single_child (FilterTest    *fixture,
676                               gconstpointer  user_data)
677
678 {
679   set_path_visibility (fixture, "2:2", FALSE);
680
681   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
682   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
683
684   filter_test_enable_filter (fixture);
685
686   check_filter_model (fixture);
687   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
688   check_level_length (fixture->filter, "2", LEVEL_LENGTH - 1);
689 }
690
691 static void
692 unfiltered_hide_single_multi_level (FilterTest    *fixture,
693                                     gconstpointer  user_data)
694
695 {
696   set_path_visibility (fixture, "2:2:2", FALSE);
697   set_path_visibility (fixture, "2:2", FALSE);
698
699   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
700   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
701   check_level_length (fixture->filter, "2:2", LEVEL_LENGTH);
702
703   filter_test_enable_filter (fixture);
704
705   check_filter_model (fixture);
706   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
707   check_level_length (fixture->filter, "2", LEVEL_LENGTH - 1);
708
709   set_path_visibility (fixture, "2:2", TRUE);
710
711   check_filter_model (fixture);
712   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
713   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
714   check_level_length (fixture->filter, "2:2", LEVEL_LENGTH - 1);
715 }
716
717
718 static void
719 unfiltered_vroot_hide_single (FilterTest    *fixture,
720                               gconstpointer  user_data)
721
722 {
723   GtkTreePath *path = (GtkTreePath *)user_data;
724
725   set_path_visibility (fixture, "2:2", FALSE);
726
727   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
728
729   filter_test_enable_filter (fixture);
730
731   check_filter_model_with_root (fixture, path);
732   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 1);
733 }
734
735 static void
736 unfiltered_vroot_hide_single_child (FilterTest    *fixture,
737                                     gconstpointer  user_data)
738
739 {
740   GtkTreePath *path = (GtkTreePath *)user_data;
741
742   set_path_visibility (fixture, "2:2:2", FALSE);
743
744   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
745   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
746
747   filter_test_enable_filter (fixture);
748
749   check_filter_model_with_root (fixture, path);
750   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
751   check_level_length (fixture->filter, "2", LEVEL_LENGTH - 1);
752 }
753
754 static void
755 unfiltered_vroot_hide_single_multi_level (FilterTest    *fixture,
756                                           gconstpointer  user_data)
757
758 {
759   GtkTreePath *path = (GtkTreePath *)user_data;
760
761   set_path_visibility (fixture, "2:2:2:2", FALSE);
762   set_path_visibility (fixture, "2:2:2", FALSE);
763
764   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
765   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
766   check_level_length (fixture->filter, "2:2", LEVEL_LENGTH);
767
768   filter_test_enable_filter (fixture);
769
770   check_filter_model_with_root (fixture, path);
771   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
772   check_level_length (fixture->filter, "2", LEVEL_LENGTH - 1);
773
774   set_path_visibility (fixture, "2:2:2", TRUE);
775
776   check_filter_model_with_root (fixture, path);
777   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
778   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
779   check_level_length (fixture->filter, "2:2", LEVEL_LENGTH - 1);
780 }
781
782
783
784 static void
785 unfiltered_show_single (FilterTest    *fixture,
786                         gconstpointer  user_data)
787
788 {
789   set_path_visibility (fixture, "2", TRUE);
790
791   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
792
793   filter_test_enable_filter (fixture);
794
795   check_filter_model (fixture);
796   check_level_length (fixture->filter, NULL, 1);
797 }
798
799 static void
800 unfiltered_show_single_child (FilterTest    *fixture,
801                               gconstpointer  user_data)
802
803 {
804   set_path_visibility (fixture, "2:2", TRUE);
805
806   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
807   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
808
809   filter_test_enable_filter (fixture);
810
811   check_filter_model (fixture);
812   check_level_length (fixture->filter, NULL, 0);
813
814   /* From here we are filtered, "2" in the real model is "0" in the filter
815    * model.
816    */
817   set_path_visibility (fixture, "2", TRUE);
818   check_level_length (fixture->filter, NULL, 1);
819   check_level_length (fixture->filter, "0", 1);
820 }
821
822 static void
823 unfiltered_show_single_multi_level (FilterTest    *fixture,
824                                     gconstpointer  user_data)
825
826 {
827   set_path_visibility (fixture, "2:2:2", TRUE);
828   set_path_visibility (fixture, "2:2", TRUE);
829
830   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
831   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
832   check_level_length (fixture->filter, "2:2", LEVEL_LENGTH);
833
834   filter_test_enable_filter (fixture);
835
836   check_filter_model (fixture);
837   check_level_length (fixture->filter, NULL, 0);
838
839   /* From here we are filtered, "2" in the real model is "0" in the filter
840    * model.
841    */
842   set_path_visibility (fixture, "2", TRUE);
843   check_filter_model (fixture);
844   check_level_length (fixture->filter, NULL, 1);
845   check_level_length (fixture->filter, "0", 1);
846   check_level_length (fixture->filter, "0:0", 1);
847 }
848
849
850 static void
851 unfiltered_vroot_show_single (FilterTest    *fixture,
852                               gconstpointer  user_data)
853
854 {
855   GtkTreePath *path = (GtkTreePath *)user_data;
856
857   set_path_visibility (fixture, "2:2", TRUE);
858
859   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
860
861   filter_test_enable_filter (fixture);
862
863   check_filter_model_with_root (fixture, path);
864   check_level_length (fixture->filter, NULL, 1);
865 }
866
867 static void
868 unfiltered_vroot_show_single_child (FilterTest    *fixture,
869                                     gconstpointer  user_data)
870
871 {
872   GtkTreePath *path = (GtkTreePath *)user_data;
873
874   set_path_visibility (fixture, "2:2:2", TRUE);
875
876   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
877   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
878
879   filter_test_enable_filter (fixture);
880
881   check_filter_model_with_root (fixture, path);
882   check_level_length (fixture->filter, NULL, 0);
883
884   /* From here we are filtered, "2" in the real model is "0" in the filter
885    * model.
886    */
887   set_path_visibility (fixture, "2:2", TRUE);
888   check_level_length (fixture->filter, NULL, 1);
889   check_level_length (fixture->filter, "0", 1);
890 }
891
892 static void
893 unfiltered_vroot_show_single_multi_level (FilterTest    *fixture,
894                                           gconstpointer  user_data)
895
896 {
897   GtkTreePath *path = (GtkTreePath *)user_data;
898
899   set_path_visibility (fixture, "2:2:2:2", TRUE);
900   set_path_visibility (fixture, "2:2:2", TRUE);
901
902   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
903   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
904   check_level_length (fixture->filter, "2:2", LEVEL_LENGTH);
905
906   filter_test_enable_filter (fixture);
907
908   check_filter_model_with_root (fixture, path);
909   check_level_length (fixture->filter, NULL, 0);
910
911   /* From here we are filtered, "2" in the real model is "0" in the filter
912    * model.
913    */
914   set_path_visibility (fixture, "2:2", TRUE);
915   check_filter_model_with_root (fixture, path);
916   check_level_length (fixture->filter, NULL, 1);
917   check_level_length (fixture->filter, "0", 1);
918   check_level_length (fixture->filter, "0:0", 1);
919 }
920
921
922 static gboolean
923 specific_path_dependent_filter_func (GtkTreeModel *model,
924                                      GtkTreeIter  *iter,
925                                      gpointer      data)
926 {
927   GtkTreePath *path;
928
929   path = gtk_tree_model_get_path (model, iter);
930   if (gtk_tree_path_get_indices (path)[0] < 4)
931     return FALSE;
932
933   return TRUE;
934 }
935
936 static void
937 specific_path_dependent_filter (void)
938 {
939   int i;
940   GtkTreeIter iter;
941   GtkListStore *list;
942   GtkTreeModel *sort;
943   GtkTreeModel *filter;
944
945   list = gtk_list_store_new (1, G_TYPE_INT);
946   gtk_list_store_insert_with_values (list, &iter, 0, 0, 1, -1);
947   gtk_list_store_insert_with_values (list, &iter, 1, 0, 2, -1);
948   gtk_list_store_insert_with_values (list, &iter, 2, 0, 3, -1);
949   gtk_list_store_insert_with_values (list, &iter, 3, 0, 4, -1);
950   gtk_list_store_insert_with_values (list, &iter, 4, 0, 5, -1);
951   gtk_list_store_insert_with_values (list, &iter, 5, 0, 6, -1);
952   gtk_list_store_insert_with_values (list, &iter, 6, 0, 7, -1);
953   gtk_list_store_insert_with_values (list, &iter, 7, 0, 8, -1);
954
955   sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (list));
956   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (sort), NULL);
957   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
958                                           specific_path_dependent_filter_func,
959                                           NULL, NULL);
960
961   gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sort), 0,
962                                         GTK_SORT_DESCENDING);
963
964   for (i = 0; i < 4; i++)
965     {
966       if (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (list), &iter,
967                                          NULL, 1))
968         gtk_list_store_remove (list, &iter);
969
970       if (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (list), &iter,
971                                          NULL, 2))
972         gtk_list_store_remove (list, &iter);
973     }
974 }
975
976
977 static gboolean
978 specific_append_after_collapse_visible_func (GtkTreeModel *model,
979                                              GtkTreeIter  *iter,
980                                              gpointer      data)
981 {
982   gint number;
983   gboolean hide_negative_numbers;
984
985   gtk_tree_model_get (model, iter, 1, &number, -1);
986   hide_negative_numbers = GPOINTER_TO_INT (g_object_get_data (data, "private-hide-negative-numbers"));
987
988   return (number >= 0 || !hide_negative_numbers);
989 }
990
991 static void
992 specific_append_after_collapse (void)
993 {
994   /* This test is based on one of the test cases I found in my
995    * old test cases directory.  I unfortunately do not have a record
996    * from who this test case originated.  -Kris.
997    *
998    * General idea:
999    * - Construct tree.
1000    * - Show tree, expand, collapse.
1001    * - Add a row.
1002    */
1003
1004   GtkTreeIter iter;
1005   GtkTreeIter child_iter;
1006   GtkTreeIter child_iter2;
1007   GtkTreePath *append_path;
1008   GtkTreeStore *store;
1009   GtkTreeModel *filter;
1010   GtkTreeModel *sort;
1011
1012   GtkWidget *window;
1013   GtkWidget *tree_view;
1014
1015   store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_INT);
1016
1017   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
1018   g_object_set_data (G_OBJECT (filter), "private-hide-negative-numbers",
1019                      GINT_TO_POINTER (FALSE));
1020   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
1021                                           specific_append_after_collapse_visible_func,
1022                                           filter, NULL);
1023
1024   sort = gtk_tree_model_sort_new_with_model (filter);
1025
1026   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1027   tree_view = gtk_tree_view_new_with_model (sort);
1028   gtk_container_add (GTK_CONTAINER (window), tree_view);
1029   gtk_widget_realize (tree_view);
1030
1031   while (gtk_events_pending ())
1032     gtk_main_iteration ();
1033
1034   gtk_tree_store_prepend (store, &iter, NULL);
1035   gtk_tree_store_set (store, &iter,
1036                       0, "hallo", 1, 1, -1);
1037
1038   gtk_tree_store_append (store, &child_iter, &iter);
1039   gtk_tree_store_set (store, &child_iter,
1040                       0, "toemaar", 1, 1, -1);
1041
1042   gtk_tree_store_append (store, &child_iter2, &child_iter);
1043   gtk_tree_store_set (store, &child_iter2,
1044                       0, "very deep", 1, 1, -1);
1045
1046   append_path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &child_iter2);
1047
1048   gtk_tree_store_append (store, &child_iter, &iter);
1049   gtk_tree_store_set (store, &child_iter,
1050                       0, "sja", 1, 1, -1);
1051
1052   gtk_tree_store_append (store, &child_iter, &iter);
1053   gtk_tree_store_set (store, &child_iter,
1054                       0, "some word", 1, -1, -1);
1055
1056   /* Expand and collapse the tree */
1057   gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
1058   while (gtk_events_pending ())
1059     gtk_main_iteration ();
1060
1061   gtk_tree_view_collapse_all (GTK_TREE_VIEW (tree_view));
1062   while (gtk_events_pending ())
1063     gtk_main_iteration ();
1064
1065   /* Add another it */
1066   g_object_set_data (G_OBJECT (filter), "private-hide-negative-numbers",
1067                      GINT_TO_POINTER (TRUE));
1068
1069   if (gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, append_path))
1070     {
1071       gtk_tree_store_append (store, &child_iter, &iter);
1072       gtk_tree_store_set (store, &child_iter,
1073                           0, "new new new !!", 1, 1, -1);
1074     }
1075   gtk_tree_path_free (append_path);
1076
1077   /* Expand */
1078   gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
1079   while (gtk_events_pending ())
1080     gtk_main_iteration ();
1081 }
1082
1083
1084 static gint
1085 specific_sort_filter_remove_node_compare_func (GtkTreeModel  *model,
1086                                                GtkTreeIter   *iter1,
1087                                                GtkTreeIter   *iter2,
1088                                                gpointer       data)
1089 {
1090   return -1;
1091 }
1092
1093 static gboolean
1094 specific_sort_filter_remove_node_visible_func (GtkTreeModel  *model,
1095                                                GtkTreeIter   *iter,
1096                                                gpointer       data)
1097 {
1098   char *item = NULL;
1099
1100   /* Do reference the model */
1101   gtk_tree_model_get (model, iter, 0, &item, -1);
1102   g_free (item);
1103
1104   return FALSE;
1105 }
1106
1107 static void
1108 specific_sort_filter_remove_node (void)
1109 {
1110   /* This test is based on one of the test cases I found in my
1111    * old test cases directory.  I unfortunately do not have a record
1112    * from who this test case originated.  -Kris.
1113    *
1114    * General idea:
1115    *  - Create tree store, sort, filter models.  The sort model has
1116    *    a default sort func that is enabled, filter model a visible func
1117    *    that defaults to returning FALSE.
1118    *  - Remove a node from the tree store.
1119    */
1120
1121   GtkTreeIter iter;
1122   GtkTreeStore *store;
1123   GtkTreeModel *filter;
1124   GtkTreeModel *sort;
1125
1126   GtkWidget *window;
1127   GtkWidget *tree_view;
1128
1129   store = gtk_tree_store_new (1, G_TYPE_STRING);
1130   gtk_tree_store_append (store, &iter, NULL);
1131   gtk_tree_store_set (store, &iter, 0, "Hello1", -1);
1132
1133   gtk_tree_store_append (store, &iter, NULL);
1134   gtk_tree_store_set (store, &iter, 0, "Hello2", -1);
1135
1136   sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (store));
1137   gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (sort),
1138                                            specific_sort_filter_remove_node_compare_func, NULL, NULL);
1139
1140   filter = gtk_tree_model_filter_new (sort, NULL);
1141   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
1142                                           specific_sort_filter_remove_node_visible_func,
1143                                           filter, NULL);
1144
1145
1146   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1147   tree_view = gtk_tree_view_new_with_model (filter);
1148   gtk_container_add (GTK_CONTAINER (window), tree_view);
1149   gtk_widget_realize (tree_view);
1150
1151   while (gtk_events_pending ())
1152     gtk_main_iteration ();
1153
1154   /* Remove a node */
1155   gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter);
1156   gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter);
1157   gtk_tree_store_remove (store, &iter);
1158
1159   while (gtk_events_pending ())
1160     gtk_main_iteration ();
1161 }
1162
1163
1164 static void
1165 specific_sort_filter_remove_root (void)
1166 {
1167   /* This test is based on one of the test cases I found in my
1168    * old test cases directory.  I unfortunately do not have a record
1169    * from who this test case originated.  -Kris.
1170    */
1171
1172   GtkTreeModel *model, *sort, *filter;
1173   GtkTreeIter root, mid, leaf;
1174   GtkTreePath *path;
1175
1176   model = GTK_TREE_MODEL (gtk_tree_store_new (1, G_TYPE_INT));
1177   gtk_tree_store_append (GTK_TREE_STORE (model), &root, NULL);
1178   gtk_tree_store_append (GTK_TREE_STORE (model), &mid, &root);
1179   gtk_tree_store_append (GTK_TREE_STORE (model), &leaf, &mid);
1180
1181   path = gtk_tree_model_get_path (model, &mid);
1182
1183   sort = gtk_tree_model_sort_new_with_model (model);
1184   filter = gtk_tree_model_filter_new (sort, path);
1185
1186   gtk_tree_store_remove (GTK_TREE_STORE (model), &root);
1187
1188   g_object_unref (filter);
1189   g_object_unref (sort);
1190   g_object_unref (model);
1191 }
1192
1193
1194 static void
1195 specific_root_mixed_visibility (void)
1196 {
1197   int i;
1198   GtkTreeModel *filter;
1199   /* A bit nasty, apologies */
1200   FilterTest fixture;
1201
1202   fixture.store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
1203
1204   for (i = 0; i < LEVEL_LENGTH; i++)
1205     {
1206       GtkTreeIter iter;
1207
1208       gtk_tree_store_insert (fixture.store, &iter, NULL, i);
1209       if (i % 2 == 0)
1210         create_tree_store_set_values (fixture.store, &iter, TRUE);
1211       else
1212         create_tree_store_set_values (fixture.store, &iter, FALSE);
1213     }
1214
1215   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (fixture.store), NULL);
1216   fixture.filter = GTK_TREE_MODEL_FILTER (filter);
1217
1218   gtk_tree_model_filter_set_visible_column (fixture.filter, 1);
1219
1220   /* In order to trigger the potential bug, we should not access
1221    * the filter model here (so don't call the check functions).
1222    */
1223
1224   /* Change visibility of an odd row to TRUE */
1225   set_path_visibility (&fixture, "3", TRUE);
1226   check_filter_model (&fixture);
1227   check_level_length (fixture.filter, NULL, 4);
1228 }
1229
1230
1231
1232 static gboolean
1233 specific_has_child_filter_filter_func (GtkTreeModel *model,
1234                                        GtkTreeIter  *iter,
1235                                        gpointer      data)
1236 {
1237   return gtk_tree_model_iter_has_child (model, iter);
1238 }
1239
1240 static void
1241 specific_has_child_filter (void)
1242 {
1243   GtkTreeModel *filter;
1244   GtkTreeIter iter, root;
1245   /* A bit nasty, apologies */
1246   FilterTest fixture;
1247
1248   fixture.store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
1249   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (fixture.store), NULL);
1250   fixture.filter = GTK_TREE_MODEL_FILTER (filter);
1251
1252   /* We will filter on parent state using a filter function.  We will
1253    * manually keep the boolean column in sync, so that we can use
1254    * check_filter_model() to check the consistency of the model.
1255    */
1256   /* FIXME: We need a check_filter_model() that is not tied to LEVEL_LENGTH
1257    * to be able to check the structure here.  We keep the calls to
1258    * check_filter_model() commented out until then.
1259    */
1260   gtk_tree_model_filter_set_visible_func (fixture.filter,
1261                                           specific_has_child_filter_filter_func,
1262                                           NULL, NULL);
1263
1264   gtk_tree_store_append (fixture.store, &root, NULL);
1265   create_tree_store_set_values (fixture.store, &root, FALSE);
1266
1267   /* check_filter_model (&fixture); */
1268   check_level_length (fixture.filter, NULL, 0);
1269
1270   gtk_tree_store_append (fixture.store, &iter, &root);
1271   create_tree_store_set_values (fixture.store, &iter, TRUE);
1272
1273   /* Parent must now be visible.  Do the level length check first,
1274    * to avoid modifying the child model triggering a row-changed to
1275    * the filter model.
1276    */
1277   check_level_length (fixture.filter, NULL, 1);
1278   check_level_length (fixture.filter, "0", 0);
1279
1280   set_path_visibility (&fixture, "0", TRUE);
1281   /* check_filter_model (&fixture); */
1282
1283   gtk_tree_store_append (fixture.store, &root, NULL);
1284   check_level_length (fixture.filter, NULL, 1);
1285
1286   gtk_tree_store_append (fixture.store, &iter, &root);
1287   check_level_length (fixture.filter, NULL, 2);
1288   check_level_length (fixture.filter, "1", 0);
1289
1290   create_tree_store_set_values (fixture.store, &root, TRUE);
1291   create_tree_store_set_values (fixture.store, &iter, TRUE);
1292
1293   /* check_filter_model (&fixture); */
1294
1295   gtk_tree_store_append (fixture.store, &iter, &root);
1296   create_tree_store_set_values (fixture.store, &iter, TRUE);
1297   check_level_length (fixture.filter, NULL, 2);
1298   check_level_length (fixture.filter, "0", 0);
1299   check_level_length (fixture.filter, "1", 0);
1300
1301   /* Now remove one of the remaining child rows */
1302   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture.store),
1303                                        &iter, "0:0");
1304   gtk_tree_store_remove (fixture.store, &iter);
1305
1306   check_level_length (fixture.filter, NULL, 1);
1307   check_level_length (fixture.filter, "0", 0);
1308
1309   set_path_visibility (&fixture, "0", FALSE);
1310   /* check_filter_model (&fixture); */
1311 }
1312
1313
1314 static gboolean
1315 specific_root_has_child_filter_filter_func (GtkTreeModel *model,
1316                                             GtkTreeIter  *iter,
1317                                             gpointer      data)
1318 {
1319   int depth;
1320   GtkTreePath *path;
1321
1322   path = gtk_tree_model_get_path (model, iter);
1323   depth = gtk_tree_path_get_depth (path);
1324   gtk_tree_path_free (path);
1325
1326   if (depth > 1)
1327     return TRUE;
1328   /* else */
1329   return gtk_tree_model_iter_has_child (model, iter);
1330 }
1331
1332 static void
1333 specific_root_has_child_filter (void)
1334 {
1335   GtkTreeModel *filter;
1336   GtkTreeIter iter, root;
1337   /* A bit nasty, apologies */
1338   FilterTest fixture;
1339
1340   /* This is a variation on the above test case wherein the has-child
1341    * check for visibility only applies to root level nodes.
1342    */
1343
1344   fixture.store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
1345   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (fixture.store), NULL);
1346   fixture.filter = GTK_TREE_MODEL_FILTER (filter);
1347
1348   /* We will filter on parent state using a filter function.  We will
1349    * manually keep the boolean column in sync, so that we can use
1350    * check_filter_model() to check the consistency of the model.
1351    */
1352   /* FIXME: We need a check_filter_model() that is not tied to LEVEL_LENGTH
1353    * to be able to check the structure here.  We keep the calls to
1354    * check_filter_model() commented out until then.
1355    */
1356   gtk_tree_model_filter_set_visible_func (fixture.filter,
1357                                           specific_root_has_child_filter_filter_func,
1358                                           NULL, NULL);
1359
1360   gtk_tree_store_append (fixture.store, &root, NULL);
1361   create_tree_store_set_values (fixture.store, &root, FALSE);
1362
1363   /* check_filter_model (&fixture); */
1364   check_level_length (fixture.filter, NULL, 0);
1365
1366   gtk_tree_store_append (fixture.store, &iter, &root);
1367   create_tree_store_set_values (fixture.store, &iter, TRUE);
1368
1369   /* Parent must now be visible.  Do the level length check first,
1370    * to avoid modifying the child model triggering a row-changed to
1371    * the filter model.
1372    */
1373   check_level_length (fixture.filter, NULL, 1);
1374   check_level_length (fixture.filter, "0", 1);
1375
1376   set_path_visibility (&fixture, "0", TRUE);
1377   /* check_filter_model (&fixture); */
1378
1379   gtk_tree_store_append (fixture.store, &root, NULL);
1380   check_level_length (fixture.filter, NULL, 1);
1381
1382   gtk_tree_store_append (fixture.store, &iter, &root);
1383   check_level_length (fixture.filter, NULL, 2);
1384   check_level_length (fixture.filter, "1", 1);
1385
1386   create_tree_store_set_values (fixture.store, &root, TRUE);
1387   create_tree_store_set_values (fixture.store, &iter, TRUE);
1388
1389   /* check_filter_model (&fixture); */
1390
1391   gtk_tree_store_append (fixture.store, &iter, &root);
1392   create_tree_store_set_values (fixture.store, &iter, TRUE);
1393   check_level_length (fixture.filter, NULL, 2);
1394   check_level_length (fixture.filter, "0", 1);
1395   check_level_length (fixture.filter, "1", 2);
1396
1397   /* Now remove one of the remaining child rows */
1398   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture.store),
1399                                        &iter, "0:0");
1400   gtk_tree_store_remove (fixture.store, &iter);
1401
1402   check_level_length (fixture.filter, NULL, 1);
1403   check_level_length (fixture.filter, "0", 2);
1404
1405   set_path_visibility (&fixture, "0", FALSE);
1406   /* check_filter_model (&fixture); */
1407 }
1408
1409
1410 static void
1411 specific_filter_add_child (void)
1412 {
1413   /* This test is based on one of the test cases I found in my
1414    * old test cases directory.  I unfortunately do not have a record
1415    * from who this test case originated.  -Kris.
1416    */
1417
1418   GtkTreeIter iter;
1419   GtkTreeIter iter_first;
1420   GtkTreeIter child;
1421   GtkTreeStore *store;
1422   GtkTreeModel *filter;
1423
1424   store = gtk_tree_store_new (1, G_TYPE_STRING);
1425
1426   gtk_tree_store_append (store, &iter_first, NULL);
1427   gtk_tree_store_set (store, &iter_first, 0, "Hello", -1);
1428
1429   gtk_tree_store_append (store, &iter, NULL);
1430   gtk_tree_store_set (store, &iter, 0, "Hello", -1);
1431
1432   gtk_tree_store_append (store, &iter, NULL);
1433   gtk_tree_store_set (store, &iter, 0, "Hello", -1);
1434
1435   gtk_tree_store_append (store, &iter, NULL);
1436   gtk_tree_store_set (store, &iter, 0, "Hello", -1);
1437
1438   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
1439
1440   gtk_tree_store_set (store, &iter, 0, "Hello", -1);
1441   gtk_tree_store_append (store, &child, &iter_first);
1442   gtk_tree_store_set (store, &child, 0, "Hello", -1);
1443 }
1444
1445
1446 static void
1447 specific_bug_300089 (void)
1448 {
1449   /* Test case for GNOME Bugzilla bug 300089.  Written by
1450    * Matthias Clasen.
1451    */
1452   GtkTreeModel *sort_model, *child_model;
1453   GtkTreePath *path;
1454   GtkTreeIter iter, iter2, sort_iter;
1455
1456   child_model = GTK_TREE_MODEL (gtk_tree_store_new (1, G_TYPE_STRING));
1457
1458   gtk_tree_store_append (GTK_TREE_STORE (child_model), &iter, NULL);
1459   gtk_tree_store_set (GTK_TREE_STORE (child_model), &iter, 0, "A", -1);
1460   gtk_tree_store_append (GTK_TREE_STORE (child_model), &iter, NULL);
1461   gtk_tree_store_set (GTK_TREE_STORE (child_model), &iter, 0, "B", -1);
1462
1463   gtk_tree_store_append (GTK_TREE_STORE (child_model), &iter2, &iter);
1464   gtk_tree_store_set (GTK_TREE_STORE (child_model), &iter2, 0, "D", -1);
1465   gtk_tree_store_append (GTK_TREE_STORE (child_model), &iter2, &iter);
1466   gtk_tree_store_set (GTK_TREE_STORE (child_model), &iter2, 0, "E", -1);
1467
1468   gtk_tree_store_append (GTK_TREE_STORE (child_model), &iter, NULL);
1469   gtk_tree_store_set (GTK_TREE_STORE (child_model), &iter, 0, "C", -1);
1470
1471
1472   sort_model = GTK_TREE_MODEL (gtk_tree_model_sort_new_with_model (child_model));
1473   gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sort_model),
1474                                         0, GTK_SORT_ASCENDING);
1475
1476   path = gtk_tree_path_new_from_indices (1, 1, -1);
1477
1478   /* make sure a level is constructed */ 
1479   gtk_tree_model_get_iter (sort_model, &sort_iter, path);
1480
1481   /* change the "E" row in a way that causes it to change position */ 
1482   gtk_tree_model_get_iter (child_model, &iter, path);
1483   gtk_tree_store_set (GTK_TREE_STORE (child_model), &iter, 0, "A", -1);
1484 }
1485
1486
1487 static int
1488 specific_bug_301558_sort_func (GtkTreeModel *model,
1489                                GtkTreeIter  *a,
1490                                GtkTreeIter  *b,
1491                                gpointer      data)
1492 {
1493   int i, j;
1494
1495   gtk_tree_model_get (model, a, 0, &i, -1);
1496   gtk_tree_model_get (model, b, 0, &j, -1);
1497
1498   return j - i;
1499 }
1500
1501 static void
1502 specific_bug_301558 (void)
1503 {
1504   /* Test case for GNOME Bugzilla bug 301558 provided by
1505    * Markku Vire.
1506    */
1507   GtkTreeStore *tree;
1508   GtkTreeModel *filter;
1509   GtkTreeModel *sort;
1510   GtkTreeIter root, iter, iter2;
1511   GtkWidget *view;
1512   int i;
1513   gboolean add;
1514
1515   tree = gtk_tree_store_new (2, G_TYPE_INT, G_TYPE_BOOLEAN);
1516   gtk_tree_store_append (tree, &iter, NULL);
1517   gtk_tree_store_set (tree, &iter, 0, 123, 1, TRUE, -1);
1518   gtk_tree_store_append (tree, &iter2, &iter);
1519   gtk_tree_store_set (tree, &iter2, 0, 73, 1, TRUE, -1);
1520
1521   sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (tree));
1522   gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (sort),
1523                                            specific_bug_301558_sort_func,
1524                                            NULL, NULL);
1525
1526   filter = gtk_tree_model_filter_new (sort, NULL);
1527   gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter), 1);
1528
1529   view = gtk_tree_view_new_with_model (filter);
1530
1531   while (gtk_events_pending ())
1532     gtk_main_iteration ();
1533
1534   add = TRUE;
1535
1536   for (i = 0; i < 10; i++)
1537     {
1538       if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (tree), &root))
1539         g_assert_not_reached ();
1540
1541       if (add)
1542         {
1543           gtk_tree_store_append (tree, &iter, &root);
1544           gtk_tree_store_set (tree, &iter, 0, 456, 1, TRUE, -1);
1545         }
1546       else
1547         {
1548           int n;
1549           n = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (tree), &root);
1550           gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (tree), &iter,
1551                                          &root, n - 1);
1552           gtk_tree_store_remove (tree, &iter);
1553         }
1554
1555       add = !add;
1556     }
1557 }
1558
1559
1560 static gboolean
1561 specific_bug_311955_filter_func (GtkTreeModel *model,
1562                                  GtkTreeIter  *iter,
1563                                  gpointer      data)
1564 {
1565   int value;
1566
1567   gtk_tree_model_get (model, iter, 0, &value, -1);
1568
1569   return (value != 0);
1570 }
1571
1572 static void
1573 specific_bug_311955 (void)
1574 {
1575   /* This is a test case for GNOME Bugzilla bug 311955.  It was written
1576    * by Markku Vire.
1577    */
1578   GtkTreeIter iter, child, root;
1579   GtkTreeStore *store;
1580   GtkTreeModel *sort;
1581   GtkTreeModel *filter;
1582
1583   GtkWidget *window;
1584   GtkWidget *tree_view;
1585   int i;
1586   int n;
1587
1588   store = gtk_tree_store_new (1, G_TYPE_INT);
1589
1590   gtk_tree_store_append (store, &root, NULL);
1591   gtk_tree_store_set (store, &root, 0, 33, -1);
1592
1593   gtk_tree_store_append (store, &iter, &root);
1594   gtk_tree_store_set (store, &iter, 0, 50, -1);
1595
1596   gtk_tree_store_append (store, &iter, NULL);
1597   gtk_tree_store_set (store, &iter, 0, 22, -1);
1598
1599   sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (store));
1600   filter = gtk_tree_model_filter_new (sort, NULL);
1601
1602   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
1603                                           specific_bug_311955_filter_func,
1604                                           NULL, NULL);
1605
1606   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1607   tree_view = gtk_tree_view_new_with_model (filter);
1608   g_object_unref (store);
1609
1610   gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
1611
1612   while (gtk_events_pending ())
1613     gtk_main_iteration ();
1614
1615   /* Fill model */
1616   for (i = 0; i < 4; i++)
1617     {
1618       gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &root);
1619
1620       gtk_tree_store_append (store, &iter, &root);
1621
1622       if (i < 3)
1623         gtk_tree_store_set (store, &iter, 0, i, -1);
1624
1625       if (i % 2 == 0)
1626         {
1627           gtk_tree_store_append (store, &child, &iter);
1628           gtk_tree_store_set (store, &child, 0, 10, -1);
1629         }
1630     }
1631
1632   while (gtk_events_pending ())
1633     gtk_main_iteration ();
1634
1635   /* Remove bottommost child from the tree. */
1636   gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &root);
1637   n = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (store), &root);
1638
1639   if (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (store), &iter, &root, n - 2))
1640     {
1641       if (gtk_tree_model_iter_children (GTK_TREE_MODEL (store), &child, &iter))
1642         gtk_tree_store_remove (store, &child);
1643     }
1644   else
1645     g_assert_not_reached ();
1646 }
1647
1648 static void
1649 specific_bug_346800 (void)
1650 {
1651   /* This is a test case for GNOME Bugzilla bug 346800.  It was written
1652    * by Jonathan Matthew.
1653    */
1654
1655   GtkTreeIter node_iters[50];
1656   GtkTreeIter child_iters[50];
1657   GtkTreeModel *model;
1658   GtkTreeModelFilter *filter;
1659   GtkTreeStore *store;
1660   GType *columns;
1661   int i;
1662   int items = 50;
1663   columns = g_new (GType, 2);
1664   columns[0] = G_TYPE_STRING;
1665   columns[1] = G_TYPE_BOOLEAN;
1666   store = gtk_tree_store_newv (2, columns);
1667   model = GTK_TREE_MODEL (store);
1668
1669   filter = GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (model, NULL));
1670   gtk_tree_model_filter_set_visible_column (filter, 1);
1671
1672   for (i=0; i<items; i++)
1673     {
1674       /* allocate random amounts of junk, otherwise the filter model's arrays can expand without moving */
1675
1676       g_malloc (138);
1677       gtk_tree_store_append (store, &node_iters[i], NULL);
1678       gtk_tree_store_set (store, &node_iters[i],
1679                           0, "something",
1680                           1, ((i%6) == 0) ? FALSE : TRUE,
1681                           -1);
1682
1683       g_malloc (47);
1684       gtk_tree_store_append (store, &child_iters[i], &node_iters[i]);
1685       gtk_tree_store_set (store, &child_iters[i],
1686                           0, "something else",
1687                           1, FALSE,
1688                           -1);
1689       gtk_tree_model_filter_refilter (filter);
1690
1691       if (i > 6)
1692         {
1693           gtk_tree_store_set (GTK_TREE_STORE (model), &child_iters[i-1], 1,
1694                               (i & 1) ? TRUE : FALSE, -1);
1695           gtk_tree_model_filter_refilter (filter);
1696
1697           gtk_tree_store_set (GTK_TREE_STORE (model), &child_iters[i-2], 1,
1698                               (i & 1) ? FALSE: TRUE, -1);
1699           gtk_tree_model_filter_refilter (filter);
1700         }
1701     }
1702 }
1703
1704
1705 static void
1706 specific_bug_364946 (void)
1707 {
1708   /* This is a test case for GNOME Bugzilla bug 364946.  It was written
1709    * by Andreas Koehler.
1710    */
1711   GtkTreeStore *store;
1712   GtkTreeIter a, aa, aaa, aab, iter;
1713   GtkTreeModel *s_model;
1714
1715   store = gtk_tree_store_new (1, G_TYPE_STRING);
1716
1717   gtk_tree_store_append (store, &a, NULL);
1718   gtk_tree_store_set (store, &a, 0, "0", -1);
1719
1720   gtk_tree_store_append (store, &aa, &a);
1721   gtk_tree_store_set (store, &aa, 0, "0:0", -1);
1722
1723   gtk_tree_store_append (store, &aaa, &aa);
1724   gtk_tree_store_set (store, &aaa, 0, "0:0:0", -1);
1725
1726   gtk_tree_store_append (store, &aab, &aa);
1727   gtk_tree_store_set (store, &aab, 0, "0:0:1", -1);
1728
1729   s_model = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (store));
1730   gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (s_model), 0,
1731                                         GTK_SORT_ASCENDING);
1732
1733   gtk_tree_model_get_iter_from_string (s_model, &iter, "0:0:0");
1734
1735   gtk_tree_store_set (store, &aaa, 0, "0:0:0", -1);
1736   gtk_tree_store_remove (store, &aaa);
1737   gtk_tree_store_remove (store, &aab);
1738
1739   gtk_tree_model_sort_clear_cache (GTK_TREE_MODEL_SORT (s_model));
1740 }
1741
1742
1743 static gboolean
1744 specific_bug_464173_visible_func (GtkTreeModel *model,
1745                                   GtkTreeIter  *iter,
1746                                   gpointer      data)
1747 {
1748   gboolean *visible = (gboolean *)data;
1749
1750   return *visible;
1751 }
1752
1753 static void
1754 specific_bug_464173 (void)
1755 {
1756   /* Test case for GNOME Bugzilla bug 464173, test case written
1757    * by Andreas Koehler.
1758    */
1759   GtkTreeStore *model;
1760   GtkTreeModelFilter *f_model;
1761   GtkTreeIter iter1, iter2;
1762   GtkWidget *view;
1763   gboolean visible = TRUE;
1764
1765   model = gtk_tree_store_new (1, G_TYPE_STRING);
1766   gtk_tree_store_append (model, &iter1, NULL);
1767   gtk_tree_store_set (model, &iter1, 0, "Foo", -1);
1768   gtk_tree_store_append (model, &iter2, &iter1);
1769   gtk_tree_store_set (model, &iter2, 0, "Bar", -1);
1770
1771   f_model = GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (GTK_TREE_MODEL(model), NULL));
1772   gtk_tree_model_filter_set_visible_func (f_model,
1773                                           specific_bug_464173_visible_func,
1774                                           &visible, NULL);
1775
1776   view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (f_model));
1777
1778   visible = FALSE;
1779   gtk_tree_model_filter_refilter (f_model);
1780 }
1781
1782
1783 static gboolean
1784 specific_bug_540201_filter_func (GtkTreeModel *model,
1785                                  GtkTreeIter  *iter,
1786                                  gpointer      data)
1787 {
1788   gboolean has_children;
1789
1790   has_children = gtk_tree_model_iter_has_child (model, iter);
1791
1792   return has_children;
1793 }
1794
1795 static void
1796 specific_bug_540201 (void)
1797 {
1798   /* Test case for GNOME Bugzilla bug 540201, steps provided by
1799    * Charles Day.
1800    */
1801   GtkTreeIter iter, root;
1802   GtkTreeStore *store;
1803   GtkTreeModel *filter;
1804
1805   GtkWidget *tree_view;
1806
1807   store = gtk_tree_store_new (1, G_TYPE_INT);
1808
1809   gtk_tree_store_append (store, &root, NULL);
1810   gtk_tree_store_set (store, &root, 0, 33, -1);
1811
1812   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
1813   tree_view = gtk_tree_view_new_with_model (filter);
1814
1815   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
1816                                           specific_bug_540201_filter_func,
1817                                           NULL, NULL);
1818
1819   gtk_tree_store_append (store, &iter, &root);
1820   gtk_tree_store_set (store, &iter, 0, 50, -1);
1821
1822   gtk_tree_store_append (store, &iter, &root);
1823   gtk_tree_store_set (store, &iter, 0, 22, -1);
1824
1825
1826   gtk_tree_store_append (store, &root, NULL);
1827   gtk_tree_store_set (store, &root, 0, 33, -1);
1828
1829   gtk_tree_store_append (store, &iter, &root);
1830   gtk_tree_store_set (store, &iter, 0, 22, -1);
1831 }
1832
1833
1834 static gboolean
1835 specific_bug_549287_visible_func (GtkTreeModel *model,
1836                                   GtkTreeIter  *iter,
1837                                   gpointer      data)
1838 {
1839   gboolean result = FALSE;
1840
1841   result = gtk_tree_model_iter_has_child (model, iter);
1842
1843   return result;
1844 }
1845
1846 static void
1847 specific_bug_549287 (void)
1848 {
1849   /* Test case for GNOME Bugzilla bug 529287, provided by Julient Puydt */
1850
1851   int i;
1852   GtkTreeStore *store;
1853   GtkTreeModel *filtered;
1854   GtkWidget *view;
1855   GtkTreeIter iter;
1856   GtkTreeIter *swap, *parent, *child;
1857
1858   store = gtk_tree_store_new (1, G_TYPE_STRING);
1859   filtered = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
1860   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filtered),
1861                                           specific_bug_549287_visible_func,
1862                                           NULL, NULL);
1863
1864   view = gtk_tree_view_new_with_model (filtered);
1865
1866   for (i = 0; i < 4; i++)
1867     {
1868       if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter))
1869         {
1870           parent = gtk_tree_iter_copy (&iter);
1871           child = gtk_tree_iter_copy (&iter);
1872
1873           while (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (store),
1874                                                 child, parent, 0))
1875             {
1876
1877               swap = parent;
1878               parent = child;
1879               child = swap;
1880             }
1881
1882           gtk_tree_store_append (store, child, parent);
1883           gtk_tree_store_set (store, child,
1884                               0, "Something",
1885                               -1);
1886
1887           gtk_tree_iter_free (parent);
1888           gtk_tree_iter_free (child);
1889         }
1890       else
1891         {
1892           gtk_tree_store_append (store, &iter, NULL);
1893           gtk_tree_store_set (store, &iter,
1894                               0, "Something",
1895                               -1);
1896         }
1897
1898       /* since we inserted something, we changed the visibility conditions: */
1899       gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (filtered));
1900     }
1901 }
1902
1903 /* main */
1904
1905 int
1906 main (int    argc,
1907       char **argv)
1908 {
1909   gtk_test_init (&argc, &argv, NULL);
1910
1911   g_test_add ("/FilterModel/self/verify-test-suite",
1912               FilterTest, NULL,
1913               filter_test_setup,
1914               verify_test_suite,
1915               filter_test_teardown);
1916
1917   g_test_add ("/FilterModel/self/verify-test-suite/vroot/depth-1",
1918               FilterTest, gtk_tree_path_new_from_indices (2, -1),
1919               filter_test_setup,
1920               verify_test_suite_vroot,
1921               filter_test_teardown);
1922   g_test_add ("/FilterModel/self/verify-test-suite/vroot/depth-2",
1923               FilterTest, gtk_tree_path_new_from_indices (2, 3, -1),
1924               filter_test_setup,
1925               verify_test_suite_vroot,
1926               filter_test_teardown);
1927
1928
1929   g_test_add ("/FilterModel/filled/hide-root-level",
1930               FilterTest, NULL,
1931               filter_test_setup,
1932               filled_hide_root_level,
1933               filter_test_teardown);
1934   g_test_add ("/FilterModel/filled/hide-child-levels",
1935               FilterTest, NULL,
1936               filter_test_setup,
1937               filled_hide_child_levels,
1938               filter_test_teardown);
1939
1940   g_test_add ("/FilterModel/filled/hide-root-level/vroot",
1941               FilterTest, gtk_tree_path_new_from_indices (2, -1),
1942               filter_test_setup,
1943               filled_vroot_hide_root_level,
1944               filter_test_teardown);
1945   g_test_add ("/FilterModel/filled/hide-child-levels/vroot",
1946               FilterTest, gtk_tree_path_new_from_indices (2, -1),
1947               filter_test_setup,
1948               filled_vroot_hide_child_levels,
1949               filter_test_teardown);
1950
1951
1952   g_test_add ("/FilterModel/empty/show-nodes",
1953               FilterTest, NULL,
1954               filter_test_setup_empty,
1955               empty_show_nodes,
1956               filter_test_teardown);
1957
1958   g_test_add ("/FilterModel/empty/show-nodes/vroot",
1959               FilterTest, gtk_tree_path_new_from_indices (2, -1),
1960               filter_test_setup_empty,
1961               empty_vroot_show_nodes,
1962               filter_test_teardown);
1963
1964
1965   g_test_add ("/FilterModel/unfiltered/hide-single",
1966               FilterTest, NULL,
1967               filter_test_setup_unfiltered,
1968               unfiltered_hide_single,
1969               filter_test_teardown);
1970   g_test_add ("/FilterModel/unfiltered/hide-single-child",
1971               FilterTest, NULL,
1972               filter_test_setup_unfiltered,
1973               unfiltered_hide_single_child,
1974               filter_test_teardown);
1975   g_test_add ("/FilterModel/unfiltered/hide-single-multi-level",
1976               FilterTest, NULL,
1977               filter_test_setup_unfiltered,
1978               unfiltered_hide_single_multi_level,
1979               filter_test_teardown);
1980
1981   g_test_add ("/FilterModel/unfiltered/hide-single/vroot",
1982               FilterTest, gtk_tree_path_new_from_indices (2, -1),
1983               filter_test_setup_unfiltered,
1984               unfiltered_vroot_hide_single,
1985               filter_test_teardown);
1986   g_test_add ("/FilterModel/unfiltered/hide-single-child/vroot",
1987               FilterTest, gtk_tree_path_new_from_indices (2, -1),
1988               filter_test_setup_unfiltered,
1989               unfiltered_vroot_hide_single_child,
1990               filter_test_teardown);
1991   g_test_add ("/FilterModel/unfiltered/hide-single-multi-level/vroot",
1992               FilterTest, gtk_tree_path_new_from_indices (2, -1),
1993               filter_test_setup_unfiltered,
1994               unfiltered_vroot_hide_single_multi_level,
1995               filter_test_teardown);
1996
1997
1998
1999   g_test_add ("/FilterModel/unfiltered/show-single",
2000               FilterTest, NULL,
2001               filter_test_setup_empty_unfiltered,
2002               unfiltered_show_single,
2003               filter_test_teardown);
2004   g_test_add ("/FilterModel/unfiltered/show-single-child",
2005               FilterTest, NULL,
2006               filter_test_setup_empty_unfiltered,
2007               unfiltered_show_single_child,
2008               filter_test_teardown);
2009   g_test_add ("/FilterModel/unfiltered/show-single-multi-level",
2010               FilterTest, NULL,
2011               filter_test_setup_empty_unfiltered,
2012               unfiltered_show_single_multi_level,
2013               filter_test_teardown);
2014
2015   g_test_add ("/FilterModel/unfiltered/show-single/vroot",
2016               FilterTest, gtk_tree_path_new_from_indices (2, -1),
2017               filter_test_setup_empty_unfiltered,
2018               unfiltered_vroot_show_single,
2019               filter_test_teardown);
2020   g_test_add ("/FilterModel/unfiltered/show-single-child/vroot",
2021               FilterTest, gtk_tree_path_new_from_indices (2, -1),
2022               filter_test_setup_empty_unfiltered,
2023               unfiltered_vroot_show_single_child,
2024               filter_test_teardown);
2025   g_test_add ("/FilterModel/unfiltered/show-single-multi-level/vroot",
2026               FilterTest, gtk_tree_path_new_from_indices (2, -1),
2027               filter_test_setup_empty_unfiltered,
2028               unfiltered_vroot_show_single_multi_level,
2029               filter_test_teardown);
2030
2031
2032   g_test_add_func ("/FilterModel/specific/path-dependent-filter",
2033                    specific_path_dependent_filter);
2034   g_test_add_func ("/FilterModel/specific/append-after-collapse",
2035                    specific_append_after_collapse);
2036   g_test_add_func ("/FilterModel/specific/sort-filter-remove-node",
2037                    specific_sort_filter_remove_node);
2038   g_test_add_func ("/FilterModel/specific/sort-filter-remove-root",
2039                    specific_sort_filter_remove_root);
2040   g_test_add_func ("/FilterModel/specific/root-mixed-visibility",
2041                    specific_root_mixed_visibility);
2042   g_test_add_func ("/FilterModel/specific/has-child-filter",
2043                    specific_has_child_filter);
2044   g_test_add_func ("/FilterModel/specific/root-has-child-filter",
2045                    specific_root_has_child_filter);
2046   g_test_add_func ("/FilterModel/specific/filter-add-child",
2047                    specific_filter_add_child);
2048
2049   g_test_add_func ("/FilterModel/specific/bug-300089",
2050                    specific_bug_300089);
2051   g_test_add_func ("/FilterModel/specific/bug-301558",
2052                    specific_bug_301558);
2053   g_test_add_func ("/FilterModel/specific/bug-311955",
2054                    specific_bug_311955);
2055   g_test_add_func ("/FilterModel/specific/bug-346800",
2056                    specific_bug_346800);
2057   g_test_add_func ("/FilterModel/specific/bug-364946",
2058                    specific_bug_364946);
2059   g_test_add_func ("/FilterModel/specific/bug-464173",
2060                    specific_bug_464173);
2061   g_test_add_func ("/FilterModel/specific/bug-540201",
2062                    specific_bug_540201);
2063   g_test_add_func ("/FilterModel/specific/bug-549287",
2064                    specific_bug_549287);
2065
2066   return g_test_run ();
2067 }