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