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