]> Pileus Git - ~andy/gtk/blob - gtk/tests/filtermodel.c
Refilter is required after setting visible column
[~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       GtkTreeIter iter;
280
281       gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (filter),
282                                            &iter, level);
283       l = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (filter), &iter);
284       g_return_if_fail (l == length);
285     }
286 }
287
288 static void
289 set_path_visibility (FilterTest  *fixture,
290                      const gchar *path,
291                      gboolean     visible)
292 {
293   GtkTreeIter store_iter;
294
295   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
296                                        &store_iter, path);
297   gtk_tree_store_set (fixture->store, &store_iter,
298                       1, visible,
299                       -1);
300 }
301
302 static void
303 insert_path_with_visibility (FilterTest  *fixture,
304                              const gchar *path_string,
305                              gboolean     visible)
306 {
307   int position;
308   GtkTreePath *path;
309   GtkTreeIter parent, iter;
310
311   path = gtk_tree_path_new_from_string (path_string);
312   position = gtk_tree_path_get_indices (path)[gtk_tree_path_get_depth (path)];
313   gtk_tree_path_up (path);
314
315   if (gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->store), &parent, path))
316     {
317       gtk_tree_store_insert (fixture->store, &iter, &parent, position);
318       create_tree_store_set_values (fixture->store, &iter, visible);
319     }
320   gtk_tree_path_free (path);
321 }
322
323 /*
324  * The actual tests.
325  */
326
327 static void
328 verify_test_suite (FilterTest    *fixture,
329                    gconstpointer  user_data)
330 {
331   check_filter_model (fixture);
332 }
333
334 static void
335 verify_test_suite_vroot (FilterTest    *fixture,
336                          gconstpointer  user_data)
337 {
338   check_filter_model_with_root (fixture, (GtkTreePath *)user_data);
339 }
340
341
342 static void
343 filled_hide_root_level (FilterTest    *fixture,
344                         gconstpointer  user_data)
345 {
346   set_path_visibility (fixture, "2", FALSE);
347   check_filter_model (fixture);
348   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 1);
349
350   set_path_visibility (fixture, "0", FALSE);
351   check_filter_model (fixture);
352   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 2);
353
354   set_path_visibility (fixture, "4", FALSE);
355   check_filter_model (fixture);
356   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 3);
357
358
359   /* Hide remaining */
360   set_path_visibility (fixture, "1", FALSE);
361   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 4);
362
363   set_path_visibility (fixture, "3", FALSE);
364   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 5);
365
366   check_filter_model (fixture);
367
368   /* Show some */
369   set_path_visibility (fixture, "1", TRUE);
370   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 4);
371
372   set_path_visibility (fixture, "3", TRUE);
373   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 3);
374
375   check_filter_model (fixture);
376 }
377
378 static void
379 filled_hide_child_levels (FilterTest    *fixture,
380                           gconstpointer  user_data)
381 {
382   set_path_visibility (fixture, "0:2", FALSE);
383   check_filter_model (fixture);
384   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
385   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 1);
386
387   set_path_visibility (fixture, "0:4", FALSE);
388   check_filter_model (fixture);
389   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
390   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
391
392   set_path_visibility (fixture, "0:4:3", FALSE);
393   check_filter_model (fixture);
394   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
395   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
396
397   set_path_visibility (fixture, "0:4:0", FALSE);
398   set_path_visibility (fixture, "0:4:1", FALSE);
399   set_path_visibility (fixture, "0:4:2", FALSE);
400   set_path_visibility (fixture, "0:4:4", FALSE);
401   check_filter_model (fixture);
402   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
403   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
404
405   set_path_visibility (fixture, "0:4", TRUE);
406   /* Since "0:2" is hidden, "0:4" must be "0:3" in the filter model */
407   check_filter_model (fixture);
408   check_level_length (fixture->filter, "0:3", 0);
409
410   set_path_visibility (fixture, "0:2", TRUE);
411   check_filter_model (fixture);
412   check_level_length (fixture->filter, "0:2", LEVEL_LENGTH);
413   check_level_length (fixture->filter, "0:3", LEVEL_LENGTH);
414   check_level_length (fixture->filter, "0:4", 0);
415
416   set_path_visibility (fixture, "0:4:2", TRUE);
417   set_path_visibility (fixture, "0:4:4", TRUE);
418   check_level_length (fixture->filter, "0:4", 2);
419 }
420
421
422 static void
423 filled_vroot_hide_root_level (FilterTest    *fixture,
424                               gconstpointer  user_data)
425 {
426   GtkTreePath *path = (GtkTreePath *)user_data;
427
428   /* These changes do not affect the filter's root level */
429   set_path_visibility (fixture, "0", FALSE);
430   check_filter_model_with_root (fixture, path);
431   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
432   check_level_length (fixture->filter, "0", LEVEL_LENGTH);
433
434   set_path_visibility (fixture, "4", FALSE);
435   check_filter_model_with_root (fixture, path);
436   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
437   check_level_length (fixture->filter, "0", LEVEL_LENGTH);
438
439   /* Even though we set the virtual root parent node to FALSE,
440    * the virtual root contents remain.
441    */
442   set_path_visibility (fixture, "2", FALSE);
443   check_filter_model_with_root (fixture, path);
444   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
445   check_level_length (fixture->filter, "0", LEVEL_LENGTH);
446
447   /* No change */
448   set_path_visibility (fixture, "1", FALSE);
449   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
450   check_level_length (fixture->filter, "0", LEVEL_LENGTH);
451
452   set_path_visibility (fixture, "3", FALSE);
453   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
454   check_level_length (fixture->filter, "0", LEVEL_LENGTH);
455
456   check_filter_model_with_root (fixture, path);
457
458   /* Show some */
459   set_path_visibility (fixture, "2", TRUE);
460   check_filter_model_with_root (fixture, path);
461   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
462   check_level_length (fixture->filter, "0", LEVEL_LENGTH);
463
464   set_path_visibility (fixture, "1", TRUE);
465   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
466   check_level_length (fixture->filter, "0", LEVEL_LENGTH);
467
468   set_path_visibility (fixture, "3", TRUE);
469   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
470   check_level_length (fixture->filter, "0", LEVEL_LENGTH);
471
472   check_filter_model_with_root (fixture, path);
473
474   /* Now test changes in the virtual root level */
475   set_path_visibility (fixture, "2:2", FALSE);
476   check_filter_model_with_root (fixture, path);
477   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 1);
478
479   set_path_visibility (fixture, "2:4", FALSE);
480   check_filter_model_with_root (fixture, path);
481   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 2);
482
483   set_path_visibility (fixture, "1:4", FALSE);
484   check_filter_model_with_root (fixture, path);
485   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 2);
486
487   set_path_visibility (fixture, "2:4", TRUE);
488   check_filter_model_with_root (fixture, path);
489   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 1);
490
491   set_path_visibility (fixture, "2", FALSE);
492   check_filter_model_with_root (fixture, path);
493   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 1);
494
495   set_path_visibility (fixture, "2:0", FALSE);
496   set_path_visibility (fixture, "2:1", FALSE);
497   set_path_visibility (fixture, "2:2", FALSE);
498   set_path_visibility (fixture, "2:3", FALSE);
499   set_path_visibility (fixture, "2:4", FALSE);
500   check_filter_model_with_root (fixture, path);
501   check_level_length (fixture->filter, NULL, 0);
502
503   set_path_visibility (fixture, "2", TRUE);
504   check_filter_model_with_root (fixture, path);
505   check_level_length (fixture->filter, NULL, 0);
506
507   set_path_visibility (fixture, "1:4", FALSE);
508   check_filter_model_with_root (fixture, path);
509   check_level_length (fixture->filter, NULL, 0);
510
511   set_path_visibility (fixture, "2:4", TRUE);
512   check_filter_model_with_root (fixture, path);
513   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 4);
514
515   set_path_visibility (fixture, "2:4", FALSE);
516   check_filter_model_with_root (fixture, path);
517   check_level_length (fixture->filter, NULL, 0);
518
519   set_path_visibility (fixture, "2", FALSE);
520   check_filter_model_with_root (fixture, path);
521   check_level_length (fixture->filter, NULL, 0);
522
523   set_path_visibility (fixture, "2:0", TRUE);
524   set_path_visibility (fixture, "2:1", TRUE);
525   set_path_visibility (fixture, "2:2", TRUE);
526   check_filter_model_with_root (fixture, path);
527   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 2);
528
529   set_path_visibility (fixture, "2", TRUE);
530   check_filter_model_with_root (fixture, path);
531   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 2);
532 }
533
534 static void
535 filled_vroot_hide_child_levels (FilterTest    *fixture,
536                                 gconstpointer  user_data)
537 {
538   GtkTreePath *path = (GtkTreePath *)user_data;
539
540   set_path_visibility (fixture, "2:0:2", FALSE);
541   check_filter_model_with_root (fixture, path);
542   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
543   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 1);
544
545   set_path_visibility (fixture, "2:0:4", FALSE);
546   check_filter_model_with_root (fixture, path);
547   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
548   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
549
550   set_path_visibility (fixture, "2:0:4:3", FALSE);
551   check_filter_model_with_root (fixture, path);
552   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
553   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
554
555   set_path_visibility (fixture, "2:0:4:0", FALSE);
556   set_path_visibility (fixture, "2:0:4:1", FALSE);
557   set_path_visibility (fixture, "2:0:4:2", FALSE);
558   set_path_visibility (fixture, "2:0:4:4", FALSE);
559   check_filter_model_with_root (fixture, path);
560   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
561   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
562
563   set_path_visibility (fixture, "2:0:4", TRUE);
564   /* Since "0:2" is hidden, "0:4" must be "0:3" in the filter model */
565   check_filter_model_with_root (fixture, path);
566   check_level_length (fixture->filter, "0:3", 0);
567
568   set_path_visibility (fixture, "2:0:2", TRUE);
569   check_filter_model_with_root (fixture, path);
570   check_level_length (fixture->filter, "0:2", LEVEL_LENGTH);
571   check_level_length (fixture->filter, "0:3", LEVEL_LENGTH);
572   check_level_length (fixture->filter, "0:4", 0);
573
574   set_path_visibility (fixture, "2:0:4:2", TRUE);
575   set_path_visibility (fixture, "2:0:4:4", TRUE);
576   check_level_length (fixture->filter, "0:4", 2);
577 }
578
579
580 static void
581 empty_show_nodes (FilterTest    *fixture,
582                   gconstpointer  user_data)
583 {
584   check_filter_model (fixture);
585   check_level_length (fixture->filter, NULL, 0);
586
587   set_path_visibility (fixture, "3", TRUE);
588   check_filter_model (fixture);
589   check_level_length (fixture->filter, NULL, 1);
590   check_level_length (fixture->filter, "0", 0);
591
592   set_path_visibility (fixture, "3:2:2", TRUE);
593   check_filter_model (fixture);
594   check_level_length (fixture->filter, NULL, 1);
595   check_level_length (fixture->filter, "0", 0);
596
597   set_path_visibility (fixture, "3:2", TRUE);
598   check_filter_model (fixture);
599   check_level_length (fixture->filter, NULL, 1);
600   check_level_length (fixture->filter, "0", 1);
601   check_level_length (fixture->filter, "0:0", 1);
602   check_level_length (fixture->filter, "0:0:0", 0);
603
604   set_path_visibility (fixture, "3", FALSE);
605   check_filter_model (fixture);
606   check_level_length (fixture->filter, NULL, 0);
607
608   set_path_visibility (fixture, "3:2:1", TRUE);
609   set_path_visibility (fixture, "3", TRUE);
610   check_filter_model (fixture);
611   check_level_length (fixture->filter, NULL, 1);
612   check_level_length (fixture->filter, "0", 1);
613   check_level_length (fixture->filter, "0:0", 2);
614   check_level_length (fixture->filter, "0:0:0", 0);
615 }
616
617 static void
618 empty_vroot_show_nodes (FilterTest    *fixture,
619                         gconstpointer  user_data)
620 {
621   GtkTreePath *path = (GtkTreePath *)user_data;
622
623   check_filter_model_with_root (fixture, path);
624   check_level_length (fixture->filter, NULL, 0);
625
626   set_path_visibility (fixture, "2", TRUE);
627   check_filter_model_with_root (fixture, path);
628   check_level_length (fixture->filter, NULL, 0);
629
630   set_path_visibility (fixture, "2:2:2", TRUE);
631   check_filter_model_with_root (fixture, path);
632   check_level_length (fixture->filter, NULL, 0);
633
634   set_path_visibility (fixture, "2:2", TRUE);
635   check_filter_model_with_root (fixture, path);
636   check_level_length (fixture->filter, NULL, 1);
637   check_level_length (fixture->filter, "0", 1);
638   check_level_length (fixture->filter, "0:0", 0);
639
640   set_path_visibility (fixture, "3", TRUE);
641   check_filter_model_with_root (fixture, path);
642   check_level_length (fixture->filter, NULL, 1);
643
644   set_path_visibility (fixture, "2:2", FALSE);
645   check_filter_model_with_root (fixture, path);
646   check_level_length (fixture->filter, NULL, 0);
647
648   set_path_visibility (fixture, "2:2:1", TRUE);
649   set_path_visibility (fixture, "2:2", TRUE);
650   check_filter_model_with_root (fixture, path);
651   check_level_length (fixture->filter, NULL, 1);
652   check_level_length (fixture->filter, "0", 2);
653   check_level_length (fixture->filter, "0:1", 0);
654 }
655
656
657 static void
658 unfiltered_hide_single (FilterTest    *fixture,
659                         gconstpointer  user_data)
660
661 {
662   set_path_visibility (fixture, "2", FALSE);
663
664   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
665
666   filter_test_enable_filter (fixture);
667
668   check_filter_model (fixture);
669   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 1);
670 }
671
672 static void
673 unfiltered_hide_single_child (FilterTest    *fixture,
674                               gconstpointer  user_data)
675
676 {
677   set_path_visibility (fixture, "2:2", FALSE);
678
679   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
680   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
681
682   filter_test_enable_filter (fixture);
683
684   check_filter_model (fixture);
685   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
686   check_level_length (fixture->filter, "2", LEVEL_LENGTH - 1);
687 }
688
689 static void
690 unfiltered_hide_single_multi_level (FilterTest    *fixture,
691                                     gconstpointer  user_data)
692
693 {
694   set_path_visibility (fixture, "2:2:2", FALSE);
695   set_path_visibility (fixture, "2:2", FALSE);
696
697   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
698   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
699   check_level_length (fixture->filter, "2:2", LEVEL_LENGTH);
700
701   filter_test_enable_filter (fixture);
702
703   check_filter_model (fixture);
704   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
705   check_level_length (fixture->filter, "2", LEVEL_LENGTH - 1);
706
707   set_path_visibility (fixture, "2:2", TRUE);
708
709   check_filter_model (fixture);
710   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
711   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
712   check_level_length (fixture->filter, "2:2", LEVEL_LENGTH - 1);
713 }
714
715
716 static void
717 unfiltered_show_single (FilterTest    *fixture,
718                         gconstpointer  user_data)
719
720 {
721   set_path_visibility (fixture, "2", TRUE);
722
723   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
724
725   filter_test_enable_filter (fixture);
726
727   check_filter_model (fixture);
728   check_level_length (fixture->filter, NULL, 1);
729 }
730
731 static void
732 unfiltered_show_single_child (FilterTest    *fixture,
733                               gconstpointer  user_data)
734
735 {
736   set_path_visibility (fixture, "2:2", TRUE);
737
738   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
739   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
740
741   filter_test_enable_filter (fixture);
742
743   check_filter_model (fixture);
744   check_level_length (fixture->filter, NULL, 0);
745
746   set_path_visibility (fixture, "2", TRUE);
747   check_level_length (fixture->filter, NULL, 1);
748   check_level_length (fixture->filter, "2", 1);
749 }
750
751 static void
752 unfiltered_show_single_multi_level (FilterTest    *fixture,
753                                     gconstpointer  user_data)
754
755 {
756   set_path_visibility (fixture, "2:2:2", TRUE);
757   set_path_visibility (fixture, "2:2", TRUE);
758
759   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
760   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
761   check_level_length (fixture->filter, "2:2", LEVEL_LENGTH);
762
763   filter_test_enable_filter (fixture);
764
765   check_filter_model (fixture);
766   check_level_length (fixture->filter, NULL, 0);
767
768   set_path_visibility (fixture, "2", TRUE);
769   check_filter_model (fixture);
770   check_level_length (fixture->filter, NULL, 1);
771   check_level_length (fixture->filter, "2", 1);
772   check_level_length (fixture->filter, "2:2", 1);
773 }
774
775
776 static gboolean
777 specific_path_dependent_filter_func (GtkTreeModel *model,
778                                      GtkTreeIter  *iter,
779                                      gpointer      data)
780 {
781   GtkTreePath *path;
782
783   path = gtk_tree_model_get_path (model, iter);
784   if (gtk_tree_path_get_indices (path)[0] < 4)
785     return FALSE;
786
787   return TRUE;
788 }
789
790 static void
791 specific_path_dependent_filter (void)
792 {
793   int i;
794   GtkTreeIter iter;
795   GtkListStore *list;
796   GtkTreeModel *sort;
797   GtkTreeModel *filter;
798
799   list = gtk_list_store_new (1, G_TYPE_INT);
800   gtk_list_store_insert_with_values (list, &iter, 0, 0, 1, -1);
801   gtk_list_store_insert_with_values (list, &iter, 1, 0, 2, -1);
802   gtk_list_store_insert_with_values (list, &iter, 2, 0, 3, -1);
803   gtk_list_store_insert_with_values (list, &iter, 3, 0, 4, -1);
804   gtk_list_store_insert_with_values (list, &iter, 4, 0, 5, -1);
805   gtk_list_store_insert_with_values (list, &iter, 5, 0, 6, -1);
806   gtk_list_store_insert_with_values (list, &iter, 6, 0, 7, -1);
807   gtk_list_store_insert_with_values (list, &iter, 7, 0, 8, -1);
808
809   sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (list));
810   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (sort), NULL);
811   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
812                                           specific_path_dependent_filter_func,
813                                           NULL, NULL);
814
815   gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sort), 0,
816                                         GTK_SORT_DESCENDING);
817
818   for (i = 0; i < 4; i++)
819     {
820       if (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (list), &iter,
821                                          NULL, 1))
822         gtk_list_store_remove (list, &iter);
823
824       if (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (list), &iter,
825                                          NULL, 2))
826         gtk_list_store_remove (list, &iter);
827     }
828 }
829
830
831 static gboolean
832 specific_append_after_collapse_visible_func (GtkTreeModel *model,
833                                              GtkTreeIter  *iter,
834                                              gpointer      data)
835 {
836   gint number;
837   gboolean hide_negative_numbers;
838
839   gtk_tree_model_get (model, iter, 1, &number, -1);
840   hide_negative_numbers = GPOINTER_TO_INT (g_object_get_data (data, "private-hide-negative-numbers"));
841
842   return (number >= 0 || !hide_negative_numbers);
843 }
844
845 static void
846 specific_append_after_collapse (void)
847 {
848   /* This test is based on one of the test cases I found in my
849    * old test cases directory.  I unfortunately do not have a record
850    * from who this test case originated.  -Kris.
851    *
852    * General idea:
853    * - Construct tree.
854    * - Show tree, expand, collapse.
855    * - Add a row.
856    */
857
858   GtkTreeIter iter;
859   GtkTreeIter child_iter;
860   GtkTreeIter child_iter2;
861   GtkTreePath *append_path;
862   GtkTreeStore *store;
863   GtkTreeModel *filter;
864   GtkTreeModel *sort;
865
866   GtkWidget *window;
867   GtkWidget *tree_view;
868
869   store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_INT);
870
871   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
872   g_object_set_data (G_OBJECT (filter), "private-hide-negative-numbers",
873                      GINT_TO_POINTER (FALSE));
874   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
875                                           specific_append_after_collapse_visible_func,
876                                           filter, NULL);
877
878   sort = gtk_tree_model_sort_new_with_model (filter);
879
880   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
881   tree_view = gtk_tree_view_new_with_model (sort);
882   gtk_container_add (GTK_CONTAINER (window), tree_view);
883   gtk_widget_realize (tree_view);
884
885   while (gtk_events_pending ())
886     gtk_main_iteration ();
887
888   gtk_tree_store_prepend (store, &iter, NULL);
889   gtk_tree_store_set (store, &iter,
890                       0, "hallo", 1, 1, -1);
891
892   gtk_tree_store_append (store, &child_iter, &iter);
893   gtk_tree_store_set (store, &child_iter,
894                       0, "toemaar", 1, 1, -1);
895
896   gtk_tree_store_append (store, &child_iter2, &child_iter);
897   gtk_tree_store_set (store, &child_iter2,
898                       0, "very deep", 1, 1, -1);
899
900   append_path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &child_iter2);
901
902   gtk_tree_store_append (store, &child_iter, &iter);
903   gtk_tree_store_set (store, &child_iter,
904                       0, "sja", 1, 1, -1);
905
906   gtk_tree_store_append (store, &child_iter, &iter);
907   gtk_tree_store_set (store, &child_iter,
908                       0, "some word", 1, -1, -1);
909
910   /* Expand and collapse the tree */
911   gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
912   while (gtk_events_pending ())
913     gtk_main_iteration ();
914
915   gtk_tree_view_collapse_all (GTK_TREE_VIEW (tree_view));
916   while (gtk_events_pending ())
917     gtk_main_iteration ();
918
919   /* Add another it */
920   g_object_set_data (G_OBJECT (filter), "private-hide-negative-numbers",
921                      GINT_TO_POINTER (TRUE));
922
923   if (gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, append_path))
924     {
925       gtk_tree_store_append (store, &child_iter, &iter);
926       gtk_tree_store_set (store, &child_iter,
927                           0, "new new new !!", 1, 1, -1);
928     }
929   gtk_tree_path_free (append_path);
930
931   /* Expand */
932   gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
933   while (gtk_events_pending ())
934     gtk_main_iteration ();
935 }
936
937
938 static gint
939 specific_sort_filter_remove_node_compare_func (GtkTreeModel  *model,
940                                                GtkTreeIter   *iter1,
941                                                GtkTreeIter   *iter2,
942                                                gpointer       data)
943 {
944   return -1;
945 }
946
947 static gboolean
948 specific_sort_filter_remove_node_visible_func (GtkTreeModel  *model,
949                                                GtkTreeIter   *iter,
950                                                gpointer       data)
951 {
952   char *item = NULL;
953
954   /* Do reference the model */
955   gtk_tree_model_get (model, iter, 0, &item, -1);
956   g_free (item);
957
958   return FALSE;
959 }
960
961 static void
962 specific_sort_filter_remove_node (void)
963 {
964   /* This test is based on one of the test cases I found in my
965    * old test cases directory.  I unfortunately do not have a record
966    * from who this test case originated.  -Kris.
967    *
968    * General idea:
969    *  - Create tree store, sort, filter models.  The sort model has
970    *    a default sort func that is enabled, filter model a visible func
971    *    that defaults to returning FALSE.
972    *  - Remove a node from the tree store.
973    */
974
975   GtkTreeIter iter;
976   GtkTreeStore *store;
977   GtkTreeModel *filter;
978   GtkTreeModel *sort;
979
980   GtkWidget *window;
981   GtkWidget *tree_view;
982
983   store = gtk_tree_store_new (1, G_TYPE_STRING);
984   gtk_tree_store_append (store, &iter, NULL);
985   gtk_tree_store_set (store, &iter, 0, "Hello1", -1);
986
987   gtk_tree_store_append (store, &iter, NULL);
988   gtk_tree_store_set (store, &iter, 0, "Hello2", -1);
989
990   sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (store));
991   gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (sort),
992                                            specific_sort_filter_remove_node_compare_func, NULL, NULL);
993
994   filter = gtk_tree_model_filter_new (sort, NULL);
995   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
996                                           specific_sort_filter_remove_node_visible_func,
997                                           filter, NULL);
998
999
1000   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1001   tree_view = gtk_tree_view_new_with_model (filter);
1002   gtk_container_add (GTK_CONTAINER (window), tree_view);
1003   gtk_widget_realize (tree_view);
1004
1005   while (gtk_events_pending ())
1006     gtk_main_iteration ();
1007
1008   /* Remove a node */
1009   gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter);
1010   gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter);
1011   gtk_tree_store_remove (store, &iter);
1012
1013   while (gtk_events_pending ())
1014     gtk_main_iteration ();
1015 }
1016
1017
1018 static void
1019 specific_sort_filter_remove_root (void)
1020 {
1021   /* This test is based on one of the test cases I found in my
1022    * old test cases directory.  I unfortunately do not have a record
1023    * from who this test case originated.  -Kris.
1024    */
1025
1026   GtkTreeModel *model, *sort, *filter;
1027   GtkTreeIter root, mid, leaf;
1028   GtkTreePath *path;
1029
1030   model = GTK_TREE_MODEL (gtk_tree_store_new (1, G_TYPE_INT));
1031   gtk_tree_store_append (GTK_TREE_STORE (model), &root, NULL);
1032   gtk_tree_store_append (GTK_TREE_STORE (model), &mid, &root);
1033   gtk_tree_store_append (GTK_TREE_STORE (model), &leaf, &mid);
1034
1035   path = gtk_tree_model_get_path (model, &mid);
1036
1037   sort = gtk_tree_model_sort_new_with_model (model);
1038   filter = gtk_tree_model_filter_new (sort, path);
1039
1040   gtk_tree_store_remove (GTK_TREE_STORE (model), &root);
1041
1042   g_object_unref (filter);
1043   g_object_unref (sort);
1044   g_object_unref (model);
1045 }
1046
1047
1048 static void
1049 specific_filter_add_child (void)
1050 {
1051   /* This test is based on one of the test cases I found in my
1052    * old test cases directory.  I unfortunately do not have a record
1053    * from who this test case originated.  -Kris.
1054    */
1055
1056   GtkTreeIter iter;
1057   GtkTreeIter iter_first;
1058   GtkTreeIter child;
1059   GtkTreeStore *store;
1060   GtkTreeModel *filter;
1061
1062   store = gtk_tree_store_new (1, G_TYPE_STRING);
1063
1064   gtk_tree_store_append (store, &iter_first, NULL);
1065   gtk_tree_store_set (store, &iter_first, 0, "Hello", -1);
1066
1067   gtk_tree_store_append (store, &iter, NULL);
1068   gtk_tree_store_set (store, &iter, 0, "Hello", -1);
1069
1070   gtk_tree_store_append (store, &iter, NULL);
1071   gtk_tree_store_set (store, &iter, 0, "Hello", -1);
1072
1073   gtk_tree_store_append (store, &iter, NULL);
1074   gtk_tree_store_set (store, &iter, 0, "Hello", -1);
1075
1076   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
1077
1078   gtk_tree_store_set (store, &iter, 0, "Hello", -1);
1079   gtk_tree_store_append (store, &child, &iter_first);
1080   gtk_tree_store_set (store, &child, 0, "Hello", -1);
1081 }
1082
1083
1084 static void
1085 specific_bug_300089 (void)
1086 {
1087   /* Test case for GNOME Bugzilla bug 300089.  Written by
1088    * Matthias Clasen.
1089    */
1090   GtkTreeModel *sort_model, *child_model;
1091   GtkTreePath *path;
1092   GtkTreeIter iter, iter2, sort_iter;
1093
1094   child_model = GTK_TREE_MODEL (gtk_tree_store_new (1, G_TYPE_STRING));
1095
1096   gtk_tree_store_append (GTK_TREE_STORE (child_model), &iter, NULL);
1097   gtk_tree_store_set (GTK_TREE_STORE (child_model), &iter, 0, "A", -1);
1098   gtk_tree_store_append (GTK_TREE_STORE (child_model), &iter, NULL);
1099   gtk_tree_store_set (GTK_TREE_STORE (child_model), &iter, 0, "B", -1);
1100
1101   gtk_tree_store_append (GTK_TREE_STORE (child_model), &iter2, &iter);
1102   gtk_tree_store_set (GTK_TREE_STORE (child_model), &iter2, 0, "D", -1);
1103   gtk_tree_store_append (GTK_TREE_STORE (child_model), &iter2, &iter);
1104   gtk_tree_store_set (GTK_TREE_STORE (child_model), &iter2, 0, "E", -1);
1105
1106   gtk_tree_store_append (GTK_TREE_STORE (child_model), &iter, NULL);
1107   gtk_tree_store_set (GTK_TREE_STORE (child_model), &iter, 0, "C", -1);
1108
1109
1110   sort_model = GTK_TREE_MODEL (gtk_tree_model_sort_new_with_model (child_model));
1111   gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sort_model),
1112                                         0, GTK_SORT_ASCENDING);
1113
1114   path = gtk_tree_path_new_from_indices (1, 1, -1);
1115
1116   /* make sure a level is constructed */ 
1117   gtk_tree_model_get_iter (sort_model, &sort_iter, path);
1118
1119   /* change the "E" row in a way that causes it to change position */ 
1120   gtk_tree_model_get_iter (child_model, &iter, path);
1121   gtk_tree_store_set (GTK_TREE_STORE (child_model), &iter, 0, "A", -1);
1122 }
1123
1124
1125 static int
1126 specific_bug_301558_sort_func (GtkTreeModel *model,
1127                                GtkTreeIter  *a,
1128                                GtkTreeIter  *b,
1129                                gpointer      data)
1130 {
1131   int i, j;
1132
1133   gtk_tree_model_get (model, a, 0, &i, -1);
1134   gtk_tree_model_get (model, b, 0, &j, -1);
1135
1136   return j - i;
1137 }
1138
1139 static void
1140 specific_bug_301558 (void)
1141 {
1142   /* Test case for GNOME Bugzilla bug 301558 provided by
1143    * Markku Vire.
1144    */
1145   GtkTreeStore *tree;
1146   GtkTreeModel *filter;
1147   GtkTreeModel *sort;
1148   GtkTreeIter root, iter, iter2;
1149   GtkWidget *view;
1150   int i;
1151   gboolean add;
1152
1153   tree = gtk_tree_store_new (2, G_TYPE_INT, G_TYPE_BOOLEAN);
1154   gtk_tree_store_append (tree, &iter, NULL);
1155   gtk_tree_store_set (tree, &iter, 0, 123, 1, TRUE, -1);
1156   gtk_tree_store_append (tree, &iter2, &iter);
1157   gtk_tree_store_set (tree, &iter2, 0, 73, 1, TRUE, -1);
1158
1159   sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (tree));
1160   gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (sort),
1161                                            specific_bug_301558_sort_func,
1162                                            NULL, NULL);
1163
1164   filter = gtk_tree_model_filter_new (sort, NULL);
1165   gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter), 1);
1166
1167   view = gtk_tree_view_new_with_model (filter);
1168
1169   while (gtk_events_pending ())
1170     gtk_main_iteration ();
1171
1172   add = TRUE;
1173
1174   for (i = 0; i < 10; i++)
1175     {
1176       if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (tree), &root))
1177         g_assert_not_reached ();
1178
1179       if (add)
1180         {
1181           gtk_tree_store_append (tree, &iter, &root);
1182           gtk_tree_store_set (tree, &iter, 0, 456, 1, TRUE, -1);
1183         }
1184       else
1185         {
1186           int n;
1187           n = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (tree), &root);
1188           gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (tree), &iter,
1189                                          &root, n - 1);
1190           gtk_tree_store_remove (tree, &iter);
1191         }
1192
1193       add = !add;
1194     }
1195 }
1196
1197
1198 static gboolean
1199 specific_bug_311955_filter_func (GtkTreeModel *model,
1200                                  GtkTreeIter  *iter,
1201                                  gpointer      data)
1202 {
1203   int value;
1204
1205   gtk_tree_model_get (model, iter, 0, &value, -1);
1206
1207   return (value != 0);
1208 }
1209
1210 static void
1211 specific_bug_311955 (void)
1212 {
1213   /* This is a test case for GNOME Bugzilla bug 311955.  It was written
1214    * by Markku Vire.
1215    */
1216   GtkTreeIter iter, child, root;
1217   GtkTreeStore *store;
1218   GtkTreeModel *sort;
1219   GtkTreeModel *filter;
1220
1221   GtkWidget *window;
1222   GtkWidget *tree_view;
1223   int i;
1224   int n;
1225
1226   store = gtk_tree_store_new (1, G_TYPE_INT);
1227
1228   gtk_tree_store_append (store, &root, NULL);
1229   gtk_tree_store_set (store, &root, 0, 33, -1);
1230
1231   gtk_tree_store_append (store, &iter, &root);
1232   gtk_tree_store_set (store, &iter, 0, 50, -1);
1233
1234   gtk_tree_store_append (store, &iter, NULL);
1235   gtk_tree_store_set (store, &iter, 0, 22, -1);
1236
1237   sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (store));
1238   filter = gtk_tree_model_filter_new (sort, NULL);
1239
1240   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
1241                                           specific_bug_311955_filter_func,
1242                                           NULL, NULL);
1243
1244   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1245   tree_view = gtk_tree_view_new_with_model (filter);
1246   g_object_unref (store);
1247
1248   gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
1249
1250   while (gtk_events_pending ())
1251     gtk_main_iteration ();
1252
1253   /* Fill model */
1254   for (i = 0; i < 4; i++)
1255     {
1256       gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &root);
1257
1258       gtk_tree_store_append (store, &iter, &root);
1259
1260       if (i < 3)
1261         gtk_tree_store_set (store, &iter, 0, i, -1);
1262
1263       if (i % 2 == 0)
1264         {
1265           gtk_tree_store_append (store, &child, &iter);
1266           gtk_tree_store_set (store, &child, 0, 10, -1);
1267         }
1268     }
1269
1270   while (gtk_events_pending ())
1271     gtk_main_iteration ();
1272
1273   /* Remove bottommost child from the tree. */
1274   gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &root);
1275   n = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (store), &root);
1276
1277   if (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (store), &iter, &root, n - 2))
1278     {
1279       if (gtk_tree_model_iter_children (GTK_TREE_MODEL (store), &child, &iter))
1280         gtk_tree_store_remove (store, &child);
1281     }
1282   else
1283     g_assert_not_reached ();
1284 }
1285
1286 static void
1287 specific_bug_346800 (void)
1288 {
1289   /* This is a test case for GNOME Bugzilla bug 346800.  It was written
1290    * by Jonathan Matthew.
1291    */
1292
1293   GtkTreeIter node_iters[50];
1294   GtkTreeIter child_iters[50];
1295   GtkTreeModel *model;
1296   GtkTreeModelFilter *filter;
1297   GtkTreeStore *store;
1298   GType *columns;
1299   int i;
1300   int items = 50;
1301   columns = g_new (GType, 2);
1302   columns[0] = G_TYPE_STRING;
1303   columns[1] = G_TYPE_BOOLEAN;
1304   store = gtk_tree_store_newv (2, columns);
1305   model = GTK_TREE_MODEL (store);
1306
1307   filter = GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (model, NULL));
1308   gtk_tree_model_filter_set_visible_column (filter, 1);
1309
1310   for (i=0; i<items; i++)
1311     {
1312       /* allocate random amounts of junk, otherwise the filter model's arrays can expand without moving */
1313
1314       g_malloc (138);
1315       gtk_tree_store_append (store, &node_iters[i], NULL);
1316       gtk_tree_store_set (store, &node_iters[i],
1317                           0, "something",
1318                           1, ((i%6) == 0) ? FALSE : TRUE,
1319                           -1);
1320
1321       g_malloc (47);
1322       gtk_tree_store_append (store, &child_iters[i], &node_iters[i]);
1323       gtk_tree_store_set (store, &child_iters[i],
1324                           0, "something else",
1325                           1, FALSE,
1326                           -1);
1327       gtk_tree_model_filter_refilter (filter);
1328
1329       if (i > 6)
1330         {
1331           gtk_tree_store_set (GTK_TREE_STORE (model), &child_iters[i-1], 1,
1332                               (i & 1) ? TRUE : FALSE, -1);
1333           gtk_tree_model_filter_refilter (filter);
1334
1335           gtk_tree_store_set (GTK_TREE_STORE (model), &child_iters[i-2], 1,
1336                               (i & 1) ? FALSE: TRUE, -1);
1337           gtk_tree_model_filter_refilter (filter);
1338         }
1339     }
1340 }
1341
1342
1343 static void
1344 specific_bug_364946 (void)
1345 {
1346   /* This is a test case for GNOME Bugzilla bug 364946.  It was written
1347    * by Andreas Koehler.
1348    */
1349   GtkTreeStore *store;
1350   GtkTreeIter a, aa, aaa, aab, iter;
1351   GtkTreeModel *s_model;
1352
1353   store = gtk_tree_store_new (1, G_TYPE_STRING);
1354
1355   gtk_tree_store_append (store, &a, NULL);
1356   gtk_tree_store_set (store, &a, 0, "0", -1);
1357
1358   gtk_tree_store_append (store, &aa, &a);
1359   gtk_tree_store_set (store, &aa, 0, "0:0", -1);
1360
1361   gtk_tree_store_append (store, &aaa, &aa);
1362   gtk_tree_store_set (store, &aaa, 0, "0:0:0", -1);
1363
1364   gtk_tree_store_append (store, &aab, &aa);
1365   gtk_tree_store_set (store, &aab, 0, "0:0:1", -1);
1366
1367   s_model = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (store));
1368   gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (s_model), 0,
1369                                         GTK_SORT_ASCENDING);
1370
1371   gtk_tree_model_get_iter_from_string (s_model, &iter, "0:0:0");
1372
1373   gtk_tree_store_set (store, &aaa, 0, "0:0:0", -1);
1374   gtk_tree_store_remove (store, &aaa);
1375   gtk_tree_store_remove (store, &aab);
1376
1377   gtk_tree_model_sort_clear_cache (GTK_TREE_MODEL_SORT (s_model));
1378 }
1379
1380
1381 static gboolean
1382 specific_bug_464173_visible_func (GtkTreeModel *model,
1383                                   GtkTreeIter  *iter,
1384                                   gpointer      data)
1385 {
1386   gboolean *visible = (gboolean *)data;
1387
1388   return *visible;
1389 }
1390
1391 static void
1392 specific_bug_464173 (void)
1393 {
1394   /* Test case for GNOME Bugzilla bug 464173, test case written
1395    * by Andreas Koehler.
1396    */
1397   GtkTreeStore *model;
1398   GtkTreeModelFilter *f_model;
1399   GtkTreeIter iter1, iter2;
1400   GtkWidget *view;
1401   gboolean visible = TRUE;
1402
1403   model = gtk_tree_store_new (1, G_TYPE_STRING);
1404   gtk_tree_store_append (model, &iter1, NULL);
1405   gtk_tree_store_set (model, &iter1, 0, "Foo", -1);
1406   gtk_tree_store_append (model, &iter2, &iter1);
1407   gtk_tree_store_set (model, &iter2, 0, "Bar", -1);
1408
1409   f_model = GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (GTK_TREE_MODEL(model), NULL));
1410   gtk_tree_model_filter_set_visible_func (f_model,
1411                                           specific_bug_464173_visible_func,
1412                                           &visible, NULL);
1413
1414   view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (f_model));
1415
1416   visible = FALSE;
1417   gtk_tree_model_filter_refilter (f_model);
1418 }
1419
1420
1421 static gboolean
1422 specific_bug_540201_filter_func (GtkTreeModel *model,
1423                                  GtkTreeIter  *iter,
1424                                  gpointer      data)
1425 {
1426   gboolean has_children;
1427
1428   has_children = gtk_tree_model_iter_has_child (model, iter);
1429
1430   return has_children;
1431 }
1432
1433 static void
1434 specific_bug_540201 (void)
1435 {
1436   /* Test case for GNOME Bugzilla bug 540201, steps provided by
1437    * Charles Day.
1438    */
1439   GtkTreeIter iter, root;
1440   GtkTreeStore *store;
1441   GtkTreeModel *filter;
1442
1443   GtkWidget *tree_view;
1444
1445   store = gtk_tree_store_new (1, G_TYPE_INT);
1446
1447   gtk_tree_store_append (store, &root, NULL);
1448   gtk_tree_store_set (store, &root, 0, 33, -1);
1449
1450   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
1451   tree_view = gtk_tree_view_new_with_model (filter);
1452
1453   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
1454                                           specific_bug_540201_filter_func,
1455                                           NULL, NULL);
1456
1457   gtk_tree_store_append (store, &iter, &root);
1458   gtk_tree_store_set (store, &iter, 0, 50, -1);
1459
1460   gtk_tree_store_append (store, &iter, &root);
1461   gtk_tree_store_set (store, &iter, 0, 22, -1);
1462
1463
1464   gtk_tree_store_append (store, &root, NULL);
1465   gtk_tree_store_set (store, &root, 0, 33, -1);
1466
1467   gtk_tree_store_append (store, &iter, &root);
1468   gtk_tree_store_set (store, &iter, 0, 22, -1);
1469 }
1470
1471
1472 static gboolean
1473 specific_bug_549287_visible_func (GtkTreeModel *model,
1474                                   GtkTreeIter  *iter,
1475                                   gpointer      data)
1476 {
1477   gboolean result = FALSE;
1478
1479   result = gtk_tree_model_iter_has_child (model, iter);
1480
1481   return result;
1482 }
1483
1484 static void
1485 specific_bug_549287 (void)
1486 {
1487   /* Test case for GNOME Bugzilla bug 529287, provided by Julient Puydt */
1488
1489   int i;
1490   GtkTreeStore *store;
1491   GtkTreeModel *filtered;
1492   GtkWidget *view;
1493   GtkTreeIter iter;
1494   GtkTreeIter *swap, *parent, *child;
1495
1496   store = gtk_tree_store_new (1, G_TYPE_STRING);
1497   filtered = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
1498   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filtered),
1499                                           specific_bug_549287_visible_func,
1500                                           NULL, NULL);
1501
1502   view = gtk_tree_view_new_with_model (filtered);
1503
1504   for (i = 0; i < 4; i++)
1505     {
1506       if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter))
1507         {
1508           parent = gtk_tree_iter_copy (&iter);
1509           child = gtk_tree_iter_copy (&iter);
1510
1511           while (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (store),
1512                                                 child, parent, 0))
1513             {
1514
1515               swap = parent;
1516               parent = child;
1517               child = swap;
1518             }
1519
1520           gtk_tree_store_append (store, child, parent);
1521           gtk_tree_store_set (store, child,
1522                               0, "Something",
1523                               -1);
1524
1525           gtk_tree_iter_free (parent);
1526           gtk_tree_iter_free (child);
1527         }
1528       else
1529         {
1530           gtk_tree_store_append (store, &iter, NULL);
1531           gtk_tree_store_set (store, &iter,
1532                               0, "Something",
1533                               -1);
1534         }
1535
1536       /* since we inserted something, we changed the visibility conditions: */
1537       gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (filtered));
1538     }
1539 }
1540
1541 /* main */
1542
1543 int
1544 main (int    argc,
1545       char **argv)
1546 {
1547   gtk_test_init (&argc, &argv, NULL);
1548
1549   g_test_add ("/FilterModel/self/verify-test-suite",
1550               FilterTest, NULL,
1551               filter_test_setup,
1552               verify_test_suite,
1553               filter_test_teardown);
1554
1555   g_test_add ("/FilterModel/self/verify-test-suite/vroot/depth-1",
1556               FilterTest, gtk_tree_path_new_from_indices (2, -1),
1557               filter_test_setup,
1558               verify_test_suite_vroot,
1559               filter_test_teardown);
1560   g_test_add ("/FilterModel/self/verify-test-suite/vroot/depth-2",
1561               FilterTest, gtk_tree_path_new_from_indices (2, 3, -1),
1562               filter_test_setup,
1563               verify_test_suite_vroot,
1564               filter_test_teardown);
1565
1566
1567   g_test_add ("/FilterModel/filled/hide-root-level",
1568               FilterTest, NULL,
1569               filter_test_setup,
1570               filled_hide_root_level,
1571               filter_test_teardown);
1572   g_test_add ("/FilterModel/filled/hide-child-levels",
1573               FilterTest, NULL,
1574               filter_test_setup,
1575               filled_hide_child_levels,
1576               filter_test_teardown);
1577
1578   g_test_add ("/FilterModel/filled/hide-root-level/vroot",
1579               FilterTest, gtk_tree_path_new_from_indices (2, -1),
1580               filter_test_setup,
1581               filled_vroot_hide_root_level,
1582               filter_test_teardown);
1583   g_test_add ("/FilterModel/filled/hide-child-levels/vroot",
1584               FilterTest, gtk_tree_path_new_from_indices (2, -1),
1585               filter_test_setup,
1586               filled_vroot_hide_child_levels,
1587               filter_test_teardown);
1588
1589
1590   g_test_add ("/FilterModel/empty/show-nodes",
1591               FilterTest, NULL,
1592               filter_test_setup_empty,
1593               empty_show_nodes,
1594               filter_test_teardown);
1595
1596   g_test_add ("/FilterModel/empty/show-nodes/vroot",
1597               FilterTest, gtk_tree_path_new_from_indices (2, -1),
1598               filter_test_setup_empty,
1599               empty_vroot_show_nodes,
1600               filter_test_teardown);
1601
1602
1603   g_test_add ("/FilterModel/unfiltered/hide-single",
1604               FilterTest, NULL,
1605               filter_test_setup_unfiltered,
1606               unfiltered_hide_single,
1607               filter_test_teardown);
1608   g_test_add ("/FilterModel/unfiltered/hide-single-child",
1609               FilterTest, NULL,
1610               filter_test_setup_unfiltered,
1611               unfiltered_hide_single_child,
1612               filter_test_teardown);
1613   g_test_add ("/FilterModel/unfiltered/hide-single-multi-level",
1614               FilterTest, NULL,
1615               filter_test_setup_unfiltered,
1616               unfiltered_hide_single_multi_level,
1617               filter_test_teardown);
1618
1619   g_test_add ("/FilterModel/unfiltered/show-single",
1620               FilterTest, NULL,
1621               filter_test_setup_empty_unfiltered,
1622               unfiltered_show_single,
1623               filter_test_teardown);
1624   g_test_add ("/FilterModel/unfiltered/show-single-child",
1625               FilterTest, NULL,
1626               filter_test_setup_empty_unfiltered,
1627               unfiltered_show_single_child,
1628               filter_test_teardown);
1629   g_test_add ("/FilterModel/unfiltered/show-single-multi-level",
1630               FilterTest, NULL,
1631               filter_test_setup_empty_unfiltered,
1632               unfiltered_show_single_multi_level,
1633               filter_test_teardown);
1634
1635
1636   g_test_add_func ("/FilterModel/specific/path-dependent-filter",
1637                    specific_path_dependent_filter);
1638   g_test_add_func ("/FilterModel/specific/append-after-collapse",
1639                    specific_append_after_collapse);
1640   g_test_add_func ("/FilterModel/specific/sort-filter-remove-node",
1641                    specific_sort_filter_remove_node);
1642   g_test_add_func ("/FilterModel/specific/sort-filter-remove-root",
1643                    specific_sort_filter_remove_root);
1644   g_test_add_func ("/FilterModel/specific/filter-add-child",
1645                    specific_filter_add_child);
1646
1647   g_test_add_func ("/FilterModel/specific/bug-300089",
1648                    specific_bug_300089);
1649   g_test_add_func ("/FilterModel/specific/bug-301558",
1650                    specific_bug_301558);
1651   g_test_add_func ("/FilterModel/specific/bug-311955",
1652                    specific_bug_311955);
1653   g_test_add_func ("/FilterModel/specific/bug-346800",
1654                    specific_bug_346800);
1655   g_test_add_func ("/FilterModel/specific/bug-364946",
1656                    specific_bug_364946);
1657   g_test_add_func ("/FilterModel/specific/bug-464173",
1658                    specific_bug_464173);
1659   g_test_add_func ("/FilterModel/specific/bug-540201",
1660                    specific_bug_540201);
1661   g_test_add_func ("/FilterModel/specific/bug-549287",
1662                    specific_bug_549287);
1663
1664   return g_test_run ();
1665 }