]> Pileus Git - ~andy/gtk/blob - gtk/tests/filtermodel.c
Correct unfiltered test cases
[~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_show_single (FilterTest    *fixture,
720                         gconstpointer  user_data)
721
722 {
723   set_path_visibility (fixture, "2", TRUE);
724
725   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
726
727   filter_test_enable_filter (fixture);
728
729   check_filter_model (fixture);
730   check_level_length (fixture->filter, NULL, 1);
731 }
732
733 static void
734 unfiltered_show_single_child (FilterTest    *fixture,
735                               gconstpointer  user_data)
736
737 {
738   set_path_visibility (fixture, "2:2", TRUE);
739
740   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
741   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
742
743   filter_test_enable_filter (fixture);
744
745   check_filter_model (fixture);
746   check_level_length (fixture->filter, NULL, 0);
747
748   /* From here we are filtered, "2" in the real model is "0" in the filter
749    * model.
750    */
751   set_path_visibility (fixture, "2", TRUE);
752   check_level_length (fixture->filter, NULL, 1);
753   check_level_length (fixture->filter, "0", 1);
754 }
755
756 static void
757 unfiltered_show_single_multi_level (FilterTest    *fixture,
758                                     gconstpointer  user_data)
759
760 {
761   set_path_visibility (fixture, "2:2:2", TRUE);
762   set_path_visibility (fixture, "2:2", TRUE);
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 (fixture);
771   check_level_length (fixture->filter, NULL, 0);
772
773   /* From here we are filtered, "2" in the real model is "0" in the filter
774    * model.
775    */
776   set_path_visibility (fixture, "2", TRUE);
777   check_filter_model (fixture);
778   check_level_length (fixture->filter, NULL, 1);
779   check_level_length (fixture->filter, "0", 1);
780   check_level_length (fixture->filter, "0:0", 1);
781 }
782
783
784 static gboolean
785 specific_path_dependent_filter_func (GtkTreeModel *model,
786                                      GtkTreeIter  *iter,
787                                      gpointer      data)
788 {
789   GtkTreePath *path;
790
791   path = gtk_tree_model_get_path (model, iter);
792   if (gtk_tree_path_get_indices (path)[0] < 4)
793     return FALSE;
794
795   return TRUE;
796 }
797
798 static void
799 specific_path_dependent_filter (void)
800 {
801   int i;
802   GtkTreeIter iter;
803   GtkListStore *list;
804   GtkTreeModel *sort;
805   GtkTreeModel *filter;
806
807   list = gtk_list_store_new (1, G_TYPE_INT);
808   gtk_list_store_insert_with_values (list, &iter, 0, 0, 1, -1);
809   gtk_list_store_insert_with_values (list, &iter, 1, 0, 2, -1);
810   gtk_list_store_insert_with_values (list, &iter, 2, 0, 3, -1);
811   gtk_list_store_insert_with_values (list, &iter, 3, 0, 4, -1);
812   gtk_list_store_insert_with_values (list, &iter, 4, 0, 5, -1);
813   gtk_list_store_insert_with_values (list, &iter, 5, 0, 6, -1);
814   gtk_list_store_insert_with_values (list, &iter, 6, 0, 7, -1);
815   gtk_list_store_insert_with_values (list, &iter, 7, 0, 8, -1);
816
817   sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (list));
818   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (sort), NULL);
819   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
820                                           specific_path_dependent_filter_func,
821                                           NULL, NULL);
822
823   gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sort), 0,
824                                         GTK_SORT_DESCENDING);
825
826   for (i = 0; i < 4; i++)
827     {
828       if (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (list), &iter,
829                                          NULL, 1))
830         gtk_list_store_remove (list, &iter);
831
832       if (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (list), &iter,
833                                          NULL, 2))
834         gtk_list_store_remove (list, &iter);
835     }
836 }
837
838
839 static gboolean
840 specific_append_after_collapse_visible_func (GtkTreeModel *model,
841                                              GtkTreeIter  *iter,
842                                              gpointer      data)
843 {
844   gint number;
845   gboolean hide_negative_numbers;
846
847   gtk_tree_model_get (model, iter, 1, &number, -1);
848   hide_negative_numbers = GPOINTER_TO_INT (g_object_get_data (data, "private-hide-negative-numbers"));
849
850   return (number >= 0 || !hide_negative_numbers);
851 }
852
853 static void
854 specific_append_after_collapse (void)
855 {
856   /* This test is based on one of the test cases I found in my
857    * old test cases directory.  I unfortunately do not have a record
858    * from who this test case originated.  -Kris.
859    *
860    * General idea:
861    * - Construct tree.
862    * - Show tree, expand, collapse.
863    * - Add a row.
864    */
865
866   GtkTreeIter iter;
867   GtkTreeIter child_iter;
868   GtkTreeIter child_iter2;
869   GtkTreePath *append_path;
870   GtkTreeStore *store;
871   GtkTreeModel *filter;
872   GtkTreeModel *sort;
873
874   GtkWidget *window;
875   GtkWidget *tree_view;
876
877   store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_INT);
878
879   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
880   g_object_set_data (G_OBJECT (filter), "private-hide-negative-numbers",
881                      GINT_TO_POINTER (FALSE));
882   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
883                                           specific_append_after_collapse_visible_func,
884                                           filter, NULL);
885
886   sort = gtk_tree_model_sort_new_with_model (filter);
887
888   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
889   tree_view = gtk_tree_view_new_with_model (sort);
890   gtk_container_add (GTK_CONTAINER (window), tree_view);
891   gtk_widget_realize (tree_view);
892
893   while (gtk_events_pending ())
894     gtk_main_iteration ();
895
896   gtk_tree_store_prepend (store, &iter, NULL);
897   gtk_tree_store_set (store, &iter,
898                       0, "hallo", 1, 1, -1);
899
900   gtk_tree_store_append (store, &child_iter, &iter);
901   gtk_tree_store_set (store, &child_iter,
902                       0, "toemaar", 1, 1, -1);
903
904   gtk_tree_store_append (store, &child_iter2, &child_iter);
905   gtk_tree_store_set (store, &child_iter2,
906                       0, "very deep", 1, 1, -1);
907
908   append_path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &child_iter2);
909
910   gtk_tree_store_append (store, &child_iter, &iter);
911   gtk_tree_store_set (store, &child_iter,
912                       0, "sja", 1, 1, -1);
913
914   gtk_tree_store_append (store, &child_iter, &iter);
915   gtk_tree_store_set (store, &child_iter,
916                       0, "some word", 1, -1, -1);
917
918   /* Expand and collapse the tree */
919   gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
920   while (gtk_events_pending ())
921     gtk_main_iteration ();
922
923   gtk_tree_view_collapse_all (GTK_TREE_VIEW (tree_view));
924   while (gtk_events_pending ())
925     gtk_main_iteration ();
926
927   /* Add another it */
928   g_object_set_data (G_OBJECT (filter), "private-hide-negative-numbers",
929                      GINT_TO_POINTER (TRUE));
930
931   if (gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, append_path))
932     {
933       gtk_tree_store_append (store, &child_iter, &iter);
934       gtk_tree_store_set (store, &child_iter,
935                           0, "new new new !!", 1, 1, -1);
936     }
937   gtk_tree_path_free (append_path);
938
939   /* Expand */
940   gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
941   while (gtk_events_pending ())
942     gtk_main_iteration ();
943 }
944
945
946 static gint
947 specific_sort_filter_remove_node_compare_func (GtkTreeModel  *model,
948                                                GtkTreeIter   *iter1,
949                                                GtkTreeIter   *iter2,
950                                                gpointer       data)
951 {
952   return -1;
953 }
954
955 static gboolean
956 specific_sort_filter_remove_node_visible_func (GtkTreeModel  *model,
957                                                GtkTreeIter   *iter,
958                                                gpointer       data)
959 {
960   char *item = NULL;
961
962   /* Do reference the model */
963   gtk_tree_model_get (model, iter, 0, &item, -1);
964   g_free (item);
965
966   return FALSE;
967 }
968
969 static void
970 specific_sort_filter_remove_node (void)
971 {
972   /* This test is based on one of the test cases I found in my
973    * old test cases directory.  I unfortunately do not have a record
974    * from who this test case originated.  -Kris.
975    *
976    * General idea:
977    *  - Create tree store, sort, filter models.  The sort model has
978    *    a default sort func that is enabled, filter model a visible func
979    *    that defaults to returning FALSE.
980    *  - Remove a node from the tree store.
981    */
982
983   GtkTreeIter iter;
984   GtkTreeStore *store;
985   GtkTreeModel *filter;
986   GtkTreeModel *sort;
987
988   GtkWidget *window;
989   GtkWidget *tree_view;
990
991   store = gtk_tree_store_new (1, G_TYPE_STRING);
992   gtk_tree_store_append (store, &iter, NULL);
993   gtk_tree_store_set (store, &iter, 0, "Hello1", -1);
994
995   gtk_tree_store_append (store, &iter, NULL);
996   gtk_tree_store_set (store, &iter, 0, "Hello2", -1);
997
998   sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (store));
999   gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (sort),
1000                                            specific_sort_filter_remove_node_compare_func, NULL, NULL);
1001
1002   filter = gtk_tree_model_filter_new (sort, NULL);
1003   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
1004                                           specific_sort_filter_remove_node_visible_func,
1005                                           filter, NULL);
1006
1007
1008   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1009   tree_view = gtk_tree_view_new_with_model (filter);
1010   gtk_container_add (GTK_CONTAINER (window), tree_view);
1011   gtk_widget_realize (tree_view);
1012
1013   while (gtk_events_pending ())
1014     gtk_main_iteration ();
1015
1016   /* Remove a node */
1017   gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter);
1018   gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter);
1019   gtk_tree_store_remove (store, &iter);
1020
1021   while (gtk_events_pending ())
1022     gtk_main_iteration ();
1023 }
1024
1025
1026 static void
1027 specific_sort_filter_remove_root (void)
1028 {
1029   /* This test is based on one of the test cases I found in my
1030    * old test cases directory.  I unfortunately do not have a record
1031    * from who this test case originated.  -Kris.
1032    */
1033
1034   GtkTreeModel *model, *sort, *filter;
1035   GtkTreeIter root, mid, leaf;
1036   GtkTreePath *path;
1037
1038   model = GTK_TREE_MODEL (gtk_tree_store_new (1, G_TYPE_INT));
1039   gtk_tree_store_append (GTK_TREE_STORE (model), &root, NULL);
1040   gtk_tree_store_append (GTK_TREE_STORE (model), &mid, &root);
1041   gtk_tree_store_append (GTK_TREE_STORE (model), &leaf, &mid);
1042
1043   path = gtk_tree_model_get_path (model, &mid);
1044
1045   sort = gtk_tree_model_sort_new_with_model (model);
1046   filter = gtk_tree_model_filter_new (sort, path);
1047
1048   gtk_tree_store_remove (GTK_TREE_STORE (model), &root);
1049
1050   g_object_unref (filter);
1051   g_object_unref (sort);
1052   g_object_unref (model);
1053 }
1054
1055
1056 static void
1057 specific_filter_add_child (void)
1058 {
1059   /* This test is based on one of the test cases I found in my
1060    * old test cases directory.  I unfortunately do not have a record
1061    * from who this test case originated.  -Kris.
1062    */
1063
1064   GtkTreeIter iter;
1065   GtkTreeIter iter_first;
1066   GtkTreeIter child;
1067   GtkTreeStore *store;
1068   GtkTreeModel *filter;
1069
1070   store = gtk_tree_store_new (1, G_TYPE_STRING);
1071
1072   gtk_tree_store_append (store, &iter_first, NULL);
1073   gtk_tree_store_set (store, &iter_first, 0, "Hello", -1);
1074
1075   gtk_tree_store_append (store, &iter, NULL);
1076   gtk_tree_store_set (store, &iter, 0, "Hello", -1);
1077
1078   gtk_tree_store_append (store, &iter, NULL);
1079   gtk_tree_store_set (store, &iter, 0, "Hello", -1);
1080
1081   gtk_tree_store_append (store, &iter, NULL);
1082   gtk_tree_store_set (store, &iter, 0, "Hello", -1);
1083
1084   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
1085
1086   gtk_tree_store_set (store, &iter, 0, "Hello", -1);
1087   gtk_tree_store_append (store, &child, &iter_first);
1088   gtk_tree_store_set (store, &child, 0, "Hello", -1);
1089 }
1090
1091
1092 static void
1093 specific_bug_300089 (void)
1094 {
1095   /* Test case for GNOME Bugzilla bug 300089.  Written by
1096    * Matthias Clasen.
1097    */
1098   GtkTreeModel *sort_model, *child_model;
1099   GtkTreePath *path;
1100   GtkTreeIter iter, iter2, sort_iter;
1101
1102   child_model = GTK_TREE_MODEL (gtk_tree_store_new (1, G_TYPE_STRING));
1103
1104   gtk_tree_store_append (GTK_TREE_STORE (child_model), &iter, NULL);
1105   gtk_tree_store_set (GTK_TREE_STORE (child_model), &iter, 0, "A", -1);
1106   gtk_tree_store_append (GTK_TREE_STORE (child_model), &iter, NULL);
1107   gtk_tree_store_set (GTK_TREE_STORE (child_model), &iter, 0, "B", -1);
1108
1109   gtk_tree_store_append (GTK_TREE_STORE (child_model), &iter2, &iter);
1110   gtk_tree_store_set (GTK_TREE_STORE (child_model), &iter2, 0, "D", -1);
1111   gtk_tree_store_append (GTK_TREE_STORE (child_model), &iter2, &iter);
1112   gtk_tree_store_set (GTK_TREE_STORE (child_model), &iter2, 0, "E", -1);
1113
1114   gtk_tree_store_append (GTK_TREE_STORE (child_model), &iter, NULL);
1115   gtk_tree_store_set (GTK_TREE_STORE (child_model), &iter, 0, "C", -1);
1116
1117
1118   sort_model = GTK_TREE_MODEL (gtk_tree_model_sort_new_with_model (child_model));
1119   gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sort_model),
1120                                         0, GTK_SORT_ASCENDING);
1121
1122   path = gtk_tree_path_new_from_indices (1, 1, -1);
1123
1124   /* make sure a level is constructed */ 
1125   gtk_tree_model_get_iter (sort_model, &sort_iter, path);
1126
1127   /* change the "E" row in a way that causes it to change position */ 
1128   gtk_tree_model_get_iter (child_model, &iter, path);
1129   gtk_tree_store_set (GTK_TREE_STORE (child_model), &iter, 0, "A", -1);
1130 }
1131
1132
1133 static int
1134 specific_bug_301558_sort_func (GtkTreeModel *model,
1135                                GtkTreeIter  *a,
1136                                GtkTreeIter  *b,
1137                                gpointer      data)
1138 {
1139   int i, j;
1140
1141   gtk_tree_model_get (model, a, 0, &i, -1);
1142   gtk_tree_model_get (model, b, 0, &j, -1);
1143
1144   return j - i;
1145 }
1146
1147 static void
1148 specific_bug_301558 (void)
1149 {
1150   /* Test case for GNOME Bugzilla bug 301558 provided by
1151    * Markku Vire.
1152    */
1153   GtkTreeStore *tree;
1154   GtkTreeModel *filter;
1155   GtkTreeModel *sort;
1156   GtkTreeIter root, iter, iter2;
1157   GtkWidget *view;
1158   int i;
1159   gboolean add;
1160
1161   tree = gtk_tree_store_new (2, G_TYPE_INT, G_TYPE_BOOLEAN);
1162   gtk_tree_store_append (tree, &iter, NULL);
1163   gtk_tree_store_set (tree, &iter, 0, 123, 1, TRUE, -1);
1164   gtk_tree_store_append (tree, &iter2, &iter);
1165   gtk_tree_store_set (tree, &iter2, 0, 73, 1, TRUE, -1);
1166
1167   sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (tree));
1168   gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (sort),
1169                                            specific_bug_301558_sort_func,
1170                                            NULL, NULL);
1171
1172   filter = gtk_tree_model_filter_new (sort, NULL);
1173   gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter), 1);
1174
1175   view = gtk_tree_view_new_with_model (filter);
1176
1177   while (gtk_events_pending ())
1178     gtk_main_iteration ();
1179
1180   add = TRUE;
1181
1182   for (i = 0; i < 10; i++)
1183     {
1184       if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (tree), &root))
1185         g_assert_not_reached ();
1186
1187       if (add)
1188         {
1189           gtk_tree_store_append (tree, &iter, &root);
1190           gtk_tree_store_set (tree, &iter, 0, 456, 1, TRUE, -1);
1191         }
1192       else
1193         {
1194           int n;
1195           n = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (tree), &root);
1196           gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (tree), &iter,
1197                                          &root, n - 1);
1198           gtk_tree_store_remove (tree, &iter);
1199         }
1200
1201       add = !add;
1202     }
1203 }
1204
1205
1206 static gboolean
1207 specific_bug_311955_filter_func (GtkTreeModel *model,
1208                                  GtkTreeIter  *iter,
1209                                  gpointer      data)
1210 {
1211   int value;
1212
1213   gtk_tree_model_get (model, iter, 0, &value, -1);
1214
1215   return (value != 0);
1216 }
1217
1218 static void
1219 specific_bug_311955 (void)
1220 {
1221   /* This is a test case for GNOME Bugzilla bug 311955.  It was written
1222    * by Markku Vire.
1223    */
1224   GtkTreeIter iter, child, root;
1225   GtkTreeStore *store;
1226   GtkTreeModel *sort;
1227   GtkTreeModel *filter;
1228
1229   GtkWidget *window;
1230   GtkWidget *tree_view;
1231   int i;
1232   int n;
1233
1234   store = gtk_tree_store_new (1, G_TYPE_INT);
1235
1236   gtk_tree_store_append (store, &root, NULL);
1237   gtk_tree_store_set (store, &root, 0, 33, -1);
1238
1239   gtk_tree_store_append (store, &iter, &root);
1240   gtk_tree_store_set (store, &iter, 0, 50, -1);
1241
1242   gtk_tree_store_append (store, &iter, NULL);
1243   gtk_tree_store_set (store, &iter, 0, 22, -1);
1244
1245   sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (store));
1246   filter = gtk_tree_model_filter_new (sort, NULL);
1247
1248   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
1249                                           specific_bug_311955_filter_func,
1250                                           NULL, NULL);
1251
1252   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1253   tree_view = gtk_tree_view_new_with_model (filter);
1254   g_object_unref (store);
1255
1256   gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
1257
1258   while (gtk_events_pending ())
1259     gtk_main_iteration ();
1260
1261   /* Fill model */
1262   for (i = 0; i < 4; i++)
1263     {
1264       gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &root);
1265
1266       gtk_tree_store_append (store, &iter, &root);
1267
1268       if (i < 3)
1269         gtk_tree_store_set (store, &iter, 0, i, -1);
1270
1271       if (i % 2 == 0)
1272         {
1273           gtk_tree_store_append (store, &child, &iter);
1274           gtk_tree_store_set (store, &child, 0, 10, -1);
1275         }
1276     }
1277
1278   while (gtk_events_pending ())
1279     gtk_main_iteration ();
1280
1281   /* Remove bottommost child from the tree. */
1282   gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &root);
1283   n = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (store), &root);
1284
1285   if (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (store), &iter, &root, n - 2))
1286     {
1287       if (gtk_tree_model_iter_children (GTK_TREE_MODEL (store), &child, &iter))
1288         gtk_tree_store_remove (store, &child);
1289     }
1290   else
1291     g_assert_not_reached ();
1292 }
1293
1294 static void
1295 specific_bug_346800 (void)
1296 {
1297   /* This is a test case for GNOME Bugzilla bug 346800.  It was written
1298    * by Jonathan Matthew.
1299    */
1300
1301   GtkTreeIter node_iters[50];
1302   GtkTreeIter child_iters[50];
1303   GtkTreeModel *model;
1304   GtkTreeModelFilter *filter;
1305   GtkTreeStore *store;
1306   GType *columns;
1307   int i;
1308   int items = 50;
1309   columns = g_new (GType, 2);
1310   columns[0] = G_TYPE_STRING;
1311   columns[1] = G_TYPE_BOOLEAN;
1312   store = gtk_tree_store_newv (2, columns);
1313   model = GTK_TREE_MODEL (store);
1314
1315   filter = GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (model, NULL));
1316   gtk_tree_model_filter_set_visible_column (filter, 1);
1317
1318   for (i=0; i<items; i++)
1319     {
1320       /* allocate random amounts of junk, otherwise the filter model's arrays can expand without moving */
1321
1322       g_malloc (138);
1323       gtk_tree_store_append (store, &node_iters[i], NULL);
1324       gtk_tree_store_set (store, &node_iters[i],
1325                           0, "something",
1326                           1, ((i%6) == 0) ? FALSE : TRUE,
1327                           -1);
1328
1329       g_malloc (47);
1330       gtk_tree_store_append (store, &child_iters[i], &node_iters[i]);
1331       gtk_tree_store_set (store, &child_iters[i],
1332                           0, "something else",
1333                           1, FALSE,
1334                           -1);
1335       gtk_tree_model_filter_refilter (filter);
1336
1337       if (i > 6)
1338         {
1339           gtk_tree_store_set (GTK_TREE_STORE (model), &child_iters[i-1], 1,
1340                               (i & 1) ? TRUE : FALSE, -1);
1341           gtk_tree_model_filter_refilter (filter);
1342
1343           gtk_tree_store_set (GTK_TREE_STORE (model), &child_iters[i-2], 1,
1344                               (i & 1) ? FALSE: TRUE, -1);
1345           gtk_tree_model_filter_refilter (filter);
1346         }
1347     }
1348 }
1349
1350
1351 static void
1352 specific_bug_364946 (void)
1353 {
1354   /* This is a test case for GNOME Bugzilla bug 364946.  It was written
1355    * by Andreas Koehler.
1356    */
1357   GtkTreeStore *store;
1358   GtkTreeIter a, aa, aaa, aab, iter;
1359   GtkTreeModel *s_model;
1360
1361   store = gtk_tree_store_new (1, G_TYPE_STRING);
1362
1363   gtk_tree_store_append (store, &a, NULL);
1364   gtk_tree_store_set (store, &a, 0, "0", -1);
1365
1366   gtk_tree_store_append (store, &aa, &a);
1367   gtk_tree_store_set (store, &aa, 0, "0:0", -1);
1368
1369   gtk_tree_store_append (store, &aaa, &aa);
1370   gtk_tree_store_set (store, &aaa, 0, "0:0:0", -1);
1371
1372   gtk_tree_store_append (store, &aab, &aa);
1373   gtk_tree_store_set (store, &aab, 0, "0:0:1", -1);
1374
1375   s_model = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (store));
1376   gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (s_model), 0,
1377                                         GTK_SORT_ASCENDING);
1378
1379   gtk_tree_model_get_iter_from_string (s_model, &iter, "0:0:0");
1380
1381   gtk_tree_store_set (store, &aaa, 0, "0:0:0", -1);
1382   gtk_tree_store_remove (store, &aaa);
1383   gtk_tree_store_remove (store, &aab);
1384
1385   gtk_tree_model_sort_clear_cache (GTK_TREE_MODEL_SORT (s_model));
1386 }
1387
1388
1389 static gboolean
1390 specific_bug_464173_visible_func (GtkTreeModel *model,
1391                                   GtkTreeIter  *iter,
1392                                   gpointer      data)
1393 {
1394   gboolean *visible = (gboolean *)data;
1395
1396   return *visible;
1397 }
1398
1399 static void
1400 specific_bug_464173 (void)
1401 {
1402   /* Test case for GNOME Bugzilla bug 464173, test case written
1403    * by Andreas Koehler.
1404    */
1405   GtkTreeStore *model;
1406   GtkTreeModelFilter *f_model;
1407   GtkTreeIter iter1, iter2;
1408   GtkWidget *view;
1409   gboolean visible = TRUE;
1410
1411   model = gtk_tree_store_new (1, G_TYPE_STRING);
1412   gtk_tree_store_append (model, &iter1, NULL);
1413   gtk_tree_store_set (model, &iter1, 0, "Foo", -1);
1414   gtk_tree_store_append (model, &iter2, &iter1);
1415   gtk_tree_store_set (model, &iter2, 0, "Bar", -1);
1416
1417   f_model = GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (GTK_TREE_MODEL(model), NULL));
1418   gtk_tree_model_filter_set_visible_func (f_model,
1419                                           specific_bug_464173_visible_func,
1420                                           &visible, NULL);
1421
1422   view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (f_model));
1423
1424   visible = FALSE;
1425   gtk_tree_model_filter_refilter (f_model);
1426 }
1427
1428
1429 static gboolean
1430 specific_bug_540201_filter_func (GtkTreeModel *model,
1431                                  GtkTreeIter  *iter,
1432                                  gpointer      data)
1433 {
1434   gboolean has_children;
1435
1436   has_children = gtk_tree_model_iter_has_child (model, iter);
1437
1438   return has_children;
1439 }
1440
1441 static void
1442 specific_bug_540201 (void)
1443 {
1444   /* Test case for GNOME Bugzilla bug 540201, steps provided by
1445    * Charles Day.
1446    */
1447   GtkTreeIter iter, root;
1448   GtkTreeStore *store;
1449   GtkTreeModel *filter;
1450
1451   GtkWidget *tree_view;
1452
1453   store = gtk_tree_store_new (1, G_TYPE_INT);
1454
1455   gtk_tree_store_append (store, &root, NULL);
1456   gtk_tree_store_set (store, &root, 0, 33, -1);
1457
1458   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
1459   tree_view = gtk_tree_view_new_with_model (filter);
1460
1461   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
1462                                           specific_bug_540201_filter_func,
1463                                           NULL, NULL);
1464
1465   gtk_tree_store_append (store, &iter, &root);
1466   gtk_tree_store_set (store, &iter, 0, 50, -1);
1467
1468   gtk_tree_store_append (store, &iter, &root);
1469   gtk_tree_store_set (store, &iter, 0, 22, -1);
1470
1471
1472   gtk_tree_store_append (store, &root, NULL);
1473   gtk_tree_store_set (store, &root, 0, 33, -1);
1474
1475   gtk_tree_store_append (store, &iter, &root);
1476   gtk_tree_store_set (store, &iter, 0, 22, -1);
1477 }
1478
1479
1480 static gboolean
1481 specific_bug_549287_visible_func (GtkTreeModel *model,
1482                                   GtkTreeIter  *iter,
1483                                   gpointer      data)
1484 {
1485   gboolean result = FALSE;
1486
1487   result = gtk_tree_model_iter_has_child (model, iter);
1488
1489   return result;
1490 }
1491
1492 static void
1493 specific_bug_549287 (void)
1494 {
1495   /* Test case for GNOME Bugzilla bug 529287, provided by Julient Puydt */
1496
1497   int i;
1498   GtkTreeStore *store;
1499   GtkTreeModel *filtered;
1500   GtkWidget *view;
1501   GtkTreeIter iter;
1502   GtkTreeIter *swap, *parent, *child;
1503
1504   store = gtk_tree_store_new (1, G_TYPE_STRING);
1505   filtered = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
1506   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filtered),
1507                                           specific_bug_549287_visible_func,
1508                                           NULL, NULL);
1509
1510   view = gtk_tree_view_new_with_model (filtered);
1511
1512   for (i = 0; i < 4; i++)
1513     {
1514       if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter))
1515         {
1516           parent = gtk_tree_iter_copy (&iter);
1517           child = gtk_tree_iter_copy (&iter);
1518
1519           while (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (store),
1520                                                 child, parent, 0))
1521             {
1522
1523               swap = parent;
1524               parent = child;
1525               child = swap;
1526             }
1527
1528           gtk_tree_store_append (store, child, parent);
1529           gtk_tree_store_set (store, child,
1530                               0, "Something",
1531                               -1);
1532
1533           gtk_tree_iter_free (parent);
1534           gtk_tree_iter_free (child);
1535         }
1536       else
1537         {
1538           gtk_tree_store_append (store, &iter, NULL);
1539           gtk_tree_store_set (store, &iter,
1540                               0, "Something",
1541                               -1);
1542         }
1543
1544       /* since we inserted something, we changed the visibility conditions: */
1545       gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (filtered));
1546     }
1547 }
1548
1549 /* main */
1550
1551 int
1552 main (int    argc,
1553       char **argv)
1554 {
1555   gtk_test_init (&argc, &argv, NULL);
1556
1557   g_test_add ("/FilterModel/self/verify-test-suite",
1558               FilterTest, NULL,
1559               filter_test_setup,
1560               verify_test_suite,
1561               filter_test_teardown);
1562
1563   g_test_add ("/FilterModel/self/verify-test-suite/vroot/depth-1",
1564               FilterTest, gtk_tree_path_new_from_indices (2, -1),
1565               filter_test_setup,
1566               verify_test_suite_vroot,
1567               filter_test_teardown);
1568   g_test_add ("/FilterModel/self/verify-test-suite/vroot/depth-2",
1569               FilterTest, gtk_tree_path_new_from_indices (2, 3, -1),
1570               filter_test_setup,
1571               verify_test_suite_vroot,
1572               filter_test_teardown);
1573
1574
1575   g_test_add ("/FilterModel/filled/hide-root-level",
1576               FilterTest, NULL,
1577               filter_test_setup,
1578               filled_hide_root_level,
1579               filter_test_teardown);
1580   g_test_add ("/FilterModel/filled/hide-child-levels",
1581               FilterTest, NULL,
1582               filter_test_setup,
1583               filled_hide_child_levels,
1584               filter_test_teardown);
1585
1586   g_test_add ("/FilterModel/filled/hide-root-level/vroot",
1587               FilterTest, gtk_tree_path_new_from_indices (2, -1),
1588               filter_test_setup,
1589               filled_vroot_hide_root_level,
1590               filter_test_teardown);
1591   g_test_add ("/FilterModel/filled/hide-child-levels/vroot",
1592               FilterTest, gtk_tree_path_new_from_indices (2, -1),
1593               filter_test_setup,
1594               filled_vroot_hide_child_levels,
1595               filter_test_teardown);
1596
1597
1598   g_test_add ("/FilterModel/empty/show-nodes",
1599               FilterTest, NULL,
1600               filter_test_setup_empty,
1601               empty_show_nodes,
1602               filter_test_teardown);
1603
1604   g_test_add ("/FilterModel/empty/show-nodes/vroot",
1605               FilterTest, gtk_tree_path_new_from_indices (2, -1),
1606               filter_test_setup_empty,
1607               empty_vroot_show_nodes,
1608               filter_test_teardown);
1609
1610
1611   g_test_add ("/FilterModel/unfiltered/hide-single",
1612               FilterTest, NULL,
1613               filter_test_setup_unfiltered,
1614               unfiltered_hide_single,
1615               filter_test_teardown);
1616   g_test_add ("/FilterModel/unfiltered/hide-single-child",
1617               FilterTest, NULL,
1618               filter_test_setup_unfiltered,
1619               unfiltered_hide_single_child,
1620               filter_test_teardown);
1621   g_test_add ("/FilterModel/unfiltered/hide-single-multi-level",
1622               FilterTest, NULL,
1623               filter_test_setup_unfiltered,
1624               unfiltered_hide_single_multi_level,
1625               filter_test_teardown);
1626
1627   g_test_add ("/FilterModel/unfiltered/show-single",
1628               FilterTest, NULL,
1629               filter_test_setup_empty_unfiltered,
1630               unfiltered_show_single,
1631               filter_test_teardown);
1632   g_test_add ("/FilterModel/unfiltered/show-single-child",
1633               FilterTest, NULL,
1634               filter_test_setup_empty_unfiltered,
1635               unfiltered_show_single_child,
1636               filter_test_teardown);
1637   g_test_add ("/FilterModel/unfiltered/show-single-multi-level",
1638               FilterTest, NULL,
1639               filter_test_setup_empty_unfiltered,
1640               unfiltered_show_single_multi_level,
1641               filter_test_teardown);
1642
1643
1644   g_test_add_func ("/FilterModel/specific/path-dependent-filter",
1645                    specific_path_dependent_filter);
1646   g_test_add_func ("/FilterModel/specific/append-after-collapse",
1647                    specific_append_after_collapse);
1648   g_test_add_func ("/FilterModel/specific/sort-filter-remove-node",
1649                    specific_sort_filter_remove_node);
1650   g_test_add_func ("/FilterModel/specific/sort-filter-remove-root",
1651                    specific_sort_filter_remove_root);
1652   g_test_add_func ("/FilterModel/specific/filter-add-child",
1653                    specific_filter_add_child);
1654
1655   g_test_add_func ("/FilterModel/specific/bug-300089",
1656                    specific_bug_300089);
1657   g_test_add_func ("/FilterModel/specific/bug-301558",
1658                    specific_bug_301558);
1659   g_test_add_func ("/FilterModel/specific/bug-311955",
1660                    specific_bug_311955);
1661   g_test_add_func ("/FilterModel/specific/bug-346800",
1662                    specific_bug_346800);
1663   g_test_add_func ("/FilterModel/specific/bug-364946",
1664                    specific_bug_364946);
1665   g_test_add_func ("/FilterModel/specific/bug-464173",
1666                    specific_bug_464173);
1667   g_test_add_func ("/FilterModel/specific/bug-540201",
1668                    specific_bug_540201);
1669   g_test_add_func ("/FilterModel/specific/bug-549287",
1670                    specific_bug_549287);
1671
1672   return g_test_run ();
1673 }