1 /* Extensive GtkTreeModelFilter tests.
2 * Copyright (C) 2009,2011 Kristian Rietveld <kris@gtk.org>
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.
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.
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.
24 * - Proper coverage checking to see if the unit tests cover
26 * - Verify if the ref counting is done properly for both the
27 * normal ref_count and the zero_ref_count. One way to test
28 * this area is by collapsing/expanding branches on the view
29 * that is connected to the filter model.
30 * - Check if the iterator stamp is incremented at the correct times.
38 #define LEVEL_LENGTH 5
41 create_tree_store_set_values (GtkTreeStore *store,
48 path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), iter);
49 path_string = gtk_tree_path_to_string (path);
51 gtk_tree_store_set (store, iter,
56 gtk_tree_path_free (path);
61 create_tree_store_recurse (int depth,
68 for (i = 0; i < LEVEL_LENGTH; i++)
72 gtk_tree_store_insert (store, &iter, parent, i);
73 create_tree_store_set_values (store, &iter, visible);
76 create_tree_store_recurse (depth - 1, store, &iter, visible);
81 create_tree_store (int depth,
86 store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
88 create_tree_store_recurse (depth, store, NULL, visible);
102 ROW_HAS_CHILD_TOGGLED,
109 signal_name_to_string (SignalName signal)
114 return "row-inserted";
117 return "row-deleted";
120 return "row-changed";
122 case ROW_HAS_CHILD_TOGGLED:
123 return "row-has-child-toggled";
126 return "rows-reordered";
145 signal_new (SignalName signal, GtkTreePath *path)
149 s = g_new0 (Signal, 1);
151 s->path = gtk_tree_path_copy (path);
157 signal_free (Signal *s)
160 gtk_tree_path_free (s->path);
169 GtkTreeModel *client;
170 gulong signal_ids[LAST_SIGNAL];
176 signal_monitor_generic_handler (SignalMonitor *m,
183 if (g_queue_is_empty (m->queue))
187 path_str = gtk_tree_path_to_string (path);
188 g_error ("Signal queue empty, got signal %s path %s\n",
189 signal_name_to_string (signal), path_str);
192 g_assert_not_reached ();
195 if (m->client != model)
197 g_error ("Model mismatch; expected %p, got %p\n",
199 g_assert_not_reached ();
202 s = g_queue_peek_tail (m->queue);
205 /* For debugging: output signals that are coming in. Leaks memory. */
206 g_print ("signal=%s path=%s\n", signal_name_to_string (signal),
207 gtk_tree_path_to_string (path));
210 if (s->signal != signal
211 || gtk_tree_path_compare (s->path, path) != 0)
213 gchar *path_str, *s_path_str;
215 s_path_str = gtk_tree_path_to_string (s->path);
216 path_str = gtk_tree_path_to_string (path);
218 g_error ("Signals don't match; expected signal %s path %s, got signal %s path %s\n",
219 signal_name_to_string (s->signal), s_path_str,
220 signal_name_to_string (signal), path_str);
225 g_assert_not_reached ();
228 s = g_queue_pop_tail (m->queue);
234 signal_monitor_row_inserted (GtkTreeModel *model,
239 signal_monitor_generic_handler (data, ROW_INSERTED,
244 signal_monitor_row_deleted (GtkTreeModel *model,
248 signal_monitor_generic_handler (data, ROW_DELETED,
253 signal_monitor_row_changed (GtkTreeModel *model,
258 signal_monitor_generic_handler (data, ROW_CHANGED,
263 signal_monitor_row_has_child_toggled (GtkTreeModel *model,
268 signal_monitor_generic_handler (data, ROW_HAS_CHILD_TOGGLED,
273 signal_monitor_rows_reordered (GtkTreeModel *model,
279 signal_monitor_generic_handler (data, ROWS_REORDERED,
283 static SignalMonitor *
284 signal_monitor_new (GtkTreeModel *client)
288 m = g_new0 (SignalMonitor, 1);
289 m->client = g_object_ref (client);
290 m->queue = g_queue_new ();
292 m->signal_ids[ROW_INSERTED] = g_signal_connect (client,
294 G_CALLBACK (signal_monitor_row_inserted),
296 m->signal_ids[ROW_DELETED] = g_signal_connect (client,
298 G_CALLBACK (signal_monitor_row_deleted),
300 m->signal_ids[ROW_CHANGED] = g_signal_connect (client,
302 G_CALLBACK (signal_monitor_row_changed),
304 m->signal_ids[ROW_HAS_CHILD_TOGGLED] = g_signal_connect (client,
305 "row-has-child-toggled",
306 G_CALLBACK (signal_monitor_row_has_child_toggled),
308 m->signal_ids[ROWS_REORDERED] = g_signal_connect (client,
310 G_CALLBACK (signal_monitor_rows_reordered),
317 signal_monitor_free (SignalMonitor *m)
321 for (i = 0; i < LAST_SIGNAL; i++)
322 g_signal_handler_disconnect (m->client, m->signal_ids[i]);
324 g_object_unref (m->client);
327 g_queue_free (m->queue);
333 signal_monitor_assert_is_empty (SignalMonitor *m)
335 g_assert (g_queue_is_empty (m->queue));
339 signal_monitor_append_signal_path (SignalMonitor *m,
345 s = signal_new (signal, path);
346 g_queue_push_head (m->queue, s);
350 signal_monitor_append_signal (SignalMonitor *m,
352 const gchar *path_string)
357 path = gtk_tree_path_new_from_string (path_string);
359 s = signal_new (signal, path);
360 g_queue_push_head (m->queue, s);
362 gtk_tree_path_free (path);
371 GtkWidget *tree_view;
374 GtkTreeModelFilter *filter;
376 SignalMonitor *monitor;
378 guint block_signals : 1;
383 filter_test_store_signal (FilterTest *fixture)
385 if (fixture->block_signals)
386 g_signal_stop_emission_by_name (fixture->store, "row-changed");
391 filter_test_setup_generic (FilterTest *fixture,
392 gconstpointer test_data,
397 const GtkTreePath *vroot = test_data;
398 GtkTreeModel *filter;
400 fixture->store = create_tree_store (depth, !empty);
402 g_signal_connect_swapped (fixture->store, "row-changed",
403 G_CALLBACK (filter_test_store_signal), fixture);
405 /* Please forgive me for casting const away. */
406 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (fixture->store),
407 (GtkTreePath *)vroot);
408 fixture->filter = GTK_TREE_MODEL_FILTER (filter);
411 gtk_tree_model_filter_set_visible_column (fixture->filter, 1);
413 /* We need a tree view that's listening to get ref counting from that
416 fixture->tree_view = gtk_tree_view_new_with_model (filter);
418 fixture->monitor = signal_monitor_new (filter);
422 filter_test_setup_expand_root (FilterTest *fixture)
427 path = gtk_tree_path_new_from_indices (0, -1);
429 for (i = 0; i < LEVEL_LENGTH; i++)
431 gtk_tree_view_expand_row (GTK_TREE_VIEW (fixture->tree_view),
433 gtk_tree_path_next (path);
435 gtk_tree_path_free (path);
439 filter_test_setup (FilterTest *fixture,
440 gconstpointer test_data)
442 filter_test_setup_generic (fixture, test_data, 3, FALSE, FALSE);
446 filter_test_setup_empty (FilterTest *fixture,
447 gconstpointer test_data)
449 filter_test_setup_generic (fixture, test_data, 3, TRUE, FALSE);
453 filter_test_setup_unfiltered (FilterTest *fixture,
454 gconstpointer test_data)
456 filter_test_setup_generic (fixture, test_data, 3, FALSE, TRUE);
460 filter_test_setup_unfiltered_root_expanded (FilterTest *fixture,
461 gconstpointer test_data)
463 filter_test_setup_unfiltered (fixture, test_data);
464 filter_test_setup_expand_root (fixture);
468 filter_test_setup_empty_unfiltered (FilterTest *fixture,
469 gconstpointer test_data)
471 filter_test_setup_generic (fixture, test_data, 3, TRUE, TRUE);
475 filter_test_setup_empty_unfiltered_root_expanded (FilterTest *fixture,
476 gconstpointer test_data)
478 filter_test_setup_empty_unfiltered (fixture, test_data);
479 filter_test_setup_expand_root (fixture);
483 strip_virtual_root (GtkTreePath *path,
484 GtkTreePath *root_path)
486 GtkTreePath *real_path;
491 int depth = gtk_tree_path_get_depth (path);
492 int root_depth = gtk_tree_path_get_depth (root_path);
494 real_path = gtk_tree_path_new ();
496 for (j = 0; j < depth - root_depth; j++)
497 gtk_tree_path_append_index (real_path,
498 gtk_tree_path_get_indices (path)[root_depth + j]);
501 real_path = gtk_tree_path_copy (path);
507 count_visible (FilterTest *fixture,
508 GtkTreePath *store_path)
514 gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->store),
517 for (i = 0; i < LEVEL_LENGTH; i++)
521 gtk_tree_model_get (GTK_TREE_MODEL (fixture->store), &iter,
533 filter_test_append_refilter_signals_recurse (FilterTest *fixture,
534 GtkTreePath *store_path,
535 GtkTreePath *filter_path,
537 GtkTreePath *root_path)
540 int rows_deleted = 0;
543 gtk_tree_path_down (store_path);
544 gtk_tree_path_down (filter_path);
546 gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->store),
549 for (i = 0; i < LEVEL_LENGTH; i++)
552 GtkTreePath *real_path;
554 gtk_tree_model_get (GTK_TREE_MODEL (fixture->store), &iter,
559 (!gtk_tree_path_is_descendant (store_path, root_path)
560 || !gtk_tree_path_compare (store_path, root_path)))
562 if (!gtk_tree_path_compare (store_path, root_path))
565 && gtk_tree_model_iter_has_child (GTK_TREE_MODEL (fixture->store),
568 GtkTreePath *store_copy;
569 GtkTreePath *filter_copy;
571 store_copy = gtk_tree_path_copy (store_path);
572 filter_copy = gtk_tree_path_copy (filter_path);
573 filter_test_append_refilter_signals_recurse (fixture,
578 gtk_tree_path_free (store_copy);
579 gtk_tree_path_free (filter_copy);
583 gtk_tree_path_next (store_path);
584 gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &iter);
587 gtk_tree_path_next (filter_path);
592 real_path = strip_virtual_root (filter_path, root_path);
596 /* This row will be inserted */
597 signal_monitor_append_signal_path (fixture->monitor, ROW_CHANGED,
600 if (gtk_tree_model_iter_has_child (GTK_TREE_MODEL (fixture->store),
603 signal_monitor_append_signal_path (fixture->monitor,
604 ROW_HAS_CHILD_TOGGLED,
609 GtkTreePath *store_copy;
610 GtkTreePath *filter_copy;
612 store_copy = gtk_tree_path_copy (store_path);
613 filter_copy = gtk_tree_path_copy (filter_path);
614 filter_test_append_refilter_signals_recurse (fixture,
619 gtk_tree_path_free (store_copy);
620 gtk_tree_path_free (filter_copy);
624 GtkTreePath *tmp_path;
626 /* If all child rows are invisible, then the last row to
627 * become invisible will emit row-has-child-toggled on the
631 tmp_path = gtk_tree_path_copy (store_path);
632 gtk_tree_path_append_index (tmp_path, 0);
634 if (count_visible (fixture, tmp_path) == 0)
635 signal_monitor_append_signal_path (fixture->monitor,
636 ROW_HAS_CHILD_TOGGLED,
639 gtk_tree_path_free (tmp_path);
643 gtk_tree_path_next (filter_path);
647 /* This row will be deleted */
649 signal_monitor_append_signal_path (fixture->monitor, ROW_DELETED,
653 gtk_tree_path_free (real_path);
655 gtk_tree_path_next (store_path);
656 gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &iter);
659 if (rows_deleted == LEVEL_LENGTH
660 && gtk_tree_path_get_depth (filter_path) > 1)
662 GtkTreePath *real_path;
664 gtk_tree_path_up (store_path);
665 gtk_tree_path_up (filter_path);
667 /* A row-has-child-toggled will be emitted on the parent */
670 && gtk_tree_path_is_descendant (store_path, root_path)
671 && gtk_tree_path_compare (store_path, root_path)))
673 real_path = strip_virtual_root (filter_path, root_path);
674 signal_monitor_append_signal_path (fixture->monitor,
675 ROW_HAS_CHILD_TOGGLED,
678 gtk_tree_path_free (real_path);
684 filter_test_append_refilter_signals (FilterTest *fixture,
687 /* A special function that walks the tree store like the
688 * model validation functions below.
691 GtkTreePath *filter_path;
693 path = gtk_tree_path_new ();
694 filter_path = gtk_tree_path_new ();
695 filter_test_append_refilter_signals_recurse (fixture,
700 gtk_tree_path_free (path);
701 gtk_tree_path_free (filter_path);
705 filter_test_append_refilter_signals_with_vroot (FilterTest *fixture,
707 GtkTreePath *root_path)
709 /* A special function that walks the tree store like the
710 * model validation functions below.
713 GtkTreePath *filter_path;
715 path = gtk_tree_path_new ();
716 filter_path = gtk_tree_path_new ();
717 filter_test_append_refilter_signals_recurse (fixture,
722 gtk_tree_path_free (path);
723 gtk_tree_path_free (filter_path);
727 filter_test_enable_filter (FilterTest *fixture)
729 gtk_tree_model_filter_set_visible_column (fixture->filter, 1);
730 gtk_tree_model_filter_refilter (fixture->filter);
734 filter_test_block_signals (FilterTest *fixture)
736 fixture->block_signals = TRUE;
740 filter_test_unblock_signals (FilterTest *fixture)
742 fixture->block_signals = FALSE;
746 filter_test_teardown (FilterTest *fixture,
747 gconstpointer test_data)
749 signal_monitor_free (fixture->monitor);
751 gtk_widget_destroy (fixture->tree_view);
753 g_object_unref (fixture->filter);
754 g_object_unref (fixture->store);
758 * Model structure validation
762 check_filter_model_recurse (FilterTest *fixture,
763 GtkTreePath *store_parent_path,
764 GtkTreePath *filter_parent_path)
767 GtkTreeIter store_iter;
768 GtkTreeIter filter_iter;
769 gboolean store_has_next, filter_has_next;
771 gtk_tree_path_down (store_parent_path);
772 gtk_tree_path_down (filter_parent_path);
774 store_has_next = gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->store),
775 &store_iter, store_parent_path);
776 filter_has_next = gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->filter),
777 &filter_iter, filter_parent_path);
779 for (i = 0; i < LEVEL_LENGTH; i++)
783 g_return_if_fail (store_has_next == TRUE);
785 gtk_tree_model_get (GTK_TREE_MODEL (fixture->store),
793 gchar *filter_str, *store_str;
795 g_return_if_fail (filter_has_next == TRUE);
798 tmp = gtk_tree_model_get_path (GTK_TREE_MODEL (fixture->filter),
800 g_return_if_fail (gtk_tree_path_compare (tmp, filter_parent_path) == 0);
802 /* Verify model content */
803 gtk_tree_model_get (GTK_TREE_MODEL (fixture->store),
807 gtk_tree_model_get (GTK_TREE_MODEL (fixture->filter),
812 g_return_if_fail (g_strcmp0 (store_str, filter_str) == 0);
817 if (gtk_tree_model_iter_has_child (GTK_TREE_MODEL (fixture->filter),
820 g_return_if_fail (gtk_tree_model_iter_has_child (GTK_TREE_MODEL (fixture->store), &store_iter));
822 check_filter_model_recurse (fixture,
823 gtk_tree_path_copy (store_parent_path),
827 /* Only when we do not recurse we need to free tmp */
828 gtk_tree_path_free (tmp);
830 gtk_tree_path_next (filter_parent_path);
831 filter_has_next = gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->filter), &filter_iter);
834 gtk_tree_path_next (store_parent_path);
835 store_has_next = gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &store_iter);
838 /* Both models should have no more content! */
839 g_return_if_fail (store_has_next == FALSE);
840 g_return_if_fail (filter_has_next == FALSE);
842 gtk_tree_path_free (store_parent_path);
843 gtk_tree_path_free (filter_parent_path);
847 check_filter_model (FilterTest *fixture)
851 if (fixture->monitor)
852 signal_monitor_assert_is_empty (fixture->monitor);
854 path = gtk_tree_path_new ();
856 check_filter_model_recurse (fixture, path, gtk_tree_path_copy (path));
860 check_filter_model_with_root (FilterTest *fixture,
863 if (fixture->monitor)
864 signal_monitor_assert_is_empty (fixture->monitor);
866 check_filter_model_recurse (fixture,
867 gtk_tree_path_copy (path),
868 gtk_tree_path_new ());
874 check_level_length (GtkTreeModelFilter *filter,
876 const int expected_length)
882 model_length = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (filter), NULL);
883 g_assert_cmpint (model_length, ==, expected_length);
888 gboolean retrieved_iter = FALSE;
891 retrieved_iter = gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (filter),
893 g_return_if_fail (retrieved_iter);
894 model_length = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (filter), &iter);
895 g_assert_cmpint (model_length, ==, expected_length);
900 set_path_visibility (FilterTest *fixture,
904 GtkTreeIter store_iter;
906 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
908 gtk_tree_store_set (fixture->store, &store_iter,
915 insert_path_with_visibility (FilterTest *fixture,
916 const gchar *path_string,
921 GtkTreeIter parent, iter;
923 path = gtk_tree_path_new_from_string (path_string);
924 position = gtk_tree_path_get_indices (path)[gtk_tree_path_get_depth (path)];
925 gtk_tree_path_up (path);
927 if (gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->store), &parent, path))
929 gtk_tree_store_insert (fixture->store, &iter, &parent, position);
930 create_tree_store_set_values (fixture->store, &iter, visible);
932 gtk_tree_path_free (path);
941 verify_test_suite (FilterTest *fixture,
942 gconstpointer user_data)
944 check_filter_model (fixture);
948 verify_test_suite_vroot (FilterTest *fixture,
949 gconstpointer user_data)
951 check_filter_model_with_root (fixture, (GtkTreePath *)user_data);
956 filled_hide_root_level (FilterTest *fixture,
957 gconstpointer user_data)
959 signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "2");
960 set_path_visibility (fixture, "2", FALSE);
961 check_filter_model (fixture);
962 check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 1);
964 signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
965 set_path_visibility (fixture, "0", FALSE);
966 check_filter_model (fixture);
967 check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 2);
969 signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "2");
970 set_path_visibility (fixture, "4", FALSE);
971 check_filter_model (fixture);
972 check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 3);
976 signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
977 signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
979 set_path_visibility (fixture, "1", FALSE);
980 check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 4);
982 set_path_visibility (fixture, "3", FALSE);
983 check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 5);
985 check_filter_model (fixture);
988 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
989 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
990 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "1");
991 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "1");
993 set_path_visibility (fixture, "1", TRUE);
994 check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 4);
996 set_path_visibility (fixture, "3", TRUE);
997 check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 3);
999 check_filter_model (fixture);
1003 filled_hide_child_levels (FilterTest *fixture,
1004 gconstpointer user_data)
1006 set_path_visibility (fixture, "0:2", FALSE);
1007 check_filter_model (fixture);
1008 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1009 check_level_length (fixture->filter, "0", LEVEL_LENGTH - 1);
1011 set_path_visibility (fixture, "0:4", FALSE);
1012 check_filter_model (fixture);
1013 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1014 check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
1016 set_path_visibility (fixture, "0:4:3", FALSE);
1017 check_filter_model (fixture);
1018 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1019 check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
1021 set_path_visibility (fixture, "0:4:0", FALSE);
1022 set_path_visibility (fixture, "0:4:1", FALSE);
1023 set_path_visibility (fixture, "0:4:2", FALSE);
1024 set_path_visibility (fixture, "0:4:4", FALSE);
1025 check_filter_model (fixture);
1026 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1027 check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
1029 /* Since "0:2" is hidden, "0:4" must be "0:3" in the filter model */
1030 set_path_visibility (fixture, "0:4", TRUE);
1031 check_filter_model (fixture);
1032 check_level_length (fixture->filter, "0:3", 0);
1034 set_path_visibility (fixture, "0:2", TRUE);
1035 check_filter_model (fixture);
1036 check_level_length (fixture->filter, "0:2", LEVEL_LENGTH);
1037 check_level_length (fixture->filter, "0:3", LEVEL_LENGTH);
1038 check_level_length (fixture->filter, "0:4", 0);
1040 /* Once 0:4:0 got inserted, 0:4 became a parent. Because 0:4 is
1041 * not visible, not signals are emitted.
1043 set_path_visibility (fixture, "0:4:2", TRUE);
1044 set_path_visibility (fixture, "0:4:4", TRUE);
1045 signal_monitor_assert_is_empty (fixture->monitor);
1046 check_level_length (fixture->filter, "0:4", 2);
1050 filled_hide_child_levels_root_expanded (FilterTest *fixture,
1051 gconstpointer user_data)
1055 path = gtk_tree_path_new_from_indices (0, -1);
1056 gtk_tree_view_expand_row (GTK_TREE_VIEW (fixture->tree_view), path, FALSE);
1057 gtk_tree_path_free (path);
1059 signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0:2");
1060 set_path_visibility (fixture, "0:2", FALSE);
1061 check_filter_model (fixture);
1062 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1063 check_level_length (fixture->filter, "0", LEVEL_LENGTH - 1);
1065 signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0:3");
1066 set_path_visibility (fixture, "0:4", FALSE);
1067 check_filter_model (fixture);
1068 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1069 check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
1071 set_path_visibility (fixture, "0:4:3", FALSE);
1072 check_filter_model (fixture);
1073 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1074 check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
1076 set_path_visibility (fixture, "0:4:0", FALSE);
1077 set_path_visibility (fixture, "0:4:1", FALSE);
1078 set_path_visibility (fixture, "0:4:2", FALSE);
1079 set_path_visibility (fixture, "0:4:4", FALSE);
1080 check_filter_model (fixture);
1081 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1082 check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
1084 /* Since "0:2" is hidden, "0:4" must be "0:3" in the filter model */
1085 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0:3");
1086 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0:3");
1087 set_path_visibility (fixture, "0:4", TRUE);
1088 check_filter_model (fixture);
1089 check_level_length (fixture->filter, "0:3", 0);
1091 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0:2");
1092 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0:2");
1093 set_path_visibility (fixture, "0:2", TRUE);
1094 check_filter_model (fixture);
1095 check_level_length (fixture->filter, "0:2", LEVEL_LENGTH);
1096 check_level_length (fixture->filter, "0:3", LEVEL_LENGTH);
1097 check_level_length (fixture->filter, "0:4", 0);
1099 /* has-child-toggled for 0:4 is required. */
1100 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0:4");
1101 set_path_visibility (fixture, "0:4:2", TRUE);
1102 set_path_visibility (fixture, "0:4:4", TRUE);
1103 signal_monitor_assert_is_empty (fixture->monitor);
1104 check_level_length (fixture->filter, "0:4", 2);
1109 filled_vroot_hide_root_level (FilterTest *fixture,
1110 gconstpointer user_data)
1112 GtkTreePath *path = (GtkTreePath *)user_data;
1114 /* These changes do not affect the filter's root level */
1115 set_path_visibility (fixture, "0", FALSE);
1116 check_filter_model_with_root (fixture, path);
1117 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1118 check_level_length (fixture->filter, "0", LEVEL_LENGTH);
1120 set_path_visibility (fixture, "4", FALSE);
1121 check_filter_model_with_root (fixture, path);
1122 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1123 check_level_length (fixture->filter, "0", LEVEL_LENGTH);
1125 /* Even though we set the virtual root parent node to FALSE,
1126 * the virtual root contents remain.
1128 set_path_visibility (fixture, "2", FALSE);
1129 check_filter_model_with_root (fixture, path);
1130 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1131 check_level_length (fixture->filter, "0", LEVEL_LENGTH);
1134 set_path_visibility (fixture, "1", FALSE);
1135 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1136 check_level_length (fixture->filter, "0", LEVEL_LENGTH);
1138 set_path_visibility (fixture, "3", FALSE);
1139 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1140 check_level_length (fixture->filter, "0", LEVEL_LENGTH);
1142 check_filter_model_with_root (fixture, path);
1145 set_path_visibility (fixture, "2", TRUE);
1146 check_filter_model_with_root (fixture, path);
1147 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1148 check_level_length (fixture->filter, "0", LEVEL_LENGTH);
1150 set_path_visibility (fixture, "1", TRUE);
1151 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1152 check_level_length (fixture->filter, "0", LEVEL_LENGTH);
1154 set_path_visibility (fixture, "3", TRUE);
1155 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1156 check_level_length (fixture->filter, "0", LEVEL_LENGTH);
1158 check_filter_model_with_root (fixture, path);
1160 /* Now test changes in the virtual root level */
1161 signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "2");
1162 set_path_visibility (fixture, "2:2", FALSE);
1163 check_filter_model_with_root (fixture, path);
1164 check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 1);
1166 signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "3");
1167 set_path_visibility (fixture, "2:4", FALSE);
1168 check_filter_model_with_root (fixture, path);
1169 check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 2);
1171 set_path_visibility (fixture, "1:4", FALSE);
1172 check_filter_model_with_root (fixture, path);
1173 check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 2);
1175 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "3");
1176 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "3");
1177 set_path_visibility (fixture, "2:4", TRUE);
1178 check_filter_model_with_root (fixture, path);
1179 check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 1);
1181 set_path_visibility (fixture, "2", FALSE);
1182 check_filter_model_with_root (fixture, path);
1183 check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 1);
1185 signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
1186 signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
1187 signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
1188 signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
1189 set_path_visibility (fixture, "2:0", FALSE);
1190 set_path_visibility (fixture, "2:1", FALSE);
1191 set_path_visibility (fixture, "2:2", FALSE);
1192 set_path_visibility (fixture, "2:3", FALSE);
1193 set_path_visibility (fixture, "2:4", FALSE);
1194 check_filter_model_with_root (fixture, path);
1195 check_level_length (fixture->filter, NULL, 0);
1197 set_path_visibility (fixture, "2", TRUE);
1198 check_filter_model_with_root (fixture, path);
1199 check_level_length (fixture->filter, NULL, 0);
1201 set_path_visibility (fixture, "1:4", FALSE);
1202 check_filter_model_with_root (fixture, path);
1203 check_level_length (fixture->filter, NULL, 0);
1205 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1206 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1207 set_path_visibility (fixture, "2:4", TRUE);
1208 check_filter_model_with_root (fixture, path);
1209 check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 4);
1211 signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
1212 set_path_visibility (fixture, "2:4", FALSE);
1213 check_filter_model_with_root (fixture, path);
1214 check_level_length (fixture->filter, NULL, 0);
1216 set_path_visibility (fixture, "2", FALSE);
1217 check_filter_model_with_root (fixture, path);
1218 check_level_length (fixture->filter, NULL, 0);
1220 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1221 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1222 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "1");
1223 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "1");
1224 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "2");
1225 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2");
1226 set_path_visibility (fixture, "2:0", TRUE);
1227 set_path_visibility (fixture, "2:1", TRUE);
1228 set_path_visibility (fixture, "2:2", TRUE);
1229 check_filter_model_with_root (fixture, path);
1230 check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 2);
1232 set_path_visibility (fixture, "2", TRUE);
1233 check_filter_model_with_root (fixture, path);
1234 check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 2);
1238 filled_vroot_hide_child_levels (FilterTest *fixture,
1239 gconstpointer user_data)
1241 GtkTreePath *path = (GtkTreePath *)user_data;
1243 set_path_visibility (fixture, "2:0:2", FALSE);
1244 check_filter_model_with_root (fixture, path);
1245 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1246 check_level_length (fixture->filter, "0", LEVEL_LENGTH - 1);
1248 set_path_visibility (fixture, "2:0:4", FALSE);
1249 check_filter_model_with_root (fixture, path);
1250 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1251 check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
1253 set_path_visibility (fixture, "2:0:4:3", FALSE);
1254 check_filter_model_with_root (fixture, path);
1255 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1256 check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
1258 set_path_visibility (fixture, "2:0:4:0", FALSE);
1259 set_path_visibility (fixture, "2:0:4:1", FALSE);
1260 set_path_visibility (fixture, "2:0:4:2", FALSE);
1261 set_path_visibility (fixture, "2:0:4:4", FALSE);
1262 check_filter_model_with_root (fixture, path);
1263 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1264 check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
1266 /* Since "0:2" is hidden, "0:4" must be "0:3" in the filter model */
1267 set_path_visibility (fixture, "2:0:4", TRUE);
1268 check_filter_model_with_root (fixture, path);
1269 check_level_length (fixture->filter, "0:3", 0);
1271 set_path_visibility (fixture, "2:0:2", TRUE);
1272 check_filter_model_with_root (fixture, path);
1273 check_level_length (fixture->filter, "0:2", LEVEL_LENGTH);
1274 check_level_length (fixture->filter, "0:3", LEVEL_LENGTH);
1275 check_level_length (fixture->filter, "0:4", 0);
1277 /* Once 0:4:0 got inserted, 0:4 became a parent */
1278 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0:4");
1279 set_path_visibility (fixture, "2:0:4:2", TRUE);
1280 set_path_visibility (fixture, "2:0:4:4", TRUE);
1281 check_level_length (fixture->filter, "0:4", 2);
1285 filled_vroot_hide_child_levels_root_expanded (FilterTest *fixture,
1286 gconstpointer user_data)
1288 GtkTreePath *path = (GtkTreePath *)user_data;
1289 GtkTreePath *tmp_path;
1291 tmp_path = gtk_tree_path_new_from_indices (0, -1);
1292 gtk_tree_view_expand_row (GTK_TREE_VIEW (fixture->tree_view), tmp_path, FALSE);
1293 gtk_tree_path_free (tmp_path);
1295 signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0:2");
1296 set_path_visibility (fixture, "2:0:2", FALSE);
1297 check_filter_model_with_root (fixture, path);
1298 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1299 check_level_length (fixture->filter, "0", LEVEL_LENGTH - 1);
1301 signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0:3");
1302 set_path_visibility (fixture, "2:0:4", FALSE);
1303 check_filter_model_with_root (fixture, path);
1304 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1305 check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
1307 set_path_visibility (fixture, "2:0:4:3", FALSE);
1308 check_filter_model_with_root (fixture, path);
1309 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1310 check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
1312 set_path_visibility (fixture, "2:0:4:0", FALSE);
1313 set_path_visibility (fixture, "2:0:4:1", FALSE);
1314 set_path_visibility (fixture, "2:0:4:2", FALSE);
1315 set_path_visibility (fixture, "2:0:4:4", FALSE);
1316 check_filter_model_with_root (fixture, path);
1317 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1318 check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
1320 /* Since "0:2" is hidden, "0:4" must be "0:3" in the filter model */
1321 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0:3");
1322 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0:3");
1323 set_path_visibility (fixture, "2:0:4", TRUE);
1324 check_filter_model_with_root (fixture, path);
1325 check_level_length (fixture->filter, "0:3", 0);
1327 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0:2");
1328 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0:2");
1329 set_path_visibility (fixture, "2:0:2", TRUE);
1330 check_filter_model_with_root (fixture, path);
1331 check_level_length (fixture->filter, "0:2", LEVEL_LENGTH);
1332 check_level_length (fixture->filter, "0:3", LEVEL_LENGTH);
1333 check_level_length (fixture->filter, "0:4", 0);
1335 /* Once 0:4:0 got inserted, 0:4 became a parent */
1336 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0:4");
1337 set_path_visibility (fixture, "2:0:4:2", TRUE);
1338 set_path_visibility (fixture, "2:0:4:4", TRUE);
1339 check_level_length (fixture->filter, "0:4", 2);
1343 empty_show_nodes (FilterTest *fixture,
1344 gconstpointer user_data)
1346 check_filter_model (fixture);
1347 check_level_length (fixture->filter, NULL, 0);
1349 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1350 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1351 set_path_visibility (fixture, "3", TRUE);
1352 check_filter_model (fixture);
1353 check_level_length (fixture->filter, NULL, 1);
1354 check_level_length (fixture->filter, "0", 0);
1356 set_path_visibility (fixture, "3:2:2", TRUE);
1357 check_filter_model (fixture);
1358 check_level_length (fixture->filter, NULL, 1);
1359 check_level_length (fixture->filter, "0", 0);
1361 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1362 set_path_visibility (fixture, "3:2", TRUE);
1363 check_filter_model (fixture);
1364 check_level_length (fixture->filter, NULL, 1);
1365 check_level_length (fixture->filter, "0", 1);
1366 check_level_length (fixture->filter, "0:0", 1);
1367 check_level_length (fixture->filter, "0:0:0", 0);
1369 signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
1370 set_path_visibility (fixture, "3", FALSE);
1371 check_filter_model (fixture);
1372 check_level_length (fixture->filter, NULL, 0);
1374 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1375 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1376 set_path_visibility (fixture, "3:2:1", TRUE);
1377 set_path_visibility (fixture, "3", TRUE);
1378 check_filter_model (fixture);
1379 check_level_length (fixture->filter, NULL, 1);
1380 check_level_length (fixture->filter, "0", 1);
1381 check_level_length (fixture->filter, "0:0", 2);
1382 check_level_length (fixture->filter, "0:0:0", 0);
1386 empty_show_multiple_nodes (FilterTest *fixture,
1387 gconstpointer user_data)
1390 GtkTreePath *changed_path;
1392 check_filter_model (fixture);
1393 check_level_length (fixture->filter, NULL, 0);
1395 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1396 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1397 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "1");
1398 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "1");
1400 /* We simulate a change in visible func condition with this. The
1401 * visibility state of multiple nodes changes at once, we emit row-changed
1402 * for these nodes (and others) after that.
1404 filter_test_block_signals (fixture);
1405 set_path_visibility (fixture, "3", TRUE);
1406 set_path_visibility (fixture, "4", TRUE);
1407 filter_test_unblock_signals (fixture);
1409 changed_path = gtk_tree_path_new ();
1410 gtk_tree_path_append_index (changed_path, 2);
1411 gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->store),
1412 &iter, changed_path);
1413 /* Invisible node - so no signals expected */
1414 gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1415 changed_path, &iter);
1417 gtk_tree_path_next (changed_path);
1418 gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &iter);
1419 gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1420 changed_path, &iter);
1422 gtk_tree_path_next (changed_path);
1423 gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &iter);
1424 gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1425 changed_path, &iter);
1427 gtk_tree_path_free (changed_path);
1429 check_filter_model (fixture);
1430 check_level_length (fixture->filter, NULL, 2);
1431 check_level_length (fixture->filter, "0", 0);
1433 set_path_visibility (fixture, "3:2:2", TRUE);
1434 check_filter_model (fixture);
1435 check_level_length (fixture->filter, NULL, 2);
1436 check_level_length (fixture->filter, "0", 0);
1438 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1439 set_path_visibility (fixture, "3:2", TRUE);
1440 check_filter_model (fixture);
1441 check_level_length (fixture->filter, NULL, 2);
1442 check_level_length (fixture->filter, "0", 1);
1443 check_level_length (fixture->filter, "0:0", 1);
1444 check_level_length (fixture->filter, "0:0:0", 0);
1446 signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
1447 set_path_visibility (fixture, "3", FALSE);
1448 check_filter_model (fixture);
1449 check_level_length (fixture->filter, NULL, 1);
1451 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1452 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1453 set_path_visibility (fixture, "3:2:1", TRUE);
1454 set_path_visibility (fixture, "3", TRUE);
1455 check_filter_model (fixture);
1456 check_level_length (fixture->filter, NULL, 2);
1457 check_level_length (fixture->filter, "0", 1);
1458 check_level_length (fixture->filter, "0:0", 2);
1459 check_level_length (fixture->filter, "0:0:0", 0);
1463 empty_vroot_show_nodes (FilterTest *fixture,
1464 gconstpointer user_data)
1466 GtkTreePath *path = (GtkTreePath *)user_data;
1468 check_filter_model_with_root (fixture, path);
1469 check_level_length (fixture->filter, NULL, 0);
1471 set_path_visibility (fixture, "2", TRUE);
1472 check_filter_model_with_root (fixture, path);
1473 check_level_length (fixture->filter, NULL, 0);
1475 set_path_visibility (fixture, "2:2:2", TRUE);
1476 check_filter_model_with_root (fixture, path);
1477 check_level_length (fixture->filter, NULL, 0);
1479 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1480 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1481 set_path_visibility (fixture, "2:2", TRUE);
1482 check_filter_model_with_root (fixture, path);
1483 check_level_length (fixture->filter, NULL, 1);
1484 check_level_length (fixture->filter, "0", 1);
1485 check_level_length (fixture->filter, "0:0", 0);
1487 set_path_visibility (fixture, "3", TRUE);
1488 check_filter_model_with_root (fixture, path);
1489 check_level_length (fixture->filter, NULL, 1);
1491 signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
1492 set_path_visibility (fixture, "2:2", FALSE);
1493 check_filter_model_with_root (fixture, path);
1494 check_level_length (fixture->filter, NULL, 0);
1496 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1497 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1498 set_path_visibility (fixture, "2:2:1", TRUE);
1499 set_path_visibility (fixture, "2:2", TRUE);
1500 check_filter_model_with_root (fixture, path);
1501 check_level_length (fixture->filter, NULL, 1);
1502 check_level_length (fixture->filter, "0", 2);
1503 check_level_length (fixture->filter, "0:1", 0);
1507 empty_vroot_show_multiple_nodes (FilterTest *fixture,
1508 gconstpointer user_data)
1511 GtkTreePath *changed_path;
1512 GtkTreePath *path = (GtkTreePath *)user_data;
1514 check_filter_model_with_root (fixture, path);
1515 check_level_length (fixture->filter, NULL, 0);
1517 /* We simulate a change in visible func condition with this. The
1518 * visibility state of multiple nodes changes at once, we emit row-changed
1519 * for these nodes (and others) after that.
1521 filter_test_block_signals (fixture);
1522 set_path_visibility (fixture, "2", TRUE);
1523 set_path_visibility (fixture, "3", TRUE);
1524 filter_test_unblock_signals (fixture);
1526 changed_path = gtk_tree_path_new ();
1527 gtk_tree_path_append_index (changed_path, 1);
1528 gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->store),
1529 &iter, changed_path);
1530 gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1531 changed_path, &iter);
1533 gtk_tree_path_next (changed_path);
1534 gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &iter);
1535 gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1536 changed_path, &iter);
1538 gtk_tree_path_next (changed_path);
1539 gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &iter);
1540 gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1541 changed_path, &iter);
1543 gtk_tree_path_next (changed_path);
1544 gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &iter);
1545 gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1546 changed_path, &iter);
1548 gtk_tree_path_free (changed_path);
1550 check_filter_model_with_root (fixture, path);
1551 check_level_length (fixture->filter, NULL, 0);
1553 set_path_visibility (fixture, "2:2:2", TRUE);
1554 check_filter_model_with_root (fixture, path);
1555 check_level_length (fixture->filter, NULL, 0);
1557 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1558 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1559 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "1");
1560 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "1");
1562 /* Again, we simulate a call to refilter */
1563 filter_test_block_signals (fixture);
1564 set_path_visibility (fixture, "2:2", TRUE);
1565 set_path_visibility (fixture, "2:3", TRUE);
1566 filter_test_unblock_signals (fixture);
1568 changed_path = gtk_tree_path_new ();
1569 gtk_tree_path_append_index (changed_path, 2);
1570 gtk_tree_path_append_index (changed_path, 1);
1571 gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->store),
1572 &iter, changed_path);
1573 gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1574 changed_path, &iter);
1576 gtk_tree_path_next (changed_path);
1577 gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &iter);
1578 gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1579 changed_path, &iter);
1581 gtk_tree_path_next (changed_path);
1582 gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &iter);
1583 gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1584 changed_path, &iter);
1586 gtk_tree_path_next (changed_path);
1587 gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &iter);
1588 gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1589 changed_path, &iter);
1591 gtk_tree_path_free (changed_path);
1593 check_filter_model_with_root (fixture, path);
1594 check_level_length (fixture->filter, NULL, 2);
1595 check_level_length (fixture->filter, "0", 1);
1596 check_level_length (fixture->filter, "0:0", 0);
1598 set_path_visibility (fixture, "3", TRUE);
1599 check_filter_model_with_root (fixture, path);
1600 check_level_length (fixture->filter, NULL, 2);
1602 signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
1603 set_path_visibility (fixture, "2:2", FALSE);
1604 check_filter_model_with_root (fixture, path);
1605 check_level_length (fixture->filter, NULL, 1);
1607 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1608 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1609 set_path_visibility (fixture, "2:2:1", TRUE);
1610 set_path_visibility (fixture, "2:2", TRUE);
1611 check_filter_model_with_root (fixture, path);
1612 check_level_length (fixture->filter, NULL, 2);
1613 check_level_length (fixture->filter, "0", 2);
1614 check_level_length (fixture->filter, "0:1", 0);
1619 unfiltered_hide_single (FilterTest *fixture,
1620 gconstpointer user_data)
1623 signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2");
1624 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2");
1625 set_path_visibility (fixture, "2", FALSE);
1627 signal_monitor_assert_is_empty (fixture->monitor);
1628 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1630 /* The view only shows the root level, so we only expect signals
1631 * for the root level.
1633 filter_test_append_refilter_signals (fixture, 1);
1634 filter_test_enable_filter (fixture);
1636 check_filter_model (fixture);
1637 check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 1);
1641 unfiltered_hide_single_root_expanded (FilterTest *fixture,
1642 gconstpointer user_data)
1645 signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2");
1646 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2");
1647 set_path_visibility (fixture, "2", FALSE);
1649 signal_monitor_assert_is_empty (fixture->monitor);
1650 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1652 filter_test_append_refilter_signals (fixture, 2);
1653 filter_test_enable_filter (fixture);
1655 check_filter_model (fixture);
1656 check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 1);
1660 unfiltered_hide_single_child (FilterTest *fixture,
1661 gconstpointer user_data)
1664 /* This row is not shown, so its signal is not propagated */
1665 set_path_visibility (fixture, "2:2", FALSE);
1667 signal_monitor_assert_is_empty (fixture->monitor);
1668 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1669 check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1671 /* The view only shows the root level, so we only expect signals
1672 * for the root level.
1674 filter_test_append_refilter_signals (fixture, 0);
1675 filter_test_enable_filter (fixture);
1677 check_filter_model (fixture);
1678 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1679 check_level_length (fixture->filter, "2", LEVEL_LENGTH - 1);
1683 unfiltered_hide_single_child_root_expanded (FilterTest *fixture,
1684 gconstpointer user_data)
1687 signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2:2");
1688 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
1689 set_path_visibility (fixture, "2:2", FALSE);
1691 signal_monitor_assert_is_empty (fixture->monitor);
1692 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1693 check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1695 filter_test_append_refilter_signals (fixture, 2);
1696 filter_test_enable_filter (fixture);
1698 check_filter_model (fixture);
1699 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1700 check_level_length (fixture->filter, "2", LEVEL_LENGTH - 1);
1704 unfiltered_hide_single_multi_level (FilterTest *fixture,
1705 gconstpointer user_data)
1708 /* This row is not shown, so its signal is not propagated */
1709 set_path_visibility (fixture, "2:2:2", FALSE);
1711 /* This row is not shown, so its signal is not propagated */
1712 set_path_visibility (fixture, "2:2", FALSE);
1714 signal_monitor_assert_is_empty (fixture->monitor);
1715 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1716 check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1717 check_level_length (fixture->filter, "2:2", LEVEL_LENGTH);
1719 /* The view only shows the root level, so we only expect signals
1720 * for the root level.
1722 filter_test_append_refilter_signals (fixture, 1);
1723 filter_test_enable_filter (fixture);
1725 check_filter_model (fixture);
1726 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1727 check_level_length (fixture->filter, "2", LEVEL_LENGTH - 1);
1729 set_path_visibility (fixture, "2:2", TRUE);
1731 check_filter_model (fixture);
1732 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1733 check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1734 check_level_length (fixture->filter, "2:2", LEVEL_LENGTH - 1);
1738 unfiltered_hide_single_multi_level_root_expanded (FilterTest *fixture,
1739 gconstpointer user_data)
1742 /* This row is not shown, so its signal is not propagated */
1743 set_path_visibility (fixture, "2:2:2", FALSE);
1745 signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2:2");
1746 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
1747 set_path_visibility (fixture, "2:2", FALSE);
1749 signal_monitor_assert_is_empty (fixture->monitor);
1750 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1751 check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1752 check_level_length (fixture->filter, "2:2", LEVEL_LENGTH);
1754 filter_test_append_refilter_signals (fixture, 2);
1755 filter_test_enable_filter (fixture);
1757 check_filter_model (fixture);
1758 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1759 check_level_length (fixture->filter, "2", LEVEL_LENGTH - 1);
1761 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "2:2");
1762 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
1763 set_path_visibility (fixture, "2:2", TRUE);
1765 check_filter_model (fixture);
1766 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1767 check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1768 check_level_length (fixture->filter, "2:2", LEVEL_LENGTH - 1);
1774 unfiltered_vroot_hide_single (FilterTest *fixture,
1775 gconstpointer user_data)
1778 GtkTreePath *path = (GtkTreePath *)user_data;
1780 signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2");
1781 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2");
1782 set_path_visibility (fixture, "2:2", FALSE);
1784 signal_monitor_assert_is_empty (fixture->monitor);
1785 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1787 /* The view only shows the root level, so we only expect signals
1788 * for the root level. (Though for the depth argument, we have to
1789 * take the virtual root into account).
1791 filter_test_append_refilter_signals_with_vroot (fixture, 2, path);
1792 filter_test_enable_filter (fixture);
1794 check_filter_model_with_root (fixture, path);
1795 check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 1);
1799 unfiltered_vroot_hide_single_child (FilterTest *fixture,
1800 gconstpointer user_data)
1803 GtkTreePath *path = (GtkTreePath *)user_data;
1805 /* Not visible, so no signal will be received. */
1806 set_path_visibility (fixture, "2:2:2", FALSE);
1808 signal_monitor_assert_is_empty (fixture->monitor);
1809 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1810 check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1812 /* The view only shows the root level, so we only expect signals
1813 * for the root level. (Though for the depth argument, we have to
1814 * take the virtual root into account).
1816 filter_test_append_refilter_signals_with_vroot (fixture, 2, path);
1817 filter_test_enable_filter (fixture);
1819 check_filter_model_with_root (fixture, path);
1820 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1821 check_level_length (fixture->filter, "2", LEVEL_LENGTH - 1);
1825 unfiltered_vroot_hide_single_child_root_expanded (FilterTest *fixture,
1826 gconstpointer user_data)
1829 GtkTreePath *path = (GtkTreePath *)user_data;
1831 signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2:2");
1832 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
1833 set_path_visibility (fixture, "2:2:2", FALSE);
1835 signal_monitor_assert_is_empty (fixture->monitor);
1836 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1837 check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1839 filter_test_append_refilter_signals_with_vroot (fixture, 3, path);
1840 filter_test_enable_filter (fixture);
1842 check_filter_model_with_root (fixture, path);
1843 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1844 check_level_length (fixture->filter, "2", LEVEL_LENGTH - 1);
1848 unfiltered_vroot_hide_single_multi_level (FilterTest *fixture,
1849 gconstpointer user_data)
1852 GtkTreePath *path = (GtkTreePath *)user_data;
1854 /* This row is not shown, so its signal is not propagated */
1855 set_path_visibility (fixture, "2:2:2:2", FALSE);
1857 /* Not shown, so no signal */
1858 set_path_visibility (fixture, "2:2:2", FALSE);
1860 signal_monitor_assert_is_empty (fixture->monitor);
1861 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1862 check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1863 check_level_length (fixture->filter, "2:2", LEVEL_LENGTH);
1865 /* We only expect signals for the root level. The depth is 2
1866 * because we have to take the virtual root into account.
1868 filter_test_append_refilter_signals_with_vroot (fixture, 2, path);
1869 filter_test_enable_filter (fixture);
1871 check_filter_model_with_root (fixture, path);
1872 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1873 check_level_length (fixture->filter, "2", LEVEL_LENGTH - 1);
1875 /* Not shown, so no signal */
1876 set_path_visibility (fixture, "2:2:2", TRUE);
1878 check_filter_model_with_root (fixture, path);
1879 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1880 check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1881 check_level_length (fixture->filter, "2:2", LEVEL_LENGTH - 1);
1885 unfiltered_vroot_hide_single_multi_level_root_expanded (FilterTest *fixture,
1886 gconstpointer user_data)
1889 GtkTreePath *path = (GtkTreePath *)user_data;
1891 /* This row is not shown, so its signal is not propagated */
1892 set_path_visibility (fixture, "2:2:2:2", FALSE);
1894 signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2:2");
1895 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
1896 set_path_visibility (fixture, "2:2:2", FALSE);
1898 signal_monitor_assert_is_empty (fixture->monitor);
1899 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1900 check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1901 check_level_length (fixture->filter, "2:2", LEVEL_LENGTH);
1903 filter_test_append_refilter_signals_with_vroot (fixture, 3, path);
1904 filter_test_enable_filter (fixture);
1906 check_filter_model_with_root (fixture, path);
1907 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1908 check_level_length (fixture->filter, "2", LEVEL_LENGTH - 1);
1910 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "2:2");
1911 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
1912 set_path_visibility (fixture, "2:2:2", TRUE);
1914 check_filter_model_with_root (fixture, path);
1915 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1916 check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1917 check_level_length (fixture->filter, "2:2", LEVEL_LENGTH - 1);
1921 unfiltered_show_single (FilterTest *fixture,
1922 gconstpointer user_data)
1925 signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2");
1926 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2");
1927 set_path_visibility (fixture, "2", TRUE);
1929 signal_monitor_assert_is_empty (fixture->monitor);
1930 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1932 /* We only expect signals for the root level */
1933 filter_test_append_refilter_signals (fixture, 1);
1934 filter_test_enable_filter (fixture);
1936 check_filter_model (fixture);
1937 check_level_length (fixture->filter, NULL, 1);
1941 unfiltered_show_single_child (FilterTest *fixture,
1942 gconstpointer user_data)
1945 set_path_visibility (fixture, "2:2", TRUE);
1947 signal_monitor_assert_is_empty (fixture->monitor);
1948 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1949 check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1951 /* We only expect signals for the root level */
1952 filter_test_append_refilter_signals (fixture, 1);
1953 filter_test_enable_filter (fixture);
1955 check_filter_model (fixture);
1956 check_level_length (fixture->filter, NULL, 0);
1958 /* From here we are filtered, "2" in the real model is "0" in the filter
1961 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1962 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1963 set_path_visibility (fixture, "2", TRUE);
1964 signal_monitor_assert_is_empty (fixture->monitor);
1965 check_level_length (fixture->filter, NULL, 1);
1966 check_level_length (fixture->filter, "0", 1);
1970 unfiltered_show_single_child_root_expanded (FilterTest *fixture,
1971 gconstpointer user_data)
1974 signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2:2");
1975 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
1976 set_path_visibility (fixture, "2:2", TRUE);
1978 signal_monitor_assert_is_empty (fixture->monitor);
1979 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1980 check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1982 filter_test_append_refilter_signals (fixture, 2);
1983 filter_test_enable_filter (fixture);
1985 check_filter_model (fixture);
1986 check_level_length (fixture->filter, NULL, 0);
1988 /* From here we are filtered, "2" in the real model is "0" in the filter
1991 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1992 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1993 set_path_visibility (fixture, "2", TRUE);
1994 signal_monitor_assert_is_empty (fixture->monitor);
1995 check_level_length (fixture->filter, NULL, 1);
1996 check_level_length (fixture->filter, "0", 1);
2000 unfiltered_show_single_multi_level (FilterTest *fixture,
2001 gconstpointer user_data)
2004 /* The view is not showing these rows (collapsed state), so it is not
2005 * referenced. The signal should not go through.
2007 set_path_visibility (fixture, "2:2:2", TRUE);
2008 set_path_visibility (fixture, "2:2", TRUE);
2010 signal_monitor_assert_is_empty (fixture->monitor);
2011 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
2012 check_level_length (fixture->filter, "2", LEVEL_LENGTH);
2013 check_level_length (fixture->filter, "2:2", LEVEL_LENGTH);
2015 /* We only expect signals for the first level */
2016 filter_test_append_refilter_signals (fixture, 1);
2017 filter_test_enable_filter (fixture);
2019 check_filter_model (fixture);
2020 check_level_length (fixture->filter, NULL, 0);
2022 /* From here we are filtered, "2" in the real model is "0" in the filter
2025 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
2026 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
2027 set_path_visibility (fixture, "2", TRUE);
2028 check_filter_model (fixture);
2029 check_level_length (fixture->filter, NULL, 1);
2030 check_level_length (fixture->filter, "0", 1);
2031 check_level_length (fixture->filter, "0:0", 1);
2035 unfiltered_show_single_multi_level_root_expanded (FilterTest *fixture,
2036 gconstpointer user_data)
2039 /* The view is not showing this row (collapsed state), so it is not
2040 * referenced. The signal should not go through.
2042 set_path_visibility (fixture, "2:2:2", TRUE);
2044 signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2:2");
2045 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
2046 set_path_visibility (fixture, "2:2", TRUE);
2048 signal_monitor_assert_is_empty (fixture->monitor);
2049 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
2050 check_level_length (fixture->filter, "2", LEVEL_LENGTH);
2051 check_level_length (fixture->filter, "2:2", LEVEL_LENGTH);
2053 filter_test_append_refilter_signals (fixture, 2);
2054 filter_test_enable_filter (fixture);
2056 check_filter_model (fixture);
2057 check_level_length (fixture->filter, NULL, 0);
2059 /* From here we are filtered, "2" in the real model is "0" in the filter
2062 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
2063 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
2064 set_path_visibility (fixture, "2", TRUE);
2065 check_filter_model (fixture);
2066 check_level_length (fixture->filter, NULL, 1);
2067 check_level_length (fixture->filter, "0", 1);
2068 check_level_length (fixture->filter, "0:0", 1);
2072 unfiltered_vroot_show_single (FilterTest *fixture,
2073 gconstpointer user_data)
2076 GtkTreePath *path = (GtkTreePath *)user_data;
2078 signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2");
2079 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2");
2080 set_path_visibility (fixture, "2:2", TRUE);
2082 signal_monitor_assert_is_empty (fixture->monitor);
2083 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
2085 /* The view only shows the root level, so the filter model only has
2086 * the first two levels cached.
2088 filter_test_append_refilter_signals_with_vroot (fixture, 2, path);
2089 filter_test_enable_filter (fixture);
2091 check_filter_model_with_root (fixture, path);
2092 check_level_length (fixture->filter, NULL, 1);
2096 unfiltered_vroot_show_single_child (FilterTest *fixture,
2097 gconstpointer user_data)
2100 GtkTreePath *path = (GtkTreePath *)user_data;
2102 set_path_visibility (fixture, "2:2:2", TRUE);
2104 signal_monitor_assert_is_empty (fixture->monitor);
2105 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
2106 check_level_length (fixture->filter, "2", LEVEL_LENGTH);
2108 /* The view only shows the root level, so the filter model only has
2109 * the first two levels cached.
2111 filter_test_append_refilter_signals_with_vroot (fixture, 2, path);
2112 filter_test_enable_filter (fixture);
2114 check_filter_model_with_root (fixture, path);
2115 check_level_length (fixture->filter, NULL, 0);
2117 /* From here we are filtered, "2" in the real model is "0" in the filter
2120 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
2121 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
2122 set_path_visibility (fixture, "2:2", TRUE);
2123 signal_monitor_assert_is_empty (fixture->monitor);
2124 check_level_length (fixture->filter, NULL, 1);
2125 check_level_length (fixture->filter, "0", 1);
2129 unfiltered_vroot_show_single_child_root_expanded (FilterTest *fixture,
2130 gconstpointer user_data)
2133 GtkTreePath *path = (GtkTreePath *)user_data;
2135 signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2:2");
2136 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
2137 set_path_visibility (fixture, "2:2:2", TRUE);
2139 signal_monitor_assert_is_empty (fixture->monitor);
2140 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
2141 check_level_length (fixture->filter, "2", LEVEL_LENGTH);
2143 filter_test_append_refilter_signals_with_vroot (fixture, 3, path);
2144 filter_test_enable_filter (fixture);
2146 check_filter_model_with_root (fixture, path);
2147 check_level_length (fixture->filter, NULL, 0);
2149 /* From here we are filtered, "2" in the real model is "0" in the filter
2152 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
2153 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
2154 set_path_visibility (fixture, "2:2", TRUE);
2155 signal_monitor_assert_is_empty (fixture->monitor);
2156 check_level_length (fixture->filter, NULL, 1);
2157 check_level_length (fixture->filter, "0", 1);
2162 unfiltered_vroot_show_single_multi_level (FilterTest *fixture,
2163 gconstpointer user_data)
2166 GtkTreePath *path = (GtkTreePath *)user_data;
2168 /* The view is not showing this row (collapsed state), so it is not
2169 * referenced. The signal should not go through.
2171 set_path_visibility (fixture, "2:2:2:2", TRUE);
2173 set_path_visibility (fixture, "2:2:2", TRUE);
2175 signal_monitor_assert_is_empty (fixture->monitor);
2176 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
2177 check_level_length (fixture->filter, "2", LEVEL_LENGTH);
2178 check_level_length (fixture->filter, "2:2", LEVEL_LENGTH);
2180 /* We only expect signals for the root level */
2181 filter_test_append_refilter_signals_with_vroot (fixture, 2, path);
2182 filter_test_enable_filter (fixture);
2184 check_filter_model_with_root (fixture, path);
2185 check_level_length (fixture->filter, NULL, 0);
2187 /* From here we are filtered, "2" in the real model is "0" in the filter
2190 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
2191 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
2192 set_path_visibility (fixture, "2:2", TRUE);
2193 check_filter_model_with_root (fixture, path);
2194 check_level_length (fixture->filter, NULL, 1);
2195 check_level_length (fixture->filter, "0", 1);
2196 check_level_length (fixture->filter, "0:0", 1);
2200 unfiltered_vroot_show_single_multi_level_root_expanded (FilterTest *fixture,
2201 gconstpointer user_data)
2204 GtkTreePath *path = (GtkTreePath *)user_data;
2206 /* The view is not showing this row (collapsed state), so it is not
2207 * referenced. The signal should not go through.
2209 set_path_visibility (fixture, "2:2:2:2", TRUE);
2211 signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2:2");
2212 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
2213 set_path_visibility (fixture, "2:2:2", TRUE);
2215 signal_monitor_assert_is_empty (fixture->monitor);
2216 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
2217 check_level_length (fixture->filter, "2", LEVEL_LENGTH);
2218 check_level_length (fixture->filter, "2:2", LEVEL_LENGTH);
2220 filter_test_append_refilter_signals_with_vroot (fixture, 3, path);
2221 filter_test_enable_filter (fixture);
2223 check_filter_model_with_root (fixture, path);
2224 check_level_length (fixture->filter, NULL, 0);
2226 /* From here we are filtered, "2" in the real model is "0" in the filter
2229 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
2230 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
2231 set_path_visibility (fixture, "2:2", TRUE);
2232 check_filter_model_with_root (fixture, path);
2233 check_level_length (fixture->filter, NULL, 1);
2234 check_level_length (fixture->filter, "0", 1);
2235 check_level_length (fixture->filter, "0:0", 1);
2240 insert_before (void)
2242 GtkTreeStore *store;
2243 GtkTreeModel *filter;
2244 GtkWidget *tree_view;
2245 SignalMonitor *monitor;
2247 GtkTreeIter last_iter;
2250 /* This tests two aspects of the row-inserted handling:
2251 * 1) If the newly inserted node was already handled by building
2252 * the root level, don't handle it a second time.
2253 * 2) Offsets of existing nodes must be updated when a new
2257 store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
2258 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
2259 gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter),
2262 tree_view = gtk_tree_view_new_with_model (filter);
2263 monitor = signal_monitor_new (filter);
2265 check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, 0);
2268 path = gtk_tree_path_new_from_indices (0, -1);
2269 signal_monitor_append_signal_path (monitor, ROW_INSERTED, path);
2270 gtk_tree_path_free (path);
2272 gtk_tree_store_insert_with_values (store, &iter, NULL, 0,
2273 0, "Foo", 1, TRUE, -1);
2275 signal_monitor_assert_is_empty (monitor);
2276 check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, 1);
2279 path = gtk_tree_path_new_from_indices (1, -1);
2280 signal_monitor_append_signal_path (monitor, ROW_INSERTED, path);
2281 gtk_tree_path_free (path);
2283 gtk_tree_store_insert_with_values (store, &iter, NULL, 1,
2284 0, "Foo", 1, TRUE, -1);
2287 signal_monitor_assert_is_empty (monitor);
2288 check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, 2);
2290 /* Insert on 1 again -- invisible */
2291 gtk_tree_store_insert_with_values (store, &iter, NULL, 1,
2292 0, "Foo", 1, FALSE, -1);
2294 signal_monitor_assert_is_empty (monitor);
2295 check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, 2);
2297 /* Insert on 1 again -- visible */
2298 path = gtk_tree_path_new_from_indices (1, -1);
2299 signal_monitor_append_signal_path (monitor, ROW_INSERTED, path);
2300 gtk_tree_path_free (path);
2302 gtk_tree_store_insert_with_values (store, &iter, NULL, 1,
2303 0, "Foo", 1, TRUE, -1);
2305 signal_monitor_assert_is_empty (monitor);
2306 check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, 3);
2308 /* Modify the iter that should be at the last position and check the
2311 path = gtk_tree_path_new_from_indices (2, -1);
2312 signal_monitor_append_signal_path (monitor, ROW_CHANGED, path);
2313 gtk_tree_path_free (path);
2315 gtk_tree_store_set (store, &last_iter, 0, "Foo changed", -1);
2317 signal_monitor_assert_is_empty (monitor);
2318 check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, 3);
2324 GtkTreeStore *store;
2325 GtkTreeModel *filter;
2326 GtkWidget *tree_view;
2327 SignalMonitor *monitor;
2328 GtkTreeIter parent, iter;
2331 store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
2333 gtk_tree_store_insert_with_values (store, &parent, NULL, 0,
2334 0, "Parent", 1, TRUE, -1);
2337 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
2338 gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter),
2341 tree_view = gtk_tree_view_new_with_model (filter);
2342 monitor = signal_monitor_new (filter);
2344 /* Insert child -- invisible */
2345 path = gtk_tree_path_new_from_indices (0, -1);
2346 signal_monitor_append_signal_path (monitor, ROW_HAS_CHILD_TOGGLED, path);
2347 /* The signal is received twice, once a pass through from GtkTreeStore
2348 * and one generated by GtkTreeModelFilter. Not accurate, but cannot
2351 signal_monitor_append_signal_path (monitor, ROW_HAS_CHILD_TOGGLED, path);
2352 gtk_tree_path_free (path);
2354 gtk_tree_store_insert_with_values (store, &iter, &parent, 1,
2355 0, "Child", 1, FALSE, -1);
2357 signal_monitor_assert_is_empty (monitor);
2358 check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, 1);
2361 path = gtk_tree_path_new_from_indices (0, 0, -1);
2362 gtk_tree_path_up (path); /* 0 */
2363 signal_monitor_append_signal_path (monitor, ROW_HAS_CHILD_TOGGLED, path);
2364 gtk_tree_path_free (path);
2366 gtk_tree_store_insert_with_values (store, &iter, &parent, 0,
2367 0, "Child", 1, TRUE, -1);
2369 signal_monitor_assert_is_empty (monitor);
2370 check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, 1);
2372 /* Insert child -- invisible */
2373 gtk_tree_store_insert_with_values (store, &iter, &parent, 1,
2374 0, "Child", 1, FALSE, -1);
2376 signal_monitor_assert_is_empty (monitor);
2377 check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, 1);
2385 GtkTreeIter iter, iter1, iter2, iter3;
2387 GtkTreeModel *filter;
2388 GtkWidget *view G_GNUC_UNUSED;
2390 list = gtk_list_store_new (1, G_TYPE_INT);
2391 gtk_list_store_insert_with_values (list, &iter1, 0, 0, 1, -1);
2392 gtk_list_store_insert_with_values (list, &iter, 1, 0, 2, -1);
2393 gtk_list_store_insert_with_values (list, &iter, 2, 0, 3, -1);
2394 gtk_list_store_insert_with_values (list, &iter, 3, 0, 4, -1);
2395 gtk_list_store_insert_with_values (list, &iter, 4, 0, 5, -1);
2396 gtk_list_store_insert_with_values (list, &iter, 5, 0, 6, -1);
2397 gtk_list_store_insert_with_values (list, &iter2, 6, 0, 7, -1);
2398 gtk_list_store_insert_with_values (list, &iter3, 7, 0, 8, -1);
2400 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (list), NULL);
2401 view = gtk_tree_view_new_with_model (filter);
2403 gtk_list_store_remove (list, &iter1);
2404 gtk_list_store_remove (list, &iter3);
2405 gtk_list_store_remove (list, &iter2);
2407 gtk_widget_destroy (view);
2408 g_object_unref (filter);
2409 g_object_unref (list);
2413 remove_node_vroot (void)
2415 GtkTreeIter parent, root;
2416 GtkTreeIter iter, iter1, iter2, iter3;
2418 GtkTreeModel *filter;
2420 GtkWidget *view G_GNUC_UNUSED;
2422 tree = gtk_tree_store_new (1, G_TYPE_INT);
2423 gtk_tree_store_insert_with_values (tree, &parent, NULL, 0, 0, 0, -1);
2424 gtk_tree_store_insert_with_values (tree, &root, &parent, 0, 0, 0, -1);
2426 gtk_tree_store_insert_with_values (tree, &iter1, &root, 0, 0, 1, -1);
2427 gtk_tree_store_insert_with_values (tree, &iter, &root, 1, 0, 2, -1);
2428 gtk_tree_store_insert_with_values (tree, &iter, &root, 2, 0, 3, -1);
2429 gtk_tree_store_insert_with_values (tree, &iter, &root, 3, 0, 4, -1);
2430 gtk_tree_store_insert_with_values (tree, &iter, &root, 4, 0, 5, -1);
2431 gtk_tree_store_insert_with_values (tree, &iter, &root, 5, 0, 6, -1);
2432 gtk_tree_store_insert_with_values (tree, &iter2, &root, 6, 0, 7, -1);
2433 gtk_tree_store_insert_with_values (tree, &iter3, &root, 7, 0, 8, -1);
2435 path = gtk_tree_path_new_from_indices (0, 0, -1);
2436 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (tree), path);
2437 gtk_tree_path_free (path);
2439 view = gtk_tree_view_new_with_model (filter);
2441 gtk_tree_store_remove (tree, &iter1);
2442 gtk_tree_store_remove (tree, &iter3);
2443 gtk_tree_store_remove (tree, &iter2);
2445 gtk_widget_destroy (view);
2446 g_object_unref (filter);
2447 g_object_unref (tree);
2451 remove_vroot_ancestor (void)
2453 GtkTreeIter parent, root;
2454 GtkTreeIter iter, iter1, iter2, iter3;
2456 GtkTreeModel *filter;
2458 GtkWidget *view G_GNUC_UNUSED;
2460 tree = gtk_tree_store_new (1, G_TYPE_INT);
2461 gtk_tree_store_insert_with_values (tree, &parent, NULL, 0, 0, 0, -1);
2462 gtk_tree_store_insert_with_values (tree, &root, &parent, 0, 0, 0, -1);
2464 gtk_tree_store_insert_with_values (tree, &iter1, &root, 0, 0, 1, -1);
2465 gtk_tree_store_insert_with_values (tree, &iter, &root, 1, 0, 2, -1);
2466 gtk_tree_store_insert_with_values (tree, &iter, &root, 2, 0, 3, -1);
2467 gtk_tree_store_insert_with_values (tree, &iter, &root, 3, 0, 4, -1);
2468 gtk_tree_store_insert_with_values (tree, &iter, &root, 4, 0, 5, -1);
2469 gtk_tree_store_insert_with_values (tree, &iter, &root, 5, 0, 6, -1);
2470 gtk_tree_store_insert_with_values (tree, &iter2, &root, 6, 0, 7, -1);
2471 gtk_tree_store_insert_with_values (tree, &iter3, &root, 7, 0, 8, -1);
2473 path = gtk_tree_path_new_from_indices (0, 0, -1);
2474 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (tree), path);
2475 gtk_tree_path_free (path);
2477 view = gtk_tree_view_new_with_model (filter);
2479 gtk_tree_store_remove (tree, &parent);
2481 gtk_widget_destroy (view);
2482 g_object_unref (filter);
2483 g_object_unref (tree);
2488 specific_path_dependent_filter_func (GtkTreeModel *model,
2494 path = gtk_tree_model_get_path (model, iter);
2495 if (gtk_tree_path_get_indices (path)[0] < 4)
2502 specific_path_dependent_filter (void)
2508 GtkTreeModel *filter;
2510 list = gtk_list_store_new (1, G_TYPE_INT);
2511 gtk_list_store_insert_with_values (list, &iter, 0, 0, 1, -1);
2512 gtk_list_store_insert_with_values (list, &iter, 1, 0, 2, -1);
2513 gtk_list_store_insert_with_values (list, &iter, 2, 0, 3, -1);
2514 gtk_list_store_insert_with_values (list, &iter, 3, 0, 4, -1);
2515 gtk_list_store_insert_with_values (list, &iter, 4, 0, 5, -1);
2516 gtk_list_store_insert_with_values (list, &iter, 5, 0, 6, -1);
2517 gtk_list_store_insert_with_values (list, &iter, 6, 0, 7, -1);
2518 gtk_list_store_insert_with_values (list, &iter, 7, 0, 8, -1);
2520 sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (list));
2521 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (sort), NULL);
2522 gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
2523 specific_path_dependent_filter_func,
2526 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sort), 0,
2527 GTK_SORT_DESCENDING);
2529 for (i = 0; i < 4; i++)
2531 if (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (list), &iter,
2533 gtk_list_store_remove (list, &iter);
2535 if (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (list), &iter,
2537 gtk_list_store_remove (list, &iter);
2540 g_object_unref (filter);
2541 g_object_unref (sort);
2542 g_object_unref (list);
2547 specific_append_after_collapse_visible_func (GtkTreeModel *model,
2552 gboolean hide_negative_numbers;
2554 gtk_tree_model_get (model, iter, 1, &number, -1);
2555 hide_negative_numbers = GPOINTER_TO_INT (g_object_get_data (data, "private-hide-negative-numbers"));
2557 return (number >= 0 || !hide_negative_numbers);
2561 specific_append_after_collapse (void)
2563 /* This test is based on one of the test cases I found in my
2564 * old test cases directory. I unfortunately do not have a record
2565 * from who this test case originated. -Kris.
2569 * - Show tree, expand, collapse.
2574 GtkTreeIter child_iter;
2575 GtkTreeIter child_iter2;
2576 GtkTreePath *append_path;
2577 GtkTreeStore *store;
2578 GtkTreeModel *filter;
2582 GtkWidget *tree_view;
2584 store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_INT);
2586 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
2587 g_object_set_data (G_OBJECT (filter), "private-hide-negative-numbers",
2588 GINT_TO_POINTER (FALSE));
2589 gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
2590 specific_append_after_collapse_visible_func,
2593 sort = gtk_tree_model_sort_new_with_model (filter);
2595 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2596 tree_view = gtk_tree_view_new_with_model (sort);
2597 gtk_container_add (GTK_CONTAINER (window), tree_view);
2598 gtk_widget_realize (tree_view);
2600 while (gtk_events_pending ())
2601 gtk_main_iteration ();
2603 gtk_tree_store_prepend (store, &iter, NULL);
2604 gtk_tree_store_set (store, &iter,
2605 0, "hallo", 1, 1, -1);
2607 gtk_tree_store_append (store, &child_iter, &iter);
2608 gtk_tree_store_set (store, &child_iter,
2609 0, "toemaar", 1, 1, -1);
2611 gtk_tree_store_append (store, &child_iter2, &child_iter);
2612 gtk_tree_store_set (store, &child_iter2,
2613 0, "very deep", 1, 1, -1);
2615 append_path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &child_iter2);
2617 gtk_tree_store_append (store, &child_iter, &iter);
2618 gtk_tree_store_set (store, &child_iter,
2619 0, "sja", 1, 1, -1);
2621 gtk_tree_store_append (store, &child_iter, &iter);
2622 gtk_tree_store_set (store, &child_iter,
2623 0, "some word", 1, -1, -1);
2625 /* Expand and collapse the tree */
2626 gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
2627 while (gtk_events_pending ())
2628 gtk_main_iteration ();
2630 gtk_tree_view_collapse_all (GTK_TREE_VIEW (tree_view));
2631 while (gtk_events_pending ())
2632 gtk_main_iteration ();
2634 /* Add another it */
2635 g_object_set_data (G_OBJECT (filter), "private-hide-negative-numbers",
2636 GINT_TO_POINTER (TRUE));
2638 if (gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, append_path))
2640 gtk_tree_store_append (store, &child_iter, &iter);
2641 gtk_tree_store_set (store, &child_iter,
2642 0, "new new new !!", 1, 1, -1);
2644 gtk_tree_path_free (append_path);
2647 gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
2648 while (gtk_events_pending ())
2649 gtk_main_iteration ();
2654 specific_sort_filter_remove_node_compare_func (GtkTreeModel *model,
2663 specific_sort_filter_remove_node_visible_func (GtkTreeModel *model,
2669 /* Do reference the model */
2670 gtk_tree_model_get (model, iter, 0, &item, -1);
2677 specific_sort_filter_remove_node (void)
2679 /* This test is based on one of the test cases I found in my
2680 * old test cases directory. I unfortunately do not have a record
2681 * from who this test case originated. -Kris.
2684 * - Create tree store, sort, filter models. The sort model has
2685 * a default sort func that is enabled, filter model a visible func
2686 * that defaults to returning FALSE.
2687 * - Remove a node from the tree store.
2691 GtkTreeStore *store;
2692 GtkTreeModel *filter;
2696 GtkWidget *tree_view;
2698 store = gtk_tree_store_new (1, G_TYPE_STRING);
2699 gtk_tree_store_append (store, &iter, NULL);
2700 gtk_tree_store_set (store, &iter, 0, "Hello1", -1);
2702 gtk_tree_store_append (store, &iter, NULL);
2703 gtk_tree_store_set (store, &iter, 0, "Hello2", -1);
2705 sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (store));
2706 gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (sort),
2707 specific_sort_filter_remove_node_compare_func, NULL, NULL);
2709 filter = gtk_tree_model_filter_new (sort, NULL);
2710 gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
2711 specific_sort_filter_remove_node_visible_func,
2715 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2716 tree_view = gtk_tree_view_new_with_model (filter);
2717 gtk_container_add (GTK_CONTAINER (window), tree_view);
2718 gtk_widget_realize (tree_view);
2720 while (gtk_events_pending ())
2721 gtk_main_iteration ();
2724 gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter);
2725 gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter);
2726 gtk_tree_store_remove (store, &iter);
2728 while (gtk_events_pending ())
2729 gtk_main_iteration ();
2734 specific_sort_filter_remove_root (void)
2736 /* This test is based on one of the test cases I found in my
2737 * old test cases directory. I unfortunately do not have a record
2738 * from who this test case originated. -Kris.
2741 GtkTreeModel *model, *sort, *filter;
2742 GtkTreeIter root, mid, leaf;
2745 model = GTK_TREE_MODEL (gtk_tree_store_new (1, G_TYPE_INT));
2746 gtk_tree_store_append (GTK_TREE_STORE (model), &root, NULL);
2747 gtk_tree_store_append (GTK_TREE_STORE (model), &mid, &root);
2748 gtk_tree_store_append (GTK_TREE_STORE (model), &leaf, &mid);
2750 path = gtk_tree_model_get_path (model, &mid);
2752 sort = gtk_tree_model_sort_new_with_model (model);
2753 filter = gtk_tree_model_filter_new (sort, path);
2755 gtk_tree_path_free (path);
2757 gtk_tree_store_remove (GTK_TREE_STORE (model), &root);
2759 g_object_unref (filter);
2760 g_object_unref (sort);
2761 g_object_unref (model);
2766 specific_root_mixed_visibility (void)
2769 GtkTreeModel *filter;
2770 /* A bit nasty, apologies */
2773 fixture.store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
2775 for (i = 0; i < LEVEL_LENGTH; i++)
2779 gtk_tree_store_insert (fixture.store, &iter, NULL, i);
2781 create_tree_store_set_values (fixture.store, &iter, TRUE);
2783 create_tree_store_set_values (fixture.store, &iter, FALSE);
2786 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (fixture.store), NULL);
2787 fixture.filter = GTK_TREE_MODEL_FILTER (filter);
2788 fixture.monitor = NULL;
2790 gtk_tree_model_filter_set_visible_column (fixture.filter, 1);
2792 /* In order to trigger the potential bug, we should not access
2793 * the filter model here (so don't call the check functions).
2796 /* Change visibility of an odd row to TRUE */
2797 set_path_visibility (&fixture, "3", TRUE);
2798 check_filter_model (&fixture);
2799 check_level_length (fixture.filter, NULL, 4);
2805 specific_has_child_filter_filter_func (GtkTreeModel *model,
2809 return gtk_tree_model_iter_has_child (model, iter);
2813 specific_has_child_filter (void)
2815 GtkTreeModel *filter;
2816 GtkTreeIter iter, root;
2817 FilterTest fixture; /* This is not how it should be done */
2818 GtkWidget *tree_view;
2820 fixture.store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
2821 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (fixture.store), NULL);
2822 fixture.filter = GTK_TREE_MODEL_FILTER (filter);
2823 fixture.monitor = signal_monitor_new (filter);
2825 tree_view = gtk_tree_view_new_with_model (filter);
2827 /* We will filter on parent state using a filter function. We will
2828 * manually keep the boolean column in sync, so that we can use
2829 * check_filter_model() to check the consistency of the model.
2831 /* FIXME: We need a check_filter_model() that is not tied to LEVEL_LENGTH
2832 * to be able to check the structure here. We keep the calls to
2833 * check_filter_model() commented out until then.
2835 gtk_tree_model_filter_set_visible_func (fixture.filter,
2836 specific_has_child_filter_filter_func,
2839 /* The first node will be initially invisible: no signals */
2840 gtk_tree_store_append (fixture.store, &root, NULL);
2841 create_tree_store_set_values (fixture.store, &root, FALSE);
2843 /* check_filter_model (&fixture); */
2844 check_level_length (fixture.filter, NULL, 0);
2845 signal_monitor_assert_is_empty (fixture.monitor);
2847 /* Insert a child node. This will cause the parent to become visible
2848 * since there is a child now.
2850 signal_monitor_append_signal (fixture.monitor, ROW_INSERTED, "0");
2851 signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
2852 signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
2854 gtk_tree_store_append (fixture.store, &iter, &root);
2855 create_tree_store_set_values (fixture.store, &iter, TRUE);
2857 /* Parent must now be visible. Do the level length check first,
2858 * to avoid modifying the child model triggering a row-changed to
2861 check_level_length (fixture.filter, NULL, 1);
2862 check_level_length (fixture.filter, "0", 0);
2863 signal_monitor_assert_is_empty (fixture.monitor);
2865 /* This should propagate row-changed */
2866 signal_monitor_append_signal (fixture.monitor, ROW_CHANGED, "0");
2867 signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
2869 set_path_visibility (&fixture, "0", TRUE);
2870 /* check_filter_model (&fixture); */
2871 signal_monitor_assert_is_empty (fixture.monitor);
2873 /* New root node, no child, so no signal */
2874 gtk_tree_store_append (fixture.store, &root, NULL);
2875 check_level_length (fixture.filter, NULL, 1);
2876 signal_monitor_assert_is_empty (fixture.monitor);
2878 /* When the child comes in, this node will become visible */
2879 signal_monitor_append_signal (fixture.monitor, ROW_INSERTED, "1");
2880 signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "1");
2881 signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "1");
2882 signal_monitor_append_signal (fixture.monitor, ROW_CHANGED, "1");
2883 signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "1");
2885 gtk_tree_store_append (fixture.store, &iter, &root);
2886 check_level_length (fixture.filter, NULL, 2);
2887 check_level_length (fixture.filter, "1", 0);
2889 create_tree_store_set_values (fixture.store, &root, TRUE);
2890 create_tree_store_set_values (fixture.store, &iter, TRUE);
2892 /* check_filter_model (&fixture); */
2893 signal_monitor_assert_is_empty (fixture.monitor);
2895 /* Add another child for 1 */
2896 gtk_tree_store_append (fixture.store, &iter, &root);
2897 create_tree_store_set_values (fixture.store, &iter, TRUE);
2898 check_level_length (fixture.filter, NULL, 2);
2899 check_level_length (fixture.filter, "0", 0);
2900 check_level_length (fixture.filter, "1", 0);
2901 signal_monitor_assert_is_empty (fixture.monitor);
2903 /* Now remove one of the remaining child rows */
2904 signal_monitor_append_signal (fixture.monitor, ROW_DELETED, "0");
2906 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture.store),
2908 gtk_tree_store_remove (fixture.store, &iter);
2910 check_level_length (fixture.filter, NULL, 1);
2911 check_level_length (fixture.filter, "0", 0);
2913 set_path_visibility (&fixture, "0", FALSE);
2914 /* check_filter_model (&fixture); */
2915 signal_monitor_assert_is_empty (fixture.monitor);
2920 specific_root_has_child_filter_filter_func (GtkTreeModel *model,
2927 path = gtk_tree_model_get_path (model, iter);
2928 depth = gtk_tree_path_get_depth (path);
2929 gtk_tree_path_free (path);
2934 return gtk_tree_model_iter_has_child (model, iter);
2938 specific_root_has_child_filter (void)
2940 GtkTreeModel *filter;
2941 GtkTreeIter iter, root;
2942 FilterTest fixture; /* This is not how it should be done ... */
2943 GtkWidget *tree_view;
2945 /* This is a variation on the above test case, specific has-child-filter,
2946 * herein the has-child check for visibility only applies to root level
2947 * nodes. In this test, children are always visible because we
2948 * only filter based on the "has child" criterion.
2951 fixture.store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
2952 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (fixture.store), NULL);
2953 fixture.filter = GTK_TREE_MODEL_FILTER (filter);
2954 fixture.monitor = signal_monitor_new (filter);
2956 tree_view = gtk_tree_view_new_with_model (filter);
2958 /* We will filter on parent state using a filter function. We will
2959 * manually keep the boolean column in sync, so that we can use
2960 * check_filter_model() to check the consistency of the model.
2962 /* FIXME: We need a check_filter_model() that is not tied to LEVEL_LENGTH
2963 * to be able to check the structure here. We keep the calls to
2964 * check_filter_model() commented out until then.
2966 gtk_tree_model_filter_set_visible_func (fixture.filter,
2967 specific_root_has_child_filter_filter_func,
2970 /* Add a first node, this will be invisible initially, so no signal
2971 * should be emitted.
2973 gtk_tree_store_append (fixture.store, &root, NULL);
2974 create_tree_store_set_values (fixture.store, &root, FALSE);
2976 signal_monitor_assert_is_empty (fixture.monitor);
2977 /* check_filter_model (&fixture); */
2978 check_level_length (fixture.filter, NULL, 0);
2980 /* Add a child node. This will cause the parent to become visible,
2981 * so we expect row-inserted signals for both.
2983 signal_monitor_append_signal (fixture.monitor, ROW_INSERTED, "0");
2984 signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
2985 signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
2987 gtk_tree_store_append (fixture.store, &iter, &root);
2988 signal_monitor_assert_is_empty (fixture.monitor);
2990 check_level_length (fixture.filter, NULL, 1);
2991 check_level_length (fixture.filter, "0", 1);
2993 /* Modify the content of iter, no signals because the parent is not
2996 create_tree_store_set_values (fixture.store, &iter, TRUE);
2997 signal_monitor_assert_is_empty (fixture.monitor);
2999 /* Parent must now be visible. Do the level length check first,
3000 * to avoid modifying the child model triggering a row-changed to
3003 check_level_length (fixture.filter, NULL, 1);
3004 check_level_length (fixture.filter, "0", 1);
3007 signal_monitor_append_signal (fixture.monitor, ROW_CHANGED, "0");
3008 signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
3010 set_path_visibility (&fixture, "0", TRUE);
3011 /* check_filter_model (&fixture); */
3013 signal_monitor_assert_is_empty (fixture.monitor);
3015 /* Insert another node in the root level. Initially invisible, so
3016 * not expecting any signal.
3018 gtk_tree_store_append (fixture.store, &root, NULL);
3019 check_level_length (fixture.filter, NULL, 1);
3021 signal_monitor_assert_is_empty (fixture.monitor);
3023 /* Adding a child node which also makes parent at path 1 visible. */
3024 signal_monitor_append_signal (fixture.monitor, ROW_INSERTED, "1");
3025 signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "1");
3026 signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "1");
3028 gtk_tree_store_append (fixture.store, &iter, &root);
3029 check_level_length (fixture.filter, NULL, 2);
3030 check_level_length (fixture.filter, "1", 1);
3032 signal_monitor_assert_is_empty (fixture.monitor);
3034 /* Check if row-changed is propagated */
3035 signal_monitor_append_signal (fixture.monitor, ROW_CHANGED, "1");
3036 signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "1");
3038 create_tree_store_set_values (fixture.store, &root, TRUE);
3039 create_tree_store_set_values (fixture.store, &iter, TRUE);
3040 /* check_filter_model (&fixture); */
3041 signal_monitor_assert_is_empty (fixture.monitor);
3043 /* Insert another child under node 1 */
3044 gtk_tree_store_append (fixture.store, &iter, &root);
3045 create_tree_store_set_values (fixture.store, &iter, TRUE);
3046 check_level_length (fixture.filter, NULL, 2);
3047 check_level_length (fixture.filter, "0", 1);
3048 check_level_length (fixture.filter, "1", 2);
3049 signal_monitor_assert_is_empty (fixture.monitor);
3051 /* Set a child node to invisible. This should not yield any
3052 * change, because filtering is only done on whether the root
3053 * node has a child, which it still has.
3055 set_path_visibility (&fixture, "0:0", FALSE);
3056 signal_monitor_assert_is_empty (fixture.monitor);
3058 /* Now remove one of the remaining child rows */
3059 signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
3060 signal_monitor_append_signal (fixture.monitor, ROW_DELETED, "0");
3062 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture.store),
3064 gtk_tree_store_remove (fixture.store, &iter);
3066 check_level_length (fixture.filter, NULL, 1);
3067 check_level_length (fixture.filter, "0", 2);
3068 signal_monitor_assert_is_empty (fixture.monitor);
3070 /* Set visibility of 0 to FALSE, no-op for filter model since
3071 * the child 0:0 is already gone
3073 set_path_visibility (&fixture, "0", FALSE);
3074 /* check_filter_model (&fixture); */
3075 signal_monitor_assert_is_empty (fixture.monitor);
3079 specific_has_child_filter_on_sort_model (void)
3081 GtkTreeModel *filter;
3082 GtkTreeModel *sort_model;
3083 GtkTreeIter iter, root;
3084 FilterTest fixture; /* This is not how it should be done */
3085 GtkWidget *tree_view;
3087 fixture.store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
3088 sort_model = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (fixture.store));
3089 filter = gtk_tree_model_filter_new (sort_model, NULL);
3090 fixture.filter = GTK_TREE_MODEL_FILTER (filter);
3091 fixture.monitor = signal_monitor_new (filter);
3093 tree_view = gtk_tree_view_new_with_model (filter);
3095 /* We will filter on parent state using a filter function. We will
3096 * manually keep the boolean column in sync, so that we can use
3097 * check_filter_model() to check the consistency of the model.
3099 /* FIXME: We need a check_filter_model() that is not tied to LEVEL_LENGTH
3100 * to be able to check the structure here. We keep the calls to
3101 * check_filter_model() commented out until then.
3103 gtk_tree_model_filter_set_visible_func (fixture.filter,
3104 specific_has_child_filter_filter_func,
3107 /* The first node will be initially invisible: no signals */
3108 gtk_tree_store_append (fixture.store, &root, NULL);
3109 create_tree_store_set_values (fixture.store, &root, FALSE);
3111 /* check_filter_model (&fixture); */
3112 check_level_length (fixture.filter, NULL, 0);
3113 signal_monitor_assert_is_empty (fixture.monitor);
3115 /* Insert a child node. This will cause the parent to become visible
3116 * since there is a child now.
3118 signal_monitor_append_signal (fixture.monitor, ROW_INSERTED, "0");
3119 signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
3121 gtk_tree_store_append (fixture.store, &iter, &root);
3122 create_tree_store_set_values (fixture.store, &iter, TRUE);
3124 /* Parent must now be visible. Do the level length check first,
3125 * to avoid modifying the child model triggering a row-changed to
3128 check_level_length (fixture.filter, NULL, 1);
3129 check_level_length (fixture.filter, "0", 0);
3130 signal_monitor_assert_is_empty (fixture.monitor);
3132 /* This should propagate row-changed */
3133 signal_monitor_append_signal (fixture.monitor, ROW_CHANGED, "0");
3134 signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
3136 set_path_visibility (&fixture, "0", TRUE);
3137 /* check_filter_model (&fixture); */
3138 signal_monitor_assert_is_empty (fixture.monitor);
3140 /* New root node, no child, so no signal */
3141 gtk_tree_store_append (fixture.store, &root, NULL);
3142 check_level_length (fixture.filter, NULL, 1);
3143 signal_monitor_assert_is_empty (fixture.monitor);
3145 /* When the child comes in, this node will become visible */
3146 signal_monitor_append_signal (fixture.monitor, ROW_INSERTED, "1");
3147 signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "1");
3148 signal_monitor_append_signal (fixture.monitor, ROW_CHANGED, "1");
3149 signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "1");
3151 gtk_tree_store_append (fixture.store, &iter, &root);
3152 check_level_length (fixture.filter, NULL, 2);
3153 check_level_length (fixture.filter, "1", 0);
3155 create_tree_store_set_values (fixture.store, &root, TRUE);
3156 create_tree_store_set_values (fixture.store, &iter, TRUE);
3158 /* check_filter_model (&fixture); */
3159 signal_monitor_assert_is_empty (fixture.monitor);
3161 /* Add another child for 1 */
3162 gtk_tree_store_append (fixture.store, &iter, &root);
3163 create_tree_store_set_values (fixture.store, &iter, TRUE);
3164 check_level_length (fixture.filter, NULL, 2);
3165 check_level_length (fixture.filter, "0", 0);
3166 check_level_length (fixture.filter, "1", 0);
3167 signal_monitor_assert_is_empty (fixture.monitor);
3169 /* Now remove one of the remaining child rows */
3170 signal_monitor_append_signal (fixture.monitor, ROW_DELETED, "0");
3172 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture.store),
3174 gtk_tree_store_remove (fixture.store, &iter);
3176 check_level_length (fixture.filter, NULL, 1);
3177 check_level_length (fixture.filter, "0", 0);
3179 set_path_visibility (&fixture, "0", FALSE);
3180 /* check_filter_model (&fixture); */
3181 signal_monitor_assert_is_empty (fixture.monitor);
3185 specific_at_least_2_children_filter_filter_func (GtkTreeModel *model,
3189 return gtk_tree_model_iter_n_children (model, iter) >= 2;
3193 specific_at_least_2_children_filter (void)
3195 GtkTreeModel *filter;
3196 GtkTreeIter iter, root;
3197 FilterTest fixture; /* This is not how it should be done */
3198 GtkWidget *tree_view;
3200 fixture.store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
3201 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (fixture.store), NULL);
3202 fixture.filter = GTK_TREE_MODEL_FILTER (filter);
3203 fixture.monitor = signal_monitor_new (filter);
3205 tree_view = gtk_tree_view_new_with_model (filter);
3207 gtk_tree_model_filter_set_visible_func (fixture.filter,
3208 specific_at_least_2_children_filter_filter_func,
3211 /* The first node will be initially invisible: no signals */
3212 gtk_tree_store_append (fixture.store, &root, NULL);
3213 create_tree_store_set_values (fixture.store, &root, FALSE);
3215 /* check_filter_model (&fixture); */
3216 check_level_length (fixture.filter, NULL, 0);
3217 signal_monitor_assert_is_empty (fixture.monitor);
3219 /* Insert a child node. Nothing should happen.
3221 gtk_tree_store_append (fixture.store, &iter, &root);
3222 create_tree_store_set_values (fixture.store, &iter, TRUE);
3224 check_level_length (fixture.filter, NULL, 0);
3225 signal_monitor_assert_is_empty (fixture.monitor);
3227 /* Insert a second child node. This will cause the parent to become
3230 signal_monitor_append_signal (fixture.monitor, ROW_INSERTED, "0");
3231 signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
3233 gtk_tree_store_append (fixture.store, &iter, &root);
3234 create_tree_store_set_values (fixture.store, &iter, TRUE);
3236 /* Parent must now be visible. Do the level length check first,
3237 * to avoid modifying the child model triggering a row-changed to
3240 check_level_length (fixture.filter, NULL, 1);
3241 check_level_length (fixture.filter, "0", 0);
3242 signal_monitor_assert_is_empty (fixture.monitor);
3244 /* This should propagate row-changed */
3245 signal_monitor_append_signal (fixture.monitor, ROW_CHANGED, "0");
3246 signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
3248 set_path_visibility (&fixture, "0", TRUE);
3249 /* check_filter_model (&fixture); */
3250 signal_monitor_assert_is_empty (fixture.monitor);
3252 /* New root node, no child, so no signal */
3253 gtk_tree_store_append (fixture.store, &root, NULL);
3254 check_level_length (fixture.filter, NULL, 1);
3255 signal_monitor_assert_is_empty (fixture.monitor);
3257 /* First child, no signal, no change */
3258 gtk_tree_store_append (fixture.store, &iter, &root);
3259 check_level_length (fixture.filter, NULL, 1);
3260 signal_monitor_assert_is_empty (fixture.monitor);
3262 /* When the second child comes in, this node will become visible */
3263 signal_monitor_append_signal (fixture.monitor, ROW_INSERTED, "1");
3264 signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "1");
3265 signal_monitor_append_signal (fixture.monitor, ROW_CHANGED, "1");
3266 signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "1");
3268 gtk_tree_store_append (fixture.store, &iter, &root);
3269 check_level_length (fixture.filter, NULL, 2);
3270 check_level_length (fixture.filter, "1", 0);
3272 create_tree_store_set_values (fixture.store, &root, TRUE);
3273 create_tree_store_set_values (fixture.store, &iter, TRUE);
3275 /* check_filter_model (&fixture); */
3276 signal_monitor_assert_is_empty (fixture.monitor);
3278 /* Add another child for 1 */
3279 gtk_tree_store_append (fixture.store, &iter, &root);
3280 create_tree_store_set_values (fixture.store, &iter, TRUE);
3281 check_level_length (fixture.filter, NULL, 2);
3282 check_level_length (fixture.filter, "0", 0);
3283 check_level_length (fixture.filter, "1", 0);
3284 signal_monitor_assert_is_empty (fixture.monitor);
3286 /* Now remove one of the remaining child rows */
3287 signal_monitor_append_signal (fixture.monitor, ROW_DELETED, "0");
3289 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture.store),
3291 gtk_tree_store_remove (fixture.store, &iter);
3293 check_level_length (fixture.filter, NULL, 1);
3294 check_level_length (fixture.filter, "0", 0);
3296 set_path_visibility (&fixture, "0", FALSE);
3297 /* check_filter_model (&fixture); */
3298 signal_monitor_assert_is_empty (fixture.monitor);
3302 specific_at_least_2_children_filter_on_sort_model (void)
3304 GtkTreeModel *filter;
3305 GtkTreeModel *sort_model;
3306 GtkTreeIter iter, root;
3307 FilterTest fixture; /* This is not how it should be done */
3308 GtkWidget *tree_view;
3310 fixture.store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
3311 sort_model = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (fixture.store));
3312 filter = gtk_tree_model_filter_new (sort_model, NULL);
3313 fixture.filter = GTK_TREE_MODEL_FILTER (filter);
3314 fixture.monitor = signal_monitor_new (filter);
3316 tree_view = gtk_tree_view_new_with_model (filter);
3318 gtk_tree_model_filter_set_visible_func (fixture.filter,
3319 specific_at_least_2_children_filter_filter_func,
3322 /* The first node will be initially invisible: no signals */
3323 gtk_tree_store_append (fixture.store, &root, NULL);
3324 create_tree_store_set_values (fixture.store, &root, FALSE);
3326 /* check_filter_model (&fixture); */
3327 check_level_length (fixture.filter, NULL, 0);
3328 signal_monitor_assert_is_empty (fixture.monitor);
3330 /* Insert a child node. Nothing should happen.
3332 gtk_tree_store_append (fixture.store, &iter, &root);
3333 create_tree_store_set_values (fixture.store, &iter, TRUE);
3335 check_level_length (fixture.filter, NULL, 0);
3336 signal_monitor_assert_is_empty (fixture.monitor);
3339 GtkTreePath *path = gtk_tree_path_new_from_indices (0, 0, -1);
3340 GtkTreeRowReference *ref;
3342 ref = gtk_tree_row_reference_new (sort_model, path);
3343 gtk_tree_path_free (path);
3346 /* Insert a second child node. This will cause the parent to become
3349 signal_monitor_append_signal (fixture.monitor, ROW_INSERTED, "0");
3350 signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
3352 gtk_tree_store_append (fixture.store, &iter, &root);
3353 create_tree_store_set_values (fixture.store, &iter, TRUE);
3355 /* Parent must now be visible. Do the level length check first,
3356 * to avoid modifying the child model triggering a row-changed to
3359 check_level_length (fixture.filter, NULL, 1);
3360 check_level_length (fixture.filter, "0", 0);
3361 signal_monitor_assert_is_empty (fixture.monitor);
3363 /* This should propagate row-changed */
3364 signal_monitor_append_signal (fixture.monitor, ROW_CHANGED, "0");
3365 signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
3367 set_path_visibility (&fixture, "0", TRUE);
3368 /* check_filter_model (&fixture); */
3369 signal_monitor_assert_is_empty (fixture.monitor);
3371 /* New root node, no child, so no signal */
3372 gtk_tree_store_append (fixture.store, &root, NULL);
3373 check_level_length (fixture.filter, NULL, 1);
3374 signal_monitor_assert_is_empty (fixture.monitor);
3379 specific_filter_add_child (void)
3381 /* This test is based on one of the test cases I found in my
3382 * old test cases directory. I unfortunately do not have a record
3383 * from who this test case originated. -Kris.
3387 GtkTreeIter iter_first;
3389 GtkTreeStore *store;
3390 GtkTreeModel *filter G_GNUC_UNUSED;
3392 store = gtk_tree_store_new (1, G_TYPE_STRING);
3394 gtk_tree_store_append (store, &iter_first, NULL);
3395 gtk_tree_store_set (store, &iter_first, 0, "Hello", -1);
3397 gtk_tree_store_append (store, &iter, NULL);
3398 gtk_tree_store_set (store, &iter, 0, "Hello", -1);
3400 gtk_tree_store_append (store, &iter, NULL);
3401 gtk_tree_store_set (store, &iter, 0, "Hello", -1);
3403 gtk_tree_store_append (store, &iter, NULL);
3404 gtk_tree_store_set (store, &iter, 0, "Hello", -1);
3406 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
3408 gtk_tree_store_set (store, &iter, 0, "Hello", -1);
3409 gtk_tree_store_append (store, &child, &iter_first);
3410 gtk_tree_store_set (store, &child, 0, "Hello", -1);
3414 specific_list_store_clear (void)
3418 GtkTreeModel *filter;
3419 GtkWidget *view G_GNUC_UNUSED;
3421 list = gtk_list_store_new (1, G_TYPE_INT);
3422 gtk_list_store_insert_with_values (list, &iter, 0, 0, 1, -1);
3423 gtk_list_store_insert_with_values (list, &iter, 1, 0, 2, -1);
3424 gtk_list_store_insert_with_values (list, &iter, 2, 0, 3, -1);
3425 gtk_list_store_insert_with_values (list, &iter, 3, 0, 4, -1);
3426 gtk_list_store_insert_with_values (list, &iter, 4, 0, 5, -1);
3427 gtk_list_store_insert_with_values (list, &iter, 5, 0, 6, -1);
3428 gtk_list_store_insert_with_values (list, &iter, 6, 0, 7, -1);
3429 gtk_list_store_insert_with_values (list, &iter, 7, 0, 8, -1);
3431 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (list), NULL);
3432 view = gtk_tree_view_new_with_model (filter);
3434 gtk_list_store_clear (list);
3438 specific_sort_ref_leaf_and_remove_ancestor (void)
3440 GtkTreeIter iter, child, child2, child3;
3444 GtkTreeRowReference *rowref;
3445 GtkWidget *view G_GNUC_UNUSED;
3447 tree = gtk_tree_store_new (1, G_TYPE_INT);
3448 gtk_tree_store_insert_with_values (tree, &iter, NULL, 0, 0, 1, -1);
3449 gtk_tree_store_insert_with_values (tree, &iter, NULL, 1, 0, 2, -1);
3450 gtk_tree_store_insert_with_values (tree, &iter, NULL, 2, 0, 3, -1);
3451 gtk_tree_store_insert_with_values (tree, &iter, NULL, 3, 0, 4, -1);
3453 gtk_tree_store_insert_with_values (tree, &child, &iter, 0, 0, 50, -1);
3454 gtk_tree_store_insert_with_values (tree, &child2, &child, 0, 0, 6, -1);
3455 gtk_tree_store_insert_with_values (tree, &child3, &child2, 0, 0, 7, -1);
3457 sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (tree));
3458 view = gtk_tree_view_new_with_model (sort);
3459 gtk_tree_view_expand_all (GTK_TREE_VIEW (view));
3461 path = gtk_tree_path_new_from_indices (3, 0, 0, 0, -1);
3462 rowref = gtk_tree_row_reference_new (sort, path);
3463 gtk_tree_path_free (path);
3465 path = gtk_tree_path_new_from_indices (3, 0, 0, 0, -1);
3466 rowref = gtk_tree_row_reference_new (sort, path);
3467 gtk_tree_path_free (path);
3469 path = gtk_tree_path_new_from_indices (3, 0, -1);
3470 rowref = gtk_tree_row_reference_new (sort, path);
3471 gtk_tree_path_free (path);
3473 path = gtk_tree_path_new_from_indices (3, -1);
3474 rowref = gtk_tree_row_reference_new (sort, path);
3475 gtk_tree_path_free (path);
3477 /* Deleting a parent */
3478 path = gtk_tree_path_new_from_indices (3, 0, -1);
3479 gtk_tree_model_get_iter (GTK_TREE_MODEL (tree), &iter, path);
3480 gtk_tree_store_remove (tree, &iter);
3481 gtk_tree_path_free (path);
3483 gtk_tree_row_reference_free (rowref);
3487 specific_ref_leaf_and_remove_ancestor (void)
3489 GtkTreeIter iter, child, child2, child3;
3491 GtkTreeModel *filter;
3493 GtkTreeRowReference *rowref;
3494 GtkWidget *view G_GNUC_UNUSED;
3496 tree = gtk_tree_store_new (1, G_TYPE_INT);
3497 gtk_tree_store_insert_with_values (tree, &iter, NULL, 0, 0, 1, -1);
3498 gtk_tree_store_insert_with_values (tree, &iter, NULL, 1, 0, 2, -1);
3499 gtk_tree_store_insert_with_values (tree, &iter, NULL, 2, 0, 3, -1);
3500 gtk_tree_store_insert_with_values (tree, &iter, NULL, 3, 0, 4, -1);
3502 gtk_tree_store_insert_with_values (tree, &child, &iter, 0, 0, 50, -1);
3503 gtk_tree_store_insert_with_values (tree, &child2, &child, 0, 0, 6, -1);
3504 gtk_tree_store_insert_with_values (tree, &child3, &child2, 0, 0, 7, -1);
3506 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (tree), NULL);
3507 view = gtk_tree_view_new_with_model (filter);
3508 gtk_tree_view_expand_all (GTK_TREE_VIEW (view));
3510 path = gtk_tree_path_new_from_indices (3, 0, 0, 0, -1);
3511 rowref = gtk_tree_row_reference_new (filter, path);
3512 gtk_tree_path_free (path);
3514 path = gtk_tree_path_new_from_indices (3, 0, 0, 0, -1);
3515 rowref = gtk_tree_row_reference_new (filter, path);
3516 gtk_tree_path_free (path);
3518 path = gtk_tree_path_new_from_indices (3, 0, -1);
3519 rowref = gtk_tree_row_reference_new (filter, path);
3520 gtk_tree_path_free (path);
3522 path = gtk_tree_path_new_from_indices (3, -1);
3523 rowref = gtk_tree_row_reference_new (filter, path);
3524 gtk_tree_path_free (path);
3526 /* Deleting a parent */
3527 path = gtk_tree_path_new_from_indices (3, 0, -1);
3528 gtk_tree_model_get_iter (GTK_TREE_MODEL (tree), &iter, path);
3529 gtk_tree_store_remove (tree, &iter);
3530 gtk_tree_path_free (path);
3532 gtk_tree_row_reference_free (rowref);
3536 specific_virtual_ref_leaf_and_remove_ancestor (void)
3538 GtkTreeIter iter, child, child2, child3;
3540 GtkTreeModel *filter;
3542 GtkTreeRowReference *rowref;
3543 GtkWidget *view G_GNUC_UNUSED;
3545 tree = gtk_tree_store_new (1, G_TYPE_INT);
3546 gtk_tree_store_insert_with_values (tree, &iter, NULL, 0, 0, 1, -1);
3547 gtk_tree_store_insert_with_values (tree, &iter, NULL, 1, 0, 2, -1);
3548 gtk_tree_store_insert_with_values (tree, &iter, NULL, 2, 0, 3, -1);
3549 gtk_tree_store_insert_with_values (tree, &iter, NULL, 3, 0, 4, -1);
3551 gtk_tree_store_insert_with_values (tree, &child, &iter, 0, 0, 50, -1);
3552 gtk_tree_store_insert_with_values (tree, &child2, &child, 0, 0, 6, -1);
3553 gtk_tree_store_insert_with_values (tree, &child3, &child2, 0, 0, 7, -1);
3555 /* Set a virtual root of 3:0 */
3556 path = gtk_tree_path_new_from_indices (3, 0, -1);
3557 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (tree), path);
3558 gtk_tree_path_free (path);
3560 view = gtk_tree_view_new_with_model (filter);
3561 gtk_tree_view_expand_all (GTK_TREE_VIEW (view));
3563 path = gtk_tree_path_new_from_indices (0, 0, -1);
3564 rowref = gtk_tree_row_reference_new (filter, path);
3565 gtk_tree_path_free (path);
3567 path = gtk_tree_path_new_from_indices (0, 0, -1);
3568 rowref = gtk_tree_row_reference_new (filter, path);
3569 gtk_tree_path_free (path);
3571 path = gtk_tree_path_new_from_indices (0, -1);
3572 rowref = gtk_tree_row_reference_new (filter, path);
3573 gtk_tree_path_free (path);
3575 /* Deleting the virtual root */
3576 path = gtk_tree_path_new_from_indices (3, 0, -1);
3577 gtk_tree_model_get_iter (GTK_TREE_MODEL (tree), &iter, path);
3578 gtk_tree_store_remove (tree, &iter);
3579 gtk_tree_path_free (path);
3581 gtk_tree_row_reference_free (rowref);
3586 specific_bug_301558_sort_func (GtkTreeModel *model,
3593 gtk_tree_model_get (model, a, 0, &i, -1);
3594 gtk_tree_model_get (model, b, 0, &j, -1);
3600 specific_bug_301558 (void)
3602 /* Test case for GNOME Bugzilla bug 301558 provided by
3606 GtkTreeModel *filter;
3608 GtkTreeIter root, iter, iter2;
3609 GtkWidget *view G_GNUC_UNUSED;
3613 g_test_bug ("301558");
3615 tree = gtk_tree_store_new (2, G_TYPE_INT, G_TYPE_BOOLEAN);
3616 gtk_tree_store_append (tree, &iter, NULL);
3617 gtk_tree_store_set (tree, &iter, 0, 123, 1, TRUE, -1);
3618 gtk_tree_store_append (tree, &iter2, &iter);
3619 gtk_tree_store_set (tree, &iter2, 0, 73, 1, TRUE, -1);
3621 sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (tree));
3622 gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (sort),
3623 specific_bug_301558_sort_func,
3626 filter = gtk_tree_model_filter_new (sort, NULL);
3627 gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter), 1);
3629 view = gtk_tree_view_new_with_model (filter);
3631 while (gtk_events_pending ())
3632 gtk_main_iteration ();
3636 for (i = 0; i < 10; i++)
3638 if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (tree), &root))
3639 g_assert_not_reached ();
3643 gtk_tree_store_append (tree, &iter, &root);
3644 gtk_tree_store_set (tree, &iter, 0, 456, 1, TRUE, -1);
3649 n = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (tree), &root);
3650 gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (tree), &iter,
3652 gtk_tree_store_remove (tree, &iter);
3661 specific_bug_311955_filter_func (GtkTreeModel *model,
3667 gtk_tree_model_get (model, iter, 0, &value, -1);
3669 return (value != 0);
3673 specific_bug_311955 (void)
3675 /* This is a test case for GNOME Bugzilla bug 311955. It was written
3678 GtkTreeIter iter, child, root;
3679 GtkTreeStore *store;
3681 GtkTreeModel *filter;
3683 GtkWidget *window G_GNUC_UNUSED;
3684 GtkWidget *tree_view;
3689 g_test_bug ("311955");
3691 store = gtk_tree_store_new (1, G_TYPE_INT);
3693 gtk_tree_store_append (store, &root, NULL);
3694 gtk_tree_store_set (store, &root, 0, 33, -1);
3696 gtk_tree_store_append (store, &iter, &root);
3697 gtk_tree_store_set (store, &iter, 0, 50, -1);
3699 gtk_tree_store_append (store, &iter, NULL);
3700 gtk_tree_store_set (store, &iter, 0, 22, -1);
3702 sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (store));
3703 filter = gtk_tree_model_filter_new (sort, NULL);
3705 gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
3706 specific_bug_311955_filter_func,
3709 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3710 tree_view = gtk_tree_view_new_with_model (filter);
3711 g_object_unref (store);
3713 gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
3715 while (gtk_events_pending ())
3716 gtk_main_iteration ();
3718 check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, 2);
3719 check_level_length (GTK_TREE_MODEL_FILTER (filter), "0", 1);
3722 for (i = 0; i < 4; i++)
3724 gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &root);
3726 gtk_tree_store_append (store, &iter, &root);
3729 gtk_tree_store_set (store, &iter, 0, i, -1);
3733 gtk_tree_store_append (store, &child, &iter);
3734 gtk_tree_store_set (store, &child, 0, 10, -1);
3738 while (gtk_events_pending ())
3739 gtk_main_iteration ();
3741 check_level_length (GTK_TREE_MODEL_FILTER (filter), "0", 3);
3742 check_level_length (GTK_TREE_MODEL_FILTER (filter), "0:2", 1);
3744 /* Remove bottommost child from the tree. */
3745 gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &root);
3746 n = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (store), &root);
3748 if (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (store), &iter, &root, n - 2))
3750 if (gtk_tree_model_iter_children (GTK_TREE_MODEL (store), &child, &iter))
3751 gtk_tree_store_remove (store, &child);
3754 g_assert_not_reached ();
3756 path = gtk_tree_path_new_from_indices (0, 2, -1);
3757 gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path, FALSE);
3758 gtk_tree_path_free (path);
3760 check_level_length (GTK_TREE_MODEL_FILTER (filter), "0", 3);
3761 check_level_length (GTK_TREE_MODEL_FILTER (filter), "0:2", 0);
3765 specific_bug_311955_clean (void)
3767 /* Cleaned up version of the test case for GNOME Bugzilla bug 311955,
3768 * which is easier to understand.
3770 GtkTreeIter iter, child, grandchild;
3771 GtkTreeStore *store;
3773 GtkTreeModel *filter;
3775 GtkWidget *tree_view;
3778 store = gtk_tree_store_new (1, G_TYPE_INT);
3780 gtk_tree_store_append (store, &iter, NULL);
3781 gtk_tree_store_set (store, &iter, 0, 1, -1);
3783 gtk_tree_store_append (store, &child, &iter);
3784 gtk_tree_store_set (store, &child, 0, 1, -1);
3786 sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (store));
3787 filter = gtk_tree_model_filter_new (sort, NULL);
3789 gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
3790 specific_bug_311955_filter_func,
3793 tree_view = gtk_tree_view_new_with_model (filter);
3794 g_object_unref (store);
3796 gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
3798 while (gtk_events_pending ())
3799 gtk_main_iteration ();
3801 check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, 1);
3802 check_level_length (GTK_TREE_MODEL_FILTER (filter), "0", 1);
3804 gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter);
3806 gtk_tree_store_append (store, &child, &iter);
3807 gtk_tree_store_set (store, &child, 0, 0, -1);
3809 gtk_tree_store_append (store, &child, &iter);
3810 gtk_tree_store_set (store, &child, 0, 1, -1);
3812 gtk_tree_store_append (store, &child, &iter);
3813 gtk_tree_store_set (store, &child, 0, 1, -1);
3815 gtk_tree_store_append (store, &grandchild, &child);
3816 gtk_tree_store_set (store, &grandchild, 0, 1, -1);
3818 gtk_tree_store_append (store, &child, &iter);
3819 /* Don't set a value: assume 0 */
3821 /* Remove leaf node, check trigger row-has-child-toggled */
3822 path = gtk_tree_path_new_from_indices (0, 3, 0, -1);
3823 gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, path);
3824 gtk_tree_path_free (path);
3825 gtk_tree_store_remove (store, &iter);
3827 path = gtk_tree_path_new_from_indices (0, 2, -1);
3828 gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path, FALSE);
3829 gtk_tree_path_free (path);
3831 check_level_length (GTK_TREE_MODEL_FILTER (filter), "0", 3);
3832 check_level_length (GTK_TREE_MODEL_FILTER (filter), "0:2", 0);
3834 gtk_widget_destroy (tree_view);
3838 specific_bug_346800 (void)
3840 /* This is a test case for GNOME Bugzilla bug 346800. It was written
3841 * by Jonathan Matthew.
3844 GtkTreeIter node_iters[50];
3845 GtkTreeIter child_iters[50];
3846 GtkTreeModel *model;
3847 GtkTreeModelFilter *filter;
3848 GtkTreeStore *store;
3852 columns = g_new (GType, 2);
3853 columns[0] = G_TYPE_STRING;
3854 columns[1] = G_TYPE_BOOLEAN;
3855 store = gtk_tree_store_newv (2, columns);
3856 model = GTK_TREE_MODEL (store);
3858 g_test_bug ("346800");
3860 filter = GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (model, NULL));
3861 gtk_tree_model_filter_set_visible_column (filter, 1);
3863 for (i=0; i<items; i++)
3865 /* allocate random amounts of junk, otherwise the filter model's arrays can expand without moving */
3868 gtk_tree_store_append (store, &node_iters[i], NULL);
3869 gtk_tree_store_set (store, &node_iters[i],
3871 1, ((i%6) == 0) ? FALSE : TRUE,
3875 gtk_tree_store_append (store, &child_iters[i], &node_iters[i]);
3876 gtk_tree_store_set (store, &child_iters[i],
3877 0, "something else",
3880 gtk_tree_model_filter_refilter (filter);
3884 gtk_tree_store_set (GTK_TREE_STORE (model), &child_iters[i-1], 1,
3885 (i & 1) ? TRUE : FALSE, -1);
3886 gtk_tree_model_filter_refilter (filter);
3888 gtk_tree_store_set (GTK_TREE_STORE (model), &child_iters[i-2], 1,
3889 (i & 1) ? FALSE: TRUE, -1);
3890 gtk_tree_model_filter_refilter (filter);
3896 specific_bug_464173_visible_func (GtkTreeModel *model,
3900 gboolean *visible = (gboolean *)data;
3906 specific_bug_464173 (void)
3908 /* Test case for GNOME Bugzilla bug 464173, test case written
3909 * by Andreas Koehler.
3911 GtkTreeStore *model;
3912 GtkTreeModelFilter *f_model;
3913 GtkTreeIter iter1, iter2;
3914 GtkWidget *view G_GNUC_UNUSED;
3915 gboolean visible = TRUE;
3917 g_test_bug ("464173");
3919 model = gtk_tree_store_new (1, G_TYPE_STRING);
3920 gtk_tree_store_append (model, &iter1, NULL);
3921 gtk_tree_store_set (model, &iter1, 0, "Foo", -1);
3922 gtk_tree_store_append (model, &iter2, &iter1);
3923 gtk_tree_store_set (model, &iter2, 0, "Bar", -1);
3925 f_model = GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (GTK_TREE_MODEL(model), NULL));
3926 gtk_tree_model_filter_set_visible_func (f_model,
3927 specific_bug_464173_visible_func,
3930 view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (f_model));
3933 gtk_tree_model_filter_refilter (f_model);
3938 specific_bug_540201_filter_func (GtkTreeModel *model,
3942 gboolean has_children;
3944 has_children = gtk_tree_model_iter_has_child (model, iter);
3946 return has_children;
3950 specific_bug_540201 (void)
3952 /* Test case for GNOME Bugzilla bug 540201, steps provided by
3955 GtkTreeIter iter, root;
3956 GtkTreeStore *store;
3957 GtkTreeModel *filter;
3959 GtkWidget *tree_view G_GNUC_UNUSED;
3961 g_test_bug ("540201");
3963 store = gtk_tree_store_new (1, G_TYPE_INT);
3965 gtk_tree_store_append (store, &root, NULL);
3966 gtk_tree_store_set (store, &root, 0, 33, -1);
3968 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
3969 tree_view = gtk_tree_view_new_with_model (filter);
3971 gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
3972 specific_bug_540201_filter_func,
3975 gtk_tree_store_append (store, &iter, &root);
3976 gtk_tree_store_set (store, &iter, 0, 50, -1);
3978 gtk_tree_store_append (store, &iter, &root);
3979 gtk_tree_store_set (store, &iter, 0, 22, -1);
3982 gtk_tree_store_append (store, &root, NULL);
3983 gtk_tree_store_set (store, &root, 0, 33, -1);
3985 gtk_tree_store_append (store, &iter, &root);
3986 gtk_tree_store_set (store, &iter, 0, 22, -1);
3991 specific_bug_549287_visible_func (GtkTreeModel *model,
3995 gboolean result = FALSE;
3997 result = gtk_tree_model_iter_has_child (model, iter);
4003 specific_bug_549287 (void)
4005 /* Test case for GNOME Bugzilla bug 529287, provided by Julient Puydt */
4008 GtkTreeStore *store;
4009 GtkTreeModel *filtered;
4010 GtkWidget *view G_GNUC_UNUSED;
4012 GtkTreeIter *swap, *parent, *child;
4014 g_test_bug ("529287");
4016 store = gtk_tree_store_new (1, G_TYPE_STRING);
4017 filtered = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
4018 gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filtered),
4019 specific_bug_549287_visible_func,
4022 view = gtk_tree_view_new_with_model (filtered);
4024 for (i = 0; i < 4; i++)
4026 if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter))
4028 parent = gtk_tree_iter_copy (&iter);
4029 child = gtk_tree_iter_copy (&iter);
4031 while (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (store),
4040 gtk_tree_store_append (store, child, parent);
4041 gtk_tree_store_set (store, child,
4045 gtk_tree_iter_free (parent);
4046 gtk_tree_iter_free (child);
4050 gtk_tree_store_append (store, &iter, NULL);
4051 gtk_tree_store_set (store, &iter,
4056 /* since we inserted something, we changed the visibility conditions: */
4057 gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (filtered));
4062 specific_bug_621076_visible_func (GtkTreeModel *model,
4066 gboolean visible = FALSE;
4069 gtk_tree_model_get (model, iter, 0, &str, -1);
4070 if (str != NULL && g_str_has_prefix (str, "visible"))
4076 GtkTreeIter child_iter;
4079 /* Recursively check if we have a visible child */
4080 for (valid = gtk_tree_model_iter_children (model, &child_iter, iter);
4081 valid; valid = gtk_tree_model_iter_next (model, &child_iter))
4083 if (specific_bug_621076_visible_func (model, &child_iter, data))
4098 specific_bug_621076 (void)
4100 /* Test case for GNOME Bugzilla bug 621076, provided by Xavier Claessens */
4102 /* This test case differs from has-child-filter and root-has-child-filter
4103 * in that the visible function both filters on content and model
4104 * structure. Also, it is recursive.
4107 GtkTreeStore *store;
4108 GtkTreeModel *filter;
4110 GtkTreeIter group_iter;
4111 GtkTreeIter item_iter;
4112 SignalMonitor *monitor;
4114 g_test_bug ("621076");
4116 store = gtk_tree_store_new (1, G_TYPE_STRING);
4117 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
4118 gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
4119 specific_bug_621076_visible_func,
4122 view = gtk_tree_view_new_with_model (filter);
4123 g_object_ref_sink (view);
4125 monitor = signal_monitor_new (filter);
4127 signal_monitor_append_signal (monitor, ROW_INSERTED, "0");
4128 gtk_tree_store_insert_with_values (store, &item_iter, NULL, -1,
4129 0, "visible-group-0",
4131 signal_monitor_assert_is_empty (monitor);
4133 /* visible-group-0 is not expanded, so ROW_INSERTED should not be emitted
4134 * for its children. However, ROW_HAS_CHILD_TOGGLED should be emitted on
4135 * visible-group-0 to tell the view that row can be expanded. */
4136 signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "0");
4137 signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "0");
4138 group_iter = item_iter;
4139 gtk_tree_store_insert_with_values (store, &item_iter, &group_iter, -1,
4142 signal_monitor_assert_is_empty (monitor);
4144 signal_monitor_append_signal (monitor, ROW_INSERTED, "1");
4145 gtk_tree_store_insert_with_values (store, &item_iter, NULL, -1,
4146 0, "visible-group-1",
4148 signal_monitor_assert_is_empty (monitor);
4150 /* We are adding an hidden item inside visible-group-1, so
4151 * ROW_HAS_CHILD_TOGGLED should not be emitted. It is emitted though,
4152 * because the signal originating at TreeStore will be propagated,
4153 * as well a generated signal because the state of the parent *could*
4154 * change by a change in the model.
4156 signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "1");
4157 signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "1");
4158 group_iter = item_iter;
4159 gtk_tree_store_insert_with_values (store, &item_iter, &group_iter, -1,
4162 signal_monitor_assert_is_empty (monitor);
4164 /* This group is invisible and its parent too. Nothing should be emitted */
4165 group_iter = item_iter;
4166 gtk_tree_store_insert_with_values (store, &item_iter, &group_iter, -1,
4169 signal_monitor_assert_is_empty (monitor);
4171 /* Adding a visible item in this group hierarchy will make all nodes
4172 * in this path visible. The first level should simply tell the view
4173 * that it now has a child, and the view will load the tree if needed
4174 * (depends on the expanded state).
4176 signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "1");
4177 group_iter = item_iter;
4178 gtk_tree_store_insert_with_values (store, &item_iter, &group_iter, -1,
4179 0, "visible-1:0:0:0",
4181 signal_monitor_assert_is_empty (monitor);
4183 check_level_length (GTK_TREE_MODEL_FILTER (filter), "1", 1);
4185 gtk_tree_store_insert_with_values (store, &item_iter, NULL, -1,
4188 signal_monitor_assert_is_empty (monitor);
4190 /* Parent is invisible, and adding this invisible item won't change that,
4191 * so no signal should be emitted. */
4192 group_iter = item_iter;
4193 gtk_tree_store_insert_with_values (store, NULL, &group_iter, -1,
4196 signal_monitor_assert_is_empty (monitor);
4198 /* This makes group-2 visible, so it gets inserted and tells it has
4201 signal_monitor_append_signal (monitor, ROW_INSERTED, "2");
4202 signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "2");
4203 gtk_tree_store_insert_with_values (store, NULL, &group_iter, -1,
4206 signal_monitor_assert_is_empty (monitor);
4208 /* group-2 is already visible, so this time it is a normal insertion */
4209 gtk_tree_store_insert_with_values (store, NULL, &group_iter, -1,
4212 signal_monitor_assert_is_empty (monitor);
4215 gtk_tree_store_insert_with_values (store, &item_iter, NULL, -1,
4218 signal_monitor_assert_is_empty (monitor);
4220 /* Parent is invisible, and adding this invisible item won't change that,
4221 * so no signal should be emitted. */
4222 group_iter = item_iter;
4223 gtk_tree_store_insert_with_values (store, NULL, &group_iter, -1,
4226 signal_monitor_assert_is_empty (monitor);
4228 gtk_tree_store_insert_with_values (store, &item_iter, &group_iter, -1,
4231 signal_monitor_assert_is_empty (monitor);
4233 /* This will make group 3 visible. */
4234 signal_monitor_append_signal (monitor, ROW_INSERTED, "3");
4235 signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "3");
4236 signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "3");
4237 gtk_tree_store_set (store, &item_iter, 0, "visible-3:1", -1);
4238 signal_monitor_assert_is_empty (monitor);
4240 /* Make sure all groups are expanded, so the filter has the tree cached */
4241 gtk_tree_view_expand_all (GTK_TREE_VIEW (view));
4242 while (gtk_events_pending ())
4243 gtk_main_iteration ();
4245 /* Should only yield a row-changed */
4246 signal_monitor_append_signal (monitor, ROW_CHANGED, "3:0");
4247 gtk_tree_store_set (store, &item_iter, 0, "visible-3:1", -1);
4248 signal_monitor_assert_is_empty (monitor);
4250 /* Now remove/hide some items. If a group loses its last item, the group
4251 * should be deleted instead of the item.
4254 signal_monitor_append_signal (monitor, ROW_DELETED, "2:1");
4255 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (store), &item_iter, "2:2");
4256 gtk_tree_store_remove (store, &item_iter);
4257 signal_monitor_assert_is_empty (monitor);
4259 signal_monitor_append_signal (monitor, ROW_DELETED, "2:0");
4260 signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "2");
4261 signal_monitor_append_signal (monitor, ROW_DELETED, "2");
4262 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (store), &item_iter, "2:1");
4263 gtk_tree_store_set (store, &item_iter, 0, "invisible-2:1", -1);
4264 signal_monitor_assert_is_empty (monitor);
4266 signal_monitor_append_signal (monitor, ROW_DELETED, "1:0:0:0");
4267 signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "1:0:0");
4268 signal_monitor_append_signal (monitor, ROW_DELETED, "1:0");
4269 signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "1");
4270 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (store), &item_iter, "1:0:0:0");
4271 gtk_tree_store_remove (store, &item_iter);
4272 signal_monitor_assert_is_empty (monitor);
4274 /* Hide a group using row-changed instead of row-deleted */
4275 /* Caution: group 2 is gone, so offsets of the signals have moved. */
4276 signal_monitor_append_signal (monitor, ROW_DELETED, "2:0");
4277 signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "2");
4278 signal_monitor_append_signal (monitor, ROW_DELETED, "2");
4279 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (store), &item_iter,
4281 gtk_tree_store_set (store, &item_iter, 0, "invisible-3:1", -1);
4282 signal_monitor_assert_is_empty (monitor);
4287 GtkTreeViewColumn *col;
4289 gtk_tree_view_expand_all (GTK_TREE_VIEW (view));
4291 col = gtk_tree_view_column_new_with_attributes ("foo",
4292 gtk_cell_renderer_text_new (),
4294 gtk_tree_view_append_column (GTK_TREE_VIEW (view), col);
4296 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4297 g_signal_connect (window, "delete-event",
4298 G_CALLBACK (gtk_widget_destroy), NULL);
4299 g_signal_connect (window, "destroy",
4300 G_CALLBACK (gtk_main_quit), NULL);
4302 gtk_container_add (GTK_CONTAINER (window), view);
4304 gtk_widget_show (view);
4305 gtk_widget_show (window);
4312 signal_monitor_free (monitor);
4313 g_object_unref (view);
4314 g_object_unref (store);
4315 g_object_unref (filter);
4321 register_filter_model_tests (void)
4323 g_test_add ("/TreeModelFilter/self/verify-test-suite",
4327 filter_test_teardown);
4329 g_test_add ("/TreeModelFilter/self/verify-test-suite/vroot/depth-1",
4330 FilterTest, gtk_tree_path_new_from_indices (2, -1),
4332 verify_test_suite_vroot,
4333 filter_test_teardown);
4334 g_test_add ("/TreeModelFilter/self/verify-test-suite/vroot/depth-2",
4335 FilterTest, gtk_tree_path_new_from_indices (2, 3, -1),
4337 verify_test_suite_vroot,
4338 filter_test_teardown);
4341 g_test_add ("/TreeModelFilter/filled/hide-root-level",
4344 filled_hide_root_level,
4345 filter_test_teardown);
4346 g_test_add ("/TreeModelFilter/filled/hide-child-levels",
4349 filled_hide_child_levels,
4350 filter_test_teardown);
4351 g_test_add ("/TreeModelFilter/filled/hide-child-levels/root-expanded",
4354 filled_hide_child_levels_root_expanded,
4355 filter_test_teardown);
4357 g_test_add ("/TreeModelFilter/filled/hide-root-level/vroot",
4358 FilterTest, gtk_tree_path_new_from_indices (2, -1),
4360 filled_vroot_hide_root_level,
4361 filter_test_teardown);
4362 g_test_add ("/TreeModelFilter/filled/hide-child-levels/vroot",
4363 FilterTest, gtk_tree_path_new_from_indices (2, -1),
4365 filled_vroot_hide_child_levels,
4366 filter_test_teardown);
4367 g_test_add ("/TreeModelFilter/filled/hide-child-levels/vroot-root-expanded",
4368 FilterTest, gtk_tree_path_new_from_indices (2, -1),
4370 filled_vroot_hide_child_levels_root_expanded,
4371 filter_test_teardown);
4374 g_test_add ("/TreeModelFilter/empty/show-nodes",
4376 filter_test_setup_empty,
4378 filter_test_teardown);
4379 g_test_add ("/TreeModelFilter/empty/show-multiple-nodes",
4381 filter_test_setup_empty,
4382 empty_show_multiple_nodes,
4383 filter_test_teardown);
4385 g_test_add ("/TreeModelFilter/empty/show-nodes/vroot",
4386 FilterTest, gtk_tree_path_new_from_indices (2, -1),
4387 filter_test_setup_empty,
4388 empty_vroot_show_nodes,
4389 filter_test_teardown);
4390 g_test_add ("/TreeModelFilter/empty/show-multiple-nodes/vroot",
4391 FilterTest, gtk_tree_path_new_from_indices (2, -1),
4392 filter_test_setup_empty,
4393 empty_vroot_show_multiple_nodes,
4394 filter_test_teardown);
4397 g_test_add ("/TreeModelFilter/unfiltered/hide-single",
4399 filter_test_setup_unfiltered,
4400 unfiltered_hide_single,
4401 filter_test_teardown);
4402 g_test_add ("/TreeModelFilter/unfiltered/hide-single/root-expanded",
4404 filter_test_setup_unfiltered_root_expanded,
4405 unfiltered_hide_single_root_expanded,
4406 filter_test_teardown);
4407 g_test_add ("/TreeModelFilter/unfiltered/hide-single-child",
4409 filter_test_setup_unfiltered,
4410 unfiltered_hide_single_child,
4411 filter_test_teardown);
4412 g_test_add ("/TreeModelFilter/unfiltered/hide-single-child/root-expanded",
4414 filter_test_setup_unfiltered_root_expanded,
4415 unfiltered_hide_single_child_root_expanded,
4416 filter_test_teardown);
4417 g_test_add ("/TreeModelFilter/unfiltered/hide-single-multi-level",
4419 filter_test_setup_unfiltered,
4420 unfiltered_hide_single_multi_level,
4421 filter_test_teardown);
4422 g_test_add ("/TreeModelFilter/unfiltered/hide-single-multi-level/root-expanded",
4424 filter_test_setup_unfiltered_root_expanded,
4425 unfiltered_hide_single_multi_level_root_expanded,
4426 filter_test_teardown);
4428 g_test_add ("/TreeModelFilter/unfiltered/hide-single/vroot",
4429 FilterTest, gtk_tree_path_new_from_indices (2, -1),
4430 filter_test_setup_unfiltered,
4431 unfiltered_vroot_hide_single,
4432 filter_test_teardown);
4433 g_test_add ("/TreeModelFilter/unfiltered/hide-single-child/vroot",
4434 FilterTest, gtk_tree_path_new_from_indices (2, -1),
4435 filter_test_setup_unfiltered,
4436 unfiltered_vroot_hide_single_child,
4437 filter_test_teardown);
4438 g_test_add ("/TreeModelFilter/unfiltered/hide-single-child/vroot/root-expanded",
4439 FilterTest, gtk_tree_path_new_from_indices (2, -1),
4440 filter_test_setup_unfiltered_root_expanded,
4441 unfiltered_vroot_hide_single_child_root_expanded,
4442 filter_test_teardown);
4443 g_test_add ("/TreeModelFilter/unfiltered/hide-single-multi-level/vroot",
4444 FilterTest, gtk_tree_path_new_from_indices (2, -1),
4445 filter_test_setup_unfiltered,
4446 unfiltered_vroot_hide_single_multi_level,
4447 filter_test_teardown);
4448 g_test_add ("/TreeModelFilter/unfiltered/hide-single-multi-level/vroot/root-expanded",
4449 FilterTest, gtk_tree_path_new_from_indices (2, -1),
4450 filter_test_setup_unfiltered_root_expanded,
4451 unfiltered_vroot_hide_single_multi_level_root_expanded,
4452 filter_test_teardown);
4456 g_test_add ("/TreeModelFilter/unfiltered/show-single",
4458 filter_test_setup_empty_unfiltered,
4459 unfiltered_show_single,
4460 filter_test_teardown);
4461 g_test_add ("/TreeModelFilter/unfiltered/show-single-child",
4463 filter_test_setup_empty_unfiltered,
4464 unfiltered_show_single_child,
4465 filter_test_teardown);
4466 g_test_add ("/TreeModelFilter/unfiltered/show-single-child/root-expanded",
4468 filter_test_setup_empty_unfiltered_root_expanded,
4469 unfiltered_show_single_child_root_expanded,
4470 filter_test_teardown);
4471 g_test_add ("/TreeModelFilter/unfiltered/show-single-multi-level",
4473 filter_test_setup_empty_unfiltered,
4474 unfiltered_show_single_multi_level,
4475 filter_test_teardown);
4476 g_test_add ("/TreeModelFilter/unfiltered/show-single-multi-level/root-expanded",
4478 filter_test_setup_empty_unfiltered_root_expanded,
4479 unfiltered_show_single_multi_level_root_expanded,
4480 filter_test_teardown);
4482 g_test_add ("/TreeModelFilter/unfiltered/show-single/vroot",
4483 FilterTest, gtk_tree_path_new_from_indices (2, -1),
4484 filter_test_setup_empty_unfiltered,
4485 unfiltered_vroot_show_single,
4486 filter_test_teardown);
4487 g_test_add ("/TreeModelFilter/unfiltered/show-single-child/vroot",
4488 FilterTest, gtk_tree_path_new_from_indices (2, -1),
4489 filter_test_setup_empty_unfiltered,
4490 unfiltered_vroot_show_single_child,
4491 filter_test_teardown);
4492 g_test_add ("/TreeModelFilter/unfiltered/show-single-child/vroot/root-expanded",
4493 FilterTest, gtk_tree_path_new_from_indices (2, -1),
4494 filter_test_setup_empty_unfiltered_root_expanded,
4495 unfiltered_vroot_show_single_child_root_expanded,
4496 filter_test_teardown);
4497 g_test_add ("/TreeModelFilter/unfiltered/show-single-multi-level/vroot",
4498 FilterTest, gtk_tree_path_new_from_indices (2, -1),
4499 filter_test_setup_empty_unfiltered,
4500 unfiltered_vroot_show_single_multi_level,
4501 filter_test_teardown);
4502 g_test_add ("/TreeModelFilter/unfiltered/show-single-multi-level/vroot/root-expanded",
4503 FilterTest, gtk_tree_path_new_from_indices (2, -1),
4504 filter_test_setup_empty_unfiltered_root_expanded,
4505 unfiltered_vroot_show_single_multi_level_root_expanded,
4506 filter_test_teardown);
4508 /* Inserts in child models after creation of filter model */
4509 g_test_add_func ("/TreeModelFilter/insert/before",
4511 g_test_add_func ("/TreeModelFilter/insert/child",
4514 /* Removals from child model after creating of filter model */
4515 g_test_add_func ("/TreeModelFilter/remove/node",
4517 g_test_add_func ("/TreeModelFilter/remove/node-vroot",
4519 g_test_add_func ("/TreeModelFilter/remove/vroot-ancestor",
4520 remove_vroot_ancestor);
4523 g_test_add_func ("/TreeModelFilter/specific/path-dependent-filter",
4524 specific_path_dependent_filter);
4525 g_test_add_func ("/TreeModelFilter/specific/append-after-collapse",
4526 specific_append_after_collapse);
4527 g_test_add_func ("/TreeModelFilter/specific/sort-filter-remove-node",
4528 specific_sort_filter_remove_node);
4529 g_test_add_func ("/TreeModelFilter/specific/sort-filter-remove-root",
4530 specific_sort_filter_remove_root);
4531 g_test_add_func ("/TreeModelFilter/specific/root-mixed-visibility",
4532 specific_root_mixed_visibility);
4533 g_test_add_func ("/TreeModelFilter/specific/has-child-filter",
4534 specific_has_child_filter);
4535 g_test_add_func ("/TreeModelFilter/specific/has-child-filter-on-sort-model",
4536 specific_has_child_filter_on_sort_model);
4537 g_test_add_func ("/TreeModelFilter/specific/at-least-2-children-filter",
4538 specific_at_least_2_children_filter);
4539 g_test_add_func ("/TreeModelFilter/specific/at-least-2-children-filter-on-sort-model",
4540 specific_at_least_2_children_filter_on_sort_model);
4541 g_test_add_func ("/TreeModelFilter/specific/root-has-child-filter",
4542 specific_root_has_child_filter);
4543 g_test_add_func ("/TreeModelFilter/specific/filter-add-child",
4544 specific_filter_add_child);
4545 g_test_add_func ("/TreeModelFilter/specific/list-store-clear",
4546 specific_list_store_clear);
4547 g_test_add_func ("/TreeModelFilter/specific/sort-ref-leaf-and-remove-ancestor",
4548 specific_sort_ref_leaf_and_remove_ancestor);
4549 g_test_add_func ("/TreeModelFilter/specific/ref-leaf-and-remove-ancestor",
4550 specific_ref_leaf_and_remove_ancestor);
4551 g_test_add_func ("/TreeModelFilter/specific/virtual-ref-leaf-and-remove-ancestor",
4552 specific_virtual_ref_leaf_and_remove_ancestor);
4554 g_test_add_func ("/TreeModelFilter/specific/bug-301558",
4555 specific_bug_301558);
4556 g_test_add_func ("/TreeModelFilter/specific/bug-311955",
4557 specific_bug_311955);
4558 g_test_add_func ("/TreeModelFilter/specific/bug-311955-clean",
4559 specific_bug_311955_clean);
4560 g_test_add_func ("/TreeModelFilter/specific/bug-346800",
4561 specific_bug_346800);
4562 g_test_add_func ("/TreeModelFilter/specific/bug-464173",
4563 specific_bug_464173);
4564 g_test_add_func ("/TreeModelFilter/specific/bug-540201",
4565 specific_bug_540201);
4566 g_test_add_func ("/TreeModelFilter/specific/bug-549287",
4567 specific_bug_549287);
4568 g_test_add_func ("/TreeModelFilter/specific/bug-621076",
4569 specific_bug_621076);