1 /* Extensive GtkTreeModelFilter tests.
2 * Copyright (C) 2009 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 (FilterTest *fixture,
423 gconstpointer test_data)
425 filter_test_setup_generic (fixture, test_data, 3, FALSE, FALSE);
429 filter_test_setup_empty (FilterTest *fixture,
430 gconstpointer test_data)
432 filter_test_setup_generic (fixture, test_data, 3, TRUE, FALSE);
436 filter_test_setup_unfiltered (FilterTest *fixture,
437 gconstpointer test_data)
439 filter_test_setup_generic (fixture, test_data, 3, FALSE, TRUE);
443 filter_test_setup_empty_unfiltered (FilterTest *fixture,
444 gconstpointer test_data)
446 filter_test_setup_generic (fixture, test_data, 3, TRUE, TRUE);
450 strip_virtual_root (GtkTreePath *path,
451 GtkTreePath *root_path)
453 GtkTreePath *real_path;
458 int depth = gtk_tree_path_get_depth (path);
459 int root_depth = gtk_tree_path_get_depth (root_path);
461 real_path = gtk_tree_path_new ();
463 for (j = 0; j < depth - root_depth; j++)
464 gtk_tree_path_append_index (real_path,
465 gtk_tree_path_get_indices (path)[root_depth + j]);
468 real_path = gtk_tree_path_copy (path);
474 filter_test_append_refilter_signals_recurse (FilterTest *fixture,
475 GtkTreePath *store_path,
476 GtkTreePath *filter_path,
478 GtkTreePath *root_path)
481 int rows_deleted = 0;
484 gtk_tree_path_down (store_path);
485 gtk_tree_path_down (filter_path);
487 gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->store),
490 for (i = 0; i < LEVEL_LENGTH; i++)
493 GtkTreePath *real_path;
495 gtk_tree_model_get (GTK_TREE_MODEL (fixture->store), &iter,
500 (!gtk_tree_path_is_descendant (store_path, root_path)
501 || !gtk_tree_path_compare (store_path, root_path)))
503 if (!gtk_tree_path_compare (store_path, root_path))
506 && gtk_tree_model_iter_has_child (GTK_TREE_MODEL (fixture->store),
509 GtkTreePath *store_copy;
510 GtkTreePath *filter_copy;
512 store_copy = gtk_tree_path_copy (store_path);
513 filter_copy = gtk_tree_path_copy (filter_path);
514 filter_test_append_refilter_signals_recurse (fixture,
519 gtk_tree_path_free (store_copy);
520 gtk_tree_path_free (filter_copy);
524 gtk_tree_path_next (store_path);
525 gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &iter);
528 gtk_tree_path_next (filter_path);
533 real_path = strip_virtual_root (filter_path, root_path);
537 /* This row will be inserted */
538 signal_monitor_append_signal_path (fixture->monitor, ROW_CHANGED,
540 signal_monitor_append_signal_path (fixture->monitor,
541 ROW_HAS_CHILD_TOGGLED,
545 && gtk_tree_model_iter_has_child (GTK_TREE_MODEL (fixture->store),
548 GtkTreePath *store_copy;
549 GtkTreePath *filter_copy;
551 store_copy = gtk_tree_path_copy (store_path);
552 filter_copy = gtk_tree_path_copy (filter_path);
553 filter_test_append_refilter_signals_recurse (fixture,
558 gtk_tree_path_free (store_copy);
559 gtk_tree_path_free (filter_copy);
562 gtk_tree_path_next (filter_path);
566 /* This row will be deleted */
568 signal_monitor_append_signal_path (fixture->monitor, ROW_DELETED,
572 gtk_tree_path_free (real_path);
574 gtk_tree_path_next (store_path);
575 gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &iter);
578 if (rows_deleted == LEVEL_LENGTH
579 && gtk_tree_path_get_depth (filter_path) > 1)
581 GtkTreePath *real_path;
583 gtk_tree_path_up (store_path);
584 gtk_tree_path_up (filter_path);
586 /* A row-has-child-toggled will be emitted on the parent */
589 && gtk_tree_path_is_descendant (store_path, root_path)
590 && gtk_tree_path_compare (store_path, root_path)))
592 real_path = strip_virtual_root (filter_path, root_path);
593 signal_monitor_append_signal_path (fixture->monitor,
594 ROW_HAS_CHILD_TOGGLED,
597 gtk_tree_path_free (real_path);
603 filter_test_append_refilter_signals (FilterTest *fixture,
606 /* A special function that walks the tree store like the
607 * model validation functions below.
610 GtkTreePath *filter_path;
612 path = gtk_tree_path_new ();
613 filter_path = gtk_tree_path_new ();
614 filter_test_append_refilter_signals_recurse (fixture,
619 gtk_tree_path_free (path);
620 gtk_tree_path_free (filter_path);
624 filter_test_append_refilter_signals_with_vroot (FilterTest *fixture,
626 GtkTreePath *root_path)
628 /* A special function that walks the tree store like the
629 * model validation functions below.
632 GtkTreePath *filter_path;
634 path = gtk_tree_path_new ();
635 filter_path = gtk_tree_path_new ();
636 filter_test_append_refilter_signals_recurse (fixture,
641 gtk_tree_path_free (path);
642 gtk_tree_path_free (filter_path);
646 filter_test_enable_filter (FilterTest *fixture)
648 gtk_tree_model_filter_set_visible_column (fixture->filter, 1);
649 gtk_tree_model_filter_refilter (fixture->filter);
653 filter_test_block_signals (FilterTest *fixture)
655 fixture->block_signals = TRUE;
659 filter_test_unblock_signals (FilterTest *fixture)
661 fixture->block_signals = FALSE;
665 filter_test_teardown (FilterTest *fixture,
666 gconstpointer test_data)
668 signal_monitor_free (fixture->monitor);
670 gtk_widget_destroy (fixture->tree_view);
672 g_object_unref (fixture->filter);
673 g_object_unref (fixture->store);
677 * Model structure validation
681 check_filter_model_recurse (FilterTest *fixture,
682 GtkTreePath *store_parent_path,
683 GtkTreePath *filter_parent_path)
686 GtkTreeIter store_iter;
687 GtkTreeIter filter_iter;
688 gboolean store_has_next, filter_has_next;
690 gtk_tree_path_down (store_parent_path);
691 gtk_tree_path_down (filter_parent_path);
693 store_has_next = gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->store),
694 &store_iter, store_parent_path);
695 filter_has_next = gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->filter),
696 &filter_iter, filter_parent_path);
698 for (i = 0; i < LEVEL_LENGTH; i++)
702 g_return_if_fail (store_has_next == TRUE);
704 gtk_tree_model_get (GTK_TREE_MODEL (fixture->store),
712 gchar *filter_str, *store_str;
714 g_return_if_fail (filter_has_next == TRUE);
717 tmp = gtk_tree_model_get_path (GTK_TREE_MODEL (fixture->filter),
719 g_return_if_fail (gtk_tree_path_compare (tmp, filter_parent_path) == 0);
721 /* Verify model content */
722 gtk_tree_model_get (GTK_TREE_MODEL (fixture->store),
726 gtk_tree_model_get (GTK_TREE_MODEL (fixture->filter),
731 g_return_if_fail (g_strcmp0 (store_str, filter_str) == 0);
736 if (gtk_tree_model_iter_has_child (GTK_TREE_MODEL (fixture->filter),
739 g_return_if_fail (gtk_tree_model_iter_has_child (GTK_TREE_MODEL (fixture->store), &store_iter));
741 check_filter_model_recurse (fixture,
742 gtk_tree_path_copy (store_parent_path),
746 /* Only when we do not recurse we need to free tmp */
747 gtk_tree_path_free (tmp);
749 gtk_tree_path_next (filter_parent_path);
750 filter_has_next = gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->filter), &filter_iter);
753 gtk_tree_path_next (store_parent_path);
754 store_has_next = gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &store_iter);
757 /* Both models should have no more content! */
758 g_return_if_fail (store_has_next == FALSE);
759 g_return_if_fail (filter_has_next == FALSE);
761 gtk_tree_path_free (store_parent_path);
762 gtk_tree_path_free (filter_parent_path);
766 check_filter_model (FilterTest *fixture)
770 if (fixture->monitor)
771 signal_monitor_assert_is_empty (fixture->monitor);
773 path = gtk_tree_path_new ();
775 check_filter_model_recurse (fixture, path, gtk_tree_path_copy (path));
779 check_filter_model_with_root (FilterTest *fixture,
782 if (fixture->monitor)
783 signal_monitor_assert_is_empty (fixture->monitor);
785 check_filter_model_recurse (fixture,
786 gtk_tree_path_copy (path),
787 gtk_tree_path_new ());
793 check_level_length (GtkTreeModelFilter *filter,
795 const int expected_length)
801 model_length = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (filter), NULL);
802 g_assert_cmpint (model_length, ==, expected_length);
807 gboolean retrieved_iter = FALSE;
810 retrieved_iter = gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (filter),
812 g_return_if_fail (retrieved_iter);
813 model_length = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (filter), &iter);
814 g_assert_cmpint (model_length, ==, expected_length);
819 set_path_visibility (FilterTest *fixture,
823 GtkTreeIter store_iter;
825 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
827 gtk_tree_store_set (fixture->store, &store_iter,
834 insert_path_with_visibility (FilterTest *fixture,
835 const gchar *path_string,
840 GtkTreeIter parent, iter;
842 path = gtk_tree_path_new_from_string (path_string);
843 position = gtk_tree_path_get_indices (path)[gtk_tree_path_get_depth (path)];
844 gtk_tree_path_up (path);
846 if (gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->store), &parent, path))
848 gtk_tree_store_insert (fixture->store, &iter, &parent, position);
849 create_tree_store_set_values (fixture->store, &iter, visible);
851 gtk_tree_path_free (path);
860 verify_test_suite (FilterTest *fixture,
861 gconstpointer user_data)
863 check_filter_model (fixture);
867 verify_test_suite_vroot (FilterTest *fixture,
868 gconstpointer user_data)
870 check_filter_model_with_root (fixture, (GtkTreePath *)user_data);
875 filled_hide_root_level (FilterTest *fixture,
876 gconstpointer user_data)
878 signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "2");
879 set_path_visibility (fixture, "2", FALSE);
880 check_filter_model (fixture);
881 check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 1);
883 signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
884 set_path_visibility (fixture, "0", FALSE);
885 check_filter_model (fixture);
886 check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 2);
888 signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "2");
889 set_path_visibility (fixture, "4", FALSE);
890 check_filter_model (fixture);
891 check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 3);
895 signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
896 signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
898 set_path_visibility (fixture, "1", FALSE);
899 check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 4);
901 set_path_visibility (fixture, "3", FALSE);
902 check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 5);
904 check_filter_model (fixture);
907 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
908 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
909 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "1");
910 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "1");
912 set_path_visibility (fixture, "1", TRUE);
913 check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 4);
915 set_path_visibility (fixture, "3", TRUE);
916 check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 3);
918 check_filter_model (fixture);
922 filled_hide_child_levels (FilterTest *fixture,
923 gconstpointer user_data)
925 signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0:2");
926 set_path_visibility (fixture, "0:2", FALSE);
927 check_filter_model (fixture);
928 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
929 check_level_length (fixture->filter, "0", LEVEL_LENGTH - 1);
931 signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0:3");
932 set_path_visibility (fixture, "0:4", FALSE);
933 check_filter_model (fixture);
934 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
935 check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
937 set_path_visibility (fixture, "0:4:3", FALSE);
938 check_filter_model (fixture);
939 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
940 check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
942 set_path_visibility (fixture, "0:4:0", FALSE);
943 set_path_visibility (fixture, "0:4:1", FALSE);
944 set_path_visibility (fixture, "0:4:2", FALSE);
945 set_path_visibility (fixture, "0:4:4", FALSE);
946 check_filter_model (fixture);
947 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
948 check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
950 /* Since "0:2" is hidden, "0:4" must be "0:3" in the filter model */
951 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0:3");
952 /* FIXME: Actually, the filter model should not be emitted the
953 * row-has-child-toggled signal here. *However* an extraneous emission
954 * of this signal does not hurt and is allowed.
956 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0:3");
957 set_path_visibility (fixture, "0:4", TRUE);
958 check_filter_model (fixture);
959 check_level_length (fixture->filter, "0:3", 0);
961 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0:2");
962 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0:2");
963 set_path_visibility (fixture, "0:2", TRUE);
964 check_filter_model (fixture);
965 check_level_length (fixture->filter, "0:2", LEVEL_LENGTH);
966 check_level_length (fixture->filter, "0:3", LEVEL_LENGTH);
967 check_level_length (fixture->filter, "0:4", 0);
969 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0:4:0");
970 /* Once 0:4:0 got inserted, 0:4 became a parent */
971 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0:4");
972 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0:4:0");
973 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0:4:1");
974 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0:4:1");
976 set_path_visibility (fixture, "0:4:2", TRUE);
977 set_path_visibility (fixture, "0:4:4", TRUE);
978 signal_monitor_assert_is_empty (fixture->monitor);
979 check_level_length (fixture->filter, "0:4", 2);
984 filled_vroot_hide_root_level (FilterTest *fixture,
985 gconstpointer user_data)
987 GtkTreePath *path = (GtkTreePath *)user_data;
989 /* These changes do not affect the filter's root level */
990 set_path_visibility (fixture, "0", FALSE);
991 check_filter_model_with_root (fixture, path);
992 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
993 check_level_length (fixture->filter, "0", LEVEL_LENGTH);
995 set_path_visibility (fixture, "4", FALSE);
996 check_filter_model_with_root (fixture, path);
997 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
998 check_level_length (fixture->filter, "0", LEVEL_LENGTH);
1000 /* Even though we set the virtual root parent node to FALSE,
1001 * the virtual root contents remain.
1003 set_path_visibility (fixture, "2", FALSE);
1004 check_filter_model_with_root (fixture, path);
1005 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1006 check_level_length (fixture->filter, "0", LEVEL_LENGTH);
1009 set_path_visibility (fixture, "1", FALSE);
1010 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1011 check_level_length (fixture->filter, "0", LEVEL_LENGTH);
1013 set_path_visibility (fixture, "3", FALSE);
1014 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1015 check_level_length (fixture->filter, "0", LEVEL_LENGTH);
1017 check_filter_model_with_root (fixture, path);
1020 set_path_visibility (fixture, "2", TRUE);
1021 check_filter_model_with_root (fixture, path);
1022 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1023 check_level_length (fixture->filter, "0", LEVEL_LENGTH);
1025 set_path_visibility (fixture, "1", TRUE);
1026 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1027 check_level_length (fixture->filter, "0", LEVEL_LENGTH);
1029 set_path_visibility (fixture, "3", TRUE);
1030 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1031 check_level_length (fixture->filter, "0", LEVEL_LENGTH);
1033 check_filter_model_with_root (fixture, path);
1035 /* Now test changes in the virtual root level */
1036 signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "2");
1037 set_path_visibility (fixture, "2:2", FALSE);
1038 check_filter_model_with_root (fixture, path);
1039 check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 1);
1041 signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "3");
1042 set_path_visibility (fixture, "2:4", FALSE);
1043 check_filter_model_with_root (fixture, path);
1044 check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 2);
1046 set_path_visibility (fixture, "1:4", FALSE);
1047 check_filter_model_with_root (fixture, path);
1048 check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 2);
1050 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "3");
1051 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "3");
1052 set_path_visibility (fixture, "2:4", TRUE);
1053 check_filter_model_with_root (fixture, path);
1054 check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 1);
1056 set_path_visibility (fixture, "2", FALSE);
1057 check_filter_model_with_root (fixture, path);
1058 check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 1);
1060 signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
1061 signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
1062 signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
1063 signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
1064 set_path_visibility (fixture, "2:0", FALSE);
1065 set_path_visibility (fixture, "2:1", FALSE);
1066 set_path_visibility (fixture, "2:2", FALSE);
1067 set_path_visibility (fixture, "2:3", FALSE);
1068 set_path_visibility (fixture, "2:4", FALSE);
1069 check_filter_model_with_root (fixture, path);
1070 check_level_length (fixture->filter, NULL, 0);
1072 set_path_visibility (fixture, "2", TRUE);
1073 check_filter_model_with_root (fixture, path);
1074 check_level_length (fixture->filter, NULL, 0);
1076 set_path_visibility (fixture, "1:4", FALSE);
1077 check_filter_model_with_root (fixture, path);
1078 check_level_length (fixture->filter, NULL, 0);
1080 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1081 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1082 set_path_visibility (fixture, "2:4", TRUE);
1083 check_filter_model_with_root (fixture, path);
1084 check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 4);
1086 signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
1087 set_path_visibility (fixture, "2:4", FALSE);
1088 check_filter_model_with_root (fixture, path);
1089 check_level_length (fixture->filter, NULL, 0);
1091 set_path_visibility (fixture, "2", FALSE);
1092 check_filter_model_with_root (fixture, path);
1093 check_level_length (fixture->filter, NULL, 0);
1095 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1096 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1097 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "1");
1098 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "1");
1099 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "2");
1100 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2");
1101 set_path_visibility (fixture, "2:0", TRUE);
1102 set_path_visibility (fixture, "2:1", TRUE);
1103 set_path_visibility (fixture, "2:2", TRUE);
1104 check_filter_model_with_root (fixture, path);
1105 check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 2);
1107 set_path_visibility (fixture, "2", TRUE);
1108 check_filter_model_with_root (fixture, path);
1109 check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 2);
1113 filled_vroot_hide_child_levels (FilterTest *fixture,
1114 gconstpointer user_data)
1116 GtkTreePath *path = (GtkTreePath *)user_data;
1118 signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0:2");
1119 set_path_visibility (fixture, "2:0:2", FALSE);
1120 check_filter_model_with_root (fixture, path);
1121 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1122 check_level_length (fixture->filter, "0", LEVEL_LENGTH - 1);
1124 signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0:3");
1125 set_path_visibility (fixture, "2:0:4", FALSE);
1126 check_filter_model_with_root (fixture, path);
1127 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1128 check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
1130 set_path_visibility (fixture, "2:0:4:3", FALSE);
1131 check_filter_model_with_root (fixture, path);
1132 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1133 check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
1135 set_path_visibility (fixture, "2:0:4:0", FALSE);
1136 set_path_visibility (fixture, "2:0:4:1", FALSE);
1137 set_path_visibility (fixture, "2:0:4:2", FALSE);
1138 set_path_visibility (fixture, "2:0:4:4", FALSE);
1139 check_filter_model_with_root (fixture, path);
1140 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1141 check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
1143 /* Since "0:2" is hidden, "0:4" must be "0:3" in the filter model */
1144 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0:3");
1145 /* FIXME: Actually, the filter model should not be emitted the
1146 * row-has-child-toggled signal here. *However* an extraneous emission
1147 * of this signal does not hurt and is allowed.
1149 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0:3");
1150 set_path_visibility (fixture, "2:0:4", TRUE);
1151 check_filter_model_with_root (fixture, path);
1152 check_level_length (fixture->filter, "0:3", 0);
1154 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0:2");
1155 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0:2");
1156 set_path_visibility (fixture, "2:0:2", TRUE);
1157 check_filter_model_with_root (fixture, path);
1158 check_level_length (fixture->filter, "0:2", LEVEL_LENGTH);
1159 check_level_length (fixture->filter, "0:3", LEVEL_LENGTH);
1160 check_level_length (fixture->filter, "0:4", 0);
1162 /* FIXME: Inconsistency! For the non-vroot case we also receive two
1163 * row-has-child-toggled signals here.
1165 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0:4:0");
1166 /* Once 0:4:0 got inserted, 0:4 became a parent */
1167 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0:4");
1168 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0:4:1");
1169 set_path_visibility (fixture, "2:0:4:2", TRUE);
1170 set_path_visibility (fixture, "2:0:4:4", TRUE);
1171 check_level_length (fixture->filter, "0:4", 2);
1176 empty_show_nodes (FilterTest *fixture,
1177 gconstpointer user_data)
1179 check_filter_model (fixture);
1180 check_level_length (fixture->filter, NULL, 0);
1182 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1183 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1184 set_path_visibility (fixture, "3", TRUE);
1185 check_filter_model (fixture);
1186 check_level_length (fixture->filter, NULL, 1);
1187 check_level_length (fixture->filter, "0", 0);
1189 set_path_visibility (fixture, "3:2:2", TRUE);
1190 check_filter_model (fixture);
1191 check_level_length (fixture->filter, NULL, 1);
1192 check_level_length (fixture->filter, "0", 0);
1194 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0:0");
1195 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1196 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0:0");
1197 set_path_visibility (fixture, "3:2", TRUE);
1198 check_filter_model (fixture);
1199 check_level_length (fixture->filter, NULL, 1);
1200 check_level_length (fixture->filter, "0", 1);
1201 check_level_length (fixture->filter, "0:0", 1);
1202 check_level_length (fixture->filter, "0:0:0", 0);
1204 signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
1205 set_path_visibility (fixture, "3", FALSE);
1206 check_filter_model (fixture);
1207 check_level_length (fixture->filter, NULL, 0);
1209 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1210 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1211 set_path_visibility (fixture, "3:2:1", TRUE);
1212 set_path_visibility (fixture, "3", TRUE);
1213 check_filter_model (fixture);
1214 check_level_length (fixture->filter, NULL, 1);
1215 check_level_length (fixture->filter, "0", 1);
1216 check_level_length (fixture->filter, "0:0", 2);
1217 check_level_length (fixture->filter, "0:0:0", 0);
1221 empty_show_multiple_nodes (FilterTest *fixture,
1222 gconstpointer user_data)
1225 GtkTreePath *changed_path;
1227 check_filter_model (fixture);
1228 check_level_length (fixture->filter, NULL, 0);
1230 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1231 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1232 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "1");
1233 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "1");
1234 signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "1");
1235 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "1");
1237 /* We simulate a change in visible func condition with this. The
1238 * visibility state of multiple nodes changes at once, we emit row-changed
1239 * for these nodes (and others) after that.
1241 filter_test_block_signals (fixture);
1242 set_path_visibility (fixture, "3", TRUE);
1243 set_path_visibility (fixture, "4", TRUE);
1244 filter_test_unblock_signals (fixture);
1246 changed_path = gtk_tree_path_new ();
1247 gtk_tree_path_append_index (changed_path, 2);
1248 gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->store),
1249 &iter, changed_path);
1250 gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1251 changed_path, &iter);
1253 gtk_tree_path_next (changed_path);
1254 gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &iter);
1255 gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1256 changed_path, &iter);
1258 gtk_tree_path_next (changed_path);
1259 gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &iter);
1260 gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1261 changed_path, &iter);
1263 gtk_tree_path_free (changed_path);
1265 check_filter_model (fixture);
1266 check_level_length (fixture->filter, NULL, 2);
1267 check_level_length (fixture->filter, "0", 0);
1269 set_path_visibility (fixture, "3:2:2", TRUE);
1270 check_filter_model (fixture);
1271 check_level_length (fixture->filter, NULL, 2);
1272 check_level_length (fixture->filter, "0", 0);
1274 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0:0");
1275 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1276 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0:0");
1277 set_path_visibility (fixture, "3:2", TRUE);
1278 check_filter_model (fixture);
1279 check_level_length (fixture->filter, NULL, 2);
1280 check_level_length (fixture->filter, "0", 1);
1281 check_level_length (fixture->filter, "0:0", 1);
1282 check_level_length (fixture->filter, "0:0:0", 0);
1284 signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
1285 set_path_visibility (fixture, "3", FALSE);
1286 check_filter_model (fixture);
1287 check_level_length (fixture->filter, NULL, 1);
1289 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1290 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1291 set_path_visibility (fixture, "3:2:1", TRUE);
1292 set_path_visibility (fixture, "3", TRUE);
1293 check_filter_model (fixture);
1294 check_level_length (fixture->filter, NULL, 2);
1295 check_level_length (fixture->filter, "0", 1);
1296 check_level_length (fixture->filter, "0:0", 2);
1297 check_level_length (fixture->filter, "0:0:0", 0);
1301 empty_vroot_show_nodes (FilterTest *fixture,
1302 gconstpointer user_data)
1304 GtkTreePath *path = (GtkTreePath *)user_data;
1306 check_filter_model_with_root (fixture, path);
1307 check_level_length (fixture->filter, NULL, 0);
1309 set_path_visibility (fixture, "2", TRUE);
1310 check_filter_model_with_root (fixture, path);
1311 check_level_length (fixture->filter, NULL, 0);
1313 set_path_visibility (fixture, "2:2:2", TRUE);
1314 check_filter_model_with_root (fixture, path);
1315 check_level_length (fixture->filter, NULL, 0);
1317 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1318 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1319 set_path_visibility (fixture, "2:2", TRUE);
1320 check_filter_model_with_root (fixture, path);
1321 check_level_length (fixture->filter, NULL, 1);
1322 check_level_length (fixture->filter, "0", 1);
1323 check_level_length (fixture->filter, "0:0", 0);
1325 set_path_visibility (fixture, "3", TRUE);
1326 check_filter_model_with_root (fixture, path);
1327 check_level_length (fixture->filter, NULL, 1);
1329 signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
1330 set_path_visibility (fixture, "2:2", FALSE);
1331 check_filter_model_with_root (fixture, path);
1332 check_level_length (fixture->filter, NULL, 0);
1334 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1335 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1336 set_path_visibility (fixture, "2:2:1", TRUE);
1337 set_path_visibility (fixture, "2:2", TRUE);
1338 check_filter_model_with_root (fixture, path);
1339 check_level_length (fixture->filter, NULL, 1);
1340 check_level_length (fixture->filter, "0", 2);
1341 check_level_length (fixture->filter, "0:1", 0);
1345 empty_vroot_show_multiple_nodes (FilterTest *fixture,
1346 gconstpointer user_data)
1349 GtkTreePath *changed_path;
1350 GtkTreePath *path = (GtkTreePath *)user_data;
1352 check_filter_model_with_root (fixture, path);
1353 check_level_length (fixture->filter, NULL, 0);
1355 /* We simulate a change in visible func condition with this. The
1356 * visibility state of multiple nodes changes at once, we emit row-changed
1357 * for these nodes (and others) after that.
1359 filter_test_block_signals (fixture);
1360 set_path_visibility (fixture, "2", TRUE);
1361 set_path_visibility (fixture, "3", TRUE);
1362 filter_test_unblock_signals (fixture);
1364 changed_path = gtk_tree_path_new ();
1365 gtk_tree_path_append_index (changed_path, 1);
1366 gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->store),
1367 &iter, changed_path);
1368 gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1369 changed_path, &iter);
1371 gtk_tree_path_next (changed_path);
1372 gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &iter);
1373 gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1374 changed_path, &iter);
1376 gtk_tree_path_next (changed_path);
1377 gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &iter);
1378 gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1379 changed_path, &iter);
1381 gtk_tree_path_next (changed_path);
1382 gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &iter);
1383 gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1384 changed_path, &iter);
1386 gtk_tree_path_free (changed_path);
1388 check_filter_model_with_root (fixture, path);
1389 check_level_length (fixture->filter, NULL, 0);
1391 set_path_visibility (fixture, "2:2:2", TRUE);
1392 check_filter_model_with_root (fixture, path);
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 /* Again, we simulate a call to refilter */
1401 filter_test_block_signals (fixture);
1402 set_path_visibility (fixture, "2:2", TRUE);
1403 set_path_visibility (fixture, "2:3", TRUE);
1404 filter_test_unblock_signals (fixture);
1406 changed_path = gtk_tree_path_new ();
1407 gtk_tree_path_append_index (changed_path, 2);
1408 gtk_tree_path_append_index (changed_path, 1);
1409 gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->store),
1410 &iter, changed_path);
1411 gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1412 changed_path, &iter);
1414 gtk_tree_path_next (changed_path);
1415 gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &iter);
1416 gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1417 changed_path, &iter);
1419 gtk_tree_path_next (changed_path);
1420 gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &iter);
1421 gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1422 changed_path, &iter);
1424 gtk_tree_path_next (changed_path);
1425 gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &iter);
1426 gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1427 changed_path, &iter);
1429 gtk_tree_path_free (changed_path);
1431 check_filter_model_with_root (fixture, path);
1432 check_level_length (fixture->filter, NULL, 2);
1433 check_level_length (fixture->filter, "0", 1);
1434 check_level_length (fixture->filter, "0:0", 0);
1436 set_path_visibility (fixture, "3", TRUE);
1437 check_filter_model_with_root (fixture, path);
1438 check_level_length (fixture->filter, NULL, 2);
1440 signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
1441 set_path_visibility (fixture, "2:2", FALSE);
1442 check_filter_model_with_root (fixture, path);
1443 check_level_length (fixture->filter, NULL, 1);
1445 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1446 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1447 set_path_visibility (fixture, "2:2:1", TRUE);
1448 set_path_visibility (fixture, "2:2", TRUE);
1449 check_filter_model_with_root (fixture, path);
1450 check_level_length (fixture->filter, NULL, 2);
1451 check_level_length (fixture->filter, "0", 2);
1452 check_level_length (fixture->filter, "0:1", 0);
1457 unfiltered_hide_single (FilterTest *fixture,
1458 gconstpointer user_data)
1461 signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2");
1462 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2");
1463 set_path_visibility (fixture, "2", FALSE);
1465 signal_monitor_assert_is_empty (fixture->monitor);
1466 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1468 /* The view only shows the root level, so the filter model only has
1469 * the first two levels cached.
1471 filter_test_append_refilter_signals (fixture, 2);
1472 filter_test_enable_filter (fixture);
1474 check_filter_model (fixture);
1475 check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 1);
1479 unfiltered_hide_single_child (FilterTest *fixture,
1480 gconstpointer user_data)
1483 signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2:2");
1484 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
1485 set_path_visibility (fixture, "2:2", FALSE);
1487 signal_monitor_assert_is_empty (fixture->monitor);
1488 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1489 check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1491 /* The view only shows the root level, so the filter model only has
1492 * the first two levels cached.
1494 filter_test_append_refilter_signals (fixture, 2);
1495 filter_test_enable_filter (fixture);
1497 check_filter_model (fixture);
1498 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1499 check_level_length (fixture->filter, "2", LEVEL_LENGTH - 1);
1503 unfiltered_hide_single_multi_level (FilterTest *fixture,
1504 gconstpointer user_data)
1507 /* This row is not shown, so its signal is not propagated */
1508 set_path_visibility (fixture, "2:2:2", FALSE);
1510 signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2:2");
1511 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
1512 set_path_visibility (fixture, "2:2", FALSE);
1514 signal_monitor_assert_is_empty (fixture->monitor);
1515 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1516 check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1517 check_level_length (fixture->filter, "2:2", LEVEL_LENGTH);
1519 /* The view only shows the root level, so the filter model only has
1520 * the first two levels cached.
1522 filter_test_append_refilter_signals (fixture, 2);
1523 filter_test_enable_filter (fixture);
1525 check_filter_model (fixture);
1526 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1527 check_level_length (fixture->filter, "2", LEVEL_LENGTH - 1);
1529 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "2:2");
1530 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
1531 set_path_visibility (fixture, "2:2", TRUE);
1533 check_filter_model (fixture);
1534 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1535 check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1536 check_level_length (fixture->filter, "2:2", LEVEL_LENGTH - 1);
1541 unfiltered_vroot_hide_single (FilterTest *fixture,
1542 gconstpointer user_data)
1545 GtkTreePath *path = (GtkTreePath *)user_data;
1547 signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2");
1548 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2");
1549 set_path_visibility (fixture, "2:2", FALSE);
1551 signal_monitor_assert_is_empty (fixture->monitor);
1552 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1554 /* The view only shows the root level, so the filter model only has
1555 * the first two levels cached. (We add an additional level to
1556 * take the virtual root into account).
1558 filter_test_append_refilter_signals_with_vroot (fixture, 3, path);
1559 filter_test_enable_filter (fixture);
1561 check_filter_model_with_root (fixture, path);
1562 check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 1);
1566 unfiltered_vroot_hide_single_child (FilterTest *fixture,
1567 gconstpointer user_data)
1570 GtkTreePath *path = (GtkTreePath *)user_data;
1572 signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2:2");
1573 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
1574 set_path_visibility (fixture, "2:2:2", FALSE);
1576 signal_monitor_assert_is_empty (fixture->monitor);
1577 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1578 check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1580 /* The view only shows the root level, so the filter model only has
1581 * the first two levels cached. (We add an additional level to take
1582 * the virtual root into account).
1584 filter_test_append_refilter_signals_with_vroot (fixture, 3, path);
1585 filter_test_enable_filter (fixture);
1587 check_filter_model_with_root (fixture, path);
1588 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1589 check_level_length (fixture->filter, "2", LEVEL_LENGTH - 1);
1593 unfiltered_vroot_hide_single_multi_level (FilterTest *fixture,
1594 gconstpointer user_data)
1597 GtkTreePath *path = (GtkTreePath *)user_data;
1599 /* This row is not shown, so its signal is not propagated */
1600 set_path_visibility (fixture, "2:2:2:2", FALSE);
1602 signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2:2");
1603 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
1604 set_path_visibility (fixture, "2:2:2", FALSE);
1606 signal_monitor_assert_is_empty (fixture->monitor);
1607 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1608 check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1609 check_level_length (fixture->filter, "2:2", LEVEL_LENGTH);
1611 /* The view only shows the root level, so the filter model only has
1612 * the first two levels cached.
1614 filter_test_append_refilter_signals_with_vroot (fixture, 3, path);
1615 filter_test_enable_filter (fixture);
1617 check_filter_model_with_root (fixture, path);
1618 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1619 check_level_length (fixture->filter, "2", LEVEL_LENGTH - 1);
1621 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "2:2");
1622 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
1623 set_path_visibility (fixture, "2:2:2", TRUE);
1625 check_filter_model_with_root (fixture, path);
1626 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1627 check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1628 check_level_length (fixture->filter, "2:2", LEVEL_LENGTH - 1);
1634 unfiltered_show_single (FilterTest *fixture,
1635 gconstpointer user_data)
1638 signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2");
1639 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2");
1640 set_path_visibility (fixture, "2", TRUE);
1642 signal_monitor_assert_is_empty (fixture->monitor);
1643 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1645 /* The view only shows the root level, so the filter model only has
1646 * the first two levels cached.
1648 filter_test_append_refilter_signals (fixture, 2);
1649 filter_test_enable_filter (fixture);
1651 check_filter_model (fixture);
1652 check_level_length (fixture->filter, NULL, 1);
1656 unfiltered_show_single_child (FilterTest *fixture,
1657 gconstpointer user_data)
1660 signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2:2");
1661 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
1662 set_path_visibility (fixture, "2:2", TRUE);
1664 signal_monitor_assert_is_empty (fixture->monitor);
1665 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1666 check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1668 /* The view only shows the root level, so the filter model only has
1669 * the first two levels cached.
1671 filter_test_append_refilter_signals (fixture, 3);
1672 filter_test_enable_filter (fixture);
1674 check_filter_model (fixture);
1675 check_level_length (fixture->filter, NULL, 0);
1677 /* From here we are filtered, "2" in the real model is "0" in the filter
1680 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1681 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1682 set_path_visibility (fixture, "2", TRUE);
1683 signal_monitor_assert_is_empty (fixture->monitor);
1684 check_level_length (fixture->filter, NULL, 1);
1685 check_level_length (fixture->filter, "0", 1);
1689 unfiltered_show_single_multi_level (FilterTest *fixture,
1690 gconstpointer user_data)
1693 /* The view is not showing this row (collapsed state), so it is not
1694 * referenced. The signal should not go through.
1696 set_path_visibility (fixture, "2:2:2", TRUE);
1698 signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2:2");
1699 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
1700 set_path_visibility (fixture, "2:2", TRUE);
1702 signal_monitor_assert_is_empty (fixture->monitor);
1703 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1704 check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1705 check_level_length (fixture->filter, "2:2", LEVEL_LENGTH);
1707 /* The view only shows the root level, so the filter model only has
1708 * the first two levels cached.
1710 filter_test_append_refilter_signals (fixture, 3);
1711 filter_test_enable_filter (fixture);
1713 check_filter_model (fixture);
1714 check_level_length (fixture->filter, NULL, 0);
1716 /* From here we are filtered, "2" in the real model is "0" in the filter
1719 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1720 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1721 set_path_visibility (fixture, "2", TRUE);
1722 check_filter_model (fixture);
1723 check_level_length (fixture->filter, NULL, 1);
1724 check_level_length (fixture->filter, "0", 1);
1725 check_level_length (fixture->filter, "0:0", 1);
1730 unfiltered_vroot_show_single (FilterTest *fixture,
1731 gconstpointer user_data)
1734 GtkTreePath *path = (GtkTreePath *)user_data;
1736 signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2");
1737 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2");
1738 set_path_visibility (fixture, "2:2", TRUE);
1740 signal_monitor_assert_is_empty (fixture->monitor);
1741 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1743 /* The view only shows the root level, so the filter model only has
1744 * the first two levels cached.
1746 filter_test_append_refilter_signals_with_vroot (fixture, 3, path);
1747 filter_test_enable_filter (fixture);
1749 check_filter_model_with_root (fixture, path);
1750 check_level_length (fixture->filter, NULL, 1);
1754 unfiltered_vroot_show_single_child (FilterTest *fixture,
1755 gconstpointer user_data)
1758 GtkTreePath *path = (GtkTreePath *)user_data;
1760 signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2:2");
1761 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
1762 set_path_visibility (fixture, "2:2:2", TRUE);
1764 signal_monitor_assert_is_empty (fixture->monitor);
1765 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1766 check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1768 /* The view only shows the root level, so the filter model only has
1769 * the first two levels cached.
1771 filter_test_append_refilter_signals_with_vroot (fixture, 2, path);
1772 filter_test_enable_filter (fixture);
1774 check_filter_model_with_root (fixture, path);
1775 check_level_length (fixture->filter, NULL, 0);
1777 /* From here we are filtered, "2" in the real model is "0" in the filter
1780 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1781 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1782 set_path_visibility (fixture, "2:2", TRUE);
1783 signal_monitor_assert_is_empty (fixture->monitor);
1784 check_level_length (fixture->filter, NULL, 1);
1785 check_level_length (fixture->filter, "0", 1);
1789 unfiltered_vroot_show_single_multi_level (FilterTest *fixture,
1790 gconstpointer user_data)
1793 GtkTreePath *path = (GtkTreePath *)user_data;
1795 /* The view is not showing this row (collapsed state), so it is not
1796 * referenced. The signal should not go through.
1798 set_path_visibility (fixture, "2:2:2:2", TRUE);
1800 signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2:2");
1801 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
1802 set_path_visibility (fixture, "2:2:2", TRUE);
1804 signal_monitor_assert_is_empty (fixture->monitor);
1805 check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1806 check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1807 check_level_length (fixture->filter, "2:2", LEVEL_LENGTH);
1809 /* The view only shows the root level, so the filter model only has
1810 * the first two levels cached.
1812 filter_test_append_refilter_signals_with_vroot (fixture, 4, path);
1813 filter_test_enable_filter (fixture);
1815 check_filter_model_with_root (fixture, path);
1816 check_level_length (fixture->filter, NULL, 0);
1818 /* From here we are filtered, "2" in the real model is "0" in the filter
1821 signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1822 signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1823 set_path_visibility (fixture, "2:2", TRUE);
1824 check_filter_model_with_root (fixture, path);
1825 check_level_length (fixture->filter, NULL, 1);
1826 check_level_length (fixture->filter, "0", 1);
1827 check_level_length (fixture->filter, "0:0", 1);
1832 insert_before (void)
1834 GtkTreeStore *store;
1835 GtkTreeModel *filter;
1836 GtkWidget *tree_view;
1837 SignalMonitor *monitor;
1839 GtkTreeIter last_iter;
1842 /* This tests two aspects of the row-inserted handling:
1843 * 1) If the newly inserted node was already handled by building
1844 * the root level, don't handle it a second time.
1845 * 2) Offsets of existing nodes must be updated when a new
1849 store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
1850 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
1851 gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter),
1854 tree_view = gtk_tree_view_new_with_model (filter);
1855 monitor = signal_monitor_new (filter);
1857 check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, 0);
1860 path = gtk_tree_path_new_from_indices (0, -1);
1861 signal_monitor_append_signal_path (monitor, ROW_INSERTED, path);
1862 gtk_tree_path_free (path);
1864 gtk_tree_store_insert_with_values (store, &iter, NULL, 0,
1865 0, "Foo", 1, TRUE, -1);
1867 signal_monitor_assert_is_empty (monitor);
1868 check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, 1);
1871 path = gtk_tree_path_new_from_indices (1, -1);
1872 signal_monitor_append_signal_path (monitor, ROW_INSERTED, path);
1873 gtk_tree_path_free (path);
1875 gtk_tree_store_insert_with_values (store, &iter, NULL, 1,
1876 0, "Foo", 1, TRUE, -1);
1879 signal_monitor_assert_is_empty (monitor);
1880 check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, 2);
1882 /* Insert on 1 again -- invisible */
1883 gtk_tree_store_insert_with_values (store, &iter, NULL, 1,
1884 0, "Foo", 1, FALSE, -1);
1886 signal_monitor_assert_is_empty (monitor);
1887 check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, 2);
1889 /* Insert on 1 again -- visible */
1890 path = gtk_tree_path_new_from_indices (1, -1);
1891 signal_monitor_append_signal_path (monitor, ROW_INSERTED, path);
1892 gtk_tree_path_free (path);
1894 gtk_tree_store_insert_with_values (store, &iter, NULL, 1,
1895 0, "Foo", 1, TRUE, -1);
1897 signal_monitor_assert_is_empty (monitor);
1898 check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, 3);
1900 /* Modify the iter that should be at the last position and check the
1903 path = gtk_tree_path_new_from_indices (2, -1);
1904 signal_monitor_append_signal_path (monitor, ROW_CHANGED, path);
1905 gtk_tree_path_free (path);
1907 gtk_tree_store_set (store, &last_iter, 0, "Foo changed", -1);
1909 signal_monitor_assert_is_empty (monitor);
1910 check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, 3);
1916 GtkTreeStore *store;
1917 GtkTreeModel *filter;
1918 GtkWidget *tree_view;
1919 SignalMonitor *monitor;
1920 GtkTreeIter parent, iter;
1923 store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
1925 gtk_tree_store_insert_with_values (store, &parent, NULL, 0,
1926 0, "Parent", 1, TRUE, -1);
1929 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
1930 gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter),
1933 tree_view = gtk_tree_view_new_with_model (filter);
1934 monitor = signal_monitor_new (filter);
1936 /* Insert child -- invisible */
1937 path = gtk_tree_path_new_from_indices (0, -1);
1938 signal_monitor_append_signal_path (monitor, ROW_HAS_CHILD_TOGGLED, path);
1939 /* The signal is received twice, once a pass through from GtkTreeStore
1940 * and one generated by GtkTreeModelFilter. Not accurate, but cannot
1943 signal_monitor_append_signal_path (monitor, ROW_HAS_CHILD_TOGGLED, path);
1944 gtk_tree_path_free (path);
1946 gtk_tree_store_insert_with_values (store, &iter, &parent, 1,
1947 0, "Child", 1, FALSE, -1);
1949 signal_monitor_assert_is_empty (monitor);
1950 check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, 1);
1953 path = gtk_tree_path_new_from_indices (0, 0, -1);
1954 signal_monitor_append_signal_path (monitor, ROW_INSERTED, path);
1955 gtk_tree_path_up (path); /* 0 */
1956 signal_monitor_append_signal_path (monitor, ROW_HAS_CHILD_TOGGLED, path);
1957 gtk_tree_path_free (path);
1959 gtk_tree_store_insert_with_values (store, &iter, &parent, 0,
1960 0, "Child", 1, TRUE, -1);
1962 signal_monitor_assert_is_empty (monitor);
1963 check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, 1);
1965 /* Insert child -- invisible */
1966 gtk_tree_store_insert_with_values (store, &iter, &parent, 1,
1967 0, "Child", 1, FALSE, -1);
1969 signal_monitor_assert_is_empty (monitor);
1970 check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, 1);
1978 GtkTreeIter iter, iter1, iter2, iter3;
1980 GtkTreeModel *filter;
1981 GtkWidget *view G_GNUC_UNUSED;
1983 list = gtk_list_store_new (1, G_TYPE_INT);
1984 gtk_list_store_insert_with_values (list, &iter1, 0, 0, 1, -1);
1985 gtk_list_store_insert_with_values (list, &iter, 1, 0, 2, -1);
1986 gtk_list_store_insert_with_values (list, &iter, 2, 0, 3, -1);
1987 gtk_list_store_insert_with_values (list, &iter, 3, 0, 4, -1);
1988 gtk_list_store_insert_with_values (list, &iter, 4, 0, 5, -1);
1989 gtk_list_store_insert_with_values (list, &iter, 5, 0, 6, -1);
1990 gtk_list_store_insert_with_values (list, &iter2, 6, 0, 7, -1);
1991 gtk_list_store_insert_with_values (list, &iter3, 7, 0, 8, -1);
1993 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (list), NULL);
1994 view = gtk_tree_view_new_with_model (filter);
1996 gtk_list_store_remove (list, &iter1);
1997 gtk_list_store_remove (list, &iter3);
1998 gtk_list_store_remove (list, &iter2);
2000 gtk_widget_destroy (view);
2001 g_object_unref (filter);
2002 g_object_unref (list);
2006 remove_node_vroot (void)
2008 GtkTreeIter parent, root;
2009 GtkTreeIter iter, iter1, iter2, iter3;
2011 GtkTreeModel *filter;
2013 GtkWidget *view G_GNUC_UNUSED;
2015 tree = gtk_tree_store_new (1, G_TYPE_INT);
2016 gtk_tree_store_insert_with_values (tree, &parent, NULL, 0, 0, 0, -1);
2017 gtk_tree_store_insert_with_values (tree, &root, &parent, 0, 0, 0, -1);
2019 gtk_tree_store_insert_with_values (tree, &iter1, &root, 0, 0, 1, -1);
2020 gtk_tree_store_insert_with_values (tree, &iter, &root, 1, 0, 2, -1);
2021 gtk_tree_store_insert_with_values (tree, &iter, &root, 2, 0, 3, -1);
2022 gtk_tree_store_insert_with_values (tree, &iter, &root, 3, 0, 4, -1);
2023 gtk_tree_store_insert_with_values (tree, &iter, &root, 4, 0, 5, -1);
2024 gtk_tree_store_insert_with_values (tree, &iter, &root, 5, 0, 6, -1);
2025 gtk_tree_store_insert_with_values (tree, &iter2, &root, 6, 0, 7, -1);
2026 gtk_tree_store_insert_with_values (tree, &iter3, &root, 7, 0, 8, -1);
2028 path = gtk_tree_path_new_from_indices (0, 0, -1);
2029 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (tree), path);
2030 gtk_tree_path_free (path);
2032 view = gtk_tree_view_new_with_model (filter);
2034 gtk_tree_store_remove (tree, &iter1);
2035 gtk_tree_store_remove (tree, &iter3);
2036 gtk_tree_store_remove (tree, &iter2);
2038 gtk_widget_destroy (view);
2039 g_object_unref (filter);
2040 g_object_unref (tree);
2044 remove_vroot_ancestor (void)
2046 GtkTreeIter parent, root;
2047 GtkTreeIter iter, iter1, iter2, iter3;
2049 GtkTreeModel *filter;
2051 GtkWidget *view G_GNUC_UNUSED;
2053 tree = gtk_tree_store_new (1, G_TYPE_INT);
2054 gtk_tree_store_insert_with_values (tree, &parent, NULL, 0, 0, 0, -1);
2055 gtk_tree_store_insert_with_values (tree, &root, &parent, 0, 0, 0, -1);
2057 gtk_tree_store_insert_with_values (tree, &iter1, &root, 0, 0, 1, -1);
2058 gtk_tree_store_insert_with_values (tree, &iter, &root, 1, 0, 2, -1);
2059 gtk_tree_store_insert_with_values (tree, &iter, &root, 2, 0, 3, -1);
2060 gtk_tree_store_insert_with_values (tree, &iter, &root, 3, 0, 4, -1);
2061 gtk_tree_store_insert_with_values (tree, &iter, &root, 4, 0, 5, -1);
2062 gtk_tree_store_insert_with_values (tree, &iter, &root, 5, 0, 6, -1);
2063 gtk_tree_store_insert_with_values (tree, &iter2, &root, 6, 0, 7, -1);
2064 gtk_tree_store_insert_with_values (tree, &iter3, &root, 7, 0, 8, -1);
2066 path = gtk_tree_path_new_from_indices (0, 0, -1);
2067 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (tree), path);
2068 gtk_tree_path_free (path);
2070 view = gtk_tree_view_new_with_model (filter);
2072 gtk_tree_store_remove (tree, &parent);
2074 gtk_widget_destroy (view);
2075 g_object_unref (filter);
2076 g_object_unref (tree);
2081 specific_path_dependent_filter_func (GtkTreeModel *model,
2087 path = gtk_tree_model_get_path (model, iter);
2088 if (gtk_tree_path_get_indices (path)[0] < 4)
2095 specific_path_dependent_filter (void)
2101 GtkTreeModel *filter;
2103 list = gtk_list_store_new (1, G_TYPE_INT);
2104 gtk_list_store_insert_with_values (list, &iter, 0, 0, 1, -1);
2105 gtk_list_store_insert_with_values (list, &iter, 1, 0, 2, -1);
2106 gtk_list_store_insert_with_values (list, &iter, 2, 0, 3, -1);
2107 gtk_list_store_insert_with_values (list, &iter, 3, 0, 4, -1);
2108 gtk_list_store_insert_with_values (list, &iter, 4, 0, 5, -1);
2109 gtk_list_store_insert_with_values (list, &iter, 5, 0, 6, -1);
2110 gtk_list_store_insert_with_values (list, &iter, 6, 0, 7, -1);
2111 gtk_list_store_insert_with_values (list, &iter, 7, 0, 8, -1);
2113 sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (list));
2114 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (sort), NULL);
2115 gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
2116 specific_path_dependent_filter_func,
2119 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sort), 0,
2120 GTK_SORT_DESCENDING);
2122 for (i = 0; i < 4; i++)
2124 if (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (list), &iter,
2126 gtk_list_store_remove (list, &iter);
2128 if (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (list), &iter,
2130 gtk_list_store_remove (list, &iter);
2133 g_object_unref (filter);
2134 g_object_unref (sort);
2135 g_object_unref (list);
2140 specific_append_after_collapse_visible_func (GtkTreeModel *model,
2145 gboolean hide_negative_numbers;
2147 gtk_tree_model_get (model, iter, 1, &number, -1);
2148 hide_negative_numbers = GPOINTER_TO_INT (g_object_get_data (data, "private-hide-negative-numbers"));
2150 return (number >= 0 || !hide_negative_numbers);
2154 specific_append_after_collapse (void)
2156 /* This test is based on one of the test cases I found in my
2157 * old test cases directory. I unfortunately do not have a record
2158 * from who this test case originated. -Kris.
2162 * - Show tree, expand, collapse.
2167 GtkTreeIter child_iter;
2168 GtkTreeIter child_iter2;
2169 GtkTreePath *append_path;
2170 GtkTreeStore *store;
2171 GtkTreeModel *filter;
2175 GtkWidget *tree_view;
2177 store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_INT);
2179 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
2180 g_object_set_data (G_OBJECT (filter), "private-hide-negative-numbers",
2181 GINT_TO_POINTER (FALSE));
2182 gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
2183 specific_append_after_collapse_visible_func,
2186 sort = gtk_tree_model_sort_new_with_model (filter);
2188 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2189 tree_view = gtk_tree_view_new_with_model (sort);
2190 gtk_container_add (GTK_CONTAINER (window), tree_view);
2191 gtk_widget_realize (tree_view);
2193 while (gtk_events_pending ())
2194 gtk_main_iteration ();
2196 gtk_tree_store_prepend (store, &iter, NULL);
2197 gtk_tree_store_set (store, &iter,
2198 0, "hallo", 1, 1, -1);
2200 gtk_tree_store_append (store, &child_iter, &iter);
2201 gtk_tree_store_set (store, &child_iter,
2202 0, "toemaar", 1, 1, -1);
2204 gtk_tree_store_append (store, &child_iter2, &child_iter);
2205 gtk_tree_store_set (store, &child_iter2,
2206 0, "very deep", 1, 1, -1);
2208 append_path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &child_iter2);
2210 gtk_tree_store_append (store, &child_iter, &iter);
2211 gtk_tree_store_set (store, &child_iter,
2212 0, "sja", 1, 1, -1);
2214 gtk_tree_store_append (store, &child_iter, &iter);
2215 gtk_tree_store_set (store, &child_iter,
2216 0, "some word", 1, -1, -1);
2218 /* Expand and collapse the tree */
2219 gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
2220 while (gtk_events_pending ())
2221 gtk_main_iteration ();
2223 gtk_tree_view_collapse_all (GTK_TREE_VIEW (tree_view));
2224 while (gtk_events_pending ())
2225 gtk_main_iteration ();
2227 /* Add another it */
2228 g_object_set_data (G_OBJECT (filter), "private-hide-negative-numbers",
2229 GINT_TO_POINTER (TRUE));
2231 if (gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, append_path))
2233 gtk_tree_store_append (store, &child_iter, &iter);
2234 gtk_tree_store_set (store, &child_iter,
2235 0, "new new new !!", 1, 1, -1);
2237 gtk_tree_path_free (append_path);
2240 gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
2241 while (gtk_events_pending ())
2242 gtk_main_iteration ();
2247 specific_sort_filter_remove_node_compare_func (GtkTreeModel *model,
2256 specific_sort_filter_remove_node_visible_func (GtkTreeModel *model,
2262 /* Do reference the model */
2263 gtk_tree_model_get (model, iter, 0, &item, -1);
2270 specific_sort_filter_remove_node (void)
2272 /* This test is based on one of the test cases I found in my
2273 * old test cases directory. I unfortunately do not have a record
2274 * from who this test case originated. -Kris.
2277 * - Create tree store, sort, filter models. The sort model has
2278 * a default sort func that is enabled, filter model a visible func
2279 * that defaults to returning FALSE.
2280 * - Remove a node from the tree store.
2284 GtkTreeStore *store;
2285 GtkTreeModel *filter;
2289 GtkWidget *tree_view;
2291 store = gtk_tree_store_new (1, G_TYPE_STRING);
2292 gtk_tree_store_append (store, &iter, NULL);
2293 gtk_tree_store_set (store, &iter, 0, "Hello1", -1);
2295 gtk_tree_store_append (store, &iter, NULL);
2296 gtk_tree_store_set (store, &iter, 0, "Hello2", -1);
2298 sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (store));
2299 gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (sort),
2300 specific_sort_filter_remove_node_compare_func, NULL, NULL);
2302 filter = gtk_tree_model_filter_new (sort, NULL);
2303 gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
2304 specific_sort_filter_remove_node_visible_func,
2308 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2309 tree_view = gtk_tree_view_new_with_model (filter);
2310 gtk_container_add (GTK_CONTAINER (window), tree_view);
2311 gtk_widget_realize (tree_view);
2313 while (gtk_events_pending ())
2314 gtk_main_iteration ();
2317 gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter);
2318 gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter);
2319 gtk_tree_store_remove (store, &iter);
2321 while (gtk_events_pending ())
2322 gtk_main_iteration ();
2327 specific_sort_filter_remove_root (void)
2329 /* This test is based on one of the test cases I found in my
2330 * old test cases directory. I unfortunately do not have a record
2331 * from who this test case originated. -Kris.
2334 GtkTreeModel *model, *sort, *filter;
2335 GtkTreeIter root, mid, leaf;
2338 model = GTK_TREE_MODEL (gtk_tree_store_new (1, G_TYPE_INT));
2339 gtk_tree_store_append (GTK_TREE_STORE (model), &root, NULL);
2340 gtk_tree_store_append (GTK_TREE_STORE (model), &mid, &root);
2341 gtk_tree_store_append (GTK_TREE_STORE (model), &leaf, &mid);
2343 path = gtk_tree_model_get_path (model, &mid);
2345 sort = gtk_tree_model_sort_new_with_model (model);
2346 filter = gtk_tree_model_filter_new (sort, path);
2348 gtk_tree_path_free (path);
2350 gtk_tree_store_remove (GTK_TREE_STORE (model), &root);
2352 g_object_unref (filter);
2353 g_object_unref (sort);
2354 g_object_unref (model);
2359 specific_root_mixed_visibility (void)
2362 GtkTreeModel *filter;
2363 /* A bit nasty, apologies */
2366 fixture.store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
2368 for (i = 0; i < LEVEL_LENGTH; i++)
2372 gtk_tree_store_insert (fixture.store, &iter, NULL, i);
2374 create_tree_store_set_values (fixture.store, &iter, TRUE);
2376 create_tree_store_set_values (fixture.store, &iter, FALSE);
2379 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (fixture.store), NULL);
2380 fixture.filter = GTK_TREE_MODEL_FILTER (filter);
2381 fixture.monitor = NULL;
2383 gtk_tree_model_filter_set_visible_column (fixture.filter, 1);
2385 /* In order to trigger the potential bug, we should not access
2386 * the filter model here (so don't call the check functions).
2389 /* Change visibility of an odd row to TRUE */
2390 set_path_visibility (&fixture, "3", TRUE);
2391 check_filter_model (&fixture);
2392 check_level_length (fixture.filter, NULL, 4);
2398 specific_has_child_filter_filter_func (GtkTreeModel *model,
2402 return gtk_tree_model_iter_has_child (model, iter);
2406 specific_has_child_filter (void)
2408 GtkTreeModel *filter;
2409 GtkTreeIter iter, root;
2410 FilterTest fixture; /* This is not how it should be done */
2411 GtkWidget *tree_view;
2413 fixture.store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
2414 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (fixture.store), NULL);
2415 fixture.filter = GTK_TREE_MODEL_FILTER (filter);
2416 fixture.monitor = signal_monitor_new (filter);
2418 tree_view = gtk_tree_view_new_with_model (filter);
2420 /* We will filter on parent state using a filter function. We will
2421 * manually keep the boolean column in sync, so that we can use
2422 * check_filter_model() to check the consistency of the model.
2424 /* FIXME: We need a check_filter_model() that is not tied to LEVEL_LENGTH
2425 * to be able to check the structure here. We keep the calls to
2426 * check_filter_model() commented out until then.
2428 gtk_tree_model_filter_set_visible_func (fixture.filter,
2429 specific_has_child_filter_filter_func,
2432 /* The first node will be initially invisible: no signals */
2433 gtk_tree_store_append (fixture.store, &root, NULL);
2434 create_tree_store_set_values (fixture.store, &root, FALSE);
2436 /* check_filter_model (&fixture); */
2437 check_level_length (fixture.filter, NULL, 0);
2438 signal_monitor_assert_is_empty (fixture.monitor);
2440 /* Insert a child node. This will cause the parent to become visible
2441 * since there is a child now.
2443 signal_monitor_append_signal (fixture.monitor, ROW_INSERTED, "0");
2444 signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
2445 signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
2447 gtk_tree_store_append (fixture.store, &iter, &root);
2448 create_tree_store_set_values (fixture.store, &iter, TRUE);
2450 /* Parent must now be visible. Do the level length check first,
2451 * to avoid modifying the child model triggering a row-changed to
2454 check_level_length (fixture.filter, NULL, 1);
2455 check_level_length (fixture.filter, "0", 0);
2456 signal_monitor_assert_is_empty (fixture.monitor);
2458 /* This should propagate row-changed */
2459 signal_monitor_append_signal (fixture.monitor, ROW_CHANGED, "0");
2460 signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
2462 set_path_visibility (&fixture, "0", TRUE);
2463 /* check_filter_model (&fixture); */
2464 signal_monitor_assert_is_empty (fixture.monitor);
2466 /* New root node, no child, so no signal */
2467 gtk_tree_store_append (fixture.store, &root, NULL);
2468 check_level_length (fixture.filter, NULL, 1);
2469 signal_monitor_assert_is_empty (fixture.monitor);
2471 /* When the child comes in, this node will become visible */
2472 signal_monitor_append_signal (fixture.monitor, ROW_INSERTED, "1");
2473 signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "1");
2474 signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "1");
2475 signal_monitor_append_signal (fixture.monitor, ROW_CHANGED, "1");
2476 signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "1");
2478 gtk_tree_store_append (fixture.store, &iter, &root);
2479 check_level_length (fixture.filter, NULL, 2);
2480 check_level_length (fixture.filter, "1", 0);
2482 create_tree_store_set_values (fixture.store, &root, TRUE);
2483 create_tree_store_set_values (fixture.store, &iter, TRUE);
2485 /* check_filter_model (&fixture); */
2486 signal_monitor_assert_is_empty (fixture.monitor);
2488 /* Add another child for 1 */
2489 gtk_tree_store_append (fixture.store, &iter, &root);
2490 create_tree_store_set_values (fixture.store, &iter, TRUE);
2491 check_level_length (fixture.filter, NULL, 2);
2492 check_level_length (fixture.filter, "0", 0);
2493 check_level_length (fixture.filter, "1", 0);
2494 signal_monitor_assert_is_empty (fixture.monitor);
2496 /* Now remove one of the remaining child rows */
2497 signal_monitor_append_signal (fixture.monitor, ROW_DELETED, "0");
2499 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture.store),
2501 gtk_tree_store_remove (fixture.store, &iter);
2503 check_level_length (fixture.filter, NULL, 1);
2504 check_level_length (fixture.filter, "0", 0);
2506 set_path_visibility (&fixture, "0", FALSE);
2507 /* check_filter_model (&fixture); */
2508 signal_monitor_assert_is_empty (fixture.monitor);
2513 specific_root_has_child_filter_filter_func (GtkTreeModel *model,
2520 path = gtk_tree_model_get_path (model, iter);
2521 depth = gtk_tree_path_get_depth (path);
2522 gtk_tree_path_free (path);
2527 return gtk_tree_model_iter_has_child (model, iter);
2531 specific_root_has_child_filter (void)
2533 GtkTreeModel *filter;
2534 GtkTreeIter iter, root;
2535 FilterTest fixture; /* This is not how it should be done ... */
2536 GtkWidget *tree_view;
2538 /* This is a variation on the above test case, specific has-child-filter,
2539 * herein the has-child check for visibility only applies to root level
2540 * nodes. In this test, children are always visible because we
2541 * only filter based on the "has child" criterion.
2544 fixture.store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
2545 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (fixture.store), NULL);
2546 fixture.filter = GTK_TREE_MODEL_FILTER (filter);
2547 fixture.monitor = signal_monitor_new (filter);
2549 tree_view = gtk_tree_view_new_with_model (filter);
2551 /* We will filter on parent state using a filter function. We will
2552 * manually keep the boolean column in sync, so that we can use
2553 * check_filter_model() to check the consistency of the model.
2555 /* FIXME: We need a check_filter_model() that is not tied to LEVEL_LENGTH
2556 * to be able to check the structure here. We keep the calls to
2557 * check_filter_model() commented out until then.
2559 gtk_tree_model_filter_set_visible_func (fixture.filter,
2560 specific_root_has_child_filter_filter_func,
2563 /* Add a first node, this will be invisible initially, so no signal
2564 * should be emitted.
2566 gtk_tree_store_append (fixture.store, &root, NULL);
2567 create_tree_store_set_values (fixture.store, &root, FALSE);
2569 signal_monitor_assert_is_empty (fixture.monitor);
2570 /* check_filter_model (&fixture); */
2571 check_level_length (fixture.filter, NULL, 0);
2573 /* Add a child node. This will cause the parent to become visible,
2574 * so we expect row-inserted signals for both.
2576 signal_monitor_append_signal (fixture.monitor, ROW_INSERTED, "0");
2577 signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
2578 signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
2580 gtk_tree_store_append (fixture.store, &iter, &root);
2581 signal_monitor_assert_is_empty (fixture.monitor);
2583 check_level_length (fixture.filter, NULL, 1);
2584 check_level_length (fixture.filter, "0", 1);
2586 /* Modify the content of iter, yields row-changed signals */
2587 signal_monitor_append_signal (fixture.monitor, ROW_CHANGED, "0:0");
2589 create_tree_store_set_values (fixture.store, &iter, TRUE);
2590 signal_monitor_assert_is_empty (fixture.monitor);
2592 /* Parent must now be visible. Do the level length check first,
2593 * to avoid modifying the child model triggering a row-changed to
2596 check_level_length (fixture.filter, NULL, 1);
2597 check_level_length (fixture.filter, "0", 1);
2600 signal_monitor_append_signal (fixture.monitor, ROW_CHANGED, "0");
2601 signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
2603 set_path_visibility (&fixture, "0", TRUE);
2604 /* check_filter_model (&fixture); */
2606 signal_monitor_assert_is_empty (fixture.monitor);
2608 /* Insert another node in the root level. Initially invisible, so
2609 * not expecting any signal.
2611 gtk_tree_store_append (fixture.store, &root, NULL);
2612 check_level_length (fixture.filter, NULL, 1);
2614 signal_monitor_assert_is_empty (fixture.monitor);
2616 /* Adding a child node which also makes parent at path 1 visible. */
2617 signal_monitor_append_signal (fixture.monitor, ROW_INSERTED, "1");
2618 signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "1");
2619 signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "1");
2621 gtk_tree_store_append (fixture.store, &iter, &root);
2622 check_level_length (fixture.filter, NULL, 2);
2623 check_level_length (fixture.filter, "1", 1);
2625 signal_monitor_assert_is_empty (fixture.monitor);
2627 /* Check if row-changed is propagated */
2628 signal_monitor_append_signal (fixture.monitor, ROW_CHANGED, "1");
2629 /* is row-has-child-toggled really necessary? */
2630 signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "1");
2631 signal_monitor_append_signal (fixture.monitor, ROW_CHANGED, "1:0");
2633 create_tree_store_set_values (fixture.store, &root, TRUE);
2634 create_tree_store_set_values (fixture.store, &iter, TRUE);
2635 /* check_filter_model (&fixture); */
2636 signal_monitor_assert_is_empty (fixture.monitor);
2638 /* Insert another child under node 1 */
2639 signal_monitor_append_signal (fixture.monitor, ROW_INSERTED, "1:1");
2640 signal_monitor_append_signal (fixture.monitor, ROW_CHANGED, "1:1");
2642 gtk_tree_store_append (fixture.store, &iter, &root);
2643 create_tree_store_set_values (fixture.store, &iter, TRUE);
2644 check_level_length (fixture.filter, NULL, 2);
2645 check_level_length (fixture.filter, "0", 1);
2646 check_level_length (fixture.filter, "1", 2);
2647 signal_monitor_assert_is_empty (fixture.monitor);
2649 /* Set a child node to invisible. This should not yield any
2650 * change, because filtering is only done on whether the root
2651 * node has a child, which it still has.
2653 signal_monitor_append_signal (fixture.monitor, ROW_CHANGED, "0:0");
2655 set_path_visibility (&fixture, "0:0", FALSE);
2656 signal_monitor_assert_is_empty (fixture.monitor);
2658 /* Now remove one of the remaining child rows */
2659 signal_monitor_append_signal (fixture.monitor, ROW_DELETED, "0:0");
2660 signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
2661 signal_monitor_append_signal (fixture.monitor, ROW_DELETED, "0");
2663 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture.store),
2665 gtk_tree_store_remove (fixture.store, &iter);
2667 check_level_length (fixture.filter, NULL, 1);
2668 check_level_length (fixture.filter, "0", 2);
2669 signal_monitor_assert_is_empty (fixture.monitor);
2671 /* Set visibility of 0 to FALSE, no-op for filter model since
2672 * the child 0:0 is already gone
2674 set_path_visibility (&fixture, "0", FALSE);
2675 /* check_filter_model (&fixture); */
2676 signal_monitor_assert_is_empty (fixture.monitor);
2681 specific_filter_add_child (void)
2683 /* This test is based on one of the test cases I found in my
2684 * old test cases directory. I unfortunately do not have a record
2685 * from who this test case originated. -Kris.
2689 GtkTreeIter iter_first;
2691 GtkTreeStore *store;
2692 GtkTreeModel *filter G_GNUC_UNUSED;
2694 store = gtk_tree_store_new (1, G_TYPE_STRING);
2696 gtk_tree_store_append (store, &iter_first, NULL);
2697 gtk_tree_store_set (store, &iter_first, 0, "Hello", -1);
2699 gtk_tree_store_append (store, &iter, NULL);
2700 gtk_tree_store_set (store, &iter, 0, "Hello", -1);
2702 gtk_tree_store_append (store, &iter, NULL);
2703 gtk_tree_store_set (store, &iter, 0, "Hello", -1);
2705 gtk_tree_store_append (store, &iter, NULL);
2706 gtk_tree_store_set (store, &iter, 0, "Hello", -1);
2708 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
2710 gtk_tree_store_set (store, &iter, 0, "Hello", -1);
2711 gtk_tree_store_append (store, &child, &iter_first);
2712 gtk_tree_store_set (store, &child, 0, "Hello", -1);
2716 specific_list_store_clear (void)
2720 GtkTreeModel *filter;
2721 GtkWidget *view G_GNUC_UNUSED;
2723 list = gtk_list_store_new (1, G_TYPE_INT);
2724 gtk_list_store_insert_with_values (list, &iter, 0, 0, 1, -1);
2725 gtk_list_store_insert_with_values (list, &iter, 1, 0, 2, -1);
2726 gtk_list_store_insert_with_values (list, &iter, 2, 0, 3, -1);
2727 gtk_list_store_insert_with_values (list, &iter, 3, 0, 4, -1);
2728 gtk_list_store_insert_with_values (list, &iter, 4, 0, 5, -1);
2729 gtk_list_store_insert_with_values (list, &iter, 5, 0, 6, -1);
2730 gtk_list_store_insert_with_values (list, &iter, 6, 0, 7, -1);
2731 gtk_list_store_insert_with_values (list, &iter, 7, 0, 8, -1);
2733 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (list), NULL);
2734 view = gtk_tree_view_new_with_model (filter);
2736 gtk_list_store_clear (list);
2740 specific_sort_ref_leaf_and_remove_ancestor (void)
2742 GtkTreeIter iter, child, child2, child3;
2746 GtkTreeRowReference *rowref;
2747 GtkWidget *view G_GNUC_UNUSED;
2749 tree = gtk_tree_store_new (1, G_TYPE_INT);
2750 gtk_tree_store_insert_with_values (tree, &iter, NULL, 0, 0, 1, -1);
2751 gtk_tree_store_insert_with_values (tree, &iter, NULL, 1, 0, 2, -1);
2752 gtk_tree_store_insert_with_values (tree, &iter, NULL, 2, 0, 3, -1);
2753 gtk_tree_store_insert_with_values (tree, &iter, NULL, 3, 0, 4, -1);
2755 gtk_tree_store_insert_with_values (tree, &child, &iter, 0, 0, 50, -1);
2756 gtk_tree_store_insert_with_values (tree, &child2, &child, 0, 0, 6, -1);
2757 gtk_tree_store_insert_with_values (tree, &child3, &child2, 0, 0, 7, -1);
2759 sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (tree));
2760 view = gtk_tree_view_new_with_model (sort);
2761 gtk_tree_view_expand_all (GTK_TREE_VIEW (view));
2763 path = gtk_tree_path_new_from_indices (3, 0, 0, 0, -1);
2764 rowref = gtk_tree_row_reference_new (sort, path);
2765 gtk_tree_path_free (path);
2767 path = gtk_tree_path_new_from_indices (3, 0, 0, 0, -1);
2768 rowref = gtk_tree_row_reference_new (sort, path);
2769 gtk_tree_path_free (path);
2771 path = gtk_tree_path_new_from_indices (3, 0, -1);
2772 rowref = gtk_tree_row_reference_new (sort, path);
2773 gtk_tree_path_free (path);
2775 path = gtk_tree_path_new_from_indices (3, -1);
2776 rowref = gtk_tree_row_reference_new (sort, path);
2777 gtk_tree_path_free (path);
2779 /* Deleting a parent */
2780 path = gtk_tree_path_new_from_indices (3, 0, -1);
2781 gtk_tree_model_get_iter (GTK_TREE_MODEL (tree), &iter, path);
2782 gtk_tree_store_remove (tree, &iter);
2783 gtk_tree_path_free (path);
2785 gtk_tree_row_reference_free (rowref);
2789 specific_ref_leaf_and_remove_ancestor (void)
2791 GtkTreeIter iter, child, child2, child3;
2793 GtkTreeModel *filter;
2795 GtkTreeRowReference *rowref;
2796 GtkWidget *view G_GNUC_UNUSED;
2798 tree = gtk_tree_store_new (1, G_TYPE_INT);
2799 gtk_tree_store_insert_with_values (tree, &iter, NULL, 0, 0, 1, -1);
2800 gtk_tree_store_insert_with_values (tree, &iter, NULL, 1, 0, 2, -1);
2801 gtk_tree_store_insert_with_values (tree, &iter, NULL, 2, 0, 3, -1);
2802 gtk_tree_store_insert_with_values (tree, &iter, NULL, 3, 0, 4, -1);
2804 gtk_tree_store_insert_with_values (tree, &child, &iter, 0, 0, 50, -1);
2805 gtk_tree_store_insert_with_values (tree, &child2, &child, 0, 0, 6, -1);
2806 gtk_tree_store_insert_with_values (tree, &child3, &child2, 0, 0, 7, -1);
2808 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (tree), NULL);
2809 view = gtk_tree_view_new_with_model (filter);
2810 gtk_tree_view_expand_all (GTK_TREE_VIEW (view));
2812 path = gtk_tree_path_new_from_indices (3, 0, 0, 0, -1);
2813 rowref = gtk_tree_row_reference_new (filter, path);
2814 gtk_tree_path_free (path);
2816 path = gtk_tree_path_new_from_indices (3, 0, 0, 0, -1);
2817 rowref = gtk_tree_row_reference_new (filter, path);
2818 gtk_tree_path_free (path);
2820 path = gtk_tree_path_new_from_indices (3, 0, -1);
2821 rowref = gtk_tree_row_reference_new (filter, path);
2822 gtk_tree_path_free (path);
2824 path = gtk_tree_path_new_from_indices (3, -1);
2825 rowref = gtk_tree_row_reference_new (filter, path);
2826 gtk_tree_path_free (path);
2828 /* Deleting a parent */
2829 path = gtk_tree_path_new_from_indices (3, 0, -1);
2830 gtk_tree_model_get_iter (GTK_TREE_MODEL (tree), &iter, path);
2831 gtk_tree_store_remove (tree, &iter);
2832 gtk_tree_path_free (path);
2834 gtk_tree_row_reference_free (rowref);
2838 specific_virtual_ref_leaf_and_remove_ancestor (void)
2840 GtkTreeIter iter, child, child2, child3;
2842 GtkTreeModel *filter;
2844 GtkTreeRowReference *rowref;
2845 GtkWidget *view G_GNUC_UNUSED;
2847 tree = gtk_tree_store_new (1, G_TYPE_INT);
2848 gtk_tree_store_insert_with_values (tree, &iter, NULL, 0, 0, 1, -1);
2849 gtk_tree_store_insert_with_values (tree, &iter, NULL, 1, 0, 2, -1);
2850 gtk_tree_store_insert_with_values (tree, &iter, NULL, 2, 0, 3, -1);
2851 gtk_tree_store_insert_with_values (tree, &iter, NULL, 3, 0, 4, -1);
2853 gtk_tree_store_insert_with_values (tree, &child, &iter, 0, 0, 50, -1);
2854 gtk_tree_store_insert_with_values (tree, &child2, &child, 0, 0, 6, -1);
2855 gtk_tree_store_insert_with_values (tree, &child3, &child2, 0, 0, 7, -1);
2857 /* Set a virtual root of 3:0 */
2858 path = gtk_tree_path_new_from_indices (3, 0, -1);
2859 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (tree), path);
2860 gtk_tree_path_free (path);
2862 view = gtk_tree_view_new_with_model (filter);
2863 gtk_tree_view_expand_all (GTK_TREE_VIEW (view));
2865 path = gtk_tree_path_new_from_indices (0, 0, -1);
2866 rowref = gtk_tree_row_reference_new (filter, path);
2867 gtk_tree_path_free (path);
2869 path = gtk_tree_path_new_from_indices (0, 0, -1);
2870 rowref = gtk_tree_row_reference_new (filter, path);
2871 gtk_tree_path_free (path);
2873 path = gtk_tree_path_new_from_indices (0, -1);
2874 rowref = gtk_tree_row_reference_new (filter, path);
2875 gtk_tree_path_free (path);
2877 /* Deleting the virtual root */
2878 path = gtk_tree_path_new_from_indices (3, 0, -1);
2879 gtk_tree_model_get_iter (GTK_TREE_MODEL (tree), &iter, path);
2880 gtk_tree_store_remove (tree, &iter);
2881 gtk_tree_path_free (path);
2883 gtk_tree_row_reference_free (rowref);
2888 specific_bug_301558_sort_func (GtkTreeModel *model,
2895 gtk_tree_model_get (model, a, 0, &i, -1);
2896 gtk_tree_model_get (model, b, 0, &j, -1);
2902 specific_bug_301558 (void)
2904 /* Test case for GNOME Bugzilla bug 301558 provided by
2908 GtkTreeModel *filter;
2910 GtkTreeIter root, iter, iter2;
2911 GtkWidget *view G_GNUC_UNUSED;
2915 g_test_bug ("301558");
2917 tree = gtk_tree_store_new (2, G_TYPE_INT, G_TYPE_BOOLEAN);
2918 gtk_tree_store_append (tree, &iter, NULL);
2919 gtk_tree_store_set (tree, &iter, 0, 123, 1, TRUE, -1);
2920 gtk_tree_store_append (tree, &iter2, &iter);
2921 gtk_tree_store_set (tree, &iter2, 0, 73, 1, TRUE, -1);
2923 sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (tree));
2924 gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (sort),
2925 specific_bug_301558_sort_func,
2928 filter = gtk_tree_model_filter_new (sort, NULL);
2929 gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter), 1);
2931 view = gtk_tree_view_new_with_model (filter);
2933 while (gtk_events_pending ())
2934 gtk_main_iteration ();
2938 for (i = 0; i < 10; i++)
2940 if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (tree), &root))
2941 g_assert_not_reached ();
2945 gtk_tree_store_append (tree, &iter, &root);
2946 gtk_tree_store_set (tree, &iter, 0, 456, 1, TRUE, -1);
2951 n = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (tree), &root);
2952 gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (tree), &iter,
2954 gtk_tree_store_remove (tree, &iter);
2963 specific_bug_311955_filter_func (GtkTreeModel *model,
2969 gtk_tree_model_get (model, iter, 0, &value, -1);
2971 return (value != 0);
2975 specific_bug_311955 (void)
2977 /* This is a test case for GNOME Bugzilla bug 311955. It was written
2980 GtkTreeIter iter, child, root;
2981 GtkTreeStore *store;
2983 GtkTreeModel *filter;
2985 GtkWidget *window G_GNUC_UNUSED;
2986 GtkWidget *tree_view;
2990 g_test_bug ("311955");
2992 store = gtk_tree_store_new (1, G_TYPE_INT);
2994 gtk_tree_store_append (store, &root, NULL);
2995 gtk_tree_store_set (store, &root, 0, 33, -1);
2997 gtk_tree_store_append (store, &iter, &root);
2998 gtk_tree_store_set (store, &iter, 0, 50, -1);
3000 gtk_tree_store_append (store, &iter, NULL);
3001 gtk_tree_store_set (store, &iter, 0, 22, -1);
3003 sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (store));
3004 filter = gtk_tree_model_filter_new (sort, NULL);
3006 gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
3007 specific_bug_311955_filter_func,
3010 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3011 tree_view = gtk_tree_view_new_with_model (filter);
3012 g_object_unref (store);
3014 gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
3016 while (gtk_events_pending ())
3017 gtk_main_iteration ();
3020 for (i = 0; i < 4; i++)
3022 gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &root);
3024 gtk_tree_store_append (store, &iter, &root);
3027 gtk_tree_store_set (store, &iter, 0, i, -1);
3031 gtk_tree_store_append (store, &child, &iter);
3032 gtk_tree_store_set (store, &child, 0, 10, -1);
3036 while (gtk_events_pending ())
3037 gtk_main_iteration ();
3039 /* Remove bottommost child from the tree. */
3040 gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &root);
3041 n = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (store), &root);
3043 if (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (store), &iter, &root, n - 2))
3045 if (gtk_tree_model_iter_children (GTK_TREE_MODEL (store), &child, &iter))
3046 gtk_tree_store_remove (store, &child);
3049 g_assert_not_reached ();
3053 specific_bug_346800 (void)
3055 /* This is a test case for GNOME Bugzilla bug 346800. It was written
3056 * by Jonathan Matthew.
3059 GtkTreeIter node_iters[50];
3060 GtkTreeIter child_iters[50];
3061 GtkTreeModel *model;
3062 GtkTreeModelFilter *filter;
3063 GtkTreeStore *store;
3067 columns = g_new (GType, 2);
3068 columns[0] = G_TYPE_STRING;
3069 columns[1] = G_TYPE_BOOLEAN;
3070 store = gtk_tree_store_newv (2, columns);
3071 model = GTK_TREE_MODEL (store);
3073 g_test_bug ("346800");
3075 filter = GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (model, NULL));
3076 gtk_tree_model_filter_set_visible_column (filter, 1);
3078 for (i=0; i<items; i++)
3080 /* allocate random amounts of junk, otherwise the filter model's arrays can expand without moving */
3083 gtk_tree_store_append (store, &node_iters[i], NULL);
3084 gtk_tree_store_set (store, &node_iters[i],
3086 1, ((i%6) == 0) ? FALSE : TRUE,
3090 gtk_tree_store_append (store, &child_iters[i], &node_iters[i]);
3091 gtk_tree_store_set (store, &child_iters[i],
3092 0, "something else",
3095 gtk_tree_model_filter_refilter (filter);
3099 gtk_tree_store_set (GTK_TREE_STORE (model), &child_iters[i-1], 1,
3100 (i & 1) ? TRUE : FALSE, -1);
3101 gtk_tree_model_filter_refilter (filter);
3103 gtk_tree_store_set (GTK_TREE_STORE (model), &child_iters[i-2], 1,
3104 (i & 1) ? FALSE: TRUE, -1);
3105 gtk_tree_model_filter_refilter (filter);
3111 specific_bug_464173_visible_func (GtkTreeModel *model,
3115 gboolean *visible = (gboolean *)data;
3121 specific_bug_464173 (void)
3123 /* Test case for GNOME Bugzilla bug 464173, test case written
3124 * by Andreas Koehler.
3126 GtkTreeStore *model;
3127 GtkTreeModelFilter *f_model;
3128 GtkTreeIter iter1, iter2;
3129 GtkWidget *view G_GNUC_UNUSED;
3130 gboolean visible = TRUE;
3132 g_test_bug ("464173");
3134 model = gtk_tree_store_new (1, G_TYPE_STRING);
3135 gtk_tree_store_append (model, &iter1, NULL);
3136 gtk_tree_store_set (model, &iter1, 0, "Foo", -1);
3137 gtk_tree_store_append (model, &iter2, &iter1);
3138 gtk_tree_store_set (model, &iter2, 0, "Bar", -1);
3140 f_model = GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (GTK_TREE_MODEL(model), NULL));
3141 gtk_tree_model_filter_set_visible_func (f_model,
3142 specific_bug_464173_visible_func,
3145 view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (f_model));
3148 gtk_tree_model_filter_refilter (f_model);
3153 specific_bug_540201_filter_func (GtkTreeModel *model,
3157 gboolean has_children;
3159 has_children = gtk_tree_model_iter_has_child (model, iter);
3161 return has_children;
3165 specific_bug_540201 (void)
3167 /* Test case for GNOME Bugzilla bug 540201, steps provided by
3170 GtkTreeIter iter, root;
3171 GtkTreeStore *store;
3172 GtkTreeModel *filter;
3174 GtkWidget *tree_view G_GNUC_UNUSED;
3176 g_test_bug ("540201");
3178 store = gtk_tree_store_new (1, G_TYPE_INT);
3180 gtk_tree_store_append (store, &root, NULL);
3181 gtk_tree_store_set (store, &root, 0, 33, -1);
3183 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
3184 tree_view = gtk_tree_view_new_with_model (filter);
3186 gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
3187 specific_bug_540201_filter_func,
3190 gtk_tree_store_append (store, &iter, &root);
3191 gtk_tree_store_set (store, &iter, 0, 50, -1);
3193 gtk_tree_store_append (store, &iter, &root);
3194 gtk_tree_store_set (store, &iter, 0, 22, -1);
3197 gtk_tree_store_append (store, &root, NULL);
3198 gtk_tree_store_set (store, &root, 0, 33, -1);
3200 gtk_tree_store_append (store, &iter, &root);
3201 gtk_tree_store_set (store, &iter, 0, 22, -1);
3206 specific_bug_549287_visible_func (GtkTreeModel *model,
3210 gboolean result = FALSE;
3212 result = gtk_tree_model_iter_has_child (model, iter);
3218 specific_bug_549287 (void)
3220 /* Test case for GNOME Bugzilla bug 529287, provided by Julient Puydt */
3223 GtkTreeStore *store;
3224 GtkTreeModel *filtered;
3225 GtkWidget *view G_GNUC_UNUSED;
3227 GtkTreeIter *swap, *parent, *child;
3229 g_test_bug ("529287");
3231 store = gtk_tree_store_new (1, G_TYPE_STRING);
3232 filtered = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
3233 gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filtered),
3234 specific_bug_549287_visible_func,
3237 view = gtk_tree_view_new_with_model (filtered);
3239 for (i = 0; i < 4; i++)
3241 if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter))
3243 parent = gtk_tree_iter_copy (&iter);
3244 child = gtk_tree_iter_copy (&iter);
3246 while (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (store),
3255 gtk_tree_store_append (store, child, parent);
3256 gtk_tree_store_set (store, child,
3260 gtk_tree_iter_free (parent);
3261 gtk_tree_iter_free (child);
3265 gtk_tree_store_append (store, &iter, NULL);
3266 gtk_tree_store_set (store, &iter,
3271 /* since we inserted something, we changed the visibility conditions: */
3272 gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (filtered));
3277 specific_bug_621076_visible_func (GtkTreeModel *model,
3281 gboolean visible = FALSE;
3284 gtk_tree_model_get (model, iter, 0, &str, -1);
3285 if (str != NULL && g_str_has_prefix (str, "visible"))
3291 GtkTreeIter child_iter;
3294 /* Recursively check if we have a visible child */
3295 for (valid = gtk_tree_model_iter_children (model, &child_iter, iter);
3296 valid; valid = gtk_tree_model_iter_next (model, &child_iter))
3298 if (specific_bug_621076_visible_func (model, &child_iter, data))
3313 specific_bug_621076 (void)
3315 /* Test case for GNOME Bugzilla bug 621076, provided by Xavier Claessens */
3317 /* This test case differs from has-child-filter and root-has-child-filter
3318 * in that the visible function both filters on content and model
3319 * structure. Also, it is recursive.
3322 GtkTreeStore *store;
3323 GtkTreeModel *filter;
3325 GtkTreeIter group_iter;
3326 GtkTreeIter item_iter;
3327 SignalMonitor *monitor;
3329 g_test_bug ("621076");
3331 store = gtk_tree_store_new (1, G_TYPE_STRING);
3332 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
3333 gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
3334 specific_bug_621076_visible_func,
3337 view = gtk_tree_view_new_with_model (filter);
3338 g_object_ref_sink (view);
3340 monitor = signal_monitor_new (filter);
3342 signal_monitor_append_signal (monitor, ROW_INSERTED, "0");
3343 gtk_tree_store_insert_with_values (store, &item_iter, NULL, -1,
3344 0, "visible-group-0",
3346 signal_monitor_assert_is_empty (monitor);
3348 /* visible-group-0 is not expanded, so ROW_INSERTED should not be emitted
3349 * for its children. However, ROW_HAS_CHILD_TOGGLED should be emitted on
3350 * visible-group-0 to tell the view that row can be expanded. */
3351 signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "0");
3352 signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "0");
3353 group_iter = item_iter;
3354 gtk_tree_store_insert_with_values (store, &item_iter, &group_iter, -1,
3357 signal_monitor_assert_is_empty (monitor);
3359 signal_monitor_append_signal (monitor, ROW_INSERTED, "1");
3360 gtk_tree_store_insert_with_values (store, &item_iter, NULL, -1,
3361 0, "visible-group-1",
3363 signal_monitor_assert_is_empty (monitor);
3365 /* We are adding an hidden item inside visible-group-1, so
3366 * ROW_HAS_CHILD_TOGGLED should not be emitted. It is emitted though,
3367 * because the signal originating at TreeStore will be propagated,
3368 * as well a generated signal because the state of the parent *could*
3369 * change by a change in the model.
3371 signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "1");
3372 signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "1");
3373 group_iter = item_iter;
3374 gtk_tree_store_insert_with_values (store, &item_iter, &group_iter, -1,
3377 signal_monitor_assert_is_empty (monitor);
3379 /* This group is invisible and its parent too. Nothing should be emitted */
3380 group_iter = item_iter;
3381 gtk_tree_store_insert_with_values (store, &item_iter, &group_iter, -1,
3384 signal_monitor_assert_is_empty (monitor);
3386 /* Adding a visible item in this group hierarchy will make all nodes
3387 * in this path visible. The first level should simply tell the view
3388 * that it now has a child, and the view will load the tree if needed
3389 * (depends on the expanded state).
3391 signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "1");
3392 group_iter = item_iter;
3393 gtk_tree_store_insert_with_values (store, &item_iter, &group_iter, -1,
3394 0, "visible-1:0:0:0",
3396 signal_monitor_assert_is_empty (monitor);
3398 check_level_length (GTK_TREE_MODEL_FILTER (filter), "1", 1);
3400 gtk_tree_store_insert_with_values (store, &item_iter, NULL, -1,
3403 signal_monitor_assert_is_empty (monitor);
3405 /* Parent is invisible, and adding this invisible item won't change that,
3406 * so no signal should be emitted. */
3407 group_iter = item_iter;
3408 gtk_tree_store_insert_with_values (store, NULL, &group_iter, -1,
3411 signal_monitor_assert_is_empty (monitor);
3413 /* This makes group-2 visible, so it gets inserted and tells it has
3416 signal_monitor_append_signal (monitor, ROW_INSERTED, "2");
3417 signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "2");
3418 gtk_tree_store_insert_with_values (store, NULL, &group_iter, -1,
3421 signal_monitor_assert_is_empty (monitor);
3423 /* group-2 is already visible, so this time it is a normal insertion */
3424 signal_monitor_append_signal (monitor, ROW_INSERTED, "2:1");
3425 gtk_tree_store_insert_with_values (store, NULL, &group_iter, -1,
3428 signal_monitor_assert_is_empty (monitor);
3431 gtk_tree_store_insert_with_values (store, &item_iter, NULL, -1,
3434 signal_monitor_assert_is_empty (monitor);
3436 /* Parent is invisible, and adding this invisible item won't change that,
3437 * so no signal should be emitted. */
3438 group_iter = item_iter;
3439 gtk_tree_store_insert_with_values (store, NULL, &group_iter, -1,
3442 signal_monitor_assert_is_empty (monitor);
3444 gtk_tree_store_insert_with_values (store, &item_iter, &group_iter, -1,
3447 signal_monitor_assert_is_empty (monitor);
3449 /* This will make group 3 visible. */
3450 signal_monitor_append_signal (monitor, ROW_INSERTED, "3");
3451 signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "3");
3452 signal_monitor_append_signal (monitor, ROW_INSERTED, "3:0");
3453 signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "3");
3454 gtk_tree_store_set (store, &item_iter, 0, "visible-3:1", -1);
3455 signal_monitor_assert_is_empty (monitor);
3457 /* Make sure all groups are expanded, so the filter has the tree cached */
3458 gtk_tree_view_expand_all (GTK_TREE_VIEW (view));
3459 while (gtk_events_pending ())
3460 gtk_main_iteration ();
3462 /* Should only yield a row-changed */
3463 signal_monitor_append_signal (monitor, ROW_CHANGED, "3:0");
3464 gtk_tree_store_set (store, &item_iter, 0, "visible-3:1", -1);
3465 signal_monitor_assert_is_empty (monitor);
3467 /* Now remove/hide some items. If a group loses its last item, the group
3468 * should be deleted instead of the item.
3471 signal_monitor_append_signal (monitor, ROW_DELETED, "2:1");
3472 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (store), &item_iter, "2:2");
3473 gtk_tree_store_remove (store, &item_iter);
3474 signal_monitor_assert_is_empty (monitor);
3476 signal_monitor_append_signal (monitor, ROW_DELETED, "2:0");
3477 signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "2");
3478 signal_monitor_append_signal (monitor, ROW_DELETED, "2");
3479 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (store), &item_iter, "2:1");
3480 gtk_tree_store_set (store, &item_iter, 0, "invisible-2:1", -1);
3481 signal_monitor_assert_is_empty (monitor);
3483 signal_monitor_append_signal (monitor, ROW_DELETED, "1:0:0:0");
3484 signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "1:0:0");
3485 signal_monitor_append_signal (monitor, ROW_DELETED, "1:0");
3486 signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "1");
3487 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (store), &item_iter, "1:0:0:0");
3488 gtk_tree_store_remove (store, &item_iter);
3489 signal_monitor_assert_is_empty (monitor);
3491 /* Hide a group using row-changed instead of row-deleted */
3492 /* Caution: group 2 is gone, so offsets of the signals have moved. */
3493 signal_monitor_append_signal (monitor, ROW_DELETED, "2:0");
3494 signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "2");
3495 signal_monitor_append_signal (monitor, ROW_DELETED, "2");
3496 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (store), &item_iter,
3498 gtk_tree_store_set (store, &item_iter, 0, "invisible-3:1", -1);
3499 signal_monitor_assert_is_empty (monitor);
3504 GtkTreeViewColumn *col;
3506 gtk_tree_view_expand_all (GTK_TREE_VIEW (view));
3508 col = gtk_tree_view_column_new_with_attributes ("foo",
3509 gtk_cell_renderer_text_new (),
3511 gtk_tree_view_append_column (GTK_TREE_VIEW (view), col);
3513 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3514 g_signal_connect (window, "delete-event",
3515 G_CALLBACK (gtk_widget_destroy), NULL);
3516 g_signal_connect (window, "destroy",
3517 G_CALLBACK (gtk_main_quit), NULL);
3519 gtk_container_add (GTK_CONTAINER (window), view);
3521 gtk_widget_show (view);
3522 gtk_widget_show (window);
3529 signal_monitor_free (monitor);
3530 g_object_unref (view);
3531 g_object_unref (store);
3532 g_object_unref (filter);
3538 register_filter_model_tests (void)
3540 g_test_add ("/TreeModelFilter/self/verify-test-suite",
3544 filter_test_teardown);
3546 g_test_add ("/TreeModelFilter/self/verify-test-suite/vroot/depth-1",
3547 FilterTest, gtk_tree_path_new_from_indices (2, -1),
3549 verify_test_suite_vroot,
3550 filter_test_teardown);
3551 g_test_add ("/TreeModelFilter/self/verify-test-suite/vroot/depth-2",
3552 FilterTest, gtk_tree_path_new_from_indices (2, 3, -1),
3554 verify_test_suite_vroot,
3555 filter_test_teardown);
3558 g_test_add ("/TreeModelFilter/filled/hide-root-level",
3561 filled_hide_root_level,
3562 filter_test_teardown);
3563 g_test_add ("/TreeModelFilter/filled/hide-child-levels",
3566 filled_hide_child_levels,
3567 filter_test_teardown);
3569 g_test_add ("/TreeModelFilter/filled/hide-root-level/vroot",
3570 FilterTest, gtk_tree_path_new_from_indices (2, -1),
3572 filled_vroot_hide_root_level,
3573 filter_test_teardown);
3574 g_test_add ("/TreeModelFilter/filled/hide-child-levels/vroot",
3575 FilterTest, gtk_tree_path_new_from_indices (2, -1),
3577 filled_vroot_hide_child_levels,
3578 filter_test_teardown);
3581 g_test_add ("/TreeModelFilter/empty/show-nodes",
3583 filter_test_setup_empty,
3585 filter_test_teardown);
3586 g_test_add ("/TreeModelFilter/empty/show-multiple-nodes",
3588 filter_test_setup_empty,
3589 empty_show_multiple_nodes,
3590 filter_test_teardown);
3592 g_test_add ("/TreeModelFilter/empty/show-nodes/vroot",
3593 FilterTest, gtk_tree_path_new_from_indices (2, -1),
3594 filter_test_setup_empty,
3595 empty_vroot_show_nodes,
3596 filter_test_teardown);
3597 g_test_add ("/TreeModelFilter/empty/show-multiple-nodes/vroot",
3598 FilterTest, gtk_tree_path_new_from_indices (2, -1),
3599 filter_test_setup_empty,
3600 empty_vroot_show_multiple_nodes,
3601 filter_test_teardown);
3604 g_test_add ("/TreeModelFilter/unfiltered/hide-single",
3606 filter_test_setup_unfiltered,
3607 unfiltered_hide_single,
3608 filter_test_teardown);
3609 g_test_add ("/TreeModelFilter/unfiltered/hide-single-child",
3611 filter_test_setup_unfiltered,
3612 unfiltered_hide_single_child,
3613 filter_test_teardown);
3614 g_test_add ("/TreeModelFilter/unfiltered/hide-single-multi-level",
3616 filter_test_setup_unfiltered,
3617 unfiltered_hide_single_multi_level,
3618 filter_test_teardown);
3620 g_test_add ("/TreeModelFilter/unfiltered/hide-single/vroot",
3621 FilterTest, gtk_tree_path_new_from_indices (2, -1),
3622 filter_test_setup_unfiltered,
3623 unfiltered_vroot_hide_single,
3624 filter_test_teardown);
3625 g_test_add ("/TreeModelFilter/unfiltered/hide-single-child/vroot",
3626 FilterTest, gtk_tree_path_new_from_indices (2, -1),
3627 filter_test_setup_unfiltered,
3628 unfiltered_vroot_hide_single_child,
3629 filter_test_teardown);
3630 g_test_add ("/TreeModelFilter/unfiltered/hide-single-multi-level/vroot",
3631 FilterTest, gtk_tree_path_new_from_indices (2, -1),
3632 filter_test_setup_unfiltered,
3633 unfiltered_vroot_hide_single_multi_level,
3634 filter_test_teardown);
3638 g_test_add ("/TreeModelFilter/unfiltered/show-single",
3640 filter_test_setup_empty_unfiltered,
3641 unfiltered_show_single,
3642 filter_test_teardown);
3643 g_test_add ("/TreeModelFilter/unfiltered/show-single-child",
3645 filter_test_setup_empty_unfiltered,
3646 unfiltered_show_single_child,
3647 filter_test_teardown);
3648 g_test_add ("/TreeModelFilter/unfiltered/show-single-multi-level",
3650 filter_test_setup_empty_unfiltered,
3651 unfiltered_show_single_multi_level,
3652 filter_test_teardown);
3654 g_test_add ("/TreeModelFilter/unfiltered/show-single/vroot",
3655 FilterTest, gtk_tree_path_new_from_indices (2, -1),
3656 filter_test_setup_empty_unfiltered,
3657 unfiltered_vroot_show_single,
3658 filter_test_teardown);
3659 g_test_add ("/TreeModelFilter/unfiltered/show-single-child/vroot",
3660 FilterTest, gtk_tree_path_new_from_indices (2, -1),
3661 filter_test_setup_empty_unfiltered,
3662 unfiltered_vroot_show_single_child,
3663 filter_test_teardown);
3664 g_test_add ("/TreeModelFilter/unfiltered/show-single-multi-level/vroot",
3665 FilterTest, gtk_tree_path_new_from_indices (2, -1),
3666 filter_test_setup_empty_unfiltered,
3667 unfiltered_vroot_show_single_multi_level,
3668 filter_test_teardown);
3670 /* Inserts in child models after creation of filter model */
3671 g_test_add_func ("/TreeModelFilter/insert/before",
3673 g_test_add_func ("/TreeModelFilter/insert/child",
3676 /* Removals from child model after creating of filter model */
3677 g_test_add_func ("/TreeModelFilter/remove/node",
3679 g_test_add_func ("/TreeModelFilter/remove/node-vroot",
3681 g_test_add_func ("/TreeModelFilter/remove/vroot-ancestor",
3682 remove_vroot_ancestor);
3685 g_test_add_func ("/TreeModelFilter/specific/path-dependent-filter",
3686 specific_path_dependent_filter);
3687 g_test_add_func ("/TreeModelFilter/specific/append-after-collapse",
3688 specific_append_after_collapse);
3689 g_test_add_func ("/TreeModelFilter/specific/sort-filter-remove-node",
3690 specific_sort_filter_remove_node);
3691 g_test_add_func ("/TreeModelFilter/specific/sort-filter-remove-root",
3692 specific_sort_filter_remove_root);
3693 g_test_add_func ("/TreeModelFilter/specific/root-mixed-visibility",
3694 specific_root_mixed_visibility);
3695 g_test_add_func ("/TreeModelFilter/specific/has-child-filter",
3696 specific_has_child_filter);
3697 g_test_add_func ("/TreeModelFilter/specific/root-has-child-filter",
3698 specific_root_has_child_filter);
3699 g_test_add_func ("/TreeModelFilter/specific/filter-add-child",
3700 specific_filter_add_child);
3701 g_test_add_func ("/TreeModelFilter/specific/list-store-clear",
3702 specific_list_store_clear);
3703 g_test_add_func ("/TreeModelFilter/specific/sort-ref-leaf-and-remove-ancestor",
3704 specific_sort_ref_leaf_and_remove_ancestor);
3705 g_test_add_func ("/TreeModelFilter/specific/ref-leaf-and-remove-ancestor",
3706 specific_ref_leaf_and_remove_ancestor);
3707 g_test_add_func ("/TreeModelFilter/specific/virtual-ref-leaf-and-remove-ancestor",
3708 specific_virtual_ref_leaf_and_remove_ancestor);
3710 g_test_add_func ("/TreeModelFilter/specific/bug-301558",
3711 specific_bug_301558);
3712 g_test_add_func ("/TreeModelFilter/specific/bug-311955",
3713 specific_bug_311955);
3714 g_test_add_func ("/TreeModelFilter/specific/bug-346800",
3715 specific_bug_346800);
3716 g_test_add_func ("/TreeModelFilter/specific/bug-464173",
3717 specific_bug_464173);
3718 g_test_add_func ("/TreeModelFilter/specific/bug-540201",
3719 specific_bug_540201);
3720 g_test_add_func ("/TreeModelFilter/specific/bug-549287",
3721 specific_bug_549287);
3722 g_test_add_func ("/TreeModelFilter/specific/bug-621076",
3723 specific_bug_621076);