1/* Extensive GtkTreeModelFilter tests.
2 * Copyright (C) 2009,2011 Kristian Rietveld <kris@gtk.org>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include <gtk/gtk.h>
19#include <string.h>
20
21#include "treemodel.h"
22#include "gtktreemodelrefcount.h"
23
24/* Left to do:
25 * - Proper coverage checking to see if the unit tests cover
26 * all possible cases.
27 * - Check if the iterator stamp is incremented at the correct times.
28 *
29 * For more thorough testing:
30 * - Test with randomized models.
31 * - Extensively test a filter model wrapping a sort model,
32 * or a sort model wrapping a filter model by:
33 * # Checking structure.
34 * # Checking for correct signals emissions.
35 * # Checking correct reference counting.
36 * # Tests should be done with the sort and filter model
37 * in various filtering and sorting states.
38 */
39
40
41/*
42 * Model creation
43 */
44
45#define LEVEL_LENGTH 5
46
47static void
48create_tree_store_set_values (GtkTreeStore *store,
49 GtkTreeIter *iter,
50 gboolean visible)
51{
52 GtkTreePath *path;
53 char *path_string;
54
55 path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), iter);
56 path_string = gtk_tree_path_to_string (path);
57
58 gtk_tree_store_set (tree_store: store, iter,
59 0, path_string,
60 1, visible,
61 -1);
62
63 gtk_tree_path_free (path);
64 g_free (mem: path_string);
65}
66
67static void
68create_tree_store_recurse (int depth,
69 GtkTreeStore *store,
70 GtkTreeIter *parent,
71 gboolean visible)
72{
73 int i;
74
75 for (i = 0; i < LEVEL_LENGTH; i++)
76 {
77 GtkTreeIter iter;
78
79 gtk_tree_store_insert (tree_store: store, iter: &iter, parent, position: i);
80 create_tree_store_set_values (store, iter: &iter, visible);
81
82 if (depth > 0)
83 create_tree_store_recurse (depth: depth - 1, store, parent: &iter, visible);
84 }
85}
86
87static GtkTreeStore *
88create_tree_store (int depth,
89 gboolean visible)
90{
91 GtkTreeStore *store;
92
93 store = gtk_tree_store_new (n_columns: 2, G_TYPE_STRING, G_TYPE_BOOLEAN);
94
95 create_tree_store_recurse (depth, store, NULL, visible);
96
97 return store;
98}
99
100/*
101 * Fixture
102 */
103
104typedef struct
105{
106 GtkWidget *tree_view;
107
108 GtkTreeStore *store;
109 GtkTreeModelFilter *filter;
110
111 SignalMonitor *monitor;
112
113 guint block_signals : 1;
114} FilterTest;
115
116
117static void
118filter_test_store_signal (FilterTest *fixture)
119{
120 if (fixture->block_signals)
121 g_signal_stop_emission_by_name (instance: fixture->store, detailed_signal: "row-changed");
122}
123
124
125static void
126filter_test_setup_generic (FilterTest *fixture,
127 gconstpointer test_data,
128 int depth,
129 gboolean empty,
130 gboolean unfiltered)
131{
132 const GtkTreePath *vroot = test_data;
133 GtkTreeModel *filter;
134
135 fixture->store = create_tree_store (depth, visible: !empty);
136
137 g_signal_connect_swapped (fixture->store, "row-changed",
138 G_CALLBACK (filter_test_store_signal), fixture);
139
140 /* Please forgive me for casting const away. */
141 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (fixture->store),
142 root: (GtkTreePath *)vroot);
143 fixture->filter = GTK_TREE_MODEL_FILTER (filter);
144
145 if (!unfiltered)
146 gtk_tree_model_filter_set_visible_column (filter: fixture->filter, column: 1);
147
148 /* We need a tree view that's listening to get ref counting from that
149 * side.
150 */
151 fixture->tree_view = gtk_tree_view_new_with_model (model: filter);
152
153 fixture->monitor = signal_monitor_new (client: filter);
154}
155
156static void
157filter_test_setup_expand_root (FilterTest *fixture)
158{
159 int i;
160 GtkTreePath *path;
161
162 path = gtk_tree_path_new_from_indices (first_index: 0, -1);
163
164 for (i = 0; i < LEVEL_LENGTH; i++)
165 {
166 gtk_tree_view_expand_row (GTK_TREE_VIEW (fixture->tree_view),
167 path, FALSE);
168 gtk_tree_path_next (path);
169 }
170 gtk_tree_path_free (path);
171}
172
173static void
174filter_test_setup (FilterTest *fixture,
175 gconstpointer test_data)
176{
177 filter_test_setup_generic (fixture, test_data, depth: 3, FALSE, FALSE);
178}
179
180static void
181filter_test_setup_empty (FilterTest *fixture,
182 gconstpointer test_data)
183{
184 filter_test_setup_generic (fixture, test_data, depth: 3, TRUE, FALSE);
185}
186
187static void
188filter_test_setup_unfiltered (FilterTest *fixture,
189 gconstpointer test_data)
190{
191 filter_test_setup_generic (fixture, test_data, depth: 3, FALSE, TRUE);
192}
193
194static void
195filter_test_setup_unfiltered_root_expanded (FilterTest *fixture,
196 gconstpointer test_data)
197{
198 filter_test_setup_unfiltered (fixture, test_data);
199 filter_test_setup_expand_root (fixture);
200}
201
202static void
203filter_test_setup_empty_unfiltered (FilterTest *fixture,
204 gconstpointer test_data)
205{
206 filter_test_setup_generic (fixture, test_data, depth: 3, TRUE, TRUE);
207}
208
209static void
210filter_test_setup_empty_unfiltered_root_expanded (FilterTest *fixture,
211 gconstpointer test_data)
212{
213 filter_test_setup_empty_unfiltered (fixture, test_data);
214 filter_test_setup_expand_root (fixture);
215}
216
217static GtkTreePath *
218strip_virtual_root (GtkTreePath *path,
219 GtkTreePath *root_path)
220{
221 GtkTreePath *real_path;
222
223 if (root_path)
224 {
225 int j;
226 int depth = gtk_tree_path_get_depth (path);
227 int root_depth = gtk_tree_path_get_depth (path: root_path);
228
229 real_path = gtk_tree_path_new ();
230
231 for (j = 0; j < depth - root_depth; j++)
232 gtk_tree_path_append_index (path: real_path,
233 index_: gtk_tree_path_get_indices (path)[root_depth + j]);
234 }
235 else
236 real_path = gtk_tree_path_copy (path);
237
238 return real_path;
239}
240
241static int
242count_visible (FilterTest *fixture,
243 GtkTreePath *store_path)
244{
245 int i;
246 int n_visible = 0;
247 GtkTreeIter iter;
248
249 gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->store),
250 iter: &iter, path: store_path);
251
252 for (i = 0; i < LEVEL_LENGTH; i++)
253 {
254 gboolean visible;
255
256 gtk_tree_model_get (GTK_TREE_MODEL (fixture->store), iter: &iter,
257 1, &visible,
258 -1);
259
260 if (visible)
261 n_visible++;
262 }
263
264 return n_visible;
265}
266
267static void
268filter_test_append_refilter_signals_recurse (FilterTest *fixture,
269 GtkTreePath *store_path,
270 GtkTreePath *filter_path,
271 int depth,
272 GtkTreePath *root_path)
273{
274 int i;
275 int rows_deleted = 0;
276 GtkTreeIter iter;
277
278 gtk_tree_path_down (path: store_path);
279 gtk_tree_path_down (path: filter_path);
280
281 gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->store),
282 iter: &iter, path: store_path);
283
284 for (i = 0; i < LEVEL_LENGTH; i++)
285 {
286 gboolean visible;
287 GtkTreePath *real_path;
288
289 gtk_tree_model_get (GTK_TREE_MODEL (fixture->store), iter: &iter,
290 1, &visible,
291 -1);
292
293 if (root_path &&
294 (!gtk_tree_path_is_descendant (path: store_path, ancestor: root_path)
295 || !gtk_tree_path_compare (a: store_path, b: root_path)))
296 {
297 if (!gtk_tree_path_compare (a: store_path, b: root_path))
298 {
299 if (depth > 1
300 && gtk_tree_model_iter_has_child (GTK_TREE_MODEL (fixture->store),
301 iter: &iter))
302 {
303 GtkTreePath *store_copy;
304 GtkTreePath *filter_copy;
305
306 store_copy = gtk_tree_path_copy (path: store_path);
307 filter_copy = gtk_tree_path_copy (path: filter_path);
308 filter_test_append_refilter_signals_recurse (fixture,
309 store_path: store_copy,
310 filter_path: filter_copy,
311 depth: depth - 1,
312 root_path);
313 gtk_tree_path_free (path: store_copy);
314 gtk_tree_path_free (path: filter_copy);
315 }
316 }
317
318 gtk_tree_path_next (path: store_path);
319 gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), iter: &iter);
320
321 if (visible)
322 gtk_tree_path_next (path: filter_path);
323
324 continue;
325 }
326
327 real_path = strip_virtual_root (path: filter_path, root_path);
328
329 if (visible)
330 {
331 /* This row will be inserted */
332 signal_monitor_append_signal_path (m: fixture->monitor, signal: ROW_CHANGED,
333 path: real_path);
334
335 if (gtk_tree_model_iter_has_child (GTK_TREE_MODEL (fixture->store),
336 iter: &iter))
337 {
338 signal_monitor_append_signal_path (m: fixture->monitor,
339 signal: ROW_HAS_CHILD_TOGGLED,
340 path: real_path);
341
342 if (depth > 1)
343 {
344 GtkTreePath *store_copy;
345 GtkTreePath *filter_copy;
346
347 store_copy = gtk_tree_path_copy (path: store_path);
348 filter_copy = gtk_tree_path_copy (path: filter_path);
349 filter_test_append_refilter_signals_recurse (fixture,
350 store_path: store_copy,
351 filter_path: filter_copy,
352 depth: depth - 1,
353 root_path);
354 gtk_tree_path_free (path: store_copy);
355 gtk_tree_path_free (path: filter_copy);
356 }
357 else if (depth == 1)
358 {
359 GtkTreePath *tmp_path;
360
361 /* If all child rows are invisible, then the last row to
362 * become invisible will emit row-has-child-toggled on the
363 * parent.
364 */
365
366 tmp_path = gtk_tree_path_copy (path: store_path);
367 gtk_tree_path_append_index (path: tmp_path, index_: 0);
368
369 if (count_visible (fixture, store_path: tmp_path) == 0)
370 signal_monitor_append_signal_path (m: fixture->monitor,
371 signal: ROW_HAS_CHILD_TOGGLED,
372 path: real_path);
373
374 gtk_tree_path_free (path: tmp_path);
375 }
376 }
377
378 gtk_tree_path_next (path: filter_path);
379 }
380 else
381 {
382 /* This row will be deleted */
383 rows_deleted++;
384 signal_monitor_append_signal_path (m: fixture->monitor, signal: ROW_DELETED,
385 path: real_path);
386 }
387
388 gtk_tree_path_free (path: real_path);
389
390 gtk_tree_path_next (path: store_path);
391 gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), iter: &iter);
392 }
393
394 if (rows_deleted == LEVEL_LENGTH
395 && gtk_tree_path_get_depth (path: filter_path) > 1)
396 {
397 GtkTreePath *real_path;
398
399 gtk_tree_path_up (path: store_path);
400 gtk_tree_path_up (path: filter_path);
401
402 /* A row-has-child-toggled will be emitted on the parent */
403 if (!root_path
404 || (root_path
405 && gtk_tree_path_is_descendant (path: store_path, ancestor: root_path)
406 && gtk_tree_path_compare (a: store_path, b: root_path)))
407 {
408 real_path = strip_virtual_root (path: filter_path, root_path);
409 signal_monitor_append_signal_path (m: fixture->monitor,
410 signal: ROW_HAS_CHILD_TOGGLED,
411 path: real_path);
412
413 gtk_tree_path_free (path: real_path);
414 }
415 }
416}
417
418static void
419filter_test_append_refilter_signals (FilterTest *fixture,
420 int depth)
421{
422 /* A special function that walks the tree store like the
423 * model validation functions below.
424 */
425 GtkTreePath *path;
426 GtkTreePath *filter_path;
427
428 path = gtk_tree_path_new ();
429 filter_path = gtk_tree_path_new ();
430 filter_test_append_refilter_signals_recurse (fixture,
431 store_path: path,
432 filter_path,
433 depth,
434 NULL);
435 gtk_tree_path_free (path);
436 gtk_tree_path_free (path: filter_path);
437}
438
439static void
440filter_test_append_refilter_signals_with_vroot (FilterTest *fixture,
441 int depth,
442 GtkTreePath *root_path)
443{
444 /* A special function that walks the tree store like the
445 * model validation functions below.
446 */
447 GtkTreePath *path;
448 GtkTreePath *filter_path;
449
450 path = gtk_tree_path_new ();
451 filter_path = gtk_tree_path_new ();
452 filter_test_append_refilter_signals_recurse (fixture,
453 store_path: path,
454 filter_path,
455 depth,
456 root_path);
457 gtk_tree_path_free (path);
458 gtk_tree_path_free (path: filter_path);
459}
460
461static void
462filter_test_enable_filter (FilterTest *fixture)
463{
464 gtk_tree_model_filter_set_visible_column (filter: fixture->filter, column: 1);
465 gtk_tree_model_filter_refilter (filter: fixture->filter);
466}
467
468static void
469filter_test_block_signals (FilterTest *fixture)
470{
471 fixture->block_signals = TRUE;
472}
473
474static void
475filter_test_unblock_signals (FilterTest *fixture)
476{
477 fixture->block_signals = FALSE;
478}
479
480static void
481filter_test_teardown (FilterTest *fixture,
482 gconstpointer test_data)
483{
484 signal_monitor_free (m: fixture->monitor);
485
486 g_object_unref (g_object_ref_sink (fixture->tree_view));
487
488 g_object_unref (object: fixture->filter);
489 g_object_unref (object: fixture->store);
490}
491
492/*
493 * Model structure validation
494 */
495
496static void
497check_filter_model_recurse (FilterTest *fixture,
498 GtkTreePath *store_parent_path,
499 GtkTreePath *filter_parent_path)
500{
501 int i;
502 GtkTreeIter store_iter;
503 GtkTreeIter filter_iter;
504 gboolean store_has_next, filter_has_next;
505
506 gtk_tree_path_down (path: store_parent_path);
507 gtk_tree_path_down (path: filter_parent_path);
508
509 store_has_next = gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->store),
510 iter: &store_iter, path: store_parent_path);
511 filter_has_next = gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->filter),
512 iter: &filter_iter, path: filter_parent_path);
513
514 for (i = 0; i < LEVEL_LENGTH; i++)
515 {
516 gboolean visible;
517
518 g_assert_true (store_has_next);
519
520 gtk_tree_model_get (GTK_TREE_MODEL (fixture->store),
521 iter: &store_iter,
522 1, &visible,
523 -1);
524
525 if (visible)
526 {
527 GtkTreePath *tmp;
528 char *filter_str, *store_str;
529
530 g_assert_true (filter_has_next);
531
532 /* Verify path */
533 tmp = gtk_tree_model_get_path (GTK_TREE_MODEL (fixture->filter),
534 iter: &filter_iter);
535 g_assert_cmpint (gtk_tree_path_compare (tmp, filter_parent_path), ==, 0);
536
537 /* Verify model content */
538 gtk_tree_model_get (GTK_TREE_MODEL (fixture->store),
539 iter: &store_iter,
540 0, &store_str,
541 -1);
542 gtk_tree_model_get (GTK_TREE_MODEL (fixture->filter),
543 iter: &filter_iter,
544 0, &filter_str,
545 -1);
546
547 g_assert_cmpint (g_strcmp0 (store_str, filter_str), ==, 0);
548
549 g_free (mem: store_str);
550 g_free (mem: filter_str);
551
552 if (gtk_tree_model_iter_has_child (GTK_TREE_MODEL (fixture->filter),
553 iter: &filter_iter))
554 {
555 g_assert_true (gtk_tree_model_iter_has_child (GTK_TREE_MODEL (fixture->store), &store_iter));
556
557 check_filter_model_recurse (fixture,
558 store_parent_path: gtk_tree_path_copy (path: store_parent_path),
559 filter_parent_path: tmp);
560 }
561 else
562 /* Only when we do not recurse we need to free tmp */
563 gtk_tree_path_free (path: tmp);
564
565 gtk_tree_path_next (path: filter_parent_path);
566 filter_has_next = gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->filter), iter: &filter_iter);
567 }
568
569 gtk_tree_path_next (path: store_parent_path);
570 store_has_next = gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), iter: &store_iter);
571 }
572
573 /* Both models should have no more content! */
574 g_assert_false (store_has_next);
575 g_assert_false (filter_has_next);
576
577 gtk_tree_path_free (path: store_parent_path);
578 gtk_tree_path_free (path: filter_parent_path);
579}
580
581static void
582check_filter_model (FilterTest *fixture)
583{
584 GtkTreePath *path;
585
586 if (fixture->monitor)
587 signal_monitor_assert_is_empty (m: fixture->monitor);
588
589 path = gtk_tree_path_new ();
590
591 check_filter_model_recurse (fixture, store_parent_path: path, filter_parent_path: gtk_tree_path_copy (path));
592}
593
594static void
595check_filter_model_with_root (FilterTest *fixture,
596 GtkTreePath *path)
597{
598 if (fixture->monitor)
599 signal_monitor_assert_is_empty (m: fixture->monitor);
600
601 check_filter_model_recurse (fixture,
602 store_parent_path: gtk_tree_path_copy (path),
603 filter_parent_path: gtk_tree_path_new ());
604}
605
606/* Helpers */
607
608static void
609check_level_length (GtkTreeModelFilter *filter,
610 const char *level,
611 const int expected_length)
612{
613 if (!level)
614 {
615 int model_length;
616
617 model_length = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (filter), NULL);
618 g_assert_cmpint (model_length, ==, expected_length);
619 }
620 else
621 {
622 int model_length;
623 gboolean retrieved_iter = FALSE;
624 GtkTreeIter iter;
625
626 retrieved_iter = gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (filter),
627 iter: &iter, path_string: level);
628 g_assert_true (retrieved_iter);
629 model_length = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (filter), iter: &iter);
630 g_assert_cmpint (model_length, ==, expected_length);
631 }
632}
633
634static void
635set_path_visibility (FilterTest *fixture,
636 const char *path,
637 gboolean visible)
638{
639 GtkTreeIter store_iter;
640
641 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
642 iter: &store_iter, path_string: path);
643 gtk_tree_store_set (tree_store: fixture->store, iter: &store_iter,
644 1, visible,
645 -1);
646}
647
648#if 0
649static void
650insert_path_with_visibility (FilterTest *fixture,
651 const char *path_string,
652 gboolean visible)
653{
654 int position;
655 GtkTreePath *path;
656 GtkTreeIter parent, iter;
657
658 path = gtk_tree_path_new_from_string (path_string);
659 position = gtk_tree_path_get_indices (path)[gtk_tree_path_get_depth (path)];
660 gtk_tree_path_up (path);
661
662 if (gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->store), &parent, path))
663 {
664 gtk_tree_store_insert (fixture->store, &iter, &parent, position);
665 create_tree_store_set_values (fixture->store, &iter, visible);
666 }
667 gtk_tree_path_free (path);
668}
669#endif
670
671/*
672 * The actual tests.
673 */
674
675static void
676verify_test_suite (FilterTest *fixture,
677 gconstpointer user_data)
678{
679 check_filter_model (fixture);
680}
681
682static void
683verify_test_suite_vroot (FilterTest *fixture,
684 gconstpointer user_data)
685{
686 check_filter_model_with_root (fixture, path: (GtkTreePath *)user_data);
687}
688
689
690static void
691filled_hide_root_level (FilterTest *fixture,
692 gconstpointer user_data)
693{
694 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_DELETED, path_string: "2");
695 set_path_visibility (fixture, path: "2", FALSE);
696 check_filter_model (fixture);
697 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH - 1);
698
699 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_DELETED, path_string: "0");
700 set_path_visibility (fixture, path: "0", FALSE);
701 check_filter_model (fixture);
702 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH - 2);
703
704 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_DELETED, path_string: "2");
705 set_path_visibility (fixture, path: "4", FALSE);
706 check_filter_model (fixture);
707 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH - 3);
708
709
710 /* Hide remaining */
711 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_DELETED, path_string: "0");
712 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_DELETED, path_string: "0");
713
714 set_path_visibility (fixture, path: "1", FALSE);
715 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH - 4);
716
717 set_path_visibility (fixture, path: "3", FALSE);
718 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH - 5);
719
720 check_filter_model (fixture);
721
722 /* Show some */
723 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_INSERTED, path_string: "0");
724 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "0");
725 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_INSERTED, path_string: "1");
726 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "1");
727
728 set_path_visibility (fixture, path: "1", TRUE);
729 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH - 4);
730
731 set_path_visibility (fixture, path: "3", TRUE);
732 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH - 3);
733
734 check_filter_model (fixture);
735}
736
737static void
738filled_hide_child_levels (FilterTest *fixture,
739 gconstpointer user_data)
740{
741 set_path_visibility (fixture, path: "0:2", FALSE);
742 check_filter_model (fixture);
743 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
744 check_level_length (filter: fixture->filter, level: "0", LEVEL_LENGTH - 1);
745
746 set_path_visibility (fixture, path: "0:4", FALSE);
747 check_filter_model (fixture);
748 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
749 check_level_length (filter: fixture->filter, level: "0", LEVEL_LENGTH - 2);
750
751 set_path_visibility (fixture, path: "0:4:3", FALSE);
752 check_filter_model (fixture);
753 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
754 check_level_length (filter: fixture->filter, level: "0", LEVEL_LENGTH - 2);
755
756 set_path_visibility (fixture, path: "0:4:0", FALSE);
757 set_path_visibility (fixture, path: "0:4:1", FALSE);
758 set_path_visibility (fixture, path: "0:4:2", FALSE);
759 set_path_visibility (fixture, path: "0:4:4", FALSE);
760 check_filter_model (fixture);
761 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
762 check_level_length (filter: fixture->filter, level: "0", LEVEL_LENGTH - 2);
763
764 /* Since "0:2" is hidden, "0:4" must be "0:3" in the filter model */
765 set_path_visibility (fixture, path: "0:4", TRUE);
766 check_filter_model (fixture);
767 check_level_length (filter: fixture->filter, level: "0:3", expected_length: 0);
768
769 set_path_visibility (fixture, path: "0:2", TRUE);
770 check_filter_model (fixture);
771 check_level_length (filter: fixture->filter, level: "0:2", LEVEL_LENGTH);
772 check_level_length (filter: fixture->filter, level: "0:3", LEVEL_LENGTH);
773 check_level_length (filter: fixture->filter, level: "0:4", expected_length: 0);
774
775 /* Once 0:4:0 got inserted, 0:4 became a parent. Because 0:4 is
776 * not visible, not signals are emitted.
777 */
778 set_path_visibility (fixture, path: "0:4:2", TRUE);
779 set_path_visibility (fixture, path: "0:4:4", TRUE);
780 signal_monitor_assert_is_empty (m: fixture->monitor);
781 check_level_length (filter: fixture->filter, level: "0:4", expected_length: 2);
782}
783
784static void
785filled_hide_child_levels_root_expanded (FilterTest *fixture,
786 gconstpointer user_data)
787{
788 GtkTreePath *path;
789
790 path = gtk_tree_path_new_from_indices (first_index: 0, -1);
791 gtk_tree_view_expand_row (GTK_TREE_VIEW (fixture->tree_view), path, FALSE);
792 gtk_tree_path_free (path);
793
794 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_DELETED, path_string: "0:2");
795 set_path_visibility (fixture, path: "0:2", FALSE);
796 check_filter_model (fixture);
797 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
798 check_level_length (filter: fixture->filter, level: "0", LEVEL_LENGTH - 1);
799
800 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_DELETED, path_string: "0:3");
801 set_path_visibility (fixture, path: "0:4", FALSE);
802 check_filter_model (fixture);
803 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
804 check_level_length (filter: fixture->filter, level: "0", LEVEL_LENGTH - 2);
805
806 set_path_visibility (fixture, path: "0:4:3", FALSE);
807 check_filter_model (fixture);
808 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
809 check_level_length (filter: fixture->filter, level: "0", LEVEL_LENGTH - 2);
810
811 set_path_visibility (fixture, path: "0:4:0", FALSE);
812 set_path_visibility (fixture, path: "0:4:1", FALSE);
813 set_path_visibility (fixture, path: "0:4:2", FALSE);
814 set_path_visibility (fixture, path: "0:4:4", FALSE);
815 check_filter_model (fixture);
816 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
817 check_level_length (filter: fixture->filter, level: "0", LEVEL_LENGTH - 2);
818
819 /* Since "0:2" is hidden, "0:4" must be "0:3" in the filter model */
820 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_INSERTED, path_string: "0:3");
821 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "0:3");
822 set_path_visibility (fixture, path: "0:4", TRUE);
823 check_filter_model (fixture);
824 check_level_length (filter: fixture->filter, level: "0:3", expected_length: 0);
825
826 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_INSERTED, path_string: "0:2");
827 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "0:2");
828 set_path_visibility (fixture, path: "0:2", TRUE);
829 check_filter_model (fixture);
830 check_level_length (filter: fixture->filter, level: "0:2", LEVEL_LENGTH);
831 check_level_length (filter: fixture->filter, level: "0:3", LEVEL_LENGTH);
832 check_level_length (filter: fixture->filter, level: "0:4", expected_length: 0);
833
834 /* has-child-toggled for 0:4 is required. */
835 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "0:4");
836 set_path_visibility (fixture, path: "0:4:2", TRUE);
837 set_path_visibility (fixture, path: "0:4:4", TRUE);
838 signal_monitor_assert_is_empty (m: fixture->monitor);
839 check_level_length (filter: fixture->filter, level: "0:4", expected_length: 2);
840}
841
842
843static void
844filled_vroot_hide_root_level (FilterTest *fixture,
845 gconstpointer user_data)
846{
847 GtkTreePath *path = (GtkTreePath *)user_data;
848
849 /* These changes do not affect the filter's root level */
850 set_path_visibility (fixture, path: "0", FALSE);
851 check_filter_model_with_root (fixture, path);
852 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
853 check_level_length (filter: fixture->filter, level: "0", LEVEL_LENGTH);
854
855 set_path_visibility (fixture, path: "4", FALSE);
856 check_filter_model_with_root (fixture, path);
857 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
858 check_level_length (filter: fixture->filter, level: "0", LEVEL_LENGTH);
859
860 /* Even though we set the virtual root parent node to FALSE,
861 * the virtual root contents remain.
862 */
863 set_path_visibility (fixture, path: "2", FALSE);
864 check_filter_model_with_root (fixture, path);
865 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
866 check_level_length (filter: fixture->filter, level: "0", LEVEL_LENGTH);
867
868 /* No change */
869 set_path_visibility (fixture, path: "1", FALSE);
870 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
871 check_level_length (filter: fixture->filter, level: "0", LEVEL_LENGTH);
872
873 set_path_visibility (fixture, path: "3", FALSE);
874 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
875 check_level_length (filter: fixture->filter, level: "0", LEVEL_LENGTH);
876
877 check_filter_model_with_root (fixture, path);
878
879 /* Show some */
880 set_path_visibility (fixture, path: "2", TRUE);
881 check_filter_model_with_root (fixture, path);
882 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
883 check_level_length (filter: fixture->filter, level: "0", LEVEL_LENGTH);
884
885 set_path_visibility (fixture, path: "1", TRUE);
886 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
887 check_level_length (filter: fixture->filter, level: "0", LEVEL_LENGTH);
888
889 set_path_visibility (fixture, path: "3", TRUE);
890 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
891 check_level_length (filter: fixture->filter, level: "0", LEVEL_LENGTH);
892
893 check_filter_model_with_root (fixture, path);
894
895 /* Now test changes in the virtual root level */
896 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_DELETED, path_string: "2");
897 set_path_visibility (fixture, path: "2:2", FALSE);
898 check_filter_model_with_root (fixture, path);
899 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH - 1);
900
901 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_DELETED, path_string: "3");
902 set_path_visibility (fixture, path: "2:4", FALSE);
903 check_filter_model_with_root (fixture, path);
904 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH - 2);
905
906 set_path_visibility (fixture, path: "1:4", FALSE);
907 check_filter_model_with_root (fixture, path);
908 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH - 2);
909
910 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_INSERTED, path_string: "3");
911 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "3");
912 set_path_visibility (fixture, path: "2:4", TRUE);
913 check_filter_model_with_root (fixture, path);
914 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH - 1);
915
916 set_path_visibility (fixture, path: "2", FALSE);
917 check_filter_model_with_root (fixture, path);
918 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH - 1);
919
920 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_DELETED, path_string: "0");
921 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_DELETED, path_string: "0");
922 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_DELETED, path_string: "0");
923 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_DELETED, path_string: "0");
924 set_path_visibility (fixture, path: "2:0", FALSE);
925 set_path_visibility (fixture, path: "2:1", FALSE);
926 set_path_visibility (fixture, path: "2:2", FALSE);
927 set_path_visibility (fixture, path: "2:3", FALSE);
928 set_path_visibility (fixture, path: "2:4", FALSE);
929 check_filter_model_with_root (fixture, path);
930 check_level_length (filter: fixture->filter, NULL, expected_length: 0);
931
932 set_path_visibility (fixture, path: "2", TRUE);
933 check_filter_model_with_root (fixture, path);
934 check_level_length (filter: fixture->filter, NULL, expected_length: 0);
935
936 set_path_visibility (fixture, path: "1:4", FALSE);
937 check_filter_model_with_root (fixture, path);
938 check_level_length (filter: fixture->filter, NULL, expected_length: 0);
939
940 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_INSERTED, path_string: "0");
941 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "0");
942 set_path_visibility (fixture, path: "2:4", TRUE);
943 check_filter_model_with_root (fixture, path);
944 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH - 4);
945
946 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_DELETED, path_string: "0");
947 set_path_visibility (fixture, path: "2:4", FALSE);
948 check_filter_model_with_root (fixture, path);
949 check_level_length (filter: fixture->filter, NULL, expected_length: 0);
950
951 set_path_visibility (fixture, path: "2", FALSE);
952 check_filter_model_with_root (fixture, path);
953 check_level_length (filter: fixture->filter, NULL, expected_length: 0);
954
955 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_INSERTED, path_string: "0");
956 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "0");
957 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_INSERTED, path_string: "1");
958 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "1");
959 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_INSERTED, path_string: "2");
960 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "2");
961 set_path_visibility (fixture, path: "2:0", TRUE);
962 set_path_visibility (fixture, path: "2:1", TRUE);
963 set_path_visibility (fixture, path: "2:2", TRUE);
964 check_filter_model_with_root (fixture, path);
965 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH - 2);
966
967 set_path_visibility (fixture, path: "2", TRUE);
968 check_filter_model_with_root (fixture, path);
969 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH - 2);
970}
971
972static void
973filled_vroot_hide_child_levels (FilterTest *fixture,
974 gconstpointer user_data)
975{
976 GtkTreePath *path = (GtkTreePath *)user_data;
977
978 set_path_visibility (fixture, path: "2:0:2", FALSE);
979 check_filter_model_with_root (fixture, path);
980 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
981 check_level_length (filter: fixture->filter, level: "0", LEVEL_LENGTH - 1);
982
983 set_path_visibility (fixture, path: "2:0:4", FALSE);
984 check_filter_model_with_root (fixture, path);
985 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
986 check_level_length (filter: fixture->filter, level: "0", LEVEL_LENGTH - 2);
987
988 set_path_visibility (fixture, path: "2:0:4:3", FALSE);
989 check_filter_model_with_root (fixture, path);
990 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
991 check_level_length (filter: fixture->filter, level: "0", LEVEL_LENGTH - 2);
992
993 set_path_visibility (fixture, path: "2:0:4:0", FALSE);
994 set_path_visibility (fixture, path: "2:0:4:1", FALSE);
995 set_path_visibility (fixture, path: "2:0:4:2", FALSE);
996 set_path_visibility (fixture, path: "2:0:4:4", FALSE);
997 check_filter_model_with_root (fixture, path);
998 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
999 check_level_length (filter: fixture->filter, level: "0", LEVEL_LENGTH - 2);
1000
1001 /* Since "0:2" is hidden, "0:4" must be "0:3" in the filter model */
1002 set_path_visibility (fixture, path: "2:0:4", TRUE);
1003 check_filter_model_with_root (fixture, path);
1004 check_level_length (filter: fixture->filter, level: "0:3", expected_length: 0);
1005
1006 set_path_visibility (fixture, path: "2:0:2", TRUE);
1007 check_filter_model_with_root (fixture, path);
1008 check_level_length (filter: fixture->filter, level: "0:2", LEVEL_LENGTH);
1009 check_level_length (filter: fixture->filter, level: "0:3", LEVEL_LENGTH);
1010 check_level_length (filter: fixture->filter, level: "0:4", expected_length: 0);
1011
1012 /* Once 0:4:0 got inserted, 0:4 became a parent. However, 0:4 is not
1013 * visible, so no signal should be emitted.
1014 */
1015 set_path_visibility (fixture, path: "2:0:4:2", TRUE);
1016 set_path_visibility (fixture, path: "2:0:4:4", TRUE);
1017 check_level_length (filter: fixture->filter, level: "0:4", expected_length: 2);
1018 signal_monitor_assert_is_empty (m: fixture->monitor);
1019}
1020
1021static void
1022filled_vroot_hide_child_levels_root_expanded (FilterTest *fixture,
1023 gconstpointer user_data)
1024{
1025 GtkTreePath *path = (GtkTreePath *)user_data;
1026 GtkTreePath *tmp_path;
1027
1028 tmp_path = gtk_tree_path_new_from_indices (first_index: 0, -1);
1029 gtk_tree_view_expand_row (GTK_TREE_VIEW (fixture->tree_view), path: tmp_path, FALSE);
1030 gtk_tree_path_free (path: tmp_path);
1031
1032 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_DELETED, path_string: "0:2");
1033 set_path_visibility (fixture, path: "2:0:2", FALSE);
1034 check_filter_model_with_root (fixture, path);
1035 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
1036 check_level_length (filter: fixture->filter, level: "0", LEVEL_LENGTH - 1);
1037
1038 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_DELETED, path_string: "0:3");
1039 set_path_visibility (fixture, path: "2:0:4", FALSE);
1040 check_filter_model_with_root (fixture, path);
1041 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
1042 check_level_length (filter: fixture->filter, level: "0", LEVEL_LENGTH - 2);
1043
1044 set_path_visibility (fixture, path: "2:0:4:3", FALSE);
1045 check_filter_model_with_root (fixture, path);
1046 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
1047 check_level_length (filter: fixture->filter, level: "0", LEVEL_LENGTH - 2);
1048
1049 set_path_visibility (fixture, path: "2:0:4:0", FALSE);
1050 set_path_visibility (fixture, path: "2:0:4:1", FALSE);
1051 set_path_visibility (fixture, path: "2:0:4:2", FALSE);
1052 set_path_visibility (fixture, path: "2:0:4:4", FALSE);
1053 check_filter_model_with_root (fixture, path);
1054 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
1055 check_level_length (filter: fixture->filter, level: "0", LEVEL_LENGTH - 2);
1056
1057 /* Since "0:2" is hidden, "0:4" must be "0:3" in the filter model */
1058 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_INSERTED, path_string: "0:3");
1059 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "0:3");
1060 set_path_visibility (fixture, path: "2:0:4", TRUE);
1061 check_filter_model_with_root (fixture, path);
1062 check_level_length (filter: fixture->filter, level: "0:3", expected_length: 0);
1063
1064 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_INSERTED, path_string: "0:2");
1065 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "0:2");
1066 set_path_visibility (fixture, path: "2:0:2", TRUE);
1067 check_filter_model_with_root (fixture, path);
1068 check_level_length (filter: fixture->filter, level: "0:2", LEVEL_LENGTH);
1069 check_level_length (filter: fixture->filter, level: "0:3", LEVEL_LENGTH);
1070 check_level_length (filter: fixture->filter, level: "0:4", expected_length: 0);
1071
1072 /* Once 0:4:0 got inserted, 0:4 became a parent */
1073 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "0:4");
1074 set_path_visibility (fixture, path: "2:0:4:2", TRUE);
1075 set_path_visibility (fixture, path: "2:0:4:4", TRUE);
1076 check_level_length (filter: fixture->filter, level: "0:4", expected_length: 2);
1077 signal_monitor_assert_is_empty (m: fixture->monitor);
1078}
1079
1080static void
1081empty_show_nodes (FilterTest *fixture,
1082 gconstpointer user_data)
1083{
1084 check_filter_model (fixture);
1085 check_level_length (filter: fixture->filter, NULL, expected_length: 0);
1086
1087 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_INSERTED, path_string: "0");
1088 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "0");
1089 set_path_visibility (fixture, path: "3", TRUE);
1090 check_filter_model (fixture);
1091 check_level_length (filter: fixture->filter, NULL, expected_length: 1);
1092 check_level_length (filter: fixture->filter, level: "0", expected_length: 0);
1093
1094 set_path_visibility (fixture, path: "3:2:2", TRUE);
1095 check_filter_model (fixture);
1096 check_level_length (filter: fixture->filter, NULL, expected_length: 1);
1097 check_level_length (filter: fixture->filter, level: "0", expected_length: 0);
1098
1099 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "0");
1100 set_path_visibility (fixture, path: "3:2", TRUE);
1101 check_filter_model (fixture);
1102 check_level_length (filter: fixture->filter, NULL, expected_length: 1);
1103 check_level_length (filter: fixture->filter, level: "0", expected_length: 1);
1104 check_level_length (filter: fixture->filter, level: "0:0", expected_length: 1);
1105 check_level_length (filter: fixture->filter, level: "0:0:0", expected_length: 0);
1106
1107 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_DELETED, path_string: "0");
1108 set_path_visibility (fixture, path: "3", FALSE);
1109 check_filter_model (fixture);
1110 check_level_length (filter: fixture->filter, NULL, expected_length: 0);
1111
1112 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_INSERTED, path_string: "0");
1113 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "0");
1114 set_path_visibility (fixture, path: "3:2:1", TRUE);
1115 set_path_visibility (fixture, path: "3", TRUE);
1116 check_filter_model (fixture);
1117 check_level_length (filter: fixture->filter, NULL, expected_length: 1);
1118 check_level_length (filter: fixture->filter, level: "0", expected_length: 1);
1119 check_level_length (filter: fixture->filter, level: "0:0", expected_length: 2);
1120 check_level_length (filter: fixture->filter, level: "0:0:0", expected_length: 0);
1121}
1122
1123static void
1124empty_show_multiple_nodes (FilterTest *fixture,
1125 gconstpointer user_data)
1126{
1127 GtkTreeIter iter;
1128 GtkTreePath *changed_path;
1129
1130 check_filter_model (fixture);
1131 check_level_length (filter: fixture->filter, NULL, expected_length: 0);
1132
1133 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_INSERTED, path_string: "0");
1134 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "0");
1135 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_INSERTED, path_string: "1");
1136 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "1");
1137
1138 /* We simulate a change in visible func condition with this. The
1139 * visibility state of multiple nodes changes at once, we emit row-changed
1140 * for these nodes (and others) after that.
1141 */
1142 filter_test_block_signals (fixture);
1143 set_path_visibility (fixture, path: "3", TRUE);
1144 set_path_visibility (fixture, path: "4", TRUE);
1145 filter_test_unblock_signals (fixture);
1146
1147 changed_path = gtk_tree_path_new ();
1148 gtk_tree_path_append_index (path: changed_path, index_: 2);
1149 gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->store),
1150 iter: &iter, path: changed_path);
1151 /* Invisible node - so no signals expected */
1152 gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1153 path: changed_path, iter: &iter);
1154
1155 gtk_tree_path_next (path: changed_path);
1156 gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), iter: &iter);
1157 gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1158 path: changed_path, iter: &iter);
1159
1160 gtk_tree_path_next (path: changed_path);
1161 gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), iter: &iter);
1162 gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1163 path: changed_path, iter: &iter);
1164
1165 gtk_tree_path_free (path: changed_path);
1166
1167 check_filter_model (fixture);
1168 check_level_length (filter: fixture->filter, NULL, expected_length: 2);
1169 check_level_length (filter: fixture->filter, level: "0", expected_length: 0);
1170
1171 set_path_visibility (fixture, path: "3:2:2", TRUE);
1172 check_filter_model (fixture);
1173 check_level_length (filter: fixture->filter, NULL, expected_length: 2);
1174 check_level_length (filter: fixture->filter, level: "0", expected_length: 0);
1175
1176 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "0");
1177 set_path_visibility (fixture, path: "3:2", TRUE);
1178 check_filter_model (fixture);
1179 check_level_length (filter: fixture->filter, NULL, expected_length: 2);
1180 check_level_length (filter: fixture->filter, level: "0", expected_length: 1);
1181 check_level_length (filter: fixture->filter, level: "0:0", expected_length: 1);
1182 check_level_length (filter: fixture->filter, level: "0:0:0", expected_length: 0);
1183
1184 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_DELETED, path_string: "0");
1185 set_path_visibility (fixture, path: "3", FALSE);
1186 check_filter_model (fixture);
1187 check_level_length (filter: fixture->filter, NULL, expected_length: 1);
1188
1189 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_INSERTED, path_string: "0");
1190 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "0");
1191 set_path_visibility (fixture, path: "3:2:1", TRUE);
1192 set_path_visibility (fixture, path: "3", TRUE);
1193 check_filter_model (fixture);
1194 check_level_length (filter: fixture->filter, NULL, expected_length: 2);
1195 check_level_length (filter: fixture->filter, level: "0", expected_length: 1);
1196 check_level_length (filter: fixture->filter, level: "0:0", expected_length: 2);
1197 check_level_length (filter: fixture->filter, level: "0:0:0", expected_length: 0);
1198}
1199
1200static void
1201empty_vroot_show_nodes (FilterTest *fixture,
1202 gconstpointer user_data)
1203{
1204 GtkTreePath *path = (GtkTreePath *)user_data;
1205
1206 check_filter_model_with_root (fixture, path);
1207 check_level_length (filter: fixture->filter, NULL, expected_length: 0);
1208
1209 set_path_visibility (fixture, path: "2", TRUE);
1210 check_filter_model_with_root (fixture, path);
1211 check_level_length (filter: fixture->filter, NULL, expected_length: 0);
1212
1213 set_path_visibility (fixture, path: "2:2:2", TRUE);
1214 check_filter_model_with_root (fixture, path);
1215 check_level_length (filter: fixture->filter, NULL, expected_length: 0);
1216
1217 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_INSERTED, path_string: "0");
1218 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "0");
1219 set_path_visibility (fixture, path: "2:2", TRUE);
1220 check_filter_model_with_root (fixture, path);
1221 check_level_length (filter: fixture->filter, NULL, expected_length: 1);
1222 check_level_length (filter: fixture->filter, level: "0", expected_length: 1);
1223 check_level_length (filter: fixture->filter, level: "0:0", expected_length: 0);
1224
1225 set_path_visibility (fixture, path: "3", TRUE);
1226 check_filter_model_with_root (fixture, path);
1227 check_level_length (filter: fixture->filter, NULL, expected_length: 1);
1228
1229 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_DELETED, path_string: "0");
1230 set_path_visibility (fixture, path: "2:2", FALSE);
1231 check_filter_model_with_root (fixture, path);
1232 check_level_length (filter: fixture->filter, NULL, expected_length: 0);
1233
1234 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_INSERTED, path_string: "0");
1235 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "0");
1236 set_path_visibility (fixture, path: "2:2:1", TRUE);
1237 set_path_visibility (fixture, path: "2:2", TRUE);
1238 check_filter_model_with_root (fixture, path);
1239 check_level_length (filter: fixture->filter, NULL, expected_length: 1);
1240 check_level_length (filter: fixture->filter, level: "0", expected_length: 2);
1241 check_level_length (filter: fixture->filter, level: "0:1", expected_length: 0);
1242}
1243
1244static void
1245empty_vroot_show_multiple_nodes (FilterTest *fixture,
1246 gconstpointer user_data)
1247{
1248 GtkTreeIter iter;
1249 GtkTreePath *changed_path;
1250 GtkTreePath *path = (GtkTreePath *)user_data;
1251
1252 check_filter_model_with_root (fixture, path);
1253 check_level_length (filter: fixture->filter, NULL, expected_length: 0);
1254
1255 /* We simulate a change in visible func condition with this. The
1256 * visibility state of multiple nodes changes at once, we emit row-changed
1257 * for these nodes (and others) after that.
1258 */
1259 filter_test_block_signals (fixture);
1260 set_path_visibility (fixture, path: "2", TRUE);
1261 set_path_visibility (fixture, path: "3", TRUE);
1262 filter_test_unblock_signals (fixture);
1263
1264 changed_path = gtk_tree_path_new ();
1265 gtk_tree_path_append_index (path: changed_path, index_: 1);
1266 gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->store),
1267 iter: &iter, path: changed_path);
1268 gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1269 path: changed_path, iter: &iter);
1270
1271 gtk_tree_path_next (path: changed_path);
1272 gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), iter: &iter);
1273 gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1274 path: changed_path, iter: &iter);
1275
1276 gtk_tree_path_next (path: changed_path);
1277 gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), iter: &iter);
1278 gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1279 path: changed_path, iter: &iter);
1280
1281 gtk_tree_path_next (path: changed_path);
1282 gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), iter: &iter);
1283 gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1284 path: changed_path, iter: &iter);
1285
1286 gtk_tree_path_free (path: changed_path);
1287
1288 check_filter_model_with_root (fixture, path);
1289 check_level_length (filter: fixture->filter, NULL, expected_length: 0);
1290
1291 set_path_visibility (fixture, path: "2:2:2", TRUE);
1292 check_filter_model_with_root (fixture, path);
1293 check_level_length (filter: fixture->filter, NULL, expected_length: 0);
1294
1295 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_INSERTED, path_string: "0");
1296 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "0");
1297 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_INSERTED, path_string: "1");
1298 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "1");
1299
1300 /* Again, we simulate a call to refilter */
1301 filter_test_block_signals (fixture);
1302 set_path_visibility (fixture, path: "2:2", TRUE);
1303 set_path_visibility (fixture, path: "2:3", TRUE);
1304 filter_test_unblock_signals (fixture);
1305
1306 changed_path = gtk_tree_path_new ();
1307 gtk_tree_path_append_index (path: changed_path, index_: 2);
1308 gtk_tree_path_append_index (path: changed_path, index_: 1);
1309 gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->store),
1310 iter: &iter, path: changed_path);
1311 gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1312 path: changed_path, iter: &iter);
1313
1314 gtk_tree_path_next (path: changed_path);
1315 gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), iter: &iter);
1316 gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1317 path: changed_path, iter: &iter);
1318
1319 gtk_tree_path_next (path: changed_path);
1320 gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), iter: &iter);
1321 gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1322 path: changed_path, iter: &iter);
1323
1324 gtk_tree_path_next (path: changed_path);
1325 gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), iter: &iter);
1326 gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1327 path: changed_path, iter: &iter);
1328
1329 gtk_tree_path_free (path: changed_path);
1330
1331 check_filter_model_with_root (fixture, path);
1332 check_level_length (filter: fixture->filter, NULL, expected_length: 2);
1333 check_level_length (filter: fixture->filter, level: "0", expected_length: 1);
1334 check_level_length (filter: fixture->filter, level: "0:0", expected_length: 0);
1335
1336 set_path_visibility (fixture, path: "3", TRUE);
1337 check_filter_model_with_root (fixture, path);
1338 check_level_length (filter: fixture->filter, NULL, expected_length: 2);
1339
1340 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_DELETED, path_string: "0");
1341 set_path_visibility (fixture, path: "2:2", FALSE);
1342 check_filter_model_with_root (fixture, path);
1343 check_level_length (filter: fixture->filter, NULL, expected_length: 1);
1344
1345 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_INSERTED, path_string: "0");
1346 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "0");
1347 set_path_visibility (fixture, path: "2:2:1", TRUE);
1348 set_path_visibility (fixture, path: "2:2", TRUE);
1349 check_filter_model_with_root (fixture, path);
1350 check_level_length (filter: fixture->filter, NULL, expected_length: 2);
1351 check_level_length (filter: fixture->filter, level: "0", expected_length: 2);
1352 check_level_length (filter: fixture->filter, level: "0:1", expected_length: 0);
1353}
1354
1355
1356static void
1357unfiltered_hide_single (FilterTest *fixture,
1358 gconstpointer user_data)
1359
1360{
1361 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_CHANGED, path_string: "2");
1362 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "2");
1363 set_path_visibility (fixture, path: "2", FALSE);
1364
1365 signal_monitor_assert_is_empty (m: fixture->monitor);
1366 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
1367
1368 /* The view only shows the root level, so we only expect signals
1369 * for the root level.
1370 */
1371 filter_test_append_refilter_signals (fixture, depth: 1);
1372 filter_test_enable_filter (fixture);
1373
1374 check_filter_model (fixture);
1375 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH - 1);
1376}
1377
1378static void
1379unfiltered_hide_single_root_expanded (FilterTest *fixture,
1380 gconstpointer user_data)
1381
1382{
1383 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_CHANGED, path_string: "2");
1384 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "2");
1385 set_path_visibility (fixture, path: "2", FALSE);
1386
1387 signal_monitor_assert_is_empty (m: fixture->monitor);
1388 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
1389
1390 filter_test_append_refilter_signals (fixture, depth: 2);
1391 filter_test_enable_filter (fixture);
1392
1393 check_filter_model (fixture);
1394 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH - 1);
1395}
1396
1397static void
1398unfiltered_hide_single_child (FilterTest *fixture,
1399 gconstpointer user_data)
1400
1401{
1402 /* This row is not shown, so its signal is not propagated */
1403 set_path_visibility (fixture, path: "2:2", FALSE);
1404
1405 signal_monitor_assert_is_empty (m: fixture->monitor);
1406 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
1407 check_level_length (filter: fixture->filter, level: "2", LEVEL_LENGTH);
1408
1409 /* The view only shows the root level, so we only expect signals
1410 * for the root level.
1411 */
1412 filter_test_append_refilter_signals (fixture, depth: 0);
1413 filter_test_enable_filter (fixture);
1414
1415 check_filter_model (fixture);
1416 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
1417 check_level_length (filter: fixture->filter, level: "2", LEVEL_LENGTH - 1);
1418}
1419
1420static void
1421unfiltered_hide_single_child_root_expanded (FilterTest *fixture,
1422 gconstpointer user_data)
1423
1424{
1425 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_CHANGED, path_string: "2:2");
1426 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "2:2");
1427 set_path_visibility (fixture, path: "2:2", FALSE);
1428
1429 signal_monitor_assert_is_empty (m: fixture->monitor);
1430 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
1431 check_level_length (filter: fixture->filter, level: "2", LEVEL_LENGTH);
1432
1433 filter_test_append_refilter_signals (fixture, depth: 2);
1434 filter_test_enable_filter (fixture);
1435
1436 check_filter_model (fixture);
1437 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
1438 check_level_length (filter: fixture->filter, level: "2", LEVEL_LENGTH - 1);
1439}
1440
1441static void
1442unfiltered_hide_single_multi_level (FilterTest *fixture,
1443 gconstpointer user_data)
1444
1445{
1446 /* This row is not shown, so its signal is not propagated */
1447 set_path_visibility (fixture, path: "2:2:2", FALSE);
1448
1449 /* This row is not shown, so its signal is not propagated */
1450 set_path_visibility (fixture, path: "2:2", FALSE);
1451
1452 signal_monitor_assert_is_empty (m: fixture->monitor);
1453 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
1454 check_level_length (filter: fixture->filter, level: "2", LEVEL_LENGTH);
1455 check_level_length (filter: fixture->filter, level: "2:2", LEVEL_LENGTH);
1456
1457 /* The view only shows the root level, so we only expect signals
1458 * for the root level.
1459 */
1460 filter_test_append_refilter_signals (fixture, depth: 1);
1461 filter_test_enable_filter (fixture);
1462
1463 check_filter_model (fixture);
1464 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
1465 check_level_length (filter: fixture->filter, level: "2", LEVEL_LENGTH - 1);
1466
1467 set_path_visibility (fixture, path: "2:2", TRUE);
1468
1469 check_filter_model (fixture);
1470 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
1471 check_level_length (filter: fixture->filter, level: "2", LEVEL_LENGTH);
1472 check_level_length (filter: fixture->filter, level: "2:2", LEVEL_LENGTH - 1);
1473}
1474
1475static void
1476unfiltered_hide_single_multi_level_root_expanded (FilterTest *fixture,
1477 gconstpointer user_data)
1478
1479{
1480 /* This row is not shown, so its signal is not propagated */
1481 set_path_visibility (fixture, path: "2:2:2", FALSE);
1482
1483 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_CHANGED, path_string: "2:2");
1484 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "2:2");
1485 set_path_visibility (fixture, path: "2:2", FALSE);
1486
1487 signal_monitor_assert_is_empty (m: fixture->monitor);
1488 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
1489 check_level_length (filter: fixture->filter, level: "2", LEVEL_LENGTH);
1490 check_level_length (filter: fixture->filter, level: "2:2", LEVEL_LENGTH);
1491
1492 filter_test_append_refilter_signals (fixture, depth: 2);
1493 filter_test_enable_filter (fixture);
1494
1495 check_filter_model (fixture);
1496 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
1497 check_level_length (filter: fixture->filter, level: "2", LEVEL_LENGTH - 1);
1498
1499 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_INSERTED, path_string: "2:2");
1500 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "2:2");
1501 set_path_visibility (fixture, path: "2:2", TRUE);
1502
1503 check_filter_model (fixture);
1504 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
1505 check_level_length (filter: fixture->filter, level: "2", LEVEL_LENGTH);
1506 check_level_length (filter: fixture->filter, level: "2:2", LEVEL_LENGTH - 1);
1507}
1508
1509
1510
1511static void
1512unfiltered_vroot_hide_single (FilterTest *fixture,
1513 gconstpointer user_data)
1514
1515{
1516 GtkTreePath *path = (GtkTreePath *)user_data;
1517
1518 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_CHANGED, path_string: "2");
1519 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "2");
1520 set_path_visibility (fixture, path: "2:2", FALSE);
1521
1522 signal_monitor_assert_is_empty (m: fixture->monitor);
1523 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
1524
1525 /* The view only shows the root level, so we only expect signals
1526 * for the root level. (Though for the depth argument, we have to
1527 * take the virtual root into account).
1528 */
1529 filter_test_append_refilter_signals_with_vroot (fixture, depth: 2, root_path: path);
1530 filter_test_enable_filter (fixture);
1531
1532 check_filter_model_with_root (fixture, path);
1533 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH - 1);
1534}
1535
1536static void
1537unfiltered_vroot_hide_single_child (FilterTest *fixture,
1538 gconstpointer user_data)
1539
1540{
1541 GtkTreePath *path = (GtkTreePath *)user_data;
1542
1543 /* Not visible, so no signal will be received. */
1544 set_path_visibility (fixture, path: "2:2:2", FALSE);
1545
1546 signal_monitor_assert_is_empty (m: fixture->monitor);
1547 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
1548 check_level_length (filter: fixture->filter, level: "2", LEVEL_LENGTH);
1549
1550 /* The view only shows the root level, so we only expect signals
1551 * for the root level. (Though for the depth argument, we have to
1552 * take the virtual root into account).
1553 */
1554 filter_test_append_refilter_signals_with_vroot (fixture, depth: 2, root_path: path);
1555 filter_test_enable_filter (fixture);
1556
1557 check_filter_model_with_root (fixture, path);
1558 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
1559 check_level_length (filter: fixture->filter, level: "2", LEVEL_LENGTH - 1);
1560}
1561
1562static void
1563unfiltered_vroot_hide_single_child_root_expanded (FilterTest *fixture,
1564 gconstpointer user_data)
1565
1566{
1567 GtkTreePath *path = (GtkTreePath *)user_data;
1568
1569 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_CHANGED, path_string: "2:2");
1570 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "2:2");
1571 set_path_visibility (fixture, path: "2:2:2", FALSE);
1572
1573 signal_monitor_assert_is_empty (m: fixture->monitor);
1574 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
1575 check_level_length (filter: fixture->filter, level: "2", LEVEL_LENGTH);
1576
1577 filter_test_append_refilter_signals_with_vroot (fixture, depth: 3, root_path: path);
1578 filter_test_enable_filter (fixture);
1579
1580 check_filter_model_with_root (fixture, path);
1581 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
1582 check_level_length (filter: fixture->filter, level: "2", LEVEL_LENGTH - 1);
1583}
1584
1585static void
1586unfiltered_vroot_hide_single_multi_level (FilterTest *fixture,
1587 gconstpointer user_data)
1588
1589{
1590 GtkTreePath *path = (GtkTreePath *)user_data;
1591
1592 /* This row is not shown, so its signal is not propagated */
1593 set_path_visibility (fixture, path: "2:2:2:2", FALSE);
1594
1595 /* Not shown, so no signal */
1596 set_path_visibility (fixture, path: "2:2:2", FALSE);
1597
1598 signal_monitor_assert_is_empty (m: fixture->monitor);
1599 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
1600 check_level_length (filter: fixture->filter, level: "2", LEVEL_LENGTH);
1601 check_level_length (filter: fixture->filter, level: "2:2", LEVEL_LENGTH);
1602
1603 /* We only expect signals for the root level. The depth is 2
1604 * because we have to take the virtual root into account.
1605 */
1606 filter_test_append_refilter_signals_with_vroot (fixture, depth: 2, root_path: path);
1607 filter_test_enable_filter (fixture);
1608
1609 check_filter_model_with_root (fixture, path);
1610 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
1611 check_level_length (filter: fixture->filter, level: "2", LEVEL_LENGTH - 1);
1612
1613 /* Not shown, so no signal */
1614 set_path_visibility (fixture, path: "2:2:2", TRUE);
1615
1616 check_filter_model_with_root (fixture, path);
1617 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
1618 check_level_length (filter: fixture->filter, level: "2", LEVEL_LENGTH);
1619 check_level_length (filter: fixture->filter, level: "2:2", LEVEL_LENGTH - 1);
1620}
1621
1622static void
1623unfiltered_vroot_hide_single_multi_level_root_expanded (FilterTest *fixture,
1624 gconstpointer user_data)
1625
1626{
1627 GtkTreePath *path = (GtkTreePath *)user_data;
1628
1629 /* This row is not shown, so its signal is not propagated */
1630 set_path_visibility (fixture, path: "2:2:2:2", FALSE);
1631
1632 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_CHANGED, path_string: "2:2");
1633 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "2:2");
1634 set_path_visibility (fixture, path: "2:2:2", FALSE);
1635
1636 signal_monitor_assert_is_empty (m: fixture->monitor);
1637 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
1638 check_level_length (filter: fixture->filter, level: "2", LEVEL_LENGTH);
1639 check_level_length (filter: fixture->filter, level: "2:2", LEVEL_LENGTH);
1640
1641 filter_test_append_refilter_signals_with_vroot (fixture, depth: 3, root_path: path);
1642 filter_test_enable_filter (fixture);
1643
1644 check_filter_model_with_root (fixture, path);
1645 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
1646 check_level_length (filter: fixture->filter, level: "2", LEVEL_LENGTH - 1);
1647
1648 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_INSERTED, path_string: "2:2");
1649 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "2:2");
1650 set_path_visibility (fixture, path: "2:2:2", TRUE);
1651
1652 check_filter_model_with_root (fixture, path);
1653 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
1654 check_level_length (filter: fixture->filter, level: "2", LEVEL_LENGTH);
1655 check_level_length (filter: fixture->filter, level: "2:2", LEVEL_LENGTH - 1);
1656}
1657
1658static void
1659unfiltered_show_single (FilterTest *fixture,
1660 gconstpointer user_data)
1661
1662{
1663 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_CHANGED, path_string: "2");
1664 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "2");
1665 set_path_visibility (fixture, path: "2", TRUE);
1666
1667 signal_monitor_assert_is_empty (m: fixture->monitor);
1668 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
1669
1670 /* We only expect signals for the root level */
1671 filter_test_append_refilter_signals (fixture, depth: 1);
1672 filter_test_enable_filter (fixture);
1673
1674 check_filter_model (fixture);
1675 check_level_length (filter: fixture->filter, NULL, expected_length: 1);
1676}
1677
1678static void
1679unfiltered_show_single_child (FilterTest *fixture,
1680 gconstpointer user_data)
1681
1682{
1683 set_path_visibility (fixture, path: "2:2", TRUE);
1684
1685 signal_monitor_assert_is_empty (m: fixture->monitor);
1686 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
1687 check_level_length (filter: fixture->filter, level: "2", LEVEL_LENGTH);
1688
1689 /* We only expect signals for the root level */
1690 filter_test_append_refilter_signals (fixture, depth: 1);
1691 filter_test_enable_filter (fixture);
1692
1693 check_filter_model (fixture);
1694 check_level_length (filter: fixture->filter, NULL, expected_length: 0);
1695
1696 /* From here we are filtered, "2" in the real model is "0" in the filter
1697 * model.
1698 */
1699 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_INSERTED, path_string: "0");
1700 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "0");
1701 set_path_visibility (fixture, path: "2", TRUE);
1702 signal_monitor_assert_is_empty (m: fixture->monitor);
1703 check_level_length (filter: fixture->filter, NULL, expected_length: 1);
1704 check_level_length (filter: fixture->filter, level: "0", expected_length: 1);
1705}
1706
1707static void
1708unfiltered_show_single_child_root_expanded (FilterTest *fixture,
1709 gconstpointer user_data)
1710
1711{
1712 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_CHANGED, path_string: "2:2");
1713 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "2:2");
1714 set_path_visibility (fixture, path: "2:2", TRUE);
1715
1716 signal_monitor_assert_is_empty (m: fixture->monitor);
1717 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
1718 check_level_length (filter: fixture->filter, level: "2", LEVEL_LENGTH);
1719
1720 filter_test_append_refilter_signals (fixture, depth: 2);
1721 filter_test_enable_filter (fixture);
1722
1723 check_filter_model (fixture);
1724 check_level_length (filter: fixture->filter, NULL, expected_length: 0);
1725
1726 /* From here we are filtered, "2" in the real model is "0" in the filter
1727 * model.
1728 */
1729 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_INSERTED, path_string: "0");
1730 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "0");
1731 set_path_visibility (fixture, path: "2", TRUE);
1732 signal_monitor_assert_is_empty (m: fixture->monitor);
1733 check_level_length (filter: fixture->filter, NULL, expected_length: 1);
1734 check_level_length (filter: fixture->filter, level: "0", expected_length: 1);
1735}
1736
1737static void
1738unfiltered_show_single_multi_level (FilterTest *fixture,
1739 gconstpointer user_data)
1740
1741{
1742 /* The view is not showing these rows (collapsed state), so it is not
1743 * referenced. The signal should not go through.
1744 */
1745 set_path_visibility (fixture, path: "2:2:2", TRUE);
1746 set_path_visibility (fixture, path: "2:2", TRUE);
1747
1748 signal_monitor_assert_is_empty (m: fixture->monitor);
1749 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
1750 check_level_length (filter: fixture->filter, level: "2", LEVEL_LENGTH);
1751 check_level_length (filter: fixture->filter, level: "2:2", LEVEL_LENGTH);
1752
1753 /* We only expect signals for the first level */
1754 filter_test_append_refilter_signals (fixture, depth: 1);
1755 filter_test_enable_filter (fixture);
1756
1757 check_filter_model (fixture);
1758 check_level_length (filter: fixture->filter, NULL, expected_length: 0);
1759
1760 /* From here we are filtered, "2" in the real model is "0" in the filter
1761 * model.
1762 */
1763 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_INSERTED, path_string: "0");
1764 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "0");
1765 set_path_visibility (fixture, path: "2", TRUE);
1766 check_filter_model (fixture);
1767 check_level_length (filter: fixture->filter, NULL, expected_length: 1);
1768 check_level_length (filter: fixture->filter, level: "0", expected_length: 1);
1769 check_level_length (filter: fixture->filter, level: "0:0", expected_length: 1);
1770}
1771
1772static void
1773unfiltered_show_single_multi_level_root_expanded (FilterTest *fixture,
1774 gconstpointer user_data)
1775
1776{
1777 /* The view is not showing this row (collapsed state), so it is not
1778 * referenced. The signal should not go through.
1779 */
1780 set_path_visibility (fixture, path: "2:2:2", TRUE);
1781
1782 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_CHANGED, path_string: "2:2");
1783 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "2:2");
1784 set_path_visibility (fixture, path: "2:2", TRUE);
1785
1786 signal_monitor_assert_is_empty (m: fixture->monitor);
1787 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
1788 check_level_length (filter: fixture->filter, level: "2", LEVEL_LENGTH);
1789 check_level_length (filter: fixture->filter, level: "2:2", LEVEL_LENGTH);
1790
1791 filter_test_append_refilter_signals (fixture, depth: 2);
1792 filter_test_enable_filter (fixture);
1793
1794 check_filter_model (fixture);
1795 check_level_length (filter: fixture->filter, NULL, expected_length: 0);
1796
1797 /* From here we are filtered, "2" in the real model is "0" in the filter
1798 * model.
1799 */
1800 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_INSERTED, path_string: "0");
1801 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "0");
1802 set_path_visibility (fixture, path: "2", TRUE);
1803 check_filter_model (fixture);
1804 check_level_length (filter: fixture->filter, NULL, expected_length: 1);
1805 check_level_length (filter: fixture->filter, level: "0", expected_length: 1);
1806 check_level_length (filter: fixture->filter, level: "0:0", expected_length: 1);
1807}
1808
1809static void
1810unfiltered_vroot_show_single (FilterTest *fixture,
1811 gconstpointer user_data)
1812
1813{
1814 GtkTreePath *path = (GtkTreePath *)user_data;
1815
1816 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_CHANGED, path_string: "2");
1817 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "2");
1818 set_path_visibility (fixture, path: "2:2", TRUE);
1819
1820 signal_monitor_assert_is_empty (m: fixture->monitor);
1821 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
1822
1823 /* The view only shows the root level, so the filter model only has
1824 * the first two levels cached.
1825 */
1826 filter_test_append_refilter_signals_with_vroot (fixture, depth: 2, root_path: path);
1827 filter_test_enable_filter (fixture);
1828
1829 check_filter_model_with_root (fixture, path);
1830 check_level_length (filter: fixture->filter, NULL, expected_length: 1);
1831}
1832
1833static void
1834unfiltered_vroot_show_single_child (FilterTest *fixture,
1835 gconstpointer user_data)
1836
1837{
1838 GtkTreePath *path = (GtkTreePath *)user_data;
1839
1840 set_path_visibility (fixture, path: "2:2:2", TRUE);
1841
1842 signal_monitor_assert_is_empty (m: fixture->monitor);
1843 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
1844 check_level_length (filter: fixture->filter, level: "2", LEVEL_LENGTH);
1845
1846 /* The view only shows the root level, so the filter model only has
1847 * the first two levels cached.
1848 */
1849 filter_test_append_refilter_signals_with_vroot (fixture, depth: 2, root_path: path);
1850 filter_test_enable_filter (fixture);
1851
1852 check_filter_model_with_root (fixture, path);
1853 check_level_length (filter: fixture->filter, NULL, expected_length: 0);
1854
1855 /* From here we are filtered, "2" in the real model is "0" in the filter
1856 * model.
1857 */
1858 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_INSERTED, path_string: "0");
1859 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "0");
1860 set_path_visibility (fixture, path: "2:2", TRUE);
1861 signal_monitor_assert_is_empty (m: fixture->monitor);
1862 check_level_length (filter: fixture->filter, NULL, expected_length: 1);
1863 check_level_length (filter: fixture->filter, level: "0", expected_length: 1);
1864}
1865
1866static void
1867unfiltered_vroot_show_single_child_root_expanded (FilterTest *fixture,
1868 gconstpointer user_data)
1869
1870{
1871 GtkTreePath *path = (GtkTreePath *)user_data;
1872
1873 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_CHANGED, path_string: "2:2");
1874 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "2:2");
1875 set_path_visibility (fixture, path: "2:2:2", TRUE);
1876
1877 signal_monitor_assert_is_empty (m: fixture->monitor);
1878 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
1879 check_level_length (filter: fixture->filter, level: "2", LEVEL_LENGTH);
1880
1881 filter_test_append_refilter_signals_with_vroot (fixture, depth: 3, root_path: path);
1882 filter_test_enable_filter (fixture);
1883
1884 check_filter_model_with_root (fixture, path);
1885 check_level_length (filter: fixture->filter, NULL, expected_length: 0);
1886
1887 /* From here we are filtered, "2" in the real model is "0" in the filter
1888 * model.
1889 */
1890 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_INSERTED, path_string: "0");
1891 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "0");
1892 set_path_visibility (fixture, path: "2:2", TRUE);
1893 signal_monitor_assert_is_empty (m: fixture->monitor);
1894 check_level_length (filter: fixture->filter, NULL, expected_length: 1);
1895 check_level_length (filter: fixture->filter, level: "0", expected_length: 1);
1896}
1897
1898
1899static void
1900unfiltered_vroot_show_single_multi_level (FilterTest *fixture,
1901 gconstpointer user_data)
1902
1903{
1904 GtkTreePath *path = (GtkTreePath *)user_data;
1905
1906 /* The view is not showing this row (collapsed state), so it is not
1907 * referenced. The signal should not go through.
1908 */
1909 set_path_visibility (fixture, path: "2:2:2:2", TRUE);
1910
1911 set_path_visibility (fixture, path: "2:2:2", TRUE);
1912
1913 signal_monitor_assert_is_empty (m: fixture->monitor);
1914 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
1915 check_level_length (filter: fixture->filter, level: "2", LEVEL_LENGTH);
1916 check_level_length (filter: fixture->filter, level: "2:2", LEVEL_LENGTH);
1917
1918 /* We only expect signals for the root level */
1919 filter_test_append_refilter_signals_with_vroot (fixture, depth: 2, root_path: path);
1920 filter_test_enable_filter (fixture);
1921
1922 check_filter_model_with_root (fixture, path);
1923 check_level_length (filter: fixture->filter, NULL, expected_length: 0);
1924
1925 /* From here we are filtered, "2" in the real model is "0" in the filter
1926 * model.
1927 */
1928 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_INSERTED, path_string: "0");
1929 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "0");
1930 set_path_visibility (fixture, path: "2:2", TRUE);
1931 check_filter_model_with_root (fixture, path);
1932 check_level_length (filter: fixture->filter, NULL, expected_length: 1);
1933 check_level_length (filter: fixture->filter, level: "0", expected_length: 1);
1934 check_level_length (filter: fixture->filter, level: "0:0", expected_length: 1);
1935}
1936
1937static void
1938unfiltered_vroot_show_single_multi_level_root_expanded (FilterTest *fixture,
1939 gconstpointer user_data)
1940
1941{
1942 GtkTreePath *path = (GtkTreePath *)user_data;
1943
1944 /* The view is not showing this row (collapsed state), so it is not
1945 * referenced. The signal should not go through.
1946 */
1947 set_path_visibility (fixture, path: "2:2:2:2", TRUE);
1948
1949 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_CHANGED, path_string: "2:2");
1950 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "2:2");
1951 set_path_visibility (fixture, path: "2:2:2", TRUE);
1952
1953 signal_monitor_assert_is_empty (m: fixture->monitor);
1954 check_level_length (filter: fixture->filter, NULL, LEVEL_LENGTH);
1955 check_level_length (filter: fixture->filter, level: "2", LEVEL_LENGTH);
1956 check_level_length (filter: fixture->filter, level: "2:2", LEVEL_LENGTH);
1957
1958 filter_test_append_refilter_signals_with_vroot (fixture, depth: 3, root_path: path);
1959 filter_test_enable_filter (fixture);
1960
1961 check_filter_model_with_root (fixture, path);
1962 check_level_length (filter: fixture->filter, NULL, expected_length: 0);
1963
1964 /* From here we are filtered, "2" in the real model is "0" in the filter
1965 * model.
1966 */
1967 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_INSERTED, path_string: "0");
1968 signal_monitor_append_signal (m: fixture->monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "0");
1969 set_path_visibility (fixture, path: "2:2", TRUE);
1970 check_filter_model_with_root (fixture, path);
1971 check_level_length (filter: fixture->filter, NULL, expected_length: 1);
1972 check_level_length (filter: fixture->filter, level: "0", expected_length: 1);
1973 check_level_length (filter: fixture->filter, level: "0:0", expected_length: 1);
1974}
1975
1976static void
1977unfiltered_rows_reordered_root_level (FilterTest *fixture,
1978 gconstpointer user_data)
1979{
1980 int order0[] = { 1, 2, 3, 4, 0 };
1981 int order1[] = { 0, 2, 1, 3, 4 };
1982 int order2[] = { 4, 0, 1, 2, 3 };
1983 GtkTreeIter iter0, iter1, iter2, iter3, iter4;
1984 GtkTreePath *path;
1985
1986 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
1987 iter: &iter0, path_string: "0");
1988 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
1989 iter: &iter1, path_string: "1");
1990 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
1991 iter: &iter2, path_string: "2");
1992 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
1993 iter: &iter3, path_string: "3");
1994 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
1995 iter: &iter4, path_string: "4");
1996
1997 path = gtk_tree_path_new ();
1998 signal_monitor_append_signal_reordered (m: fixture->monitor,
1999 signal: ROWS_REORDERED,
2000 path, new_order: order0, len: 5);
2001 gtk_tree_store_move_after (tree_store: fixture->store, iter: &iter0, position: &iter4);
2002 signal_monitor_assert_is_empty (m: fixture->monitor);
2003
2004 signal_monitor_append_signal_reordered (m: fixture->monitor,
2005 signal: ROWS_REORDERED,
2006 path, new_order: order1, len: 5);
2007 gtk_tree_store_move_after (tree_store: fixture->store, iter: &iter2, position: &iter3);
2008 signal_monitor_assert_is_empty (m: fixture->monitor);
2009
2010 signal_monitor_append_signal_reordered (m: fixture->monitor,
2011 signal: ROWS_REORDERED,
2012 path, new_order: order2, len: 5);
2013 gtk_tree_store_move_before (tree_store: fixture->store, iter: &iter0, position: &iter1);
2014 signal_monitor_assert_is_empty (m: fixture->monitor);
2015
2016 gtk_tree_path_free (path);
2017}
2018
2019static void
2020unfiltered_rows_reordered_child_level (FilterTest *fixture,
2021 gconstpointer user_data)
2022{
2023 int order0[] = { 1, 2, 3, 4, 0 };
2024 int order1[] = { 0, 2, 1, 3, 4 };
2025 int order2[] = { 4, 0, 1, 2, 3 };
2026 GtkTreeIter iter0, iter1, iter2, iter3, iter4;
2027 GtkTreePath *path;
2028
2029 /* Expand row 0 */
2030 path = gtk_tree_path_new_from_indices (first_index: 0, -1);
2031 gtk_tree_view_expand_row (GTK_TREE_VIEW (fixture->tree_view), path, FALSE);
2032
2033 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2034 iter: &iter0, path_string: "0:0");
2035 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2036 iter: &iter1, path_string: "0:1");
2037 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2038 iter: &iter2, path_string: "0:2");
2039 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2040 iter: &iter3, path_string: "0:3");
2041 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2042 iter: &iter4, path_string: "0:4");
2043
2044 signal_monitor_append_signal_reordered (m: fixture->monitor,
2045 signal: ROWS_REORDERED,
2046 path, new_order: order0, len: 5);
2047 gtk_tree_store_move_after (tree_store: fixture->store, iter: &iter0, position: &iter4);
2048 signal_monitor_assert_is_empty (m: fixture->monitor);
2049
2050 signal_monitor_append_signal_reordered (m: fixture->monitor,
2051 signal: ROWS_REORDERED,
2052 path, new_order: order1, len: 5);
2053 gtk_tree_store_move_after (tree_store: fixture->store, iter: &iter2, position: &iter3);
2054 signal_monitor_assert_is_empty (m: fixture->monitor);
2055
2056 signal_monitor_append_signal_reordered (m: fixture->monitor,
2057 signal: ROWS_REORDERED,
2058 path, new_order: order2, len: 5);
2059 gtk_tree_store_move_before (tree_store: fixture->store, iter: &iter0, position: &iter1);
2060 signal_monitor_assert_is_empty (m: fixture->monitor);
2061
2062 gtk_tree_path_free (path);
2063}
2064
2065static void
2066filtered_rows_reordered_root_level_first_hidden (FilterTest *fixture,
2067 gconstpointer user_data)
2068{
2069 int order0[] = { 1, 2, 3, 0 };
2070 int order1[] = { 0, 2, 1, 3 };
2071 int order2[] = { 3, 0, 1, 2 };
2072 GtkTreeIter iter1, iter2, iter3, iter4;
2073 GtkTreePath *path;
2074
2075 /* Hide middle path */
2076 signal_monitor_append_signal (m: fixture->monitor,
2077 signal: ROW_DELETED, path_string: "0");
2078 set_path_visibility (fixture, path: "0", FALSE);
2079 signal_monitor_assert_is_empty (m: fixture->monitor);
2080
2081 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2082 iter: &iter1, path_string: "1");
2083 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2084 iter: &iter2, path_string: "2");
2085 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2086 iter: &iter3, path_string: "3");
2087 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2088 iter: &iter4, path_string: "4");
2089
2090 path = gtk_tree_path_new ();
2091 signal_monitor_append_signal_reordered (m: fixture->monitor,
2092 signal: ROWS_REORDERED,
2093 path, new_order: order0, len: 4);
2094 gtk_tree_store_move_after (tree_store: fixture->store, iter: &iter1, position: &iter4);
2095 signal_monitor_assert_is_empty (m: fixture->monitor);
2096
2097 signal_monitor_append_signal_reordered (m: fixture->monitor,
2098 signal: ROWS_REORDERED,
2099 path, new_order: order1, len: 4);
2100 gtk_tree_store_move_after (tree_store: fixture->store, iter: &iter3, position: &iter4);
2101 signal_monitor_assert_is_empty (m: fixture->monitor);
2102
2103 signal_monitor_append_signal_reordered (m: fixture->monitor,
2104 signal: ROWS_REORDERED,
2105 path, new_order: order2, len: 4);
2106 gtk_tree_store_move_before (tree_store: fixture->store, iter: &iter1, position: &iter2);
2107 signal_monitor_assert_is_empty (m: fixture->monitor);
2108
2109 gtk_tree_path_free (path);
2110}
2111
2112static void
2113filtered_rows_reordered_root_level_middle_hidden (FilterTest *fixture,
2114 gconstpointer user_data)
2115{
2116 int order0[] = { 1, 2, 3, 0 };
2117 int order1[] = { 0, 2, 1, 3 };
2118 int order2[] = { 3, 0, 1, 2 };
2119 GtkTreeIter iter0, iter1, iter3, iter4;
2120 GtkTreePath *path;
2121
2122 /* Hide middle path */
2123 signal_monitor_append_signal (m: fixture->monitor,
2124 signal: ROW_DELETED, path_string: "2");
2125 set_path_visibility (fixture, path: "2", FALSE);
2126 signal_monitor_assert_is_empty (m: fixture->monitor);
2127
2128 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2129 iter: &iter0, path_string: "0");
2130 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2131 iter: &iter1, path_string: "1");
2132 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2133 iter: &iter3, path_string: "3");
2134 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2135 iter: &iter4, path_string: "4");
2136
2137 path = gtk_tree_path_new ();
2138 signal_monitor_append_signal_reordered (m: fixture->monitor,
2139 signal: ROWS_REORDERED,
2140 path, new_order: order0, len: 4);
2141 gtk_tree_store_move_after (tree_store: fixture->store, iter: &iter0, position: &iter4);
2142 signal_monitor_assert_is_empty (m: fixture->monitor);
2143
2144 signal_monitor_append_signal_reordered (m: fixture->monitor,
2145 signal: ROWS_REORDERED,
2146 path, new_order: order1, len: 4);
2147 gtk_tree_store_move_after (tree_store: fixture->store, iter: &iter3, position: &iter4);
2148 signal_monitor_assert_is_empty (m: fixture->monitor);
2149
2150 signal_monitor_append_signal_reordered (m: fixture->monitor,
2151 signal: ROWS_REORDERED,
2152 path, new_order: order2, len: 4);
2153 gtk_tree_store_move_before (tree_store: fixture->store, iter: &iter0, position: &iter1);
2154 signal_monitor_assert_is_empty (m: fixture->monitor);
2155
2156 gtk_tree_path_free (path);
2157}
2158
2159static void
2160filtered_rows_reordered_child_level_first_hidden (FilterTest *fixture,
2161 gconstpointer user_data)
2162{
2163 int order0[] = { 1, 2, 3, 0 };
2164 int order1[] = { 0, 2, 1, 3 };
2165 int order2[] = { 3, 0, 1, 2 };
2166 GtkTreeIter iter1, iter2, iter3, iter4;
2167 GtkTreePath *path;
2168
2169 /* Expand row 0 */
2170 path = gtk_tree_path_new_from_indices (first_index: 0, -1);
2171 gtk_tree_view_expand_row (GTK_TREE_VIEW (fixture->tree_view), path, TRUE);
2172
2173 /* Hide middle path */
2174 signal_monitor_append_signal (m: fixture->monitor,
2175 signal: ROW_DELETED, path_string: "0:0");
2176 set_path_visibility (fixture, path: "0:0", FALSE);
2177 signal_monitor_assert_is_empty (m: fixture->monitor);
2178
2179 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2180 iter: &iter1, path_string: "0:1");
2181 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2182 iter: &iter2, path_string: "0:2");
2183 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2184 iter: &iter3, path_string: "0:3");
2185 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2186 iter: &iter4, path_string: "0:4");
2187
2188 signal_monitor_append_signal_reordered (m: fixture->monitor,
2189 signal: ROWS_REORDERED,
2190 path, new_order: order0, len: 4);
2191 gtk_tree_store_move_after (tree_store: fixture->store, iter: &iter1, position: &iter4);
2192 signal_monitor_assert_is_empty (m: fixture->monitor);
2193
2194 signal_monitor_append_signal_reordered (m: fixture->monitor,
2195 signal: ROWS_REORDERED,
2196 path, new_order: order1, len: 4);
2197 gtk_tree_store_move_after (tree_store: fixture->store, iter: &iter3, position: &iter4);
2198 signal_monitor_assert_is_empty (m: fixture->monitor);
2199
2200 signal_monitor_append_signal_reordered (m: fixture->monitor,
2201 signal: ROWS_REORDERED,
2202 path, new_order: order2, len: 4);
2203 gtk_tree_store_move_before (tree_store: fixture->store, iter: &iter1, position: &iter2);
2204 signal_monitor_assert_is_empty (m: fixture->monitor);
2205
2206 gtk_tree_path_free (path);
2207}
2208
2209static void
2210filtered_rows_reordered_child_level_middle_hidden (FilterTest *fixture,
2211 gconstpointer user_data)
2212{
2213 int order0[] = { 1, 2, 3, 0 };
2214 int order1[] = { 0, 2, 1, 3 };
2215 int order2[] = { 3, 0, 1, 2 };
2216 GtkTreeIter iter0, iter1, iter3, iter4;
2217 GtkTreePath *path;
2218
2219 /* Expand row 0 */
2220 path = gtk_tree_path_new_from_indices (first_index: 0, -1);
2221 gtk_tree_view_expand_row (GTK_TREE_VIEW (fixture->tree_view), path, FALSE);
2222
2223 /* Hide middle path */
2224 signal_monitor_append_signal (m: fixture->monitor,
2225 signal: ROW_DELETED, path_string: "0:2");
2226 set_path_visibility (fixture, path: "0:2", FALSE);
2227 signal_monitor_assert_is_empty (m: fixture->monitor);
2228
2229 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2230 iter: &iter0, path_string: "0:0");
2231 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2232 iter: &iter1, path_string: "0:1");
2233 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2234 iter: &iter3, path_string: "0:3");
2235 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2236 iter: &iter4, path_string: "0:4");
2237
2238 signal_monitor_append_signal_reordered (m: fixture->monitor,
2239 signal: ROWS_REORDERED,
2240 path, new_order: order0, len: 4);
2241 gtk_tree_store_move_after (tree_store: fixture->store, iter: &iter0, position: &iter4);
2242 signal_monitor_assert_is_empty (m: fixture->monitor);
2243
2244 signal_monitor_append_signal_reordered (m: fixture->monitor,
2245 signal: ROWS_REORDERED,
2246 path, new_order: order1, len: 4);
2247 gtk_tree_store_move_after (tree_store: fixture->store, iter: &iter3, position: &iter4);
2248 signal_monitor_assert_is_empty (m: fixture->monitor);
2249
2250 signal_monitor_append_signal_reordered (m: fixture->monitor,
2251 signal: ROWS_REORDERED,
2252 path, new_order: order2, len: 4);
2253 gtk_tree_store_move_before (tree_store: fixture->store, iter: &iter0, position: &iter1);
2254 signal_monitor_assert_is_empty (m: fixture->monitor);
2255
2256 gtk_tree_path_free (path);
2257}
2258
2259static void
2260filtered_rows_reordered_child_level_4_hidden (FilterTest *fixture,
2261 gconstpointer user_data)
2262{
2263 int order0[] = { 0 };
2264 GtkTreeIter iter1, iter4;
2265 GtkTreePath *path;
2266
2267 /* Expand row 0 */
2268 path = gtk_tree_path_new_from_indices (first_index: 0, -1);
2269 gtk_tree_view_expand_row (GTK_TREE_VIEW (fixture->tree_view), path, FALSE);
2270
2271 /* Hide last 4 paths */
2272 signal_monitor_append_signal (m: fixture->monitor,
2273 signal: ROW_DELETED, path_string: "0:4");
2274 signal_monitor_append_signal (m: fixture->monitor,
2275 signal: ROW_DELETED, path_string: "0:3");
2276 signal_monitor_append_signal (m: fixture->monitor,
2277 signal: ROW_DELETED, path_string: "0:2");
2278 signal_monitor_append_signal (m: fixture->monitor,
2279 signal: ROW_DELETED, path_string: "0:0");
2280 set_path_visibility (fixture, path: "0:4", FALSE);
2281 set_path_visibility (fixture, path: "0:3", FALSE);
2282 set_path_visibility (fixture, path: "0:2", FALSE);
2283 set_path_visibility (fixture, path: "0:0", FALSE);
2284 signal_monitor_assert_is_empty (m: fixture->monitor);
2285
2286 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2287 iter: &iter1, path_string: "0:1");
2288 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2289 iter: &iter4, path_string: "0:4");
2290
2291 signal_monitor_append_signal_reordered (m: fixture->monitor,
2292 signal: ROWS_REORDERED,
2293 path, new_order: order0, len: 1);
2294 gtk_tree_store_move_after (tree_store: fixture->store, iter: &iter1, position: &iter4);
2295 signal_monitor_assert_is_empty (m: fixture->monitor);
2296
2297 gtk_tree_path_free (path);
2298}
2299
2300static void
2301filtered_rows_reordered_child_level_all_hidden (FilterTest *fixture,
2302 gconstpointer user_data)
2303{
2304 GtkTreeIter iter1, iter4;
2305 GtkTreePath *path;
2306
2307 /* Expand row 0 */
2308 path = gtk_tree_path_new_from_indices (first_index: 0, -1);
2309 gtk_tree_view_expand_row (GTK_TREE_VIEW (fixture->tree_view), path, FALSE);
2310 gtk_tree_path_free (path);
2311
2312 /* Hide last 4 paths */
2313 signal_monitor_append_signal (m: fixture->monitor,
2314 signal: ROW_DELETED, path_string: "0:4");
2315 signal_monitor_append_signal (m: fixture->monitor,
2316 signal: ROW_DELETED, path_string: "0:3");
2317 signal_monitor_append_signal (m: fixture->monitor,
2318 signal: ROW_DELETED, path_string: "0:2");
2319 signal_monitor_append_signal (m: fixture->monitor,
2320 signal: ROW_DELETED, path_string: "0:1");
2321 signal_monitor_append_signal (m: fixture->monitor,
2322 signal: ROW_DELETED, path_string: "0:0");
2323 signal_monitor_append_signal (m: fixture->monitor,
2324 signal: ROW_HAS_CHILD_TOGGLED, path_string: "0");
2325 set_path_visibility (fixture, path: "0:4", FALSE);
2326 set_path_visibility (fixture, path: "0:3", FALSE);
2327 set_path_visibility (fixture, path: "0:2", FALSE);
2328 set_path_visibility (fixture, path: "0:1", FALSE);
2329 set_path_visibility (fixture, path: "0:0", FALSE);
2330 signal_monitor_assert_is_empty (m: fixture->monitor);
2331
2332 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2333 iter: &iter1, path_string: "0:1");
2334 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2335 iter: &iter4, path_string: "0:4");
2336
2337 gtk_tree_store_move_after (tree_store: fixture->store, iter: &iter1, position: &iter4);
2338 signal_monitor_assert_is_empty (m: fixture->monitor);
2339}
2340
2341static void
2342insert_before (void)
2343{
2344 GtkTreeStore *store;
2345 GtkTreeModel *filter;
2346 GtkWidget *tree_view;
2347 SignalMonitor *monitor;
2348 GtkTreeIter iter;
2349 GtkTreeIter last_iter;
2350 GtkTreePath *path;
2351
2352 /* This tests two aspects of the row-inserted handling:
2353 * 1) If the newly inserted node was already handled by building
2354 * the root level, don't handle it a second time.
2355 * 2) Offsets of existing nodes must be updated when a new
2356 * node is inserted.
2357 */
2358
2359 store = gtk_tree_store_new (n_columns: 2, G_TYPE_STRING, G_TYPE_BOOLEAN);
2360 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
2361 gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter),
2362 column: 1);
2363
2364 tree_view = gtk_tree_view_new_with_model (model: filter);
2365 monitor = signal_monitor_new (client: filter);
2366
2367 check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, expected_length: 0);
2368
2369 /* Insert 0 */
2370 path = gtk_tree_path_new_from_indices (first_index: 0, -1);
2371 signal_monitor_append_signal_path (m: monitor, signal: ROW_INSERTED, path);
2372 gtk_tree_path_free (path);
2373
2374 gtk_tree_store_insert_with_values (tree_store: store, iter: &iter, NULL, position: 0,
2375 0, "Foo", 1, TRUE, -1);
2376
2377 signal_monitor_assert_is_empty (m: monitor);
2378 check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, expected_length: 1);
2379
2380 /* Insert 1 */
2381 path = gtk_tree_path_new_from_indices (first_index: 1, -1);
2382 signal_monitor_append_signal_path (m: monitor, signal: ROW_INSERTED, path);
2383 gtk_tree_path_free (path);
2384
2385 gtk_tree_store_insert_with_values (tree_store: store, iter: &iter, NULL, position: 1,
2386 0, "Foo", 1, TRUE, -1);
2387 last_iter = iter;
2388
2389 signal_monitor_assert_is_empty (m: monitor);
2390 check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, expected_length: 2);
2391
2392 /* Insert on 1 again -- invisible */
2393 gtk_tree_store_insert_with_values (tree_store: store, iter: &iter, NULL, position: 1,
2394 0, "Foo", 1, FALSE, -1);
2395
2396 signal_monitor_assert_is_empty (m: monitor);
2397 check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, expected_length: 2);
2398
2399 /* Insert on 1 again -- visible */
2400 path = gtk_tree_path_new_from_indices (first_index: 1, -1);
2401 signal_monitor_append_signal_path (m: monitor, signal: ROW_INSERTED, path);
2402 gtk_tree_path_free (path);
2403
2404 gtk_tree_store_insert_with_values (tree_store: store, iter: &iter, NULL, position: 1,
2405 0, "Foo", 1, TRUE, -1);
2406
2407 signal_monitor_assert_is_empty (m: monitor);
2408 check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, expected_length: 3);
2409
2410 /* Modify the iter that should be at the last position and check the
2411 * signal we get.
2412 */
2413 path = gtk_tree_path_new_from_indices (first_index: 2, -1);
2414 signal_monitor_append_signal_path (m: monitor, signal: ROW_CHANGED, path);
2415 gtk_tree_path_free (path);
2416
2417 gtk_tree_store_set (tree_store: store, iter: &last_iter, 0, "Foo changed", -1);
2418
2419 signal_monitor_assert_is_empty (m: monitor);
2420 check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, expected_length: 3);
2421
2422 g_object_unref (object: filter);
2423 g_object_unref (object: store);
2424 g_object_unref (g_object_ref_sink (tree_view));
2425}
2426
2427static void
2428insert_child (void)
2429{
2430 GtkTreeStore *store;
2431 GtkTreeModel *filter;
2432 GtkWidget *tree_view;
2433 SignalMonitor *monitor;
2434 GtkTreeIter parent, iter;
2435 GtkTreePath *path;
2436
2437 store = gtk_tree_store_new (n_columns: 2, G_TYPE_STRING, G_TYPE_BOOLEAN);
2438
2439 gtk_tree_store_insert_with_values (tree_store: store, iter: &parent, NULL, position: 0,
2440 0, "Parent", 1, TRUE, -1);
2441
2442
2443 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
2444 gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter),
2445 column: 1);
2446
2447 tree_view = gtk_tree_view_new_with_model (model: filter);
2448 monitor = signal_monitor_new (client: filter);
2449
2450 /* Insert child -- invisible */
2451 path = gtk_tree_path_new_from_indices (first_index: 0, -1);
2452 signal_monitor_append_signal_path (m: monitor, signal: ROW_HAS_CHILD_TOGGLED, path);
2453 /* The signal is received twice, once a pass through from GtkTreeStore
2454 * and one generated by GtkTreeModelFilter. Not accurate, but cannot
2455 * hurt.
2456 */
2457 signal_monitor_append_signal_path (m: monitor, signal: ROW_HAS_CHILD_TOGGLED, path);
2458 gtk_tree_path_free (path);
2459
2460 gtk_tree_store_insert_with_values (tree_store: store, iter: &iter, parent: &parent, position: 1,
2461 0, "Child", 1, FALSE, -1);
2462
2463 signal_monitor_assert_is_empty (m: monitor);
2464 check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, expected_length: 1);
2465
2466 /* Insert child */
2467 path = gtk_tree_path_new_from_indices (first_index: 0, 0, -1);
2468 gtk_tree_path_up (path); /* 0 */
2469 signal_monitor_append_signal_path (m: monitor, signal: ROW_HAS_CHILD_TOGGLED, path);
2470 gtk_tree_path_free (path);
2471
2472 gtk_tree_store_insert_with_values (tree_store: store, iter: &iter, parent: &parent, position: 0,
2473 0, "Child", 1, TRUE, -1);
2474
2475 signal_monitor_assert_is_empty (m: monitor);
2476 check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, expected_length: 1);
2477
2478 /* Insert child -- invisible */
2479 gtk_tree_store_insert_with_values (tree_store: store, iter: &iter, parent: &parent, position: 1,
2480 0, "Child", 1, FALSE, -1);
2481
2482 signal_monitor_assert_is_empty (m: monitor);
2483 check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, expected_length: 1);
2484
2485 g_object_unref (object: filter);
2486 g_object_unref (object: store);
2487 g_object_unref (g_object_ref_sink (tree_view));
2488}
2489
2490
2491
2492static void
2493remove_node (void)
2494{
2495 GtkTreeIter iter, iter1, iter2, iter3;
2496 GtkListStore *list;
2497 GtkTreeModel *filter;
2498 GtkWidget *view G_GNUC_UNUSED;
2499
2500 list = gtk_list_store_new (n_columns: 1, G_TYPE_INT);
2501 gtk_list_store_insert_with_values (list_store: list, iter: &iter1, position: 0, 0, 1, -1);
2502 gtk_list_store_insert_with_values (list_store: list, iter: &iter, position: 1, 0, 2, -1);
2503 gtk_list_store_insert_with_values (list_store: list, iter: &iter, position: 2, 0, 3, -1);
2504 gtk_list_store_insert_with_values (list_store: list, iter: &iter, position: 3, 0, 4, -1);
2505 gtk_list_store_insert_with_values (list_store: list, iter: &iter, position: 4, 0, 5, -1);
2506 gtk_list_store_insert_with_values (list_store: list, iter: &iter, position: 5, 0, 6, -1);
2507 gtk_list_store_insert_with_values (list_store: list, iter: &iter2, position: 6, 0, 7, -1);
2508 gtk_list_store_insert_with_values (list_store: list, iter: &iter3, position: 7, 0, 8, -1);
2509
2510 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (list), NULL);
2511 view = gtk_tree_view_new_with_model (model: filter);
2512
2513 gtk_list_store_remove (list_store: list, iter: &iter1);
2514 gtk_list_store_remove (list_store: list, iter: &iter3);
2515 gtk_list_store_remove (list_store: list, iter: &iter2);
2516
2517 g_object_unref (g_object_ref_sink (view));
2518 g_object_unref (object: filter);
2519 g_object_unref (object: list);
2520}
2521
2522static void
2523remove_node_vroot (void)
2524{
2525 GtkTreeIter parent, root;
2526 GtkTreeIter iter, iter1, iter2, iter3;
2527 GtkTreeStore *tree;
2528 GtkTreeModel *filter;
2529 GtkTreePath *path;
2530 GtkWidget *view G_GNUC_UNUSED;
2531
2532 tree = gtk_tree_store_new (n_columns: 1, G_TYPE_INT);
2533 gtk_tree_store_insert_with_values (tree_store: tree, iter: &parent, NULL, position: 0, 0, 0, -1);
2534 gtk_tree_store_insert_with_values (tree_store: tree, iter: &root, parent: &parent, position: 0, 0, 0, -1);
2535
2536 gtk_tree_store_insert_with_values (tree_store: tree, iter: &iter1, parent: &root, position: 0, 0, 1, -1);
2537 gtk_tree_store_insert_with_values (tree_store: tree, iter: &iter, parent: &root, position: 1, 0, 2, -1);
2538 gtk_tree_store_insert_with_values (tree_store: tree, iter: &iter, parent: &root, position: 2, 0, 3, -1);
2539 gtk_tree_store_insert_with_values (tree_store: tree, iter: &iter, parent: &root, position: 3, 0, 4, -1);
2540 gtk_tree_store_insert_with_values (tree_store: tree, iter: &iter, parent: &root, position: 4, 0, 5, -1);
2541 gtk_tree_store_insert_with_values (tree_store: tree, iter: &iter, parent: &root, position: 5, 0, 6, -1);
2542 gtk_tree_store_insert_with_values (tree_store: tree, iter: &iter2, parent: &root, position: 6, 0, 7, -1);
2543 gtk_tree_store_insert_with_values (tree_store: tree, iter: &iter3, parent: &root, position: 7, 0, 8, -1);
2544
2545 path = gtk_tree_path_new_from_indices (first_index: 0, 0, -1);
2546 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (tree), root: path);
2547 gtk_tree_path_free (path);
2548
2549 view = gtk_tree_view_new_with_model (model: filter);
2550
2551 gtk_tree_store_remove (tree_store: tree, iter: &iter1);
2552 gtk_tree_store_remove (tree_store: tree, iter: &iter3);
2553 gtk_tree_store_remove (tree_store: tree, iter: &iter2);
2554
2555 g_object_unref (g_object_ref_sink (view));
2556 g_object_unref (object: filter);
2557 g_object_unref (object: tree);
2558}
2559
2560static void
2561remove_vroot_ancestor (void)
2562{
2563 GtkTreeIter parent, root;
2564 GtkTreeIter iter, iter1, iter2, iter3;
2565 GtkTreeStore *tree;
2566 GtkTreeModel *filter;
2567 GtkTreePath *path;
2568 GtkWidget *view G_GNUC_UNUSED;
2569
2570 tree = gtk_tree_store_new (n_columns: 1, G_TYPE_INT);
2571 gtk_tree_store_insert_with_values (tree_store: tree, iter: &parent, NULL, position: 0, 0, 0, -1);
2572 gtk_tree_store_insert_with_values (tree_store: tree, iter: &root, parent: &parent, position: 0, 0, 0, -1);
2573
2574 gtk_tree_store_insert_with_values (tree_store: tree, iter: &iter1, parent: &root, position: 0, 0, 1, -1);
2575 gtk_tree_store_insert_with_values (tree_store: tree, iter: &iter, parent: &root, position: 1, 0, 2, -1);
2576 gtk_tree_store_insert_with_values (tree_store: tree, iter: &iter, parent: &root, position: 2, 0, 3, -1);
2577 gtk_tree_store_insert_with_values (tree_store: tree, iter: &iter, parent: &root, position: 3, 0, 4, -1);
2578 gtk_tree_store_insert_with_values (tree_store: tree, iter: &iter, parent: &root, position: 4, 0, 5, -1);
2579 gtk_tree_store_insert_with_values (tree_store: tree, iter: &iter, parent: &root, position: 5, 0, 6, -1);
2580 gtk_tree_store_insert_with_values (tree_store: tree, iter: &iter2, parent: &root, position: 6, 0, 7, -1);
2581 gtk_tree_store_insert_with_values (tree_store: tree, iter: &iter3, parent: &root, position: 7, 0, 8, -1);
2582
2583 path = gtk_tree_path_new_from_indices (first_index: 0, 0, -1);
2584 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (tree), root: path);
2585 gtk_tree_path_free (path);
2586
2587 view = gtk_tree_view_new_with_model (model: filter);
2588
2589 gtk_tree_store_remove (tree_store: tree, iter: &parent);
2590
2591 g_object_unref (g_object_ref_sink (view));
2592 g_object_unref (object: filter);
2593 g_object_unref (object: tree);
2594}
2595
2596static void
2597ref_count_single_level (void)
2598{
2599 GtkTreeIter iter[5];
2600 GtkTreeModel *model;
2601 GtkTreeModelRefCount *ref_model;
2602 GtkTreeModel *filter_model;
2603 GtkWidget *tree_view;
2604
2605 model = gtk_tree_model_ref_count_new ();
2606 ref_model = GTK_TREE_MODEL_REF_COUNT (model);
2607
2608 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &iter[0], NULL);
2609 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &iter[1], NULL);
2610 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &iter[2], NULL);
2611 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &iter[3], NULL);
2612 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &iter[4], NULL);
2613
2614 assert_root_level_unreferenced (ref_model);
2615
2616 filter_model = gtk_tree_model_filter_new (child_model: model, NULL);
2617 tree_view = gtk_tree_view_new_with_model (model: filter_model);
2618
2619 assert_node_ref_count (ref_model, iter: &iter[0], ref_count: 2);
2620 assert_node_ref_count (ref_model, iter: &iter[1], ref_count: 1);
2621 assert_node_ref_count (ref_model, iter: &iter[2], ref_count: 1);
2622 assert_node_ref_count (ref_model, iter: &iter[3], ref_count: 1);
2623 assert_node_ref_count (ref_model, iter: &iter[4], ref_count: 1);
2624
2625 g_object_unref (g_object_ref_sink (tree_view));
2626
2627 assert_node_ref_count (ref_model, iter: &iter[0], ref_count: 1);
2628 assert_node_ref_count (ref_model, iter: &iter[1], ref_count: 0);
2629 assert_node_ref_count (ref_model, iter: &iter[2], ref_count: 0);
2630 assert_node_ref_count (ref_model, iter: &iter[3], ref_count: 0);
2631 assert_node_ref_count (ref_model, iter: &iter[4], ref_count: 0);
2632
2633 g_object_unref (object: filter_model);
2634
2635 assert_node_ref_count (ref_model, iter: &iter[0], ref_count: 0);
2636
2637 g_object_unref (object: ref_model);
2638}
2639
2640static void
2641ref_count_two_levels (void)
2642{
2643 GtkTreeIter parent1, parent2, iter, iter_first;
2644 GtkTreeModel *model;
2645 GtkTreeModelRefCount *ref_model;
2646 GtkTreeModel *filter_model;
2647 GtkWidget *tree_view;
2648
2649 model = gtk_tree_model_ref_count_new ();
2650 ref_model = GTK_TREE_MODEL_REF_COUNT (model);
2651
2652 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &parent1, NULL);
2653 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &parent2, NULL);
2654 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &iter_first, parent: &parent2);
2655 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &iter, parent: &parent2);
2656 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &iter, parent: &parent2);
2657
2658 assert_entire_model_unreferenced (ref_model);
2659
2660 filter_model = gtk_tree_model_filter_new (child_model: model, NULL);
2661 tree_view = gtk_tree_view_new_with_model (model: filter_model);
2662
2663 /* This is quite confusing:
2664 * - node 0 has a ref count of 2 because it is referenced as the
2665 * first node in a level and by the tree view.
2666 * - node 1 has a ref count of 2 because it is referenced by its
2667 * child level and by the tree view.
2668 */
2669 assert_root_level_referenced (ref_model, ref_count: 2);
2670 assert_node_ref_count (ref_model, iter: &iter_first, ref_count: 1);
2671 assert_node_ref_count (ref_model, iter: &iter, ref_count: 0);
2672
2673 gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
2674
2675 assert_node_ref_count (ref_model, iter: &parent1, ref_count: 2);
2676 assert_node_ref_count (ref_model, iter: &parent2, ref_count: 2);
2677 assert_node_ref_count (ref_model, iter: &iter_first, ref_count: 2);
2678 assert_node_ref_count (ref_model, iter: &iter, ref_count: 1);
2679
2680 gtk_tree_view_collapse_all (GTK_TREE_VIEW (tree_view));
2681
2682 /* The child level is not destroyed because its parent is visible */
2683 assert_node_ref_count (ref_model, iter: &parent1, ref_count: 2);
2684 assert_node_ref_count (ref_model, iter: &parent2, ref_count: 2);
2685 assert_node_ref_count (ref_model, iter: &iter_first, ref_count: 1);
2686 assert_node_ref_count (ref_model, iter: &iter, ref_count: 0);
2687
2688 gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
2689
2690 assert_node_ref_count (ref_model, iter: &parent1, ref_count: 2);
2691 assert_node_ref_count (ref_model, iter: &parent2, ref_count: 2);
2692 assert_node_ref_count (ref_model, iter: &iter_first, ref_count: 1);
2693 assert_node_ref_count (ref_model, iter: &iter, ref_count: 0);
2694
2695 g_object_unref (g_object_ref_sink (tree_view));
2696
2697 assert_root_level_referenced (ref_model, ref_count: 1);
2698 assert_node_ref_count (ref_model, iter: &iter_first, ref_count: 1);
2699 assert_node_ref_count (ref_model, iter: &iter, ref_count: 0);
2700
2701 gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
2702
2703 /* The root level and first level remain cached, only the references on the
2704 * first nodes of these levels are kept.
2705 */
2706 assert_node_ref_count (ref_model, iter: &parent1, ref_count: 1);
2707 assert_node_ref_count (ref_model, iter: &parent2, ref_count: 1);
2708 assert_node_ref_count (ref_model, iter: &iter_first, ref_count: 1);
2709 assert_node_ref_count (ref_model, iter: &iter, ref_count: 0);
2710
2711 g_object_unref (object: filter_model);
2712 g_object_unref (object: ref_model);
2713}
2714
2715static void
2716ref_count_three_levels (void)
2717{
2718 GtkTreeIter grandparent1, grandparent2, parent1, parent2;
2719 GtkTreeIter iter_parent1, iter_parent2, iter_parent2_first;
2720 GtkTreeModel *model;
2721 GtkTreeModelRefCount *ref_model;
2722 GtkTreeModel *filter_model;
2723 GtkTreePath *path;
2724 GtkWidget *tree_view;
2725
2726 model = gtk_tree_model_ref_count_new ();
2727 ref_model = GTK_TREE_MODEL_REF_COUNT (model);
2728
2729 /* + grandparent1
2730 * + grandparent2
2731 * + parent1
2732 * + iter_parent1
2733 * + parent2
2734 * + iter_parent2_first
2735 * + iter_parent2
2736 */
2737
2738 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &grandparent1, NULL);
2739 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &grandparent2, NULL);
2740 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &parent1, parent: &grandparent2);
2741 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &iter_parent1, parent: &parent1);
2742 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &parent2, parent: &grandparent2);
2743 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &iter_parent2_first, parent: &parent2);
2744 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &iter_parent2, parent: &parent2);
2745
2746 assert_entire_model_unreferenced (ref_model);
2747
2748 filter_model = gtk_tree_model_filter_new (child_model: model, NULL);
2749 tree_view = gtk_tree_view_new_with_model (model: filter_model);
2750
2751 /* This is quite confusing:
2752 * - node 0 has a ref count of 2 because it is referenced as the
2753 * first node in a level and by the tree view.
2754 * - node 1 has a ref count of 2 because it is referenced by its
2755 * child level and by the tree view.
2756 */
2757 assert_root_level_referenced (ref_model, ref_count: 2);
2758 assert_node_ref_count (ref_model, iter: &parent1, ref_count: 1);
2759 assert_node_ref_count (ref_model, iter: &parent2, ref_count: 0);
2760 assert_level_unreferenced (ref_model, iter: &parent1);
2761 assert_level_unreferenced (ref_model, iter: &parent2);
2762
2763 path = gtk_tree_path_new_from_indices (first_index: 1, -1);
2764 gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path, FALSE);
2765
2766 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 2);
2767 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 2);
2768 assert_node_ref_count (ref_model, iter: &parent1, ref_count: 3);
2769 assert_node_ref_count (ref_model, iter: &parent2, ref_count: 2);
2770 assert_node_ref_count (ref_model, iter: &iter_parent1, ref_count: 1);
2771 assert_node_ref_count (ref_model, iter: &iter_parent2_first, ref_count: 1);
2772 assert_node_ref_count (ref_model, iter: &iter_parent2, ref_count: 0);
2773
2774 gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path, TRUE);
2775
2776 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 2);
2777 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 2);
2778 assert_node_ref_count (ref_model, iter: &parent1, ref_count: 3);
2779 assert_node_ref_count (ref_model, iter: &parent2, ref_count: 2);
2780 assert_node_ref_count (ref_model, iter: &iter_parent1, ref_count: 2);
2781 assert_node_ref_count (ref_model, iter: &iter_parent2_first, ref_count: 2);
2782 assert_node_ref_count (ref_model, iter: &iter_parent2, ref_count: 1);
2783
2784 gtk_tree_view_collapse_all (GTK_TREE_VIEW (tree_view));
2785
2786 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 2);
2787 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 2);
2788 assert_node_ref_count (ref_model, iter: &parent1, ref_count: 2);
2789 assert_node_ref_count (ref_model, iter: &parent2, ref_count: 1);
2790 assert_node_ref_count (ref_model, iter: &iter_parent1, ref_count: 1);
2791 assert_node_ref_count (ref_model, iter: &iter_parent2_first, ref_count: 1);
2792 assert_node_ref_count (ref_model, iter: &iter_parent2, ref_count: 0);
2793
2794 gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
2795
2796 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 2);
2797 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 2);
2798 assert_node_ref_count (ref_model, iter: &parent1, ref_count: 1);
2799 assert_node_ref_count (ref_model, iter: &parent2, ref_count: 0);
2800 assert_node_ref_count (ref_model, iter: &iter_parent1, ref_count: 0);
2801 assert_node_ref_count (ref_model, iter: &iter_parent2_first, ref_count: 0);
2802 assert_node_ref_count (ref_model, iter: &iter_parent2, ref_count: 0);
2803
2804 gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path, FALSE);
2805
2806 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 2);
2807 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 2);
2808 assert_node_ref_count (ref_model, iter: &parent1, ref_count: 3);
2809 assert_node_ref_count (ref_model, iter: &parent2, ref_count: 2);
2810 assert_node_ref_count (ref_model, iter: &iter_parent1, ref_count: 1);
2811 assert_node_ref_count (ref_model, iter: &iter_parent2_first, ref_count: 1);
2812 assert_node_ref_count (ref_model, iter: &iter_parent2, ref_count: 0);
2813
2814 gtk_tree_path_append_index (path, index_: 1);
2815 gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path, FALSE);
2816
2817 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 2);
2818 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 2);
2819 assert_node_ref_count (ref_model, iter: &parent1, ref_count: 3);
2820 assert_node_ref_count (ref_model, iter: &parent2, ref_count: 2);
2821 assert_node_ref_count (ref_model, iter: &iter_parent1, ref_count: 1);
2822 assert_node_ref_count (ref_model, iter: &iter_parent2_first, ref_count: 2);
2823 assert_node_ref_count (ref_model, iter: &iter_parent2, ref_count: 1);
2824
2825 gtk_tree_view_collapse_row (GTK_TREE_VIEW (tree_view), path);
2826
2827 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 2);
2828 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 2);
2829 assert_node_ref_count (ref_model, iter: &parent1, ref_count: 3);
2830 assert_node_ref_count (ref_model, iter: &parent2, ref_count: 2);
2831 assert_node_ref_count (ref_model, iter: &iter_parent1, ref_count: 1);
2832 assert_node_ref_count (ref_model, iter: &iter_parent2_first, ref_count: 1);
2833 assert_node_ref_count (ref_model, iter: &iter_parent2, ref_count: 0);
2834
2835 gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
2836
2837 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 2);
2838 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 2);
2839 assert_node_ref_count (ref_model, iter: &parent1, ref_count: 3);
2840 assert_node_ref_count (ref_model, iter: &parent2, ref_count: 2);
2841 assert_node_ref_count (ref_model, iter: &iter_parent1, ref_count: 1);
2842 assert_node_ref_count (ref_model, iter: &iter_parent2_first, ref_count: 1);
2843 assert_node_ref_count (ref_model, iter: &iter_parent2, ref_count: 0);
2844
2845 gtk_tree_path_up (path);
2846 gtk_tree_view_collapse_row (GTK_TREE_VIEW (tree_view), path);
2847 gtk_tree_path_free (path);
2848
2849 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 2);
2850 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 2);
2851 assert_node_ref_count (ref_model, iter: &parent1, ref_count: 2);
2852 assert_node_ref_count (ref_model, iter: &parent2, ref_count: 1);
2853 assert_node_ref_count (ref_model, iter: &iter_parent1, ref_count: 1);
2854 assert_node_ref_count (ref_model, iter: &iter_parent2_first, ref_count: 1);
2855 assert_node_ref_count (ref_model, iter: &iter_parent2, ref_count: 0);
2856
2857 gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
2858
2859 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 2);
2860 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 2);
2861 assert_node_ref_count (ref_model, iter: &parent1, ref_count: 1);
2862 assert_node_ref_count (ref_model, iter: &parent2, ref_count: 0);
2863 assert_node_ref_count (ref_model, iter: &iter_parent1, ref_count: 0);
2864 assert_node_ref_count (ref_model, iter: &iter_parent2_first, ref_count: 0);
2865 assert_node_ref_count (ref_model, iter: &iter_parent2, ref_count: 0);
2866
2867 g_object_unref (g_object_ref_sink (tree_view));
2868
2869 gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
2870
2871 /* The root level and first level remain cached, only the references on the
2872 * first nodes of these levels are kept. Grandparent2 is the parent
2873 * of the first level with parent1, so grandparent2 keeps a reference
2874 * as well.
2875 */
2876 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 1);
2877 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 1);
2878 assert_node_ref_count (ref_model, iter: &parent1, ref_count: 1);
2879 assert_node_ref_count (ref_model, iter: &parent2, ref_count: 0);
2880 assert_node_ref_count (ref_model, iter: &iter_parent1, ref_count: 0);
2881 assert_node_ref_count (ref_model, iter: &iter_parent2_first, ref_count: 0);
2882 assert_node_ref_count (ref_model, iter: &iter_parent2, ref_count: 0);
2883
2884 g_object_unref (object: filter_model);
2885 g_object_unref (object: ref_model);
2886}
2887
2888static void
2889ref_count_delete_row (void)
2890{
2891 GtkTreeIter grandparent1, grandparent2, parent1, parent2;
2892 GtkTreeIter iter_parent1, iter_parent2, iter_parent2_first;
2893 GtkTreeModel *model;
2894 GtkTreeModelRefCount *ref_model;
2895 GtkTreeModel *filter_model;
2896 GtkTreePath *path;
2897 GtkWidget *tree_view;
2898
2899 model = gtk_tree_model_ref_count_new ();
2900 ref_model = GTK_TREE_MODEL_REF_COUNT (model);
2901
2902 /* + grandparent1
2903 * + grandparent2
2904 * + parent1
2905 * + iter_parent1
2906 * + parent2
2907 * + iter_parent2_first
2908 * + iter_parent2
2909 */
2910
2911 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &grandparent1, NULL);
2912 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &grandparent2, NULL);
2913 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &parent1, parent: &grandparent2);
2914 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &iter_parent1, parent: &parent1);
2915 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &parent2, parent: &grandparent2);
2916 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &iter_parent2_first, parent: &parent2);
2917 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &iter_parent2, parent: &parent2);
2918
2919 assert_entire_model_unreferenced (ref_model);
2920
2921 filter_model = gtk_tree_model_filter_new (child_model: model, NULL);
2922 tree_view = gtk_tree_view_new_with_model (model: filter_model);
2923
2924 assert_root_level_referenced (ref_model, ref_count: 2);
2925 assert_node_ref_count (ref_model, iter: &parent1, ref_count: 1);
2926 assert_node_ref_count (ref_model, iter: &parent2, ref_count: 0);
2927 assert_level_unreferenced (ref_model, iter: &parent1);
2928 assert_level_unreferenced (ref_model, iter: &parent2);
2929
2930 path = gtk_tree_path_new_from_indices (first_index: 1, -1);
2931 gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path, TRUE);
2932 gtk_tree_path_free (path);
2933
2934 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 2);
2935 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 2);
2936 assert_node_ref_count (ref_model, iter: &parent1, ref_count: 3);
2937 assert_node_ref_count (ref_model, iter: &parent2, ref_count: 2);
2938 assert_node_ref_count (ref_model, iter: &iter_parent1, ref_count: 2);
2939 assert_node_ref_count (ref_model, iter: &iter_parent2_first, ref_count: 2);
2940 assert_node_ref_count (ref_model, iter: &iter_parent2, ref_count: 1);
2941
2942 gtk_tree_store_remove (GTK_TREE_STORE (model), iter: &iter_parent2);
2943
2944 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 2);
2945 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 2);
2946 assert_node_ref_count (ref_model, iter: &parent1, ref_count: 3);
2947 assert_node_ref_count (ref_model, iter: &parent2, ref_count: 2);
2948 assert_node_ref_count (ref_model, iter: &iter_parent1, ref_count: 2);
2949 assert_node_ref_count (ref_model, iter: &iter_parent2_first, ref_count: 2);
2950
2951 gtk_tree_store_remove (GTK_TREE_STORE (model), iter: &parent1);
2952
2953 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 2);
2954 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 2);
2955 assert_node_ref_count (ref_model, iter: &parent2, ref_count: 3);
2956 assert_level_referenced (ref_model, ref_count: 2, iter: &parent2);
2957
2958 gtk_tree_store_remove (GTK_TREE_STORE (model), iter: &grandparent2);
2959
2960 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 2);
2961
2962 gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
2963
2964 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 2);
2965
2966 g_object_unref (g_object_ref_sink (tree_view));
2967 gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
2968
2969 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 1);
2970
2971 g_object_unref (object: filter_model);
2972
2973 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 0);
2974
2975 g_object_unref (object: ref_model);
2976}
2977
2978static void
2979ref_count_filter_row_length_1 (void)
2980{
2981 GtkTreeIter level1_1;
2982 GtkTreeIter level2_1;
2983 GtkTreeIter level3_1;
2984 GtkTreeIter level4_1;
2985 GtkTreeModel *model;
2986 GtkTreeModelRefCount *ref_model;
2987 GtkTreeModel *filter_model;
2988 GtkTreePath *path;
2989 GtkWidget *tree_view;
2990 GType column_types[] = { G_TYPE_BOOLEAN };
2991
2992 model = gtk_tree_model_ref_count_new ();
2993 ref_model = GTK_TREE_MODEL_REF_COUNT (model);
2994
2995 gtk_tree_store_set_column_types (GTK_TREE_STORE (model), n_columns: 1,
2996 types: column_types);
2997
2998
2999 /* + level1_1
3000 * + level2_1
3001 * + level3_1
3002 * + level4_1
3003 *
3004 * Node level1_1 is expanded. This makes that levels 1 and 2 are
3005 * visible. Level 3 is cached because its parent is visible. Level 4
3006 * is not cached.
3007 */
3008
3009 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &level1_1, NULL);
3010 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &level2_1, parent: &level1_1);
3011 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &level3_1, parent: &level2_1);
3012 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &level4_1, parent: &level3_1);
3013
3014 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &level1_1, 0, TRUE, -1);
3015 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &level2_1, 0, TRUE, -1);
3016 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &level3_1, 0, TRUE, -1);
3017 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &level4_1, 0, TRUE, -1);
3018
3019 assert_entire_model_unreferenced (ref_model);
3020
3021 filter_model = gtk_tree_model_filter_new (child_model: model, NULL);
3022 gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), column: 0);
3023 tree_view = gtk_tree_view_new_with_model (model: filter_model);
3024
3025 assert_node_ref_count (ref_model, iter: &level1_1, ref_count: 3);
3026 assert_node_ref_count (ref_model, iter: &level2_1, ref_count: 1);
3027 assert_node_ref_count (ref_model, iter: &level3_1, ref_count: 0);
3028 assert_node_ref_count (ref_model, iter: &level4_1, ref_count: 0);
3029
3030 path = gtk_tree_path_new_from_indices (first_index: 0, -1);
3031 gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path, FALSE);
3032 gtk_tree_path_free (path);
3033
3034 assert_node_ref_count (ref_model, iter: &level1_1, ref_count: 3);
3035 assert_node_ref_count (ref_model, iter: &level2_1, ref_count: 3);
3036 assert_node_ref_count (ref_model, iter: &level3_1, ref_count: 1);
3037 assert_node_ref_count (ref_model, iter: &level4_1, ref_count: 0);
3038
3039 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &level4_1, 0, FALSE, -1);
3040
3041 assert_node_ref_count (ref_model, iter: &level1_1, ref_count: 3);
3042 assert_node_ref_count (ref_model, iter: &level2_1, ref_count: 3);
3043 assert_node_ref_count (ref_model, iter: &level3_1, ref_count: 1);
3044 assert_node_ref_count (ref_model, iter: &level4_1, ref_count: 0);
3045
3046 /* level3_1 has a visible parent, so the node is kept in the cache. */
3047 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &level3_1, 0, FALSE, -1);
3048
3049 assert_node_ref_count (ref_model, iter: &level1_1, ref_count: 3);
3050 assert_node_ref_count (ref_model, iter: &level2_1, ref_count: 3);
3051 assert_node_ref_count (ref_model, iter: &level3_1, ref_count: 1);
3052 assert_node_ref_count (ref_model, iter: &level4_1, ref_count: 0);
3053
3054 /* level2_1 has a visible parent, so is kept in the cache. However,
3055 * the external reference should be released.
3056 */
3057 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &level2_1, 0, FALSE, -1);
3058
3059 assert_node_ref_count (ref_model, iter: &level1_1, ref_count: 3);
3060 assert_node_ref_count (ref_model, iter: &level2_1, ref_count: 1);
3061 assert_node_ref_count (ref_model, iter: &level3_1, ref_count: 0);
3062 assert_node_ref_count (ref_model, iter: &level4_1, ref_count: 0);
3063
3064 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &level1_1, 0, FALSE, -1);
3065
3066 assert_node_ref_count (ref_model, iter: &level1_1, ref_count: 2);
3067 assert_node_ref_count (ref_model, iter: &level2_1, ref_count: 1);
3068 assert_node_ref_count (ref_model, iter: &level3_1, ref_count: 0);
3069 assert_node_ref_count (ref_model, iter: &level4_1, ref_count: 0);
3070
3071 g_object_unref (g_object_ref_sink (tree_view));
3072 gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
3073
3074 assert_node_ref_count (ref_model, iter: &level1_1, ref_count: 2);
3075 assert_node_ref_count (ref_model, iter: &level2_1, ref_count: 1);
3076
3077 g_object_unref (object: filter_model);
3078
3079 assert_node_ref_count (ref_model, iter: &level1_1, ref_count: 0);
3080
3081 g_object_unref (object: ref_model);
3082}
3083
3084static void
3085ref_count_filter_row_length_1_remove_in_root_level (void)
3086{
3087 GtkTreeIter level1_1;
3088 GtkTreeIter level2_1;
3089 GtkTreeIter level3_1;
3090 GtkTreeIter level4_1;
3091 GtkTreeModel *model;
3092 GtkTreeModelRefCount *ref_model;
3093 GtkTreeModel *filter_model;
3094 GtkTreePath *path;
3095 GtkWidget *tree_view;
3096 GType column_types[] = { G_TYPE_BOOLEAN };
3097
3098 model = gtk_tree_model_ref_count_new ();
3099 ref_model = GTK_TREE_MODEL_REF_COUNT (model);
3100
3101 gtk_tree_store_set_column_types (GTK_TREE_STORE (model), n_columns: 1,
3102 types: column_types);
3103
3104
3105 /* + level1_1
3106 * + level2_1
3107 * + level3_1
3108 * + level4_1
3109 */
3110
3111 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &level1_1, NULL);
3112 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &level2_1, parent: &level1_1);
3113 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &level3_1, parent: &level2_1);
3114 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &level4_1, parent: &level3_1);
3115
3116 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &level1_1, 0, TRUE, -1);
3117 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &level2_1, 0, TRUE, -1);
3118 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &level3_1, 0, TRUE, -1);
3119 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &level4_1, 0, TRUE, -1);
3120
3121 assert_entire_model_unreferenced (ref_model);
3122
3123 filter_model = gtk_tree_model_filter_new (child_model: model, NULL);
3124 gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), column: 0);
3125 tree_view = gtk_tree_view_new_with_model (model: filter_model);
3126
3127 assert_node_ref_count (ref_model, iter: &level1_1, ref_count: 3);
3128 assert_node_ref_count (ref_model, iter: &level2_1, ref_count: 1);
3129 assert_node_ref_count (ref_model, iter: &level3_1, ref_count: 0);
3130 assert_node_ref_count (ref_model, iter: &level4_1, ref_count: 0);
3131
3132 path = gtk_tree_path_new_from_indices (first_index: 0, -1);
3133 gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path, TRUE);
3134 gtk_tree_path_free (path);
3135
3136 assert_node_ref_count (ref_model, iter: &level1_1, ref_count: 3);
3137 assert_node_ref_count (ref_model, iter: &level2_1, ref_count: 3);
3138 assert_node_ref_count (ref_model, iter: &level3_1, ref_count: 3);
3139 assert_node_ref_count (ref_model, iter: &level4_1, ref_count: 2);
3140
3141 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &level1_1, 0, FALSE, -1);
3142
3143 assert_node_ref_count (ref_model, iter: &level1_1, ref_count: 2);
3144 assert_node_ref_count (ref_model, iter: &level2_1, ref_count: 1);
3145 assert_node_ref_count (ref_model, iter: &level3_1, ref_count: 0);
3146 assert_node_ref_count (ref_model, iter: &level4_1, ref_count: 0);
3147
3148 g_object_unref (g_object_ref_sink (tree_view));
3149 gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
3150
3151 assert_node_ref_count (ref_model, iter: &level1_1, ref_count: 2);
3152 assert_node_ref_count (ref_model, iter: &level2_1, ref_count: 1);
3153 assert_node_ref_count (ref_model, iter: &level3_1, ref_count: 0);
3154 assert_node_ref_count (ref_model, iter: &level4_1, ref_count: 0);
3155
3156 g_object_unref (object: filter_model);
3157
3158 assert_node_ref_count (ref_model, iter: &level1_1, ref_count: 0);
3159 assert_node_ref_count (ref_model, iter: &level2_1, ref_count: 0);
3160 assert_node_ref_count (ref_model, iter: &level3_1, ref_count: 0);
3161 assert_node_ref_count (ref_model, iter: &level4_1, ref_count: 0);
3162
3163 g_object_unref (object: ref_model);
3164}
3165
3166static void
3167ref_count_filter_row_length_1_remove_in_child_level (void)
3168{
3169 GtkTreeIter level1_1;
3170 GtkTreeIter level2_1;
3171 GtkTreeIter level3_1;
3172 GtkTreeIter level4_1;
3173 GtkTreeModel *model;
3174 GtkTreeModelRefCount *ref_model;
3175 GtkTreeModel *filter_model;
3176 GtkTreePath *path;
3177 GtkWidget *tree_view;
3178 GType column_types[] = { G_TYPE_BOOLEAN };
3179
3180 model = gtk_tree_model_ref_count_new ();
3181 ref_model = GTK_TREE_MODEL_REF_COUNT (model);
3182
3183 gtk_tree_store_set_column_types (GTK_TREE_STORE (model), n_columns: 1,
3184 types: column_types);
3185
3186
3187 /* + level1_1
3188 * + level2_1
3189 * + level3_1
3190 * + level4_1
3191 */
3192
3193 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &level1_1, NULL);
3194 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &level2_1, parent: &level1_1);
3195 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &level3_1, parent: &level2_1);
3196 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &level4_1, parent: &level3_1);
3197
3198 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &level1_1, 0, TRUE, -1);
3199 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &level2_1, 0, TRUE, -1);
3200 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &level3_1, 0, TRUE, -1);
3201 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &level4_1, 0, TRUE, -1);
3202
3203 assert_entire_model_unreferenced (ref_model);
3204
3205 filter_model = gtk_tree_model_filter_new (child_model: model, NULL);
3206 gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), column: 0);
3207 tree_view = gtk_tree_view_new_with_model (model: filter_model);
3208
3209 assert_node_ref_count (ref_model, iter: &level1_1, ref_count: 3);
3210 assert_node_ref_count (ref_model, iter: &level2_1, ref_count: 1);
3211 assert_node_ref_count (ref_model, iter: &level3_1, ref_count: 0);
3212 assert_node_ref_count (ref_model, iter: &level4_1, ref_count: 0);
3213
3214 path = gtk_tree_path_new_from_indices (first_index: 0, -1);
3215 gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path, TRUE);
3216 gtk_tree_path_free (path);
3217
3218 assert_node_ref_count (ref_model, iter: &level1_1, ref_count: 3);
3219 assert_node_ref_count (ref_model, iter: &level2_1, ref_count: 3);
3220 assert_node_ref_count (ref_model, iter: &level3_1, ref_count: 3);
3221 assert_node_ref_count (ref_model, iter: &level4_1, ref_count: 2);
3222
3223 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &level2_1, 0, FALSE, -1);
3224
3225 assert_node_ref_count (ref_model, iter: &level1_1, ref_count: 3);
3226 assert_node_ref_count (ref_model, iter: &level2_1, ref_count: 1);
3227 assert_node_ref_count (ref_model, iter: &level3_1, ref_count: 0);
3228 assert_node_ref_count (ref_model, iter: &level4_1, ref_count: 0);
3229
3230 g_object_unref (g_object_ref_sink (tree_view));
3231 gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
3232
3233 assert_node_ref_count (ref_model, iter: &level1_1, ref_count: 2);
3234 assert_node_ref_count (ref_model, iter: &level2_1, ref_count: 1);
3235 assert_node_ref_count (ref_model, iter: &level3_1, ref_count: 0);
3236 assert_node_ref_count (ref_model, iter: &level4_1, ref_count: 0);
3237
3238 g_object_unref (object: filter_model);
3239
3240 assert_node_ref_count (ref_model, iter: &level1_1, ref_count: 0);
3241 assert_node_ref_count (ref_model, iter: &level2_1, ref_count: 0);
3242 assert_node_ref_count (ref_model, iter: &level3_1, ref_count: 0);
3243 assert_node_ref_count (ref_model, iter: &level4_1, ref_count: 0);
3244
3245 g_object_unref (object: ref_model);
3246}
3247
3248static void
3249ref_count_filter_row_length_gt_1 (void)
3250{
3251 GtkTreeIter level1_1, level1_2;
3252 GtkTreeIter level2_1, level2_2;
3253 GtkTreeIter level3_1, level3_2;
3254 GtkTreeIter level4_1, level4_2;
3255 GtkTreeModel *model;
3256 GtkTreeModelRefCount *ref_model;
3257 GtkTreeModel *filter_model;
3258 GtkTreePath *path;
3259 GtkWidget *tree_view;
3260 GType column_types[] = { G_TYPE_BOOLEAN };
3261
3262 model = gtk_tree_model_ref_count_new ();
3263 ref_model = GTK_TREE_MODEL_REF_COUNT (model);
3264
3265 gtk_tree_store_set_column_types (GTK_TREE_STORE (model), n_columns: 1,
3266 types: column_types);
3267
3268
3269 /* + level1_1
3270 * + level1_2
3271 * + level2_1
3272 * + level2_2
3273 * + level3_1
3274 * + level3_2
3275 * + level4_1
3276 * + level4_2
3277 *
3278 * Node level1_2 is expanded. This makes that levels 1 and 2 are
3279 * visible. Level 3 is cached because its parent is visible. Level 4
3280 * is not cached.
3281 */
3282
3283 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &level1_1, NULL);
3284 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &level1_2, NULL);
3285 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &level2_1, parent: &level1_2);
3286 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &level2_2, parent: &level1_2);
3287 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &level3_1, parent: &level2_2);
3288 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &level3_2, parent: &level2_2);
3289 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &level4_1, parent: &level3_2);
3290 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &level4_2, parent: &level3_2);
3291
3292 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &level1_1, 0, TRUE, -1);
3293 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &level1_2, 0, TRUE, -1);
3294 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &level2_1, 0, TRUE, -1);
3295 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &level2_2, 0, TRUE, -1);
3296 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &level3_1, 0, TRUE, -1);
3297 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &level3_2, 0, TRUE, -1);
3298 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &level4_1, 0, TRUE, -1);
3299 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &level4_2, 0, TRUE, -1);
3300
3301 assert_entire_model_unreferenced (ref_model);
3302
3303 filter_model = gtk_tree_model_filter_new (child_model: model, NULL);
3304 gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), column: 0);
3305 tree_view = gtk_tree_view_new_with_model (model: filter_model);
3306
3307 assert_node_ref_count (ref_model, iter: &level1_1, ref_count: 2);
3308 assert_node_ref_count (ref_model, iter: &level1_2, ref_count: 2);
3309 assert_node_ref_count (ref_model, iter: &level2_1, ref_count: 1);
3310 assert_node_ref_count (ref_model, iter: &level2_2, ref_count: 0);
3311 assert_node_ref_count (ref_model, iter: &level3_1, ref_count: 0);
3312 assert_node_ref_count (ref_model, iter: &level3_2, ref_count: 0);
3313 assert_node_ref_count (ref_model, iter: &level4_1, ref_count: 0);
3314 assert_node_ref_count (ref_model, iter: &level4_2, ref_count: 0);
3315
3316 path = gtk_tree_path_new_from_indices (first_index: 1, -1);
3317 gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path, FALSE);
3318 gtk_tree_path_free (path);
3319
3320 assert_node_ref_count (ref_model, iter: &level1_1, ref_count: 2);
3321 assert_node_ref_count (ref_model, iter: &level1_2, ref_count: 2);
3322 assert_node_ref_count (ref_model, iter: &level2_1, ref_count: 2);
3323 assert_node_ref_count (ref_model, iter: &level2_2, ref_count: 2);
3324 assert_node_ref_count (ref_model, iter: &level3_1, ref_count: 1);
3325 assert_node_ref_count (ref_model, iter: &level3_2, ref_count: 0);
3326 assert_node_ref_count (ref_model, iter: &level4_1, ref_count: 0);
3327 assert_node_ref_count (ref_model, iter: &level4_2, ref_count: 0);
3328
3329 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &level4_1, 0, FALSE, -1);
3330
3331 assert_node_ref_count (ref_model, iter: &level1_1, ref_count: 2);
3332 assert_node_ref_count (ref_model, iter: &level1_2, ref_count: 2);
3333 assert_node_ref_count (ref_model, iter: &level2_1, ref_count: 2);
3334 assert_node_ref_count (ref_model, iter: &level2_2, ref_count: 2);
3335 assert_node_ref_count (ref_model, iter: &level3_1, ref_count: 1);
3336 assert_node_ref_count (ref_model, iter: &level3_2, ref_count: 0);
3337 assert_node_ref_count (ref_model, iter: &level4_1, ref_count: 0);
3338 assert_node_ref_count (ref_model, iter: &level4_2, ref_count: 0);
3339
3340 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &level3_1, 0, FALSE, -1);
3341
3342 assert_node_ref_count (ref_model, iter: &level1_1, ref_count: 2);
3343 assert_node_ref_count (ref_model, iter: &level1_2, ref_count: 2);
3344 assert_node_ref_count (ref_model, iter: &level2_1, ref_count: 2);
3345 assert_node_ref_count (ref_model, iter: &level2_2, ref_count: 2);
3346 assert_node_ref_count (ref_model, iter: &level3_1, ref_count: 0);
3347 assert_node_ref_count (ref_model, iter: &level3_2, ref_count: 1);
3348 assert_node_ref_count (ref_model, iter: &level4_1, ref_count: 0);
3349 assert_node_ref_count (ref_model, iter: &level4_2, ref_count: 0);
3350
3351 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &level2_2, 0, FALSE, -1);
3352
3353 assert_node_ref_count (ref_model, iter: &level1_1, ref_count: 2);
3354 assert_node_ref_count (ref_model, iter: &level1_2, ref_count: 2);
3355 assert_node_ref_count (ref_model, iter: &level2_1, ref_count: 2);
3356 assert_node_ref_count (ref_model, iter: &level2_2, ref_count: 0);
3357 assert_node_ref_count (ref_model, iter: &level3_1, ref_count: 0);
3358 assert_node_ref_count (ref_model, iter: &level3_2, ref_count: 0);
3359 assert_node_ref_count (ref_model, iter: &level4_1, ref_count: 0);
3360 assert_node_ref_count (ref_model, iter: &level4_2, ref_count: 0);
3361
3362 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &level1_2, 0, FALSE, -1);
3363
3364 assert_node_ref_count (ref_model, iter: &level1_1, ref_count: 2);
3365 assert_node_ref_count (ref_model, iter: &level1_2, ref_count: 0);
3366 assert_node_ref_count (ref_model, iter: &level2_1, ref_count: 0);
3367 assert_node_ref_count (ref_model, iter: &level2_2, ref_count: 0);
3368 assert_node_ref_count (ref_model, iter: &level3_1, ref_count: 0);
3369 assert_node_ref_count (ref_model, iter: &level3_2, ref_count: 0);
3370 assert_node_ref_count (ref_model, iter: &level4_1, ref_count: 0);
3371 assert_node_ref_count (ref_model, iter: &level4_2, ref_count: 0);
3372
3373 g_object_unref (g_object_ref_sink (tree_view));
3374 gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
3375
3376 assert_node_ref_count (ref_model, iter: &level1_1, ref_count: 1);
3377
3378 g_object_unref (object: filter_model);
3379
3380 assert_node_ref_count (ref_model, iter: &level1_1, ref_count: 0);
3381
3382 g_object_unref (object: ref_model);
3383}
3384
3385static void
3386ref_count_filter_row_length_gt_1_visible_children (void)
3387{
3388 GtkTreeIter level1_1, level1_2;
3389 GtkTreeIter level2_1, level2_2;
3390 GtkTreeIter level3_1, level3_2;
3391 GtkTreeIter level4_1, level4_2;
3392 GtkTreeModel *model;
3393 GtkTreeModelRefCount *ref_model;
3394 GtkTreeModel *filter_model;
3395 GtkTreePath *path;
3396 GtkWidget *tree_view;
3397 GType column_types[] = { G_TYPE_BOOLEAN };
3398
3399 model = gtk_tree_model_ref_count_new ();
3400 ref_model = GTK_TREE_MODEL_REF_COUNT (model);
3401
3402 gtk_tree_store_set_column_types (GTK_TREE_STORE (model), n_columns: 1,
3403 types: column_types);
3404
3405
3406 /* + level1_1
3407 * + level1_2
3408 * + level2_1
3409 * + level2_2
3410 * + level3_1
3411 * + level3_2
3412 * + level4_1
3413 * + level4_2
3414 */
3415
3416 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &level1_1, NULL);
3417 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &level1_2, NULL);
3418 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &level2_1, parent: &level1_2);
3419 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &level2_2, parent: &level1_2);
3420 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &level3_1, parent: &level2_2);
3421 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &level3_2, parent: &level2_2);
3422 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &level4_1, parent: &level3_2);
3423 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &level4_2, parent: &level3_2);
3424
3425 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &level1_1, 0, TRUE, -1);
3426 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &level1_2, 0, TRUE, -1);
3427 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &level2_1, 0, TRUE, -1);
3428 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &level2_2, 0, TRUE, -1);
3429 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &level3_1, 0, TRUE, -1);
3430 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &level3_2, 0, TRUE, -1);
3431 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &level4_1, 0, TRUE, -1);
3432 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &level4_2, 0, TRUE, -1);
3433
3434 assert_entire_model_unreferenced (ref_model);
3435
3436 filter_model = gtk_tree_model_filter_new (child_model: model, NULL);
3437 gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), column: 0);
3438 tree_view = gtk_tree_view_new_with_model (model: filter_model);
3439
3440 assert_node_ref_count (ref_model, iter: &level1_1, ref_count: 2);
3441 assert_node_ref_count (ref_model, iter: &level1_2, ref_count: 2);
3442 assert_node_ref_count (ref_model, iter: &level2_1, ref_count: 1);
3443 assert_node_ref_count (ref_model, iter: &level2_2, ref_count: 0);
3444 assert_node_ref_count (ref_model, iter: &level3_1, ref_count: 0);
3445 assert_node_ref_count (ref_model, iter: &level3_2, ref_count: 0);
3446 assert_node_ref_count (ref_model, iter: &level4_1, ref_count: 0);
3447 assert_node_ref_count (ref_model, iter: &level4_2, ref_count: 0);
3448
3449 path = gtk_tree_path_new_from_indices (first_index: 1, -1);
3450 gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path, TRUE);
3451 gtk_tree_path_free (path);
3452
3453 assert_node_ref_count (ref_model, iter: &level1_1, ref_count: 2);
3454 assert_node_ref_count (ref_model, iter: &level1_2, ref_count: 2);
3455 assert_node_ref_count (ref_model, iter: &level2_1, ref_count: 2);
3456 assert_node_ref_count (ref_model, iter: &level2_2, ref_count: 2);
3457 assert_node_ref_count (ref_model, iter: &level3_1, ref_count: 2);
3458 assert_node_ref_count (ref_model, iter: &level3_2, ref_count: 2);
3459 assert_node_ref_count (ref_model, iter: &level4_1, ref_count: 2);
3460 assert_node_ref_count (ref_model, iter: &level4_2, ref_count: 1);
3461
3462 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &level2_2, 0, FALSE, -1);
3463
3464 assert_node_ref_count (ref_model, iter: &level1_1, ref_count: 2);
3465 assert_node_ref_count (ref_model, iter: &level1_2, ref_count: 2);
3466 assert_node_ref_count (ref_model, iter: &level2_1, ref_count: 2);
3467 assert_node_ref_count (ref_model, iter: &level2_2, ref_count: 0);
3468 assert_node_ref_count (ref_model, iter: &level3_1, ref_count: 0);
3469 assert_node_ref_count (ref_model, iter: &level3_2, ref_count: 0);
3470 assert_node_ref_count (ref_model, iter: &level4_1, ref_count: 0);
3471 assert_node_ref_count (ref_model, iter: &level4_2, ref_count: 0);
3472
3473 g_object_unref (g_object_ref_sink (tree_view));
3474 gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
3475
3476 assert_node_ref_count (ref_model, iter: &level1_1, ref_count: 1);
3477 assert_node_ref_count (ref_model, iter: &level1_2, ref_count: 1);
3478 assert_node_ref_count (ref_model, iter: &level2_1, ref_count: 1);
3479 assert_node_ref_count (ref_model, iter: &level2_2, ref_count: 0);
3480 assert_node_ref_count (ref_model, iter: &level3_1, ref_count: 0);
3481 assert_node_ref_count (ref_model, iter: &level3_2, ref_count: 0);
3482 assert_node_ref_count (ref_model, iter: &level4_1, ref_count: 0);
3483 assert_node_ref_count (ref_model, iter: &level4_2, ref_count: 0);
3484
3485 g_object_unref (object: filter_model);
3486
3487 assert_node_ref_count (ref_model, iter: &level1_1, ref_count: 0);
3488 assert_node_ref_count (ref_model, iter: &level1_2, ref_count: 0);
3489 assert_node_ref_count (ref_model, iter: &level2_1, ref_count: 0);
3490 assert_node_ref_count (ref_model, iter: &level2_2, ref_count: 0);
3491 assert_node_ref_count (ref_model, iter: &level3_1, ref_count: 0);
3492 assert_node_ref_count (ref_model, iter: &level3_2, ref_count: 0);
3493 assert_node_ref_count (ref_model, iter: &level4_1, ref_count: 0);
3494 assert_node_ref_count (ref_model, iter: &level4_2, ref_count: 0);
3495
3496 g_object_unref (object: ref_model);
3497}
3498
3499static void
3500ref_count_cleanup (void)
3501{
3502 GtkTreeIter grandparent1, grandparent2, parent1, parent2;
3503 GtkTreeIter iter_parent1, iter_parent2, iter_parent2_first;
3504 GtkTreeModel *model;
3505 GtkTreeModelRefCount *ref_model;
3506 GtkTreeModel *filter_model;
3507 GtkWidget *tree_view;
3508
3509 model = gtk_tree_model_ref_count_new ();
3510 ref_model = GTK_TREE_MODEL_REF_COUNT (model);
3511
3512 /* + grandparent1
3513 * + grandparent2
3514 * + parent1
3515 * + iter_parent1
3516 * + parent2
3517 * + iter_parent2_first
3518 * + iter_parent2
3519 */
3520
3521 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &grandparent1, NULL);
3522 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &grandparent2, NULL);
3523 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &parent1, parent: &grandparent2);
3524 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &iter_parent1, parent: &parent1);
3525 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &parent2, parent: &grandparent2);
3526 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &iter_parent2_first, parent: &parent2);
3527 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &iter_parent2, parent: &parent2);
3528
3529 filter_model = gtk_tree_model_filter_new (child_model: model, NULL);
3530 tree_view = gtk_tree_view_new_with_model (model: filter_model);
3531
3532 gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
3533
3534 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 2);
3535 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 2);
3536 assert_node_ref_count (ref_model, iter: &parent1, ref_count: 3);
3537 assert_node_ref_count (ref_model, iter: &parent2, ref_count: 2);
3538 assert_node_ref_count (ref_model, iter: &iter_parent1, ref_count: 2);
3539 assert_node_ref_count (ref_model, iter: &iter_parent2_first, ref_count: 2);
3540 assert_node_ref_count (ref_model, iter: &iter_parent2, ref_count: 1);
3541
3542 g_object_unref (g_object_ref_sink (tree_view));
3543
3544 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 1);
3545 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 1);
3546 assert_node_ref_count (ref_model, iter: &parent1, ref_count: 2);
3547 assert_node_ref_count (ref_model, iter: &parent2, ref_count: 1);
3548 assert_node_ref_count (ref_model, iter: &iter_parent1, ref_count: 1);
3549 assert_node_ref_count (ref_model, iter: &iter_parent2_first, ref_count: 1);
3550 assert_node_ref_count (ref_model, iter: &iter_parent2, ref_count: 0);
3551
3552 gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
3553
3554 /* The root level and first level remain cached, only the references on the
3555 * first nodes of these levels are kept. Grandparent2 is the parent
3556 * of the first level with parent1, so grandparent2 keeps a reference
3557 * as well.
3558 */
3559 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 1);
3560 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 1);
3561 assert_node_ref_count (ref_model, iter: &parent1, ref_count: 1);
3562 assert_node_ref_count (ref_model, iter: &parent2, ref_count: 0);
3563 assert_node_ref_count (ref_model, iter: &iter_parent1, ref_count: 0);
3564 assert_node_ref_count (ref_model, iter: &iter_parent2_first, ref_count: 0);
3565 assert_node_ref_count (ref_model, iter: &iter_parent2, ref_count: 0);
3566
3567 g_object_unref (object: filter_model);
3568 g_object_unref (object: ref_model);
3569}
3570
3571static void
3572ref_count_row_ref (void)
3573{
3574 GtkTreeIter grandparent1, grandparent2, parent1, parent2;
3575 GtkTreeIter iter_parent1, iter_parent2, iter_parent2_first;
3576 GtkTreeModel *model;
3577 GtkTreeModelRefCount *ref_model;
3578 GtkTreeModel *filter_model;
3579 GtkWidget *tree_view;
3580 GtkTreePath *path;
3581 GtkTreeRowReference *row_ref;
3582
3583 model = gtk_tree_model_ref_count_new ();
3584 ref_model = GTK_TREE_MODEL_REF_COUNT (model);
3585
3586 /* + grandparent1
3587 * + grandparent2
3588 * + parent1
3589 * + iter_parent1
3590 * + parent2
3591 * + iter_parent2
3592 * + iter_parent2
3593 */
3594
3595 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &grandparent1, NULL);
3596 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &grandparent2, NULL);
3597 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &parent1, parent: &grandparent2);
3598 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &iter_parent1, parent: &parent1);
3599 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &parent2, parent: &grandparent2);
3600 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &iter_parent2_first, parent: &parent2);
3601 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &iter_parent2, parent: &parent2);
3602
3603 filter_model = gtk_tree_model_filter_new (child_model: model, NULL);
3604 tree_view = gtk_tree_view_new_with_model (model: filter_model);
3605
3606 path = gtk_tree_path_new_from_indices (first_index: 1, 1, 1, -1);
3607 row_ref = gtk_tree_row_reference_new (model: filter_model, path);
3608 gtk_tree_path_free (path);
3609
3610 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 2);
3611 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 3);
3612 assert_node_ref_count (ref_model, iter: &parent1, ref_count: 1);
3613 assert_node_ref_count (ref_model, iter: &parent2, ref_count: 2);
3614 assert_node_ref_count (ref_model, iter: &iter_parent1, ref_count: 0);
3615 assert_node_ref_count (ref_model, iter: &iter_parent2_first, ref_count: 1);
3616 assert_node_ref_count (ref_model, iter: &iter_parent2, ref_count: 1);
3617
3618 gtk_tree_row_reference_free (reference: row_ref);
3619
3620 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 2);
3621 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 2);
3622 assert_node_ref_count (ref_model, iter: &parent1, ref_count: 1);
3623 assert_node_ref_count (ref_model, iter: &parent2, ref_count: 1);
3624 assert_node_ref_count (ref_model, iter: &iter_parent1, ref_count: 0);
3625 assert_node_ref_count (ref_model, iter: &iter_parent2_first, ref_count: 1);
3626 assert_node_ref_count (ref_model, iter: &iter_parent2, ref_count: 0);
3627
3628 path = gtk_tree_path_new_from_indices (first_index: 1, 1, 1, -1);
3629 row_ref = gtk_tree_row_reference_new (model: filter_model, path);
3630 gtk_tree_path_free (path);
3631
3632 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 2);
3633 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 3);
3634 assert_node_ref_count (ref_model, iter: &parent1, ref_count: 1);
3635 assert_node_ref_count (ref_model, iter: &parent2, ref_count: 2);
3636 assert_node_ref_count (ref_model, iter: &iter_parent1, ref_count: 0);
3637 assert_node_ref_count (ref_model, iter: &iter_parent2_first, ref_count: 1);
3638 assert_node_ref_count (ref_model, iter: &iter_parent2, ref_count: 1);
3639
3640 gtk_tree_store_remove (GTK_TREE_STORE (model), iter: &parent2);
3641
3642 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 2);
3643 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 2);
3644 assert_node_ref_count (ref_model, iter: &parent1, ref_count: 1);
3645 assert_node_ref_count (ref_model, iter: &iter_parent1, ref_count: 0);
3646
3647 gtk_tree_row_reference_free (reference: row_ref);
3648
3649 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 2);
3650 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 2);
3651 assert_node_ref_count (ref_model, iter: &parent1, ref_count: 1);
3652 assert_node_ref_count (ref_model, iter: &iter_parent1, ref_count: 0);
3653
3654 g_object_unref (g_object_ref_sink (tree_view));
3655
3656 gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
3657
3658 /* The root level and first level remain cached, only the references on the
3659 * first nodes of these levels are kept. Grandparent2 is the parent
3660 * of the first level with parent1, so grandparent2 keeps a reference
3661 * as well.
3662 */
3663 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 1);
3664 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 1);
3665 assert_node_ref_count (ref_model, iter: &parent1, ref_count: 1);
3666
3667 g_object_unref (object: filter_model);
3668 g_object_unref (object: ref_model);
3669}
3670
3671static void
3672ref_count_transfer_root_level_insert (void)
3673{
3674 GtkTreeIter grandparent1, grandparent2, grandparent3;
3675 GtkTreeIter new_node;
3676 GtkTreeModel *model;
3677 GtkTreeModelRefCount *ref_model;
3678 GtkTreeModel *filter_model;
3679 GtkWidget *tree_view;
3680
3681 model = gtk_tree_model_ref_count_new ();
3682 ref_model = GTK_TREE_MODEL_REF_COUNT (model);
3683
3684 /* + grandparent1
3685 * + grandparent2
3686 * + grandparent3
3687 */
3688
3689 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &grandparent1, NULL);
3690 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &grandparent2, NULL);
3691 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &grandparent3, NULL);
3692
3693 filter_model = gtk_tree_model_filter_new (child_model: model, NULL);
3694 tree_view = gtk_tree_view_new_with_model (model: filter_model);
3695
3696 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 2);
3697 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 1);
3698 assert_node_ref_count (ref_model, iter: &grandparent3, ref_count: 1);
3699
3700 gtk_tree_store_prepend (GTK_TREE_STORE (model), iter: &new_node, NULL);
3701
3702 assert_node_ref_count (ref_model, iter: &new_node, ref_count: 2);
3703 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 1);
3704 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 1);
3705 assert_node_ref_count (ref_model, iter: &grandparent3, ref_count: 1);
3706
3707 g_object_unref (g_object_ref_sink (tree_view));
3708 g_object_unref (object: filter_model);
3709 g_object_unref (object: ref_model);
3710}
3711
3712static void
3713ref_count_transfer_root_level_remove (void)
3714{
3715 GtkTreeIter grandparent1, grandparent2, grandparent3;
3716 GtkTreeModel *model;
3717 GtkTreeModelRefCount *ref_model;
3718 GtkTreeModel *filter_model;
3719 GtkWidget *tree_view;
3720
3721 model = gtk_tree_model_ref_count_new ();
3722 ref_model = GTK_TREE_MODEL_REF_COUNT (model);
3723
3724 /* + grandparent1
3725 * + grandparent2
3726 * + grandparent3
3727 */
3728
3729 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &grandparent1, NULL);
3730 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &grandparent2, NULL);
3731 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &grandparent3, NULL);
3732
3733 filter_model = gtk_tree_model_filter_new (child_model: model, NULL);
3734 tree_view = gtk_tree_view_new_with_model (model: filter_model);
3735
3736 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 2);
3737 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 1);
3738 assert_node_ref_count (ref_model, iter: &grandparent3, ref_count: 1);
3739
3740 gtk_tree_store_remove (GTK_TREE_STORE (model), iter: &grandparent1);
3741
3742 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 2);
3743 assert_node_ref_count (ref_model, iter: &grandparent3, ref_count: 1);
3744
3745 gtk_tree_store_remove (GTK_TREE_STORE (model), iter: &grandparent2);
3746
3747 assert_node_ref_count (ref_model, iter: &grandparent3, ref_count: 2);
3748
3749 g_object_unref (g_object_ref_sink (tree_view));
3750 g_object_unref (object: filter_model);
3751 g_object_unref (object: ref_model);
3752}
3753
3754static void
3755ref_count_transfer_root_level_remove_filtered (void)
3756{
3757 GtkTreeIter grandparent1, grandparent2, grandparent3, grandparent4;
3758 GtkTreeModel *model;
3759 GtkTreeModelRefCount *ref_model;
3760 GtkTreeModel *filter_model;
3761 GtkWidget *tree_view;
3762 GType column_types[] = { G_TYPE_BOOLEAN };
3763
3764 model = gtk_tree_model_ref_count_new ();
3765 ref_model = GTK_TREE_MODEL_REF_COUNT (model);
3766
3767 gtk_tree_store_set_column_types (GTK_TREE_STORE (model), n_columns: 1,
3768 types: column_types);
3769
3770 /* + grandparent1
3771 * + grandparent2
3772 * + grandparent3
3773 * + grandparent4
3774 */
3775
3776 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &grandparent1, NULL);
3777 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &grandparent2, NULL);
3778 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &grandparent3, NULL);
3779 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &grandparent4, NULL);
3780
3781 /* Filter first node */
3782 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &grandparent1, 0, FALSE, -1);
3783 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &grandparent2, 0, TRUE, -1);
3784 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &grandparent3, 0, TRUE, -1);
3785 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &grandparent4, 0, TRUE, -1);
3786
3787 filter_model = gtk_tree_model_filter_new (child_model: model, NULL);
3788 gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), column: 0);
3789 tree_view = gtk_tree_view_new_with_model (model: filter_model);
3790
3791 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 0);
3792 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 2);
3793 assert_node_ref_count (ref_model, iter: &grandparent3, ref_count: 1);
3794 assert_node_ref_count (ref_model, iter: &grandparent4, ref_count: 1);
3795
3796 gtk_tree_store_remove (GTK_TREE_STORE (model), iter: &grandparent2);
3797
3798 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 0);
3799 assert_node_ref_count (ref_model, iter: &grandparent3, ref_count: 2);
3800 assert_node_ref_count (ref_model, iter: &grandparent4, ref_count: 1);
3801
3802 gtk_tree_store_remove (GTK_TREE_STORE (model), iter: &grandparent3);
3803
3804 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 0);
3805 assert_node_ref_count (ref_model, iter: &grandparent4, ref_count: 2);
3806
3807 gtk_tree_store_remove (GTK_TREE_STORE (model), iter: &grandparent4);
3808
3809 /* Check level length to get root level cached again */
3810 check_level_length (GTK_TREE_MODEL_FILTER (filter_model), NULL, expected_length: 0);
3811
3812 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 1);
3813
3814 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &grandparent2, NULL);
3815
3816 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 1);
3817 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 0);
3818
3819 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &grandparent2, 0, TRUE, -1);
3820
3821 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 1);
3822 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 1);
3823
3824 check_level_length (GTK_TREE_MODEL_FILTER (filter_model), NULL, expected_length: 1);
3825
3826 g_object_unref (g_object_ref_sink (tree_view));
3827 g_object_unref (object: filter_model);
3828 g_object_unref (object: ref_model);
3829}
3830
3831static void
3832ref_count_transfer_root_level_reordered (void)
3833{
3834 GtkTreeIter grandparent1, grandparent2, grandparent3;
3835 GtkTreeModel *model;
3836 GtkTreeModelRefCount *ref_model;
3837 GtkTreeModel *filter_model;
3838 GtkWidget *tree_view;
3839
3840 model = gtk_tree_model_ref_count_new ();
3841 ref_model = GTK_TREE_MODEL_REF_COUNT (model);
3842
3843 /* + grandparent1
3844 * + grandparent2
3845 * + grandparent3
3846 */
3847
3848 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &grandparent1, NULL);
3849 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &grandparent2, NULL);
3850 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &grandparent3, NULL);
3851
3852 filter_model = gtk_tree_model_filter_new (child_model: model, NULL);
3853 tree_view = gtk_tree_view_new_with_model (model: filter_model);
3854
3855 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 2);
3856 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 1);
3857 assert_node_ref_count (ref_model, iter: &grandparent3, ref_count: 1);
3858
3859 /* gtk_tree_store_move() will emit rows-reordered */
3860 gtk_tree_store_move_after (GTK_TREE_STORE (model),
3861 iter: &grandparent1, position: &grandparent3);
3862
3863 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 2);
3864 assert_node_ref_count (ref_model, iter: &grandparent3, ref_count: 1);
3865 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 1);
3866
3867 g_object_unref (g_object_ref_sink (tree_view));
3868 g_object_unref (object: filter_model);
3869 g_object_unref (object: ref_model);
3870}
3871
3872static void
3873ref_count_transfer_root_level_reordered_filtered (void)
3874{
3875 GtkTreeIter grandparent1, grandparent2, grandparent3;
3876 GtkTreeModel *model;
3877 GtkTreeModelRefCount *ref_model;
3878 GtkTreeModel *filter_model;
3879 GtkWidget *tree_view;
3880 GType column_types[] = { G_TYPE_BOOLEAN };
3881
3882 model = gtk_tree_model_ref_count_new ();
3883 ref_model = GTK_TREE_MODEL_REF_COUNT (model);
3884
3885 gtk_tree_store_set_column_types (GTK_TREE_STORE (model), n_columns: 1,
3886 types: column_types);
3887
3888 /* + grandparent1
3889 * + grandparent2
3890 * + grandparent3
3891 */
3892
3893 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &grandparent1, NULL);
3894 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &grandparent2, NULL);
3895 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &grandparent3, NULL);
3896
3897 /* Test with 1 node filtered */
3898 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &grandparent2, 0, TRUE, -1);
3899 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &grandparent3, 0, TRUE, -1);
3900
3901 filter_model = gtk_tree_model_filter_new (child_model: model, NULL);
3902 gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), column: 0);
3903 tree_view = gtk_tree_view_new_with_model (model: filter_model);
3904
3905 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 0);
3906 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 2);
3907 assert_node_ref_count (ref_model, iter: &grandparent3, ref_count: 1);
3908
3909 /* Move the invisible node grandparent1 */
3910
3911 /* gtk_tree_store_move() will emit rows-reordered */
3912 gtk_tree_store_move_after (GTK_TREE_STORE (model),
3913 iter: &grandparent1, position: &grandparent3);
3914
3915 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 2);
3916 assert_node_ref_count (ref_model, iter: &grandparent3, ref_count: 1);
3917 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 0);
3918
3919 /* Move the invisible node grandparent1 */
3920
3921 /* gtk_tree_store_move() will emit rows-reordered */
3922 gtk_tree_store_move_before (GTK_TREE_STORE (model),
3923 iter: &grandparent1, position: &grandparent2);
3924
3925 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 0);
3926 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 2);
3927 assert_node_ref_count (ref_model, iter: &grandparent3, ref_count: 1);
3928
3929 /* Now swap grandparent2 and grandparent3, first reference must transfer */
3930 /* gtk_tree_store_swap() will emit rows-reordered */
3931 gtk_tree_store_swap (GTK_TREE_STORE (model),
3932 a: &grandparent2, b: &grandparent3);
3933
3934 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 0);
3935 assert_node_ref_count (ref_model, iter: &grandparent3, ref_count: 2);
3936 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 1);
3937
3938 /* Swap back */
3939 gtk_tree_store_swap (GTK_TREE_STORE (model),
3940 a: &grandparent2, b: &grandparent3);
3941
3942 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 0);
3943 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 2);
3944 assert_node_ref_count (ref_model, iter: &grandparent3, ref_count: 1);
3945
3946 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &grandparent1, 0, TRUE, -1);
3947
3948 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 2);
3949 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 1);
3950 assert_node_ref_count (ref_model, iter: &grandparent3, ref_count: 1);
3951
3952 /* Test with two nodes filtered */
3953 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &grandparent1, 0, FALSE, -1);
3954 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &grandparent2, 0, FALSE, -1);
3955
3956 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 0);
3957 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 0);
3958 assert_node_ref_count (ref_model, iter: &grandparent3, ref_count: 2);
3959
3960 /* gtk_tree_store_move() will emit rows-reordered */
3961 gtk_tree_store_move_before (GTK_TREE_STORE (model),
3962 iter: &grandparent3, position: &grandparent1);
3963
3964 assert_node_ref_count (ref_model, iter: &grandparent3, ref_count: 2);
3965 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 0);
3966 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 0);
3967
3968 g_object_unref (g_object_ref_sink (tree_view));
3969 g_object_unref (object: filter_model);
3970 g_object_unref (object: ref_model);
3971}
3972
3973static void
3974ref_count_transfer_root_level_filter (void)
3975{
3976 GtkTreeIter grandparent1, grandparent2, grandparent3, grandparent4;
3977 GtkTreeIter new_node;
3978 GtkTreeModel *model;
3979 GtkTreeModelRefCount *ref_model;
3980 GtkTreeModel *filter_model;
3981 GtkWidget *tree_view;
3982 GType column_types[] = { G_TYPE_BOOLEAN };
3983
3984 model = gtk_tree_model_ref_count_new ();
3985 ref_model = GTK_TREE_MODEL_REF_COUNT (model);
3986
3987 gtk_tree_store_set_column_types (GTK_TREE_STORE (model), n_columns: 1,
3988 types: column_types);
3989
3990 /* + grandparent1
3991 * + grandparent2
3992 * + grandparent3
3993 * + grandparent4
3994 */
3995
3996 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &grandparent1, NULL);
3997 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &grandparent2, NULL);
3998 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &grandparent3, NULL);
3999 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &grandparent4, NULL);
4000
4001 /* Filter first node */
4002 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &grandparent1, 0, FALSE, -1);
4003 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &grandparent2, 0, TRUE, -1);
4004 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &grandparent3, 0, TRUE, -1);
4005 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &grandparent4, 0, TRUE, -1);
4006
4007 filter_model = gtk_tree_model_filter_new (child_model: model, NULL);
4008 gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), column: 0);
4009 tree_view = gtk_tree_view_new_with_model (model: filter_model);
4010
4011 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 0);
4012 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 2);
4013 assert_node_ref_count (ref_model, iter: &grandparent3, ref_count: 1);
4014 assert_node_ref_count (ref_model, iter: &grandparent4, ref_count: 1);
4015
4016 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &grandparent2, 0, FALSE, -1);
4017
4018 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 0);
4019 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 0);
4020 assert_node_ref_count (ref_model, iter: &grandparent3, ref_count: 2);
4021 assert_node_ref_count (ref_model, iter: &grandparent4, ref_count: 1);
4022
4023 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &grandparent3, 0, FALSE, -1);
4024
4025 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 0);
4026 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 0);
4027 assert_node_ref_count (ref_model, iter: &grandparent3, ref_count: 0);
4028 assert_node_ref_count (ref_model, iter: &grandparent4, ref_count: 2);
4029
4030 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &grandparent4, 0, FALSE, -1);
4031
4032 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 0);
4033 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 0);
4034 assert_node_ref_count (ref_model, iter: &grandparent3, ref_count: 0);
4035 assert_node_ref_count (ref_model, iter: &grandparent4, ref_count: 1);
4036
4037 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &grandparent2, 0, TRUE, -1);
4038
4039 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 0);
4040 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 2);
4041 assert_node_ref_count (ref_model, iter: &grandparent3, ref_count: 0);
4042 assert_node_ref_count (ref_model, iter: &grandparent4, ref_count: 0);
4043
4044 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &grandparent2, 0, FALSE, -1);
4045
4046 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 0);
4047 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 0);
4048 assert_node_ref_count (ref_model, iter: &grandparent3, ref_count: 0);
4049 assert_node_ref_count (ref_model, iter: &grandparent4, ref_count: 1);
4050
4051 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &grandparent1, 0, TRUE, -1);
4052
4053 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 2);
4054 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 0);
4055 assert_node_ref_count (ref_model, iter: &grandparent3, ref_count: 0);
4056 assert_node_ref_count (ref_model, iter: &grandparent4, ref_count: 0);
4057
4058 gtk_tree_store_prepend (GTK_TREE_STORE (model), iter: &new_node, NULL);
4059
4060 assert_node_ref_count (ref_model, iter: &new_node, ref_count: 0);
4061 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 2);
4062 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 0);
4063 assert_node_ref_count (ref_model, iter: &grandparent3, ref_count: 0);
4064 assert_node_ref_count (ref_model, iter: &grandparent4, ref_count: 0);
4065
4066 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &grandparent1, 0, FALSE, -1);
4067
4068 assert_node_ref_count (ref_model, iter: &new_node, ref_count: 0);
4069 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 0);
4070 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 0);
4071 assert_node_ref_count (ref_model, iter: &grandparent3, ref_count: 0);
4072 assert_node_ref_count (ref_model, iter: &grandparent4, ref_count: 1);
4073
4074 gtk_tree_store_remove (GTK_TREE_STORE (model), iter: &new_node);
4075 gtk_tree_store_prepend (GTK_TREE_STORE (model), iter: &new_node, NULL);
4076
4077 assert_node_ref_count (ref_model, iter: &new_node, ref_count: 0);
4078 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 0);
4079 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 0);
4080 assert_node_ref_count (ref_model, iter: &grandparent3, ref_count: 0);
4081 assert_node_ref_count (ref_model, iter: &grandparent4, ref_count: 1);
4082
4083 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &new_node, 0, TRUE, -1);
4084
4085 assert_node_ref_count (ref_model, iter: &new_node, ref_count: 2);
4086 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 0);
4087 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 0);
4088 assert_node_ref_count (ref_model, iter: &grandparent3, ref_count: 0);
4089 assert_node_ref_count (ref_model, iter: &grandparent4, ref_count: 0);
4090
4091 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &grandparent2, 0, TRUE, -1);
4092 gtk_tree_store_remove (GTK_TREE_STORE (model), iter: &new_node);
4093
4094 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 0);
4095 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 2);
4096 assert_node_ref_count (ref_model, iter: &grandparent3, ref_count: 0);
4097 assert_node_ref_count (ref_model, iter: &grandparent4, ref_count: 0);
4098
4099 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &grandparent4, 0, TRUE, -1);
4100 gtk_tree_store_remove (GTK_TREE_STORE (model), iter: &grandparent2);
4101
4102 g_object_unref (g_object_ref_sink (tree_view));
4103 g_object_unref (object: filter_model);
4104 g_object_unref (object: ref_model);
4105}
4106
4107static void
4108ref_count_transfer_child_level_insert (void)
4109{
4110 GtkTreeIter grandparent1;
4111 GtkTreeIter parent1, parent2, parent3;
4112 GtkTreeIter new_node;
4113 GtkTreeModel *model;
4114 GtkTreeModelRefCount *ref_model;
4115 GtkTreeModel *filter_model;
4116 GtkWidget *tree_view;
4117
4118 model = gtk_tree_model_ref_count_new ();
4119 ref_model = GTK_TREE_MODEL_REF_COUNT (model);
4120
4121 /* + grandparent1
4122 * + parent1
4123 * + parent2
4124 * + parent3
4125 */
4126
4127 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &grandparent1, NULL);
4128 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &parent1, parent: &grandparent1);
4129 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &parent2, parent: &grandparent1);
4130 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &parent3, parent: &grandparent1);
4131
4132 filter_model = gtk_tree_model_filter_new (child_model: model, NULL);
4133 tree_view = gtk_tree_view_new_with_model (model: filter_model);
4134
4135 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 3);
4136 assert_node_ref_count (ref_model, iter: &parent1, ref_count: 1);
4137 assert_node_ref_count (ref_model, iter: &parent2, ref_count: 0);
4138 assert_node_ref_count (ref_model, iter: &parent3, ref_count: 0);
4139
4140 gtk_tree_store_prepend (GTK_TREE_STORE (model), iter: &new_node, parent: &grandparent1);
4141
4142 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 3);
4143 assert_node_ref_count (ref_model, iter: &new_node, ref_count: 1);
4144 assert_node_ref_count (ref_model, iter: &parent1, ref_count: 0);
4145 assert_node_ref_count (ref_model, iter: &parent2, ref_count: 0);
4146 assert_node_ref_count (ref_model, iter: &parent3, ref_count: 0);
4147
4148 g_object_unref (g_object_ref_sink (tree_view));
4149 g_object_unref (object: filter_model);
4150 g_object_unref (object: ref_model);
4151}
4152
4153static void
4154ref_count_transfer_child_level_remove (void)
4155{
4156 GtkTreeIter grandparent1;
4157 GtkTreeIter parent1, parent2, parent3;
4158 GtkTreeModel *model;
4159 GtkTreeModelRefCount *ref_model;
4160 GtkTreeModel *filter_model;
4161 GtkWidget *tree_view;
4162
4163 model = gtk_tree_model_ref_count_new ();
4164 ref_model = GTK_TREE_MODEL_REF_COUNT (model);
4165
4166 /* + grandparent1
4167 * + parent1
4168 * + parent2
4169 * + parent3
4170 */
4171
4172 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &grandparent1, NULL);
4173 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &parent1, parent: &grandparent1);
4174 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &parent2, parent: &grandparent1);
4175 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &parent3, parent: &grandparent1);
4176
4177 filter_model = gtk_tree_model_filter_new (child_model: model, NULL);
4178 tree_view = gtk_tree_view_new_with_model (model: filter_model);
4179
4180 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 3);
4181 assert_node_ref_count (ref_model, iter: &parent1, ref_count: 1);
4182 assert_node_ref_count (ref_model, iter: &parent2, ref_count: 0);
4183 assert_node_ref_count (ref_model, iter: &parent3, ref_count: 0);
4184
4185 gtk_tree_store_remove (GTK_TREE_STORE (model), iter: &parent1);
4186
4187 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 3);
4188 assert_node_ref_count (ref_model, iter: &parent2, ref_count: 1);
4189 assert_node_ref_count (ref_model, iter: &parent3, ref_count: 0);
4190
4191 gtk_tree_store_remove (GTK_TREE_STORE (model), iter: &parent2);
4192
4193 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 3);
4194 assert_node_ref_count (ref_model, iter: &parent3, ref_count: 1);
4195
4196 g_object_unref (g_object_ref_sink (tree_view));
4197 g_object_unref (object: filter_model);
4198 g_object_unref (object: ref_model);
4199}
4200
4201static void
4202ref_count_transfer_child_level_remove_filtered (void)
4203{
4204 GtkTreeIter grandparent1;
4205 GtkTreeIter parent1, parent2, parent3, parent4;
4206 GtkTreeModel *model;
4207 GtkTreeModelRefCount *ref_model;
4208 GtkTreeModel *filter_model;
4209 GtkWidget *tree_view;
4210 GType column_types[] = { G_TYPE_BOOLEAN };
4211
4212 model = gtk_tree_model_ref_count_new ();
4213 ref_model = GTK_TREE_MODEL_REF_COUNT (model);
4214
4215 gtk_tree_store_set_column_types (GTK_TREE_STORE (model), n_columns: 1,
4216 types: column_types);
4217
4218 /* + grandparent1
4219 * + parent1
4220 * + parent2
4221 * + parent3
4222 * + parent4
4223 */
4224
4225 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &grandparent1, NULL);
4226 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &parent1, parent: &grandparent1);
4227 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &parent2, parent: &grandparent1);
4228 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &parent3, parent: &grandparent1);
4229 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &parent4, parent: &grandparent1);
4230
4231 /* Filter first node */
4232 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &grandparent1, 0, TRUE, -1);
4233 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &parent1, 0, FALSE, -1);
4234 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &parent2, 0, TRUE, -1);
4235 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &parent3, 0, TRUE, -1);
4236 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &parent4, 0, TRUE, -1);
4237
4238 filter_model = gtk_tree_model_filter_new (child_model: model, NULL);
4239 gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), column: 0);
4240 tree_view = gtk_tree_view_new_with_model (model: filter_model);
4241
4242 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 3);
4243 assert_node_ref_count (ref_model, iter: &parent1, ref_count: 0);
4244 assert_node_ref_count (ref_model, iter: &parent2, ref_count: 1);
4245 assert_node_ref_count (ref_model, iter: &parent3, ref_count: 0);
4246 assert_node_ref_count (ref_model, iter: &parent4, ref_count: 0);
4247
4248 gtk_tree_store_remove (GTK_TREE_STORE (model), iter: &parent2);
4249
4250 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 3);
4251 assert_node_ref_count (ref_model, iter: &parent1, ref_count: 0);
4252 assert_node_ref_count (ref_model, iter: &parent3, ref_count: 1);
4253 assert_node_ref_count (ref_model, iter: &parent4, ref_count: 0);
4254
4255 gtk_tree_store_remove (GTK_TREE_STORE (model), iter: &parent3);
4256
4257 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 3);
4258 assert_node_ref_count (ref_model, iter: &parent1, ref_count: 0);
4259 assert_node_ref_count (ref_model, iter: &parent4, ref_count: 1);
4260
4261 gtk_tree_store_remove (GTK_TREE_STORE (model), iter: &parent4);
4262
4263 /* Check level length to get level cached again */
4264 check_level_length (GTK_TREE_MODEL_FILTER (filter_model), level: "0", expected_length: 0);
4265
4266 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 3);
4267 assert_node_ref_count (ref_model, iter: &parent1, ref_count: 1);
4268
4269 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &parent2, parent: &grandparent1);
4270
4271 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 3);
4272 assert_node_ref_count (ref_model, iter: &parent1, ref_count: 1);
4273 assert_node_ref_count (ref_model, iter: &parent2, ref_count: 0);
4274
4275 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &parent2, 0, TRUE, -1);
4276
4277 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 3);
4278 assert_node_ref_count (ref_model, iter: &parent1, ref_count: 1);
4279 assert_node_ref_count (ref_model, iter: &parent2, ref_count: 0);
4280
4281 check_level_length (GTK_TREE_MODEL_FILTER (filter_model), level: "0", expected_length: 1);
4282
4283 g_object_unref (g_object_ref_sink (tree_view));
4284 g_object_unref (object: filter_model);
4285 g_object_unref (object: ref_model);
4286}
4287
4288static void
4289ref_count_transfer_child_level_reordered (void)
4290{
4291 GtkTreeIter grandparent1;
4292 GtkTreeIter parent1, parent2, parent3;
4293 GtkTreeModel *model;
4294 GtkTreeModelRefCount *ref_model;
4295 GtkTreeModel *filter_model;
4296 GtkWidget *tree_view;
4297
4298 model = gtk_tree_model_ref_count_new ();
4299 ref_model = GTK_TREE_MODEL_REF_COUNT (model);
4300
4301 /* + grandparent1
4302 * + parent1
4303 * + parent2
4304 * + parent3
4305 */
4306
4307 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &grandparent1, NULL);
4308 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &parent1, parent: &grandparent1);
4309 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &parent2, parent: &grandparent1);
4310 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &parent3, parent: &grandparent1);
4311
4312 filter_model = gtk_tree_model_filter_new (child_model: model, NULL);
4313 tree_view = gtk_tree_view_new_with_model (model: filter_model);
4314
4315 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 3);
4316 assert_node_ref_count (ref_model, iter: &parent1, ref_count: 1);
4317 assert_node_ref_count (ref_model, iter: &parent2, ref_count: 0);
4318 assert_node_ref_count (ref_model, iter: &parent3, ref_count: 0);
4319
4320 /* gtk_tree_store_move() will emit rows-reordered */
4321 gtk_tree_store_move_after (GTK_TREE_STORE (model),
4322 iter: &parent1, position: &parent3);
4323
4324 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 3);
4325 assert_node_ref_count (ref_model, iter: &parent2, ref_count: 1);
4326 assert_node_ref_count (ref_model, iter: &parent3, ref_count: 0);
4327 assert_node_ref_count (ref_model, iter: &parent1, ref_count: 0);
4328
4329 g_object_unref (g_object_ref_sink (tree_view));
4330 g_object_unref (object: filter_model);
4331 g_object_unref (object: ref_model);
4332}
4333
4334static void
4335ref_count_transfer_child_level_reordered_filtered (void)
4336{
4337 GtkTreeIter grandparent1;
4338 GtkTreeIter parent1, parent2, parent3;
4339 GtkTreeModel *model;
4340 GtkTreeModelRefCount *ref_model;
4341 GtkTreeModel *filter_model;
4342 GtkWidget *tree_view;
4343 GType column_types[] = { G_TYPE_BOOLEAN };
4344
4345 model = gtk_tree_model_ref_count_new ();
4346 ref_model = GTK_TREE_MODEL_REF_COUNT (model);
4347
4348 gtk_tree_store_set_column_types (GTK_TREE_STORE (model), n_columns: 1,
4349 types: column_types);
4350
4351 /* + grandparent1
4352 * + parent1
4353 * + parent2
4354 * + parent3
4355 */
4356
4357 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &grandparent1, NULL);
4358 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &parent1, parent: &grandparent1);
4359 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &parent2, parent: &grandparent1);
4360 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &parent3, parent: &grandparent1);
4361
4362 /* Test with 1 node filtered (parent1) */
4363 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &grandparent1, 0, TRUE, -1);
4364 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &parent2, 0, TRUE, -1);
4365 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &parent3, 0, TRUE, -1);
4366
4367 filter_model = gtk_tree_model_filter_new (child_model: model, NULL);
4368 gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), column: 0);
4369 tree_view = gtk_tree_view_new_with_model (model: filter_model);
4370
4371 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 3);
4372 assert_node_ref_count (ref_model, iter: &parent1, ref_count: 0);
4373 assert_node_ref_count (ref_model, iter: &parent2, ref_count: 1);
4374 assert_node_ref_count (ref_model, iter: &parent3, ref_count: 0);
4375
4376 /* Move invisible node parent 1 */
4377
4378 /* gtk_tree_store_move() will emit rows-reordered */
4379 gtk_tree_store_move_after (GTK_TREE_STORE (model),
4380 iter: &parent1, position: &parent3);
4381
4382 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 3);
4383 assert_node_ref_count (ref_model, iter: &parent2, ref_count: 1);
4384 assert_node_ref_count (ref_model, iter: &parent3, ref_count: 0);
4385 assert_node_ref_count (ref_model, iter: &parent1, ref_count: 0);
4386
4387 /* Move invisible node parent 1 */
4388
4389 /* gtk_tree_store_move() will emit rows-reordered */
4390 gtk_tree_store_move_before (GTK_TREE_STORE (model),
4391 iter: &parent1, position: &parent2);
4392
4393 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 3);
4394 assert_node_ref_count (ref_model, iter: &parent1, ref_count: 0);
4395 assert_node_ref_count (ref_model, iter: &parent2, ref_count: 1);
4396 assert_node_ref_count (ref_model, iter: &parent3, ref_count: 0);
4397
4398 /* Now swap parent2 and parent2, first reference must transfer */
4399 /* gtk_tree_store_swap() will emit rows-reordered */
4400 gtk_tree_store_swap (GTK_TREE_STORE (model),
4401 a: &parent2, b: &parent3);
4402
4403 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 3);
4404 assert_node_ref_count (ref_model, iter: &parent1, ref_count: 0);
4405 assert_node_ref_count (ref_model, iter: &parent3, ref_count: 1);
4406 assert_node_ref_count (ref_model, iter: &parent2, ref_count: 0);
4407
4408 /* Swap back */
4409 gtk_tree_store_swap (GTK_TREE_STORE (model),
4410 a: &parent2, b: &parent3);
4411
4412 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 3);
4413 assert_node_ref_count (ref_model, iter: &parent1, ref_count: 0);
4414 assert_node_ref_count (ref_model, iter: &parent2, ref_count: 1);
4415 assert_node_ref_count (ref_model, iter: &parent3, ref_count: 0);
4416
4417 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &parent1, 0, TRUE, -1);
4418
4419 assert_node_ref_count (ref_model, iter: &parent1, ref_count: 1);
4420 assert_node_ref_count (ref_model, iter: &parent2, ref_count: 0);
4421 assert_node_ref_count (ref_model, iter: &parent3, ref_count: 0);
4422
4423 /* Test with two nodes filtered */
4424 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &parent1, 0, FALSE, -1);
4425 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &parent2, 0, FALSE, -1);
4426
4427 assert_node_ref_count (ref_model, iter: &parent1, ref_count: 0);
4428 assert_node_ref_count (ref_model, iter: &parent2, ref_count: 0);
4429 assert_node_ref_count (ref_model, iter: &parent3, ref_count: 1);
4430
4431 /* gtk_tree_store_move() will emit rows-reordered */
4432 gtk_tree_store_move_before (GTK_TREE_STORE (model),
4433 iter: &parent3, position: &parent1);
4434
4435 assert_node_ref_count (ref_model, iter: &parent3, ref_count: 1);
4436 assert_node_ref_count (ref_model, iter: &parent2, ref_count: 0);
4437 assert_node_ref_count (ref_model, iter: &parent1, ref_count: 0);
4438
4439 g_object_unref (g_object_ref_sink (tree_view));
4440 g_object_unref (object: filter_model);
4441 g_object_unref (object: ref_model);
4442}
4443
4444static void
4445ref_count_transfer_child_level_filter (void)
4446{
4447 GtkTreeIter root;
4448 GtkTreeIter grandparent1, grandparent2, grandparent3, grandparent4;
4449 GtkTreeIter new_node;
4450 GtkTreeModel *model;
4451 GtkTreeModelRefCount *ref_model;
4452 GtkTreeModel *filter_model;
4453 GtkWidget *tree_view;
4454 GType column_types[] = { G_TYPE_BOOLEAN };
4455
4456 model = gtk_tree_model_ref_count_new ();
4457 ref_model = GTK_TREE_MODEL_REF_COUNT (model);
4458
4459 gtk_tree_store_set_column_types (GTK_TREE_STORE (model), n_columns: 1,
4460 types: column_types);
4461
4462 /* + root
4463 * + grandparent1
4464 * + grandparent2
4465 * + grandparent3
4466 * + grandparent4
4467 */
4468
4469 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &root, NULL);
4470 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &grandparent1, parent: &root);
4471 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &grandparent2, parent: &root);
4472 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &grandparent3, parent: &root);
4473 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &grandparent4, parent: &root);
4474
4475 /* Filter first node */
4476 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &root, 0, TRUE, -1);
4477 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &grandparent1, 0, FALSE, -1);
4478 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &grandparent2, 0, TRUE, -1);
4479 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &grandparent3, 0, TRUE, -1);
4480 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &grandparent4, 0, TRUE, -1);
4481
4482 filter_model = gtk_tree_model_filter_new (child_model: model, NULL);
4483 gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), column: 0);
4484 tree_view = gtk_tree_view_new_with_model (model: filter_model);
4485
4486 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 0);
4487 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 1);
4488 assert_node_ref_count (ref_model, iter: &grandparent3, ref_count: 0);
4489 assert_node_ref_count (ref_model, iter: &grandparent4, ref_count: 0);
4490
4491 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &grandparent2, 0, FALSE, -1);
4492
4493 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 0);
4494 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 0);
4495 assert_node_ref_count (ref_model, iter: &grandparent3, ref_count: 1);
4496 assert_node_ref_count (ref_model, iter: &grandparent4, ref_count: 0);
4497
4498 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &grandparent3, 0, FALSE, -1);
4499
4500 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 0);
4501 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 0);
4502 assert_node_ref_count (ref_model, iter: &grandparent3, ref_count: 0);
4503 assert_node_ref_count (ref_model, iter: &grandparent4, ref_count: 1);
4504
4505 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &grandparent4, 0, FALSE, -1);
4506
4507 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 0);
4508 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 0);
4509 assert_node_ref_count (ref_model, iter: &grandparent3, ref_count: 0);
4510 assert_node_ref_count (ref_model, iter: &grandparent4, ref_count: 1);
4511
4512 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &grandparent2, 0, TRUE, -1);
4513
4514 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 0);
4515 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 1);
4516 assert_node_ref_count (ref_model, iter: &grandparent3, ref_count: 0);
4517 assert_node_ref_count (ref_model, iter: &grandparent4, ref_count: 0);
4518
4519 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &grandparent2, 0, FALSE, -1);
4520
4521 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 0);
4522 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 0);
4523 assert_node_ref_count (ref_model, iter: &grandparent3, ref_count: 0);
4524 assert_node_ref_count (ref_model, iter: &grandparent4, ref_count: 1);
4525
4526 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &grandparent1, 0, TRUE, -1);
4527
4528 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 1);
4529 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 0);
4530 assert_node_ref_count (ref_model, iter: &grandparent3, ref_count: 0);
4531 assert_node_ref_count (ref_model, iter: &grandparent4, ref_count: 0);
4532
4533 gtk_tree_store_prepend (GTK_TREE_STORE (model), iter: &new_node, parent: &root);
4534
4535 assert_node_ref_count (ref_model, iter: &new_node, ref_count: 0);
4536 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 1);
4537 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 0);
4538 assert_node_ref_count (ref_model, iter: &grandparent3, ref_count: 0);
4539 assert_node_ref_count (ref_model, iter: &grandparent4, ref_count: 0);
4540
4541 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &grandparent1, 0, FALSE, -1);
4542
4543 assert_node_ref_count (ref_model, iter: &new_node, ref_count: 0);
4544 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 0);
4545 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 0);
4546 assert_node_ref_count (ref_model, iter: &grandparent3, ref_count: 0);
4547 assert_node_ref_count (ref_model, iter: &grandparent4, ref_count: 1);
4548
4549 gtk_tree_store_remove (GTK_TREE_STORE (model), iter: &new_node);
4550 gtk_tree_store_prepend (GTK_TREE_STORE (model), iter: &new_node, parent: &root);
4551
4552 assert_node_ref_count (ref_model, iter: &new_node, ref_count: 0);
4553 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 0);
4554 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 0);
4555 assert_node_ref_count (ref_model, iter: &grandparent3, ref_count: 0);
4556 assert_node_ref_count (ref_model, iter: &grandparent4, ref_count: 1);
4557
4558 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &new_node, 0, TRUE, -1);
4559
4560 assert_node_ref_count (ref_model, iter: &new_node, ref_count: 1);
4561 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 0);
4562 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 0);
4563 assert_node_ref_count (ref_model, iter: &grandparent3, ref_count: 0);
4564 assert_node_ref_count (ref_model, iter: &grandparent4, ref_count: 0);
4565
4566 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &grandparent2, 0, TRUE, -1);
4567 gtk_tree_store_remove (GTK_TREE_STORE (model), iter: &new_node);
4568
4569 assert_node_ref_count (ref_model, iter: &grandparent1, ref_count: 0);
4570 assert_node_ref_count (ref_model, iter: &grandparent2, ref_count: 1);
4571 assert_node_ref_count (ref_model, iter: &grandparent3, ref_count: 0);
4572 assert_node_ref_count (ref_model, iter: &grandparent4, ref_count: 0);
4573
4574 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &grandparent4, 0, TRUE, -1);
4575 gtk_tree_store_remove (GTK_TREE_STORE (model), iter: &grandparent2);
4576
4577 g_object_unref (g_object_ref_sink (tree_view));
4578 g_object_unref (object: filter_model);
4579 g_object_unref (object: ref_model);
4580}
4581
4582
4583static gboolean
4584specific_path_dependent_filter_func (GtkTreeModel *model,
4585 GtkTreeIter *iter,
4586 gpointer data)
4587{
4588 GtkTreePath *path;
4589
4590 path = gtk_tree_model_get_path (tree_model: model, iter);
4591 if (gtk_tree_path_get_indices (path)[0] < 4)
4592 return FALSE;
4593
4594 return TRUE;
4595}
4596
4597static void
4598specific_path_dependent_filter (void)
4599{
4600 int i;
4601 GtkTreeIter iter;
4602 GtkListStore *list;
4603 GtkTreeModel *sort;
4604 GtkTreeModel *filter;
4605
4606 list = gtk_list_store_new (n_columns: 1, G_TYPE_INT);
4607 gtk_list_store_insert_with_values (list_store: list, iter: &iter, position: 0, 0, 1, -1);
4608 gtk_list_store_insert_with_values (list_store: list, iter: &iter, position: 1, 0, 2, -1);
4609 gtk_list_store_insert_with_values (list_store: list, iter: &iter, position: 2, 0, 3, -1);
4610 gtk_list_store_insert_with_values (list_store: list, iter: &iter, position: 3, 0, 4, -1);
4611 gtk_list_store_insert_with_values (list_store: list, iter: &iter, position: 4, 0, 5, -1);
4612 gtk_list_store_insert_with_values (list_store: list, iter: &iter, position: 5, 0, 6, -1);
4613 gtk_list_store_insert_with_values (list_store: list, iter: &iter, position: 6, 0, 7, -1);
4614 gtk_list_store_insert_with_values (list_store: list, iter: &iter, position: 7, 0, 8, -1);
4615
4616 sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (list));
4617 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (sort), NULL);
4618 gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
4619 func: specific_path_dependent_filter_func,
4620 NULL, NULL);
4621
4622 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sort), sort_column_id: 0,
4623 order: GTK_SORT_DESCENDING);
4624
4625 for (i = 0; i < 4; i++)
4626 {
4627 if (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (list), iter: &iter,
4628 NULL, n: 1))
4629 gtk_list_store_remove (list_store: list, iter: &iter);
4630
4631 if (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (list), iter: &iter,
4632 NULL, n: 2))
4633 gtk_list_store_remove (list_store: list, iter: &iter);
4634 }
4635
4636 g_object_unref (object: filter);
4637 g_object_unref (object: sort);
4638 g_object_unref (object: list);
4639}
4640
4641
4642static gboolean
4643specific_append_after_collapse_visible_func (GtkTreeModel *model,
4644 GtkTreeIter *iter,
4645 gpointer data)
4646{
4647 int number;
4648 gboolean hide_negative_numbers;
4649
4650 gtk_tree_model_get (tree_model: model, iter, 1, &number, -1);
4651 hide_negative_numbers = GPOINTER_TO_INT (g_object_get_data (data, "private-hide-negative-numbers"));
4652
4653 return (number >= 0 || !hide_negative_numbers);
4654}
4655
4656static void
4657specific_append_after_collapse (void)
4658{
4659 /* This test is based on one of the test cases I found in my
4660 * old test cases directory. I unfortunately do not have a record
4661 * from who this test case originated. -Kris.
4662 *
4663 * General idea:
4664 * - Construct tree.
4665 * - Show tree, expand, collapse.
4666 * - Add a row.
4667 */
4668
4669 GtkTreeIter iter;
4670 GtkTreeIter child_iter;
4671 GtkTreeIter child_iter2;
4672 GtkTreePath *append_path;
4673 GtkTreeStore *store;
4674 GtkTreeModel *filter;
4675 GtkTreeModel *sort;
4676
4677 GtkWidget *window;
4678 GtkWidget *tree_view;
4679
4680 store = gtk_tree_store_new (n_columns: 2, G_TYPE_STRING, G_TYPE_INT);
4681
4682 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
4683 g_object_set_data (G_OBJECT (filter), key: "private-hide-negative-numbers",
4684 GINT_TO_POINTER (FALSE));
4685 gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
4686 func: specific_append_after_collapse_visible_func,
4687 data: filter, NULL);
4688
4689 sort = gtk_tree_model_sort_new_with_model (child_model: filter);
4690
4691 window = gtk_window_new ();
4692 tree_view = gtk_tree_view_new_with_model (model: sort);
4693 gtk_window_set_child (GTK_WINDOW (window), child: tree_view);
4694
4695 while (g_main_context_pending (NULL))
4696 g_main_context_iteration (NULL, TRUE);
4697
4698 gtk_tree_store_prepend (tree_store: store, iter: &iter, NULL);
4699 gtk_tree_store_set (tree_store: store, iter: &iter,
4700 0, "hallo", 1, 1, -1);
4701
4702 gtk_tree_store_append (tree_store: store, iter: &child_iter, parent: &iter);
4703 gtk_tree_store_set (tree_store: store, iter: &child_iter,
4704 0, "toemaar", 1, 1, -1);
4705
4706 gtk_tree_store_append (tree_store: store, iter: &child_iter2, parent: &child_iter);
4707 gtk_tree_store_set (tree_store: store, iter: &child_iter2,
4708 0, "very deep", 1, 1, -1);
4709
4710 append_path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), iter: &child_iter2);
4711
4712 gtk_tree_store_append (tree_store: store, iter: &child_iter, parent: &iter);
4713 gtk_tree_store_set (tree_store: store, iter: &child_iter,
4714 0, "sja", 1, 1, -1);
4715
4716 gtk_tree_store_append (tree_store: store, iter: &child_iter, parent: &iter);
4717 gtk_tree_store_set (tree_store: store, iter: &child_iter,
4718 0, "some word", 1, -1, -1);
4719
4720 /* Expand and collapse the tree */
4721 gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
4722 while (g_main_context_pending (NULL))
4723 g_main_context_iteration (NULL, TRUE);
4724
4725 gtk_tree_view_collapse_all (GTK_TREE_VIEW (tree_view));
4726 while (g_main_context_pending (NULL))
4727 g_main_context_iteration (NULL, TRUE);
4728
4729 /* Add another it */
4730 g_object_set_data (G_OBJECT (filter), key: "private-hide-negative-numbers",
4731 GINT_TO_POINTER (TRUE));
4732
4733 if (gtk_tree_model_get_iter (GTK_TREE_MODEL (store), iter: &iter, path: append_path))
4734 {
4735 gtk_tree_store_append (tree_store: store, iter: &child_iter, parent: &iter);
4736 gtk_tree_store_set (tree_store: store, iter: &child_iter,
4737 0, "new new new !!", 1, 1, -1);
4738 }
4739 gtk_tree_path_free (path: append_path);
4740
4741 /* Expand */
4742 gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
4743 while (g_main_context_pending (NULL))
4744 g_main_context_iteration (NULL, TRUE);
4745}
4746
4747
4748static int
4749specific_sort_filter_remove_node_compare_func (GtkTreeModel *model,
4750 GtkTreeIter *iter1,
4751 GtkTreeIter *iter2,
4752 gpointer data)
4753{
4754 return -1;
4755}
4756
4757static gboolean
4758specific_sort_filter_remove_node_visible_func (GtkTreeModel *model,
4759 GtkTreeIter *iter,
4760 gpointer data)
4761{
4762 char *item = NULL;
4763
4764 /* Do reference the model */
4765 gtk_tree_model_get (tree_model: model, iter, 0, &item, -1);
4766 g_free (mem: item);
4767
4768 return FALSE;
4769}
4770
4771static void
4772specific_sort_filter_remove_node (void)
4773{
4774 /* This test is based on one of the test cases I found in my
4775 * old test cases directory. I unfortunately do not have a record
4776 * from who this test case originated. -Kris.
4777 *
4778 * General idea:
4779 * - Create tree store, sort, filter models. The sort model has
4780 * a default sort func that is enabled, filter model a visible func
4781 * that defaults to returning FALSE.
4782 * - Remove a node from the tree store.
4783 */
4784
4785 GtkTreeIter iter;
4786 GtkTreeStore *store;
4787 GtkTreeModel *filter;
4788 GtkTreeModel *sort;
4789
4790 GtkWidget *window;
4791 GtkWidget *tree_view;
4792
4793 store = gtk_tree_store_new (n_columns: 1, G_TYPE_STRING);
4794 gtk_tree_store_append (tree_store: store, iter: &iter, NULL);
4795 gtk_tree_store_set (tree_store: store, iter: &iter, 0, "Hello1", -1);
4796
4797 gtk_tree_store_append (tree_store: store, iter: &iter, NULL);
4798 gtk_tree_store_set (tree_store: store, iter: &iter, 0, "Hello2", -1);
4799
4800 sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (store));
4801 gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (sort),
4802 sort_func: specific_sort_filter_remove_node_compare_func, NULL, NULL);
4803
4804 filter = gtk_tree_model_filter_new (child_model: sort, NULL);
4805 gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
4806 func: specific_sort_filter_remove_node_visible_func,
4807 data: filter, NULL);
4808
4809
4810 window = gtk_window_new ();
4811 tree_view = gtk_tree_view_new_with_model (model: filter);
4812 gtk_window_set_child (GTK_WINDOW (window), child: tree_view);
4813
4814 while (g_main_context_pending (NULL))
4815 g_main_context_iteration (NULL, TRUE);
4816
4817 /* Remove a node */
4818 gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), iter: &iter);
4819 gtk_tree_model_iter_next (GTK_TREE_MODEL (store), iter: &iter);
4820 gtk_tree_store_remove (tree_store: store, iter: &iter);
4821
4822 while (g_main_context_pending (NULL))
4823 g_main_context_iteration (NULL, TRUE);
4824}
4825
4826
4827static void
4828specific_sort_filter_remove_root (void)
4829{
4830 /* This test is based on one of the test cases I found in my
4831 * old test cases directory. I unfortunately do not have a record
4832 * from who this test case originated. -Kris.
4833 */
4834
4835 GtkTreeModel *model, *sort, *filter;
4836 GtkTreeIter root, mid, leaf;
4837 GtkTreePath *path;
4838
4839 model = GTK_TREE_MODEL (gtk_tree_store_new (1, G_TYPE_INT));
4840 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &root, NULL);
4841 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &mid, parent: &root);
4842 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &leaf, parent: &mid);
4843
4844 path = gtk_tree_model_get_path (tree_model: model, iter: &mid);
4845
4846 sort = gtk_tree_model_sort_new_with_model (child_model: model);
4847 filter = gtk_tree_model_filter_new (child_model: sort, root: path);
4848
4849 gtk_tree_path_free (path);
4850
4851 gtk_tree_store_remove (GTK_TREE_STORE (model), iter: &root);
4852
4853 g_object_unref (object: filter);
4854 g_object_unref (object: sort);
4855 g_object_unref (object: model);
4856}
4857
4858
4859static void
4860specific_root_mixed_visibility (void)
4861{
4862 int i;
4863 GtkTreeModel *filter;
4864 /* A bit nasty, apologies */
4865 FilterTest fixture;
4866
4867 fixture.store = gtk_tree_store_new (n_columns: 2, G_TYPE_STRING, G_TYPE_BOOLEAN);
4868
4869 for (i = 0; i < LEVEL_LENGTH; i++)
4870 {
4871 GtkTreeIter iter;
4872
4873 gtk_tree_store_insert (tree_store: fixture.store, iter: &iter, NULL, position: i);
4874 if (i % 2 == 0)
4875 create_tree_store_set_values (store: fixture.store, iter: &iter, TRUE);
4876 else
4877 create_tree_store_set_values (store: fixture.store, iter: &iter, FALSE);
4878 }
4879
4880 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (fixture.store), NULL);
4881 fixture.filter = GTK_TREE_MODEL_FILTER (filter);
4882 fixture.monitor = NULL;
4883
4884 gtk_tree_model_filter_set_visible_column (filter: fixture.filter, column: 1);
4885
4886 /* In order to trigger the potential bug, we should not access
4887 * the filter model here (so don't call the check functions).
4888 */
4889
4890 /* Change visibility of an odd row to TRUE */
4891 set_path_visibility (fixture: &fixture, path: "3", TRUE);
4892 check_filter_model (fixture: &fixture);
4893 check_level_length (filter: fixture.filter, NULL, expected_length: 4);
4894}
4895
4896
4897
4898static gboolean
4899specific_has_child_filter_filter_func (GtkTreeModel *model,
4900 GtkTreeIter *iter,
4901 gpointer data)
4902{
4903 return gtk_tree_model_iter_has_child (tree_model: model, iter);
4904}
4905
4906static void
4907specific_has_child_filter (void)
4908{
4909 GtkTreeModel *filter;
4910 GtkTreeIter iter, root;
4911 FilterTest fixture; /* This is not how it should be done */
4912 GtkWidget *tree_view;
4913
4914 fixture.store = gtk_tree_store_new (n_columns: 2, G_TYPE_STRING, G_TYPE_BOOLEAN);
4915 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (fixture.store), NULL);
4916 fixture.filter = GTK_TREE_MODEL_FILTER (filter);
4917 fixture.monitor = signal_monitor_new (client: filter);
4918
4919 tree_view = gtk_tree_view_new_with_model (model: filter);
4920
4921 /* We will filter on parent state using a filter function. We will
4922 * manually keep the boolean column in sync, so that we can use
4923 * check_filter_model() to check the consistency of the model.
4924 */
4925 /* FIXME: We need a check_filter_model() that is not tied to LEVEL_LENGTH
4926 * to be able to check the structure here. We keep the calls to
4927 * check_filter_model() commented out until then.
4928 */
4929 gtk_tree_model_filter_set_visible_func (filter: fixture.filter,
4930 func: specific_has_child_filter_filter_func,
4931 NULL, NULL);
4932
4933 /* The first node will be initially invisible: no signals */
4934 gtk_tree_store_append (tree_store: fixture.store, iter: &root, NULL);
4935 create_tree_store_set_values (store: fixture.store, iter: &root, FALSE);
4936
4937 /* check_filter_model (&fixture); */
4938 check_level_length (filter: fixture.filter, NULL, expected_length: 0);
4939 signal_monitor_assert_is_empty (m: fixture.monitor);
4940
4941 /* Insert a child node. This will cause the parent to become visible
4942 * since there is a child now.
4943 */
4944 signal_monitor_append_signal (m: fixture.monitor, signal: ROW_INSERTED, path_string: "0");
4945 signal_monitor_append_signal (m: fixture.monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "0");
4946 signal_monitor_append_signal (m: fixture.monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "0");
4947
4948 gtk_tree_store_append (tree_store: fixture.store, iter: &iter, parent: &root);
4949 create_tree_store_set_values (store: fixture.store, iter: &iter, TRUE);
4950
4951 /* Parent must now be visible. Do the level length check first,
4952 * to avoid modifying the child model triggering a row-changed to
4953 * the filter model.
4954 */
4955 check_level_length (filter: fixture.filter, NULL, expected_length: 1);
4956 check_level_length (filter: fixture.filter, level: "0", expected_length: 0);
4957 signal_monitor_assert_is_empty (m: fixture.monitor);
4958
4959 /* This should propagate row-changed */
4960 signal_monitor_append_signal (m: fixture.monitor, signal: ROW_CHANGED, path_string: "0");
4961 signal_monitor_append_signal (m: fixture.monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "0");
4962
4963 set_path_visibility (fixture: &fixture, path: "0", TRUE);
4964 /* check_filter_model (&fixture); */
4965 signal_monitor_assert_is_empty (m: fixture.monitor);
4966
4967 /* New root node, no child, so no signal */
4968 gtk_tree_store_append (tree_store: fixture.store, iter: &root, NULL);
4969 check_level_length (filter: fixture.filter, NULL, expected_length: 1);
4970 signal_monitor_assert_is_empty (m: fixture.monitor);
4971
4972 /* When the child comes in, this node will become visible */
4973 signal_monitor_append_signal (m: fixture.monitor, signal: ROW_INSERTED, path_string: "1");
4974 signal_monitor_append_signal (m: fixture.monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "1");
4975 signal_monitor_append_signal (m: fixture.monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "1");
4976 signal_monitor_append_signal (m: fixture.monitor, signal: ROW_CHANGED, path_string: "1");
4977 signal_monitor_append_signal (m: fixture.monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "1");
4978
4979 gtk_tree_store_append (tree_store: fixture.store, iter: &iter, parent: &root);
4980 check_level_length (filter: fixture.filter, NULL, expected_length: 2);
4981 check_level_length (filter: fixture.filter, level: "1", expected_length: 0);
4982
4983 create_tree_store_set_values (store: fixture.store, iter: &root, TRUE);
4984 create_tree_store_set_values (store: fixture.store, iter: &iter, TRUE);
4985
4986 /* check_filter_model (&fixture); */
4987 signal_monitor_assert_is_empty (m: fixture.monitor);
4988
4989 /* Add another child for 1 */
4990 gtk_tree_store_append (tree_store: fixture.store, iter: &iter, parent: &root);
4991 create_tree_store_set_values (store: fixture.store, iter: &iter, TRUE);
4992 check_level_length (filter: fixture.filter, NULL, expected_length: 2);
4993 check_level_length (filter: fixture.filter, level: "0", expected_length: 0);
4994 check_level_length (filter: fixture.filter, level: "1", expected_length: 0);
4995 signal_monitor_assert_is_empty (m: fixture.monitor);
4996
4997 /* Now remove one of the remaining child rows */
4998 signal_monitor_append_signal (m: fixture.monitor, signal: ROW_DELETED, path_string: "0");
4999
5000 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture.store),
5001 iter: &iter, path_string: "0:0");
5002 gtk_tree_store_remove (tree_store: fixture.store, iter: &iter);
5003
5004 check_level_length (filter: fixture.filter, NULL, expected_length: 1);
5005 check_level_length (filter: fixture.filter, level: "0", expected_length: 0);
5006
5007 set_path_visibility (fixture: &fixture, path: "0", FALSE);
5008 /* check_filter_model (&fixture); */
5009 signal_monitor_assert_is_empty (m: fixture.monitor);
5010
5011 g_object_unref (object: fixture.filter);
5012 g_object_unref (object: fixture.store);
5013 g_object_unref (g_object_ref_sink (tree_view));
5014}
5015
5016
5017static gboolean
5018specific_root_has_child_filter_filter_func (GtkTreeModel *model,
5019 GtkTreeIter *iter,
5020 gpointer data)
5021{
5022 int depth;
5023 GtkTreePath *path;
5024
5025 path = gtk_tree_model_get_path (tree_model: model, iter);
5026 depth = gtk_tree_path_get_depth (path);
5027 gtk_tree_path_free (path);
5028
5029 if (depth > 1)
5030 return TRUE;
5031 /* else */
5032 return gtk_tree_model_iter_has_child (tree_model: model, iter);
5033}
5034
5035static void
5036specific_root_has_child_filter (void)
5037{
5038 GtkTreeModel *filter;
5039 GtkTreeIter iter, root;
5040 FilterTest fixture; /* This is not how it should be done ... */
5041 GtkWidget *tree_view;
5042
5043 /* This is a variation on the above test case, specific has-child-filter,
5044 * herein the has-child check for visibility only applies to root level
5045 * nodes. In this test, children are always visible because we
5046 * only filter based on the "has child" criterion.
5047 */
5048
5049 fixture.store = gtk_tree_store_new (n_columns: 2, G_TYPE_STRING, G_TYPE_BOOLEAN);
5050 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (fixture.store), NULL);
5051 fixture.filter = GTK_TREE_MODEL_FILTER (filter);
5052 fixture.monitor = signal_monitor_new (client: filter);
5053
5054 tree_view = gtk_tree_view_new_with_model (model: filter);
5055
5056 /* We will filter on parent state using a filter function. We will
5057 * manually keep the boolean column in sync, so that we can use
5058 * check_filter_model() to check the consistency of the model.
5059 */
5060 /* FIXME: We need a check_filter_model() that is not tied to LEVEL_LENGTH
5061 * to be able to check the structure here. We keep the calls to
5062 * check_filter_model() commented out until then.
5063 */
5064 gtk_tree_model_filter_set_visible_func (filter: fixture.filter,
5065 func: specific_root_has_child_filter_filter_func,
5066 NULL, NULL);
5067
5068 /* Add a first node, this will be invisible initially, so no signal
5069 * should be emitted.
5070 */
5071 gtk_tree_store_append (tree_store: fixture.store, iter: &root, NULL);
5072 create_tree_store_set_values (store: fixture.store, iter: &root, FALSE);
5073
5074 signal_monitor_assert_is_empty (m: fixture.monitor);
5075 /* check_filter_model (&fixture); */
5076 check_level_length (filter: fixture.filter, NULL, expected_length: 0);
5077
5078 /* Add a child node. This will cause the parent to become visible,
5079 * so we expect row-inserted signals for both.
5080 */
5081 signal_monitor_append_signal (m: fixture.monitor, signal: ROW_INSERTED, path_string: "0");
5082 signal_monitor_append_signal (m: fixture.monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "0");
5083 signal_monitor_append_signal (m: fixture.monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "0");
5084
5085 gtk_tree_store_append (tree_store: fixture.store, iter: &iter, parent: &root);
5086 signal_monitor_assert_is_empty (m: fixture.monitor);
5087
5088 check_level_length (filter: fixture.filter, NULL, expected_length: 1);
5089 check_level_length (filter: fixture.filter, level: "0", expected_length: 1);
5090
5091 /* Modify the content of iter, no signals because the parent is not
5092 * expanded.
5093 */
5094 create_tree_store_set_values (store: fixture.store, iter: &iter, TRUE);
5095 signal_monitor_assert_is_empty (m: fixture.monitor);
5096
5097 /* Parent must now be visible. Do the level length check first,
5098 * to avoid modifying the child model triggering a row-changed to
5099 * the filter model.
5100 */
5101 check_level_length (filter: fixture.filter, NULL, expected_length: 1);
5102 check_level_length (filter: fixture.filter, level: "0", expected_length: 1);
5103
5104 /* Modify path 0 */
5105 signal_monitor_append_signal (m: fixture.monitor, signal: ROW_CHANGED, path_string: "0");
5106 signal_monitor_append_signal (m: fixture.monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "0");
5107
5108 set_path_visibility (fixture: &fixture, path: "0", TRUE);
5109 /* check_filter_model (&fixture); */
5110
5111 signal_monitor_assert_is_empty (m: fixture.monitor);
5112
5113 /* Insert another node in the root level. Initially invisible, so
5114 * not expecting any signal.
5115 */
5116 gtk_tree_store_append (tree_store: fixture.store, iter: &root, NULL);
5117 check_level_length (filter: fixture.filter, NULL, expected_length: 1);
5118
5119 signal_monitor_assert_is_empty (m: fixture.monitor);
5120
5121 /* Adding a child node which also makes parent at path 1 visible. */
5122 signal_monitor_append_signal (m: fixture.monitor, signal: ROW_INSERTED, path_string: "1");
5123 signal_monitor_append_signal (m: fixture.monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "1");
5124 signal_monitor_append_signal (m: fixture.monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "1");
5125
5126 gtk_tree_store_append (tree_store: fixture.store, iter: &iter, parent: &root);
5127 check_level_length (filter: fixture.filter, NULL, expected_length: 2);
5128 check_level_length (filter: fixture.filter, level: "1", expected_length: 1);
5129
5130 signal_monitor_assert_is_empty (m: fixture.monitor);
5131
5132 /* Check if row-changed is propagated */
5133 signal_monitor_append_signal (m: fixture.monitor, signal: ROW_CHANGED, path_string: "1");
5134 signal_monitor_append_signal (m: fixture.monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "1");
5135
5136 create_tree_store_set_values (store: fixture.store, iter: &root, TRUE);
5137 create_tree_store_set_values (store: fixture.store, iter: &iter, TRUE);
5138 /* check_filter_model (&fixture); */
5139 signal_monitor_assert_is_empty (m: fixture.monitor);
5140
5141 /* Insert another child under node 1 */
5142 gtk_tree_store_append (tree_store: fixture.store, iter: &iter, parent: &root);
5143 create_tree_store_set_values (store: fixture.store, iter: &iter, TRUE);
5144 check_level_length (filter: fixture.filter, NULL, expected_length: 2);
5145 check_level_length (filter: fixture.filter, level: "0", expected_length: 1);
5146 check_level_length (filter: fixture.filter, level: "1", expected_length: 2);
5147 signal_monitor_assert_is_empty (m: fixture.monitor);
5148
5149 /* Set a child node to invisible. This should not yield any
5150 * change, because filtering is only done on whether the root
5151 * node has a child, which it still has.
5152 */
5153 set_path_visibility (fixture: &fixture, path: "0:0", FALSE);
5154 signal_monitor_assert_is_empty (m: fixture.monitor);
5155
5156 /* Now remove one of the remaining child rows */
5157 signal_monitor_append_signal (m: fixture.monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "0");
5158 signal_monitor_append_signal (m: fixture.monitor, signal: ROW_DELETED, path_string: "0");
5159
5160 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture.store),
5161 iter: &iter, path_string: "0:0");
5162 gtk_tree_store_remove (tree_store: fixture.store, iter: &iter);
5163
5164 check_level_length (filter: fixture.filter, NULL, expected_length: 1);
5165 check_level_length (filter: fixture.filter, level: "0", expected_length: 2);
5166 signal_monitor_assert_is_empty (m: fixture.monitor);
5167
5168 /* Set visibility of 0 to FALSE, no-op for filter model since
5169 * the child 0:0 is already gone
5170 */
5171 set_path_visibility (fixture: &fixture, path: "0", FALSE);
5172 /* check_filter_model (&fixture); */
5173 signal_monitor_assert_is_empty (m: fixture.monitor);
5174
5175 g_object_unref (object: fixture.filter);
5176 g_object_unref (object: fixture.store);
5177 g_object_unref (g_object_ref_sink (tree_view));
5178}
5179
5180static void
5181specific_has_child_filter_on_sort_model (void)
5182{
5183 GtkTreeModel *filter;
5184 GtkTreeModel *sort_model;
5185 GtkTreeIter iter, root;
5186 FilterTest fixture; /* This is not how it should be done */
5187 GtkWidget *tree_view;
5188
5189 fixture.store = gtk_tree_store_new (n_columns: 2, G_TYPE_STRING, G_TYPE_BOOLEAN);
5190 sort_model = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (fixture.store));
5191 filter = gtk_tree_model_filter_new (child_model: sort_model, NULL);
5192 fixture.filter = GTK_TREE_MODEL_FILTER (filter);
5193 fixture.monitor = signal_monitor_new (client: filter);
5194
5195 tree_view = gtk_tree_view_new_with_model (model: filter);
5196
5197 /* We will filter on parent state using a filter function. We will
5198 * manually keep the boolean column in sync, so that we can use
5199 * check_filter_model() to check the consistency of the model.
5200 */
5201 /* FIXME: We need a check_filter_model() that is not tied to LEVEL_LENGTH
5202 * to be able to check the structure here. We keep the calls to
5203 * check_filter_model() commented out until then.
5204 */
5205 gtk_tree_model_filter_set_visible_func (filter: fixture.filter,
5206 func: specific_has_child_filter_filter_func,
5207 NULL, NULL);
5208
5209 /* The first node will be initially invisible: no signals */
5210 gtk_tree_store_append (tree_store: fixture.store, iter: &root, NULL);
5211 create_tree_store_set_values (store: fixture.store, iter: &root, FALSE);
5212
5213 /* check_filter_model (&fixture); */
5214 check_level_length (filter: fixture.filter, NULL, expected_length: 0);
5215 signal_monitor_assert_is_empty (m: fixture.monitor);
5216
5217 /* Insert a child node. This will cause the parent to become visible
5218 * since there is a child now.
5219 */
5220 signal_monitor_append_signal (m: fixture.monitor, signal: ROW_INSERTED, path_string: "0");
5221 signal_monitor_append_signal (m: fixture.monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "0");
5222
5223 gtk_tree_store_append (tree_store: fixture.store, iter: &iter, parent: &root);
5224 create_tree_store_set_values (store: fixture.store, iter: &iter, TRUE);
5225
5226 /* Parent must now be visible. Do the level length check first,
5227 * to avoid modifying the child model triggering a row-changed to
5228 * the filter model.
5229 */
5230 check_level_length (filter: fixture.filter, NULL, expected_length: 1);
5231 check_level_length (filter: fixture.filter, level: "0", expected_length: 0);
5232 signal_monitor_assert_is_empty (m: fixture.monitor);
5233
5234 /* This should propagate row-changed */
5235 signal_monitor_append_signal (m: fixture.monitor, signal: ROW_CHANGED, path_string: "0");
5236 signal_monitor_append_signal (m: fixture.monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "0");
5237
5238 set_path_visibility (fixture: &fixture, path: "0", TRUE);
5239 /* check_filter_model (&fixture); */
5240 signal_monitor_assert_is_empty (m: fixture.monitor);
5241
5242 /* New root node, no child, so no signal */
5243 gtk_tree_store_append (tree_store: fixture.store, iter: &root, NULL);
5244 check_level_length (filter: fixture.filter, NULL, expected_length: 1);
5245 signal_monitor_assert_is_empty (m: fixture.monitor);
5246
5247 /* When the child comes in, this node will become visible */
5248 signal_monitor_append_signal (m: fixture.monitor, signal: ROW_INSERTED, path_string: "1");
5249 signal_monitor_append_signal (m: fixture.monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "1");
5250 signal_monitor_append_signal (m: fixture.monitor, signal: ROW_CHANGED, path_string: "1");
5251 signal_monitor_append_signal (m: fixture.monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "1");
5252
5253 gtk_tree_store_append (tree_store: fixture.store, iter: &iter, parent: &root);
5254 check_level_length (filter: fixture.filter, NULL, expected_length: 2);
5255 check_level_length (filter: fixture.filter, level: "1", expected_length: 0);
5256
5257 create_tree_store_set_values (store: fixture.store, iter: &root, TRUE);
5258 create_tree_store_set_values (store: fixture.store, iter: &iter, TRUE);
5259
5260 /* check_filter_model (&fixture); */
5261 signal_monitor_assert_is_empty (m: fixture.monitor);
5262
5263 /* Add another child for 1 */
5264 gtk_tree_store_append (tree_store: fixture.store, iter: &iter, parent: &root);
5265 create_tree_store_set_values (store: fixture.store, iter: &iter, TRUE);
5266 check_level_length (filter: fixture.filter, NULL, expected_length: 2);
5267 check_level_length (filter: fixture.filter, level: "0", expected_length: 0);
5268 check_level_length (filter: fixture.filter, level: "1", expected_length: 0);
5269 signal_monitor_assert_is_empty (m: fixture.monitor);
5270
5271 /* Now remove one of the remaining child rows */
5272 signal_monitor_append_signal (m: fixture.monitor, signal: ROW_DELETED, path_string: "0");
5273
5274 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture.store),
5275 iter: &iter, path_string: "0:0");
5276 gtk_tree_store_remove (tree_store: fixture.store, iter: &iter);
5277
5278 check_level_length (filter: fixture.filter, NULL, expected_length: 1);
5279 check_level_length (filter: fixture.filter, level: "0", expected_length: 0);
5280
5281 set_path_visibility (fixture: &fixture, path: "0", FALSE);
5282 /* check_filter_model (&fixture); */
5283 signal_monitor_assert_is_empty (m: fixture.monitor);
5284
5285 g_object_unref (object: fixture.filter);
5286 g_object_unref (object: fixture.store);
5287 g_object_unref (g_object_ref_sink (tree_view));
5288}
5289
5290static gboolean
5291specific_at_least_2_children_filter_filter_func (GtkTreeModel *model,
5292 GtkTreeIter *iter,
5293 gpointer data)
5294{
5295 return gtk_tree_model_iter_n_children (tree_model: model, iter) >= 2;
5296}
5297
5298static void
5299specific_at_least_2_children_filter (void)
5300{
5301 GtkTreeModel *filter;
5302 GtkTreeIter iter, root;
5303 FilterTest fixture; /* This is not how it should be done */
5304 GtkWidget *tree_view;
5305
5306 fixture.store = gtk_tree_store_new (n_columns: 2, G_TYPE_STRING, G_TYPE_BOOLEAN);
5307 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (fixture.store), NULL);
5308 fixture.filter = GTK_TREE_MODEL_FILTER (filter);
5309 fixture.monitor = signal_monitor_new (client: filter);
5310
5311 tree_view = gtk_tree_view_new_with_model (model: filter);
5312
5313 gtk_tree_model_filter_set_visible_func (filter: fixture.filter,
5314 func: specific_at_least_2_children_filter_filter_func,
5315 NULL, NULL);
5316
5317 /* The first node will be initially invisible: no signals */
5318 gtk_tree_store_append (tree_store: fixture.store, iter: &root, NULL);
5319 create_tree_store_set_values (store: fixture.store, iter: &root, FALSE);
5320
5321 /* check_filter_model (&fixture); */
5322 check_level_length (filter: fixture.filter, NULL, expected_length: 0);
5323 signal_monitor_assert_is_empty (m: fixture.monitor);
5324
5325 /* Insert a child node. Nothing should happen.
5326 */
5327 gtk_tree_store_append (tree_store: fixture.store, iter: &iter, parent: &root);
5328 create_tree_store_set_values (store: fixture.store, iter: &iter, TRUE);
5329
5330 check_level_length (filter: fixture.filter, NULL, expected_length: 0);
5331 signal_monitor_assert_is_empty (m: fixture.monitor);
5332
5333 /* Insert a second child node. This will cause the parent to become
5334 * visible.
5335 */
5336 signal_monitor_append_signal (m: fixture.monitor, signal: ROW_INSERTED, path_string: "0");
5337 signal_monitor_append_signal (m: fixture.monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "0");
5338
5339 gtk_tree_store_append (tree_store: fixture.store, iter: &iter, parent: &root);
5340 create_tree_store_set_values (store: fixture.store, iter: &iter, TRUE);
5341
5342 /* Parent must now be visible. Do the level length check first,
5343 * to avoid modifying the child model triggering a row-changed to
5344 * the filter model.
5345 */
5346 check_level_length (filter: fixture.filter, NULL, expected_length: 1);
5347 check_level_length (filter: fixture.filter, level: "0", expected_length: 0);
5348 signal_monitor_assert_is_empty (m: fixture.monitor);
5349
5350 /* This should propagate row-changed */
5351 signal_monitor_append_signal (m: fixture.monitor, signal: ROW_CHANGED, path_string: "0");
5352 signal_monitor_append_signal (m: fixture.monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "0");
5353
5354 set_path_visibility (fixture: &fixture, path: "0", TRUE);
5355 /* check_filter_model (&fixture); */
5356 signal_monitor_assert_is_empty (m: fixture.monitor);
5357
5358 /* New root node, no child, so no signal */
5359 gtk_tree_store_append (tree_store: fixture.store, iter: &root, NULL);
5360 check_level_length (filter: fixture.filter, NULL, expected_length: 1);
5361 signal_monitor_assert_is_empty (m: fixture.monitor);
5362
5363 /* First child, no signal, no change */
5364 gtk_tree_store_append (tree_store: fixture.store, iter: &iter, parent: &root);
5365 check_level_length (filter: fixture.filter, NULL, expected_length: 1);
5366 signal_monitor_assert_is_empty (m: fixture.monitor);
5367
5368 /* When the second child comes in, this node will become visible */
5369 signal_monitor_append_signal (m: fixture.monitor, signal: ROW_INSERTED, path_string: "1");
5370 signal_monitor_append_signal (m: fixture.monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "1");
5371 signal_monitor_append_signal (m: fixture.monitor, signal: ROW_CHANGED, path_string: "1");
5372 signal_monitor_append_signal (m: fixture.monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "1");
5373
5374 gtk_tree_store_append (tree_store: fixture.store, iter: &iter, parent: &root);
5375 check_level_length (filter: fixture.filter, NULL, expected_length: 2);
5376 check_level_length (filter: fixture.filter, level: "1", expected_length: 0);
5377
5378 create_tree_store_set_values (store: fixture.store, iter: &root, TRUE);
5379 create_tree_store_set_values (store: fixture.store, iter: &iter, TRUE);
5380
5381 /* check_filter_model (&fixture); */
5382 signal_monitor_assert_is_empty (m: fixture.monitor);
5383
5384 /* Add another child for 1 */
5385 gtk_tree_store_append (tree_store: fixture.store, iter: &iter, parent: &root);
5386 create_tree_store_set_values (store: fixture.store, iter: &iter, TRUE);
5387 check_level_length (filter: fixture.filter, NULL, expected_length: 2);
5388 check_level_length (filter: fixture.filter, level: "0", expected_length: 0);
5389 check_level_length (filter: fixture.filter, level: "1", expected_length: 0);
5390 signal_monitor_assert_is_empty (m: fixture.monitor);
5391
5392 /* Now remove one of the remaining child rows */
5393 signal_monitor_append_signal (m: fixture.monitor, signal: ROW_DELETED, path_string: "0");
5394
5395 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture.store),
5396 iter: &iter, path_string: "0:0");
5397 gtk_tree_store_remove (tree_store: fixture.store, iter: &iter);
5398
5399 check_level_length (filter: fixture.filter, NULL, expected_length: 1);
5400 check_level_length (filter: fixture.filter, level: "0", expected_length: 0);
5401
5402 set_path_visibility (fixture: &fixture, path: "0", FALSE);
5403 /* check_filter_model (&fixture); */
5404 signal_monitor_assert_is_empty (m: fixture.monitor);
5405
5406 g_object_unref (object: fixture.filter);
5407 g_object_unref (object: fixture.store);
5408 g_object_unref (g_object_ref_sink (tree_view));
5409}
5410
5411static void
5412specific_at_least_2_children_filter_on_sort_model (void)
5413{
5414 GtkTreeRowReference *ref;
5415 GtkTreeModel *filter;
5416 GtkTreeModel *sort_model;
5417 GtkTreeIter iter, root;
5418 FilterTest fixture; /* This is not how it should be done */
5419 GtkWidget *tree_view;
5420
5421 fixture.store = gtk_tree_store_new (n_columns: 2, G_TYPE_STRING, G_TYPE_BOOLEAN);
5422 sort_model = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (fixture.store));
5423 filter = gtk_tree_model_filter_new (child_model: sort_model, NULL);
5424 fixture.filter = GTK_TREE_MODEL_FILTER (filter);
5425 fixture.monitor = signal_monitor_new (client: filter);
5426
5427 tree_view = gtk_tree_view_new_with_model (model: filter);
5428
5429 gtk_tree_model_filter_set_visible_func (filter: fixture.filter,
5430 func: specific_at_least_2_children_filter_filter_func,
5431 NULL, NULL);
5432
5433 /* The first node will be initially invisible: no signals */
5434 gtk_tree_store_append (tree_store: fixture.store, iter: &root, NULL);
5435 create_tree_store_set_values (store: fixture.store, iter: &root, FALSE);
5436
5437 /* check_filter_model (&fixture); */
5438 check_level_length (filter: fixture.filter, NULL, expected_length: 0);
5439 signal_monitor_assert_is_empty (m: fixture.monitor);
5440
5441 /* Insert a child node. Nothing should happen.
5442 */
5443 gtk_tree_store_append (tree_store: fixture.store, iter: &iter, parent: &root);
5444 create_tree_store_set_values (store: fixture.store, iter: &iter, TRUE);
5445
5446 check_level_length (filter: fixture.filter, NULL, expected_length: 0);
5447 signal_monitor_assert_is_empty (m: fixture.monitor);
5448
5449 {
5450 GtkTreePath *path = gtk_tree_path_new_from_indices (first_index: 0, 0, -1);
5451
5452 ref = gtk_tree_row_reference_new (model: sort_model, path);
5453 gtk_tree_path_free (path);
5454 }
5455
5456 /* Insert a second child node. This will cause the parent to become
5457 * visible.
5458 */
5459 signal_monitor_append_signal (m: fixture.monitor, signal: ROW_INSERTED, path_string: "0");
5460 signal_monitor_append_signal (m: fixture.monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "0");
5461
5462 gtk_tree_store_append (tree_store: fixture.store, iter: &iter, parent: &root);
5463 create_tree_store_set_values (store: fixture.store, iter: &iter, TRUE);
5464
5465 /* Parent must now be visible. Do the level length check first,
5466 * to avoid modifying the child model triggering a row-changed to
5467 * the filter model.
5468 */
5469 check_level_length (filter: fixture.filter, NULL, expected_length: 1);
5470 check_level_length (filter: fixture.filter, level: "0", expected_length: 0);
5471 signal_monitor_assert_is_empty (m: fixture.monitor);
5472
5473 /* This should propagate row-changed */
5474 signal_monitor_append_signal (m: fixture.monitor, signal: ROW_CHANGED, path_string: "0");
5475 signal_monitor_append_signal (m: fixture.monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "0");
5476
5477 set_path_visibility (fixture: &fixture, path: "0", TRUE);
5478 /* check_filter_model (&fixture); */
5479 signal_monitor_assert_is_empty (m: fixture.monitor);
5480
5481 /* New root node, no child, so no signal */
5482 gtk_tree_store_append (tree_store: fixture.store, iter: &root, NULL);
5483 check_level_length (filter: fixture.filter, NULL, expected_length: 1);
5484 signal_monitor_assert_is_empty (m: fixture.monitor);
5485
5486 gtk_tree_row_reference_free (reference: ref);
5487 g_object_unref (object: fixture.filter);
5488 g_object_unref (object: fixture.store);
5489 g_object_unref (g_object_ref_sink (tree_view));
5490}
5491
5492
5493static void
5494specific_filter_add_child (void)
5495{
5496 /* This test is based on one of the test cases I found in my
5497 * old test cases directory. I unfortunately do not have a record
5498 * from who this test case originated. -Kris.
5499 */
5500
5501 GtkTreeIter iter;
5502 GtkTreeIter iter_first;
5503 GtkTreeIter child;
5504 GtkTreeStore *store;
5505 GtkTreeModel *filter G_GNUC_UNUSED;
5506
5507 store = gtk_tree_store_new (n_columns: 1, G_TYPE_STRING);
5508
5509 gtk_tree_store_append (tree_store: store, iter: &iter_first, NULL);
5510 gtk_tree_store_set (tree_store: store, iter: &iter_first, 0, "Hello", -1);
5511
5512 gtk_tree_store_append (tree_store: store, iter: &iter, NULL);
5513 gtk_tree_store_set (tree_store: store, iter: &iter, 0, "Hello", -1);
5514
5515 gtk_tree_store_append (tree_store: store, iter: &iter, NULL);
5516 gtk_tree_store_set (tree_store: store, iter: &iter, 0, "Hello", -1);
5517
5518 gtk_tree_store_append (tree_store: store, iter: &iter, NULL);
5519 gtk_tree_store_set (tree_store: store, iter: &iter, 0, "Hello", -1);
5520
5521 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
5522
5523 gtk_tree_store_set (tree_store: store, iter: &iter, 0, "Hello", -1);
5524 gtk_tree_store_append (tree_store: store, iter: &child, parent: &iter_first);
5525 gtk_tree_store_set (tree_store: store, iter: &child, 0, "Hello", -1);
5526}
5527
5528static void
5529specific_list_store_clear (void)
5530{
5531 GtkTreeIter iter;
5532 GtkListStore *list;
5533 GtkTreeModel *filter;
5534 GtkWidget *view G_GNUC_UNUSED;
5535
5536 list = gtk_list_store_new (n_columns: 1, G_TYPE_INT);
5537 gtk_list_store_insert_with_values (list_store: list, iter: &iter, position: 0, 0, 1, -1);
5538 gtk_list_store_insert_with_values (list_store: list, iter: &iter, position: 1, 0, 2, -1);
5539 gtk_list_store_insert_with_values (list_store: list, iter: &iter, position: 2, 0, 3, -1);
5540 gtk_list_store_insert_with_values (list_store: list, iter: &iter, position: 3, 0, 4, -1);
5541 gtk_list_store_insert_with_values (list_store: list, iter: &iter, position: 4, 0, 5, -1);
5542 gtk_list_store_insert_with_values (list_store: list, iter: &iter, position: 5, 0, 6, -1);
5543 gtk_list_store_insert_with_values (list_store: list, iter: &iter, position: 6, 0, 7, -1);
5544 gtk_list_store_insert_with_values (list_store: list, iter: &iter, position: 7, 0, 8, -1);
5545
5546 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (list), NULL);
5547 view = gtk_tree_view_new_with_model (model: filter);
5548
5549 gtk_list_store_clear (list_store: list);
5550}
5551
5552static void
5553specific_sort_ref_leaf_and_remove_ancestor (void)
5554{
5555 GtkTreeIter iter, child, child2, child3;
5556 GtkTreeStore *tree;
5557 GtkTreeModel *sort;
5558 GtkTreePath *path;
5559 GtkTreeRowReference *rowref;
5560 GtkWidget *view G_GNUC_UNUSED;
5561
5562 tree = gtk_tree_store_new (n_columns: 1, G_TYPE_INT);
5563 gtk_tree_store_insert_with_values (tree_store: tree, iter: &iter, NULL, position: 0, 0, 1, -1);
5564 gtk_tree_store_insert_with_values (tree_store: tree, iter: &iter, NULL, position: 1, 0, 2, -1);
5565 gtk_tree_store_insert_with_values (tree_store: tree, iter: &iter, NULL, position: 2, 0, 3, -1);
5566 gtk_tree_store_insert_with_values (tree_store: tree, iter: &iter, NULL, position: 3, 0, 4, -1);
5567
5568 gtk_tree_store_insert_with_values (tree_store: tree, iter: &child, parent: &iter, position: 0, 0, 50, -1);
5569 gtk_tree_store_insert_with_values (tree_store: tree, iter: &child2, parent: &child, position: 0, 0, 6, -1);
5570 gtk_tree_store_insert_with_values (tree_store: tree, iter: &child3, parent: &child2, position: 0, 0, 7, -1);
5571
5572 sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (tree));
5573 view = gtk_tree_view_new_with_model (model: sort);
5574 gtk_tree_view_expand_all (GTK_TREE_VIEW (view));
5575
5576 path = gtk_tree_path_new_from_indices (first_index: 3, 0, 0, 0, -1);
5577 rowref = gtk_tree_row_reference_new (model: sort, path);
5578 gtk_tree_path_free (path);
5579
5580 path = gtk_tree_path_new_from_indices (first_index: 3, 0, 0, 0, -1);
5581 rowref = gtk_tree_row_reference_new (model: sort, path);
5582 gtk_tree_path_free (path);
5583
5584 path = gtk_tree_path_new_from_indices (first_index: 3, 0, -1);
5585 rowref = gtk_tree_row_reference_new (model: sort, path);
5586 gtk_tree_path_free (path);
5587
5588 path = gtk_tree_path_new_from_indices (first_index: 3, -1);
5589 rowref = gtk_tree_row_reference_new (model: sort, path);
5590 gtk_tree_path_free (path);
5591
5592 /* Deleting a parent */
5593 path = gtk_tree_path_new_from_indices (first_index: 3, 0, -1);
5594 gtk_tree_model_get_iter (GTK_TREE_MODEL (tree), iter: &iter, path);
5595 gtk_tree_store_remove (tree_store: tree, iter: &iter);
5596 gtk_tree_path_free (path);
5597
5598 gtk_tree_row_reference_free (reference: rowref);
5599}
5600
5601static void
5602specific_ref_leaf_and_remove_ancestor (void)
5603{
5604 GtkTreeIter iter, child, child2, child3;
5605 GtkTreeStore *tree;
5606 GtkTreeModel *filter;
5607 GtkTreePath *path;
5608 GtkTreeRowReference *rowref;
5609 GtkWidget *view G_GNUC_UNUSED;
5610
5611 tree = gtk_tree_store_new (n_columns: 1, G_TYPE_INT);
5612 gtk_tree_store_insert_with_values (tree_store: tree, iter: &iter, NULL, position: 0, 0, 1, -1);
5613 gtk_tree_store_insert_with_values (tree_store: tree, iter: &iter, NULL, position: 1, 0, 2, -1);
5614 gtk_tree_store_insert_with_values (tree_store: tree, iter: &iter, NULL, position: 2, 0, 3, -1);
5615 gtk_tree_store_insert_with_values (tree_store: tree, iter: &iter, NULL, position: 3, 0, 4, -1);
5616
5617 gtk_tree_store_insert_with_values (tree_store: tree, iter: &child, parent: &iter, position: 0, 0, 50, -1);
5618 gtk_tree_store_insert_with_values (tree_store: tree, iter: &child2, parent: &child, position: 0, 0, 6, -1);
5619 gtk_tree_store_insert_with_values (tree_store: tree, iter: &child3, parent: &child2, position: 0, 0, 7, -1);
5620
5621 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (tree), NULL);
5622 view = gtk_tree_view_new_with_model (model: filter);
5623 gtk_tree_view_expand_all (GTK_TREE_VIEW (view));
5624
5625 path = gtk_tree_path_new_from_indices (first_index: 3, 0, 0, 0, -1);
5626 rowref = gtk_tree_row_reference_new (model: filter, path);
5627 gtk_tree_path_free (path);
5628
5629 path = gtk_tree_path_new_from_indices (first_index: 3, 0, 0, 0, -1);
5630 rowref = gtk_tree_row_reference_new (model: filter, path);
5631 gtk_tree_path_free (path);
5632
5633 path = gtk_tree_path_new_from_indices (first_index: 3, 0, -1);
5634 rowref = gtk_tree_row_reference_new (model: filter, path);
5635 gtk_tree_path_free (path);
5636
5637 path = gtk_tree_path_new_from_indices (first_index: 3, -1);
5638 rowref = gtk_tree_row_reference_new (model: filter, path);
5639 gtk_tree_path_free (path);
5640
5641 /* Deleting a parent */
5642 path = gtk_tree_path_new_from_indices (first_index: 3, 0, -1);
5643 gtk_tree_model_get_iter (GTK_TREE_MODEL (tree), iter: &iter, path);
5644 gtk_tree_store_remove (tree_store: tree, iter: &iter);
5645 gtk_tree_path_free (path);
5646
5647 gtk_tree_row_reference_free (reference: rowref);
5648}
5649
5650static void
5651specific_virtual_ref_leaf_and_remove_ancestor (void)
5652{
5653 GtkTreeIter iter, child, child2, child3;
5654 GtkTreeStore *tree;
5655 GtkTreeModel *filter;
5656 GtkTreePath *path;
5657 GtkTreeRowReference *rowref;
5658 GtkWidget *view G_GNUC_UNUSED;
5659
5660 tree = gtk_tree_store_new (n_columns: 1, G_TYPE_INT);
5661 gtk_tree_store_insert_with_values (tree_store: tree, iter: &iter, NULL, position: 0, 0, 1, -1);
5662 gtk_tree_store_insert_with_values (tree_store: tree, iter: &iter, NULL, position: 1, 0, 2, -1);
5663 gtk_tree_store_insert_with_values (tree_store: tree, iter: &iter, NULL, position: 2, 0, 3, -1);
5664 gtk_tree_store_insert_with_values (tree_store: tree, iter: &iter, NULL, position: 3, 0, 4, -1);
5665
5666 gtk_tree_store_insert_with_values (tree_store: tree, iter: &child, parent: &iter, position: 0, 0, 50, -1);
5667 gtk_tree_store_insert_with_values (tree_store: tree, iter: &child2, parent: &child, position: 0, 0, 6, -1);
5668 gtk_tree_store_insert_with_values (tree_store: tree, iter: &child3, parent: &child2, position: 0, 0, 7, -1);
5669
5670 /* Set a virtual root of 3:0 */
5671 path = gtk_tree_path_new_from_indices (first_index: 3, 0, -1);
5672 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (tree), root: path);
5673 gtk_tree_path_free (path);
5674
5675 view = gtk_tree_view_new_with_model (model: filter);
5676 gtk_tree_view_expand_all (GTK_TREE_VIEW (view));
5677
5678 path = gtk_tree_path_new_from_indices (first_index: 0, 0, -1);
5679 rowref = gtk_tree_row_reference_new (model: filter, path);
5680 gtk_tree_path_free (path);
5681
5682 path = gtk_tree_path_new_from_indices (first_index: 0, 0, -1);
5683 rowref = gtk_tree_row_reference_new (model: filter, path);
5684 gtk_tree_path_free (path);
5685
5686 path = gtk_tree_path_new_from_indices (first_index: 0, -1);
5687 rowref = gtk_tree_row_reference_new (model: filter, path);
5688 gtk_tree_path_free (path);
5689
5690 /* Deleting the virtual root */
5691 path = gtk_tree_path_new_from_indices (first_index: 3, 0, -1);
5692 gtk_tree_model_get_iter (GTK_TREE_MODEL (tree), iter: &iter, path);
5693 gtk_tree_store_remove (tree_store: tree, iter: &iter);
5694 gtk_tree_path_free (path);
5695
5696 gtk_tree_row_reference_free (reference: rowref);
5697}
5698
5699
5700static int
5701specific_bug_301558_sort_func (GtkTreeModel *model,
5702 GtkTreeIter *a,
5703 GtkTreeIter *b,
5704 gpointer data)
5705{
5706 int i, j;
5707
5708 gtk_tree_model_get (tree_model: model, iter: a, 0, &i, -1);
5709 gtk_tree_model_get (tree_model: model, iter: b, 0, &j, -1);
5710
5711 return j - i;
5712}
5713
5714static void
5715specific_bug_301558 (void)
5716{
5717 /* Test case for GNOME Bugzilla bug 301558 provided by
5718 * Markku Vire.
5719 */
5720 GtkTreeStore *tree;
5721 GtkTreeModel *filter;
5722 GtkTreeModel *sort;
5723 GtkTreeIter root, iter, iter2;
5724 GtkWidget *view G_GNUC_UNUSED;
5725 int i;
5726 gboolean add;
5727
5728 /*http://bugzilla.gnome.org/show_bug.cgi?id=301558 */
5729
5730 tree = gtk_tree_store_new (n_columns: 2, G_TYPE_INT, G_TYPE_BOOLEAN);
5731 gtk_tree_store_append (tree_store: tree, iter: &iter, NULL);
5732 gtk_tree_store_set (tree_store: tree, iter: &iter, 0, 123, 1, TRUE, -1);
5733 gtk_tree_store_append (tree_store: tree, iter: &iter2, parent: &iter);
5734 gtk_tree_store_set (tree_store: tree, iter: &iter2, 0, 73, 1, TRUE, -1);
5735
5736 sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (tree));
5737 gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (sort),
5738 sort_func: specific_bug_301558_sort_func,
5739 NULL, NULL);
5740
5741 filter = gtk_tree_model_filter_new (child_model: sort, NULL);
5742 gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter), column: 1);
5743
5744 view = gtk_tree_view_new_with_model (model: filter);
5745
5746 while (g_main_context_pending (NULL))
5747 g_main_context_iteration (NULL, TRUE);
5748
5749 add = TRUE;
5750
5751 for (i = 0; i < 10; i++)
5752 {
5753 if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (tree), iter: &root))
5754 g_assert_not_reached ();
5755
5756 if (add)
5757 {
5758 gtk_tree_store_append (tree_store: tree, iter: &iter, parent: &root);
5759 gtk_tree_store_set (tree_store: tree, iter: &iter, 0, 456, 1, TRUE, -1);
5760 }
5761 else
5762 {
5763 int n;
5764 n = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (tree), iter: &root);
5765 gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (tree), iter: &iter,
5766 parent: &root, n: n - 1);
5767 gtk_tree_store_remove (tree_store: tree, iter: &iter);
5768 }
5769
5770 add = !add;
5771 }
5772}
5773
5774
5775static gboolean
5776specific_bug_311955_filter_func (GtkTreeModel *model,
5777 GtkTreeIter *iter,
5778 gpointer data)
5779{
5780 int value;
5781
5782 gtk_tree_model_get (tree_model: model, iter, 0, &value, -1);
5783
5784 return (value != 0);
5785}
5786
5787static void
5788specific_bug_311955 (void)
5789{
5790 /* This is a test case for GNOME Bugzilla bug 311955. It was written
5791 * by Markku Vire.
5792 */
5793 GtkTreeIter iter, child, root;
5794 GtkTreeStore *store;
5795 GtkTreeModel *sort;
5796 GtkTreeModel *filter;
5797
5798 GtkWidget *window G_GNUC_UNUSED;
5799 GtkWidget *tree_view;
5800 int i;
5801 int n;
5802 GtkTreePath *path;
5803
5804 /*http://bugzilla.gnome.org/show_bug.cgi?id=311955 */
5805
5806 store = gtk_tree_store_new (n_columns: 1, G_TYPE_INT);
5807
5808 gtk_tree_store_append (tree_store: store, iter: &root, NULL);
5809 gtk_tree_store_set (tree_store: store, iter: &root, 0, 33, -1);
5810
5811 gtk_tree_store_append (tree_store: store, iter: &iter, parent: &root);
5812 gtk_tree_store_set (tree_store: store, iter: &iter, 0, 50, -1);
5813
5814 gtk_tree_store_append (tree_store: store, iter: &iter, NULL);
5815 gtk_tree_store_set (tree_store: store, iter: &iter, 0, 22, -1);
5816
5817 sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (store));
5818 filter = gtk_tree_model_filter_new (child_model: sort, NULL);
5819
5820 gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
5821 func: specific_bug_311955_filter_func,
5822 NULL, NULL);
5823
5824 window = gtk_window_new ();
5825 tree_view = gtk_tree_view_new_with_model (model: filter);
5826 g_object_unref (object: store);
5827
5828 gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
5829
5830 while (g_main_context_pending (NULL))
5831 g_main_context_iteration (NULL, TRUE);
5832
5833 check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, expected_length: 2);
5834 check_level_length (GTK_TREE_MODEL_FILTER (filter), level: "0", expected_length: 1);
5835
5836 /* Fill model */
5837 for (i = 0; i < 4; i++)
5838 {
5839 gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), iter: &root);
5840
5841 gtk_tree_store_append (tree_store: store, iter: &iter, parent: &root);
5842
5843 if (i < 3)
5844 gtk_tree_store_set (tree_store: store, iter: &iter, 0, i, -1);
5845
5846 if (i % 2 == 0)
5847 {
5848 gtk_tree_store_append (tree_store: store, iter: &child, parent: &iter);
5849 gtk_tree_store_set (tree_store: store, iter: &child, 0, 10, -1);
5850 }
5851 }
5852
5853 while (g_main_context_pending (NULL))
5854 g_main_context_iteration (NULL, TRUE);
5855
5856 check_level_length (GTK_TREE_MODEL_FILTER (filter), level: "0", expected_length: 3);
5857 check_level_length (GTK_TREE_MODEL_FILTER (filter), level: "0:2", expected_length: 1);
5858
5859 /* Remove bottommost child from the tree. */
5860 gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), iter: &root);
5861 n = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (store), iter: &root);
5862
5863 if (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (store), iter: &iter, parent: &root, n: n - 2))
5864 {
5865 if (gtk_tree_model_iter_children (GTK_TREE_MODEL (store), iter: &child, parent: &iter))
5866 gtk_tree_store_remove (tree_store: store, iter: &child);
5867 }
5868 else
5869 g_assert_not_reached ();
5870
5871 path = gtk_tree_path_new_from_indices (first_index: 0, 2, -1);
5872 gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path, FALSE);
5873 gtk_tree_path_free (path);
5874
5875 check_level_length (GTK_TREE_MODEL_FILTER (filter), level: "0", expected_length: 3);
5876 check_level_length (GTK_TREE_MODEL_FILTER (filter), level: "0:2", expected_length: 0);
5877}
5878
5879static void
5880specific_bug_311955_clean (void)
5881{
5882 /* Cleaned up version of the test case for GNOME Bugzilla bug 311955,
5883 * which is easier to understand.
5884 */
5885 GtkTreeIter iter, child, grandchild;
5886 GtkTreeStore *store;
5887 GtkTreeModel *sort;
5888 GtkTreeModel *filter;
5889
5890 GtkWidget *tree_view;
5891 GtkTreePath *path;
5892
5893 store = gtk_tree_store_new (n_columns: 1, G_TYPE_INT);
5894
5895 gtk_tree_store_append (tree_store: store, iter: &iter, NULL);
5896 gtk_tree_store_set (tree_store: store, iter: &iter, 0, 1, -1);
5897
5898 gtk_tree_store_append (tree_store: store, iter: &child, parent: &iter);
5899 gtk_tree_store_set (tree_store: store, iter: &child, 0, 1, -1);
5900
5901 sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (store));
5902 filter = gtk_tree_model_filter_new (child_model: sort, NULL);
5903
5904 gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
5905 func: specific_bug_311955_filter_func,
5906 NULL, NULL);
5907
5908 tree_view = gtk_tree_view_new_with_model (model: filter);
5909 g_object_unref (object: store);
5910
5911 gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
5912
5913 while (g_main_context_pending (NULL))
5914 g_main_context_iteration (NULL, TRUE);
5915
5916 check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, expected_length: 1);
5917 check_level_length (GTK_TREE_MODEL_FILTER (filter), level: "0", expected_length: 1);
5918
5919 gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), iter: &iter);
5920
5921 gtk_tree_store_append (tree_store: store, iter: &child, parent: &iter);
5922 gtk_tree_store_set (tree_store: store, iter: &child, 0, 0, -1);
5923
5924 gtk_tree_store_append (tree_store: store, iter: &child, parent: &iter);
5925 gtk_tree_store_set (tree_store: store, iter: &child, 0, 1, -1);
5926
5927 gtk_tree_store_append (tree_store: store, iter: &child, parent: &iter);
5928 gtk_tree_store_set (tree_store: store, iter: &child, 0, 1, -1);
5929
5930 gtk_tree_store_append (tree_store: store, iter: &grandchild, parent: &child);
5931 gtk_tree_store_set (tree_store: store, iter: &grandchild, 0, 1, -1);
5932
5933 gtk_tree_store_append (tree_store: store, iter: &child, parent: &iter);
5934 /* Don't set a value: assume 0 */
5935
5936 /* Remove leaf node, check trigger row-has-child-toggled */
5937 path = gtk_tree_path_new_from_indices (first_index: 0, 3, 0, -1);
5938 gtk_tree_model_get_iter (GTK_TREE_MODEL (store), iter: &iter, path);
5939 gtk_tree_path_free (path);
5940 gtk_tree_store_remove (tree_store: store, iter: &iter);
5941
5942 path = gtk_tree_path_new_from_indices (first_index: 0, 2, -1);
5943 gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path, FALSE);
5944 gtk_tree_path_free (path);
5945
5946 check_level_length (GTK_TREE_MODEL_FILTER (filter), level: "0", expected_length: 3);
5947 check_level_length (GTK_TREE_MODEL_FILTER (filter), level: "0:2", expected_length: 0);
5948
5949 g_object_unref (g_object_ref_sink (tree_view));
5950}
5951
5952static void
5953specific_bug_346800 (void)
5954{
5955 /* This is a test case for GNOME Bugzilla bug 346800. It was written
5956 * by Jonathan Matthew.
5957 */
5958
5959 GtkTreeIter node_iters[50];
5960 GtkTreeIter child_iters[50];
5961 GtkTreeModel *model;
5962 GtkTreeModelFilter *filter;
5963 GtkTreeStore *store;
5964 GType *columns;
5965 int i;
5966 int items = 50;
5967 columns = g_new (GType, 2);
5968 columns[0] = G_TYPE_STRING;
5969 columns[1] = G_TYPE_BOOLEAN;
5970 store = gtk_tree_store_newv (n_columns: 2, types: columns);
5971 model = GTK_TREE_MODEL (store);
5972 GList *junk = NULL;
5973
5974 /*http://bugzilla.gnome.org/show_bug.cgi?id=346800 */
5975
5976 filter = GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (model, NULL));
5977 gtk_tree_model_filter_set_visible_column (filter, column: 1);
5978
5979 for (i=0; i<items; i++)
5980 {
5981 /* allocate random amounts of junk, otherwise the filter model's arrays can expand without moving */
5982
5983 junk = g_list_append (list: junk, data: g_malloc (n_bytes: 138));
5984 gtk_tree_store_append (tree_store: store, iter: &node_iters[i], NULL);
5985 gtk_tree_store_set (tree_store: store, iter: &node_iters[i],
5986 0, "something",
5987 1, ((i%6) == 0) ? FALSE : TRUE,
5988 -1);
5989
5990 junk = g_list_append (list: junk, data: g_malloc (n_bytes: 47));
5991 gtk_tree_store_append (tree_store: store, iter: &child_iters[i], parent: &node_iters[i]);
5992 gtk_tree_store_set (tree_store: store, iter: &child_iters[i],
5993 0, "something else",
5994 1, FALSE,
5995 -1);
5996 gtk_tree_model_filter_refilter (filter);
5997
5998 if (i > 6)
5999 {
6000 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &child_iters[i-1], 1,
6001 (i & 1) ? TRUE : FALSE, -1);
6002 gtk_tree_model_filter_refilter (filter);
6003
6004 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &child_iters[i-2], 1,
6005 (i & 1) ? FALSE: TRUE, -1);
6006 gtk_tree_model_filter_refilter (filter);
6007 }
6008 }
6009
6010 g_list_free_full (list: junk, free_func: g_free);
6011}
6012
6013static gboolean
6014specific_bug_464173_visible_func (GtkTreeModel *model,
6015 GtkTreeIter *iter,
6016 gpointer data)
6017{
6018 gboolean *visible = (gboolean *)data;
6019
6020 return *visible;
6021}
6022
6023static void
6024specific_bug_464173 (void)
6025{
6026 /* Test case for GNOME Bugzilla bug 464173, test case written
6027 * by Andreas Koehler.
6028 */
6029 GtkTreeStore *model;
6030 GtkTreeModelFilter *f_model;
6031 GtkTreeIter iter1, iter2;
6032 GtkWidget *view G_GNUC_UNUSED;
6033 gboolean visible = TRUE;
6034
6035 /*http://bugzilla.gnome.org/show_bug.cgi?id=464173 */
6036
6037 model = gtk_tree_store_new (n_columns: 1, G_TYPE_STRING);
6038 gtk_tree_store_append (tree_store: model, iter: &iter1, NULL);
6039 gtk_tree_store_set (tree_store: model, iter: &iter1, 0, "Foo", -1);
6040 gtk_tree_store_append (tree_store: model, iter: &iter2, parent: &iter1);
6041 gtk_tree_store_set (tree_store: model, iter: &iter2, 0, "Bar", -1);
6042
6043 f_model = GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (GTK_TREE_MODEL(model), NULL));
6044 gtk_tree_model_filter_set_visible_func (filter: f_model,
6045 func: specific_bug_464173_visible_func,
6046 data: &visible, NULL);
6047
6048 view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (f_model));
6049
6050 visible = FALSE;
6051 gtk_tree_model_filter_refilter (filter: f_model);
6052}
6053
6054
6055static gboolean
6056specific_bug_540201_filter_func (GtkTreeModel *model,
6057 GtkTreeIter *iter,
6058 gpointer data)
6059{
6060 gboolean has_children;
6061
6062 has_children = gtk_tree_model_iter_has_child (tree_model: model, iter);
6063
6064 return has_children;
6065}
6066
6067static void
6068specific_bug_540201 (void)
6069{
6070 /* Test case for GNOME Bugzilla bug 540201, steps provided by
6071 * Charles Day.
6072 */
6073 GtkTreeIter iter, root;
6074 GtkTreeStore *store;
6075 GtkTreeModel *filter;
6076
6077 GtkWidget *tree_view G_GNUC_UNUSED;
6078
6079 /*http://bugzilla.gnome.org/show_bug.cgi?id=540201 */
6080
6081 store = gtk_tree_store_new (n_columns: 1, G_TYPE_INT);
6082
6083 gtk_tree_store_append (tree_store: store, iter: &root, NULL);
6084 gtk_tree_store_set (tree_store: store, iter: &root, 0, 33, -1);
6085
6086 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
6087 tree_view = gtk_tree_view_new_with_model (model: filter);
6088
6089 gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
6090 func: specific_bug_540201_filter_func,
6091 NULL, NULL);
6092
6093 gtk_tree_store_append (tree_store: store, iter: &iter, parent: &root);
6094 gtk_tree_store_set (tree_store: store, iter: &iter, 0, 50, -1);
6095
6096 gtk_tree_store_append (tree_store: store, iter: &iter, parent: &root);
6097 gtk_tree_store_set (tree_store: store, iter: &iter, 0, 22, -1);
6098
6099
6100 gtk_tree_store_append (tree_store: store, iter: &root, NULL);
6101 gtk_tree_store_set (tree_store: store, iter: &root, 0, 33, -1);
6102
6103 gtk_tree_store_append (tree_store: store, iter: &iter, parent: &root);
6104 gtk_tree_store_set (tree_store: store, iter: &iter, 0, 22, -1);
6105}
6106
6107
6108static gboolean
6109specific_bug_549287_visible_func (GtkTreeModel *model,
6110 GtkTreeIter *iter,
6111 gpointer data)
6112{
6113 gboolean result = FALSE;
6114
6115 result = gtk_tree_model_iter_has_child (tree_model: model, iter);
6116
6117 return result;
6118}
6119
6120static void
6121specific_bug_549287 (void)
6122{
6123 /* Test case for GNOME Bugzilla bug 529287, provided by Julient Puydt */
6124
6125 int i;
6126 GtkTreeStore *store;
6127 GtkTreeModel *filtered;
6128 GtkWidget *view G_GNUC_UNUSED;
6129 GtkTreeIter iter;
6130 GtkTreeIter *swap, *parent, *child;
6131
6132 /*http://bugzilla.gnome.org/show_bug.cgi?id=529287 */
6133
6134 store = gtk_tree_store_new (n_columns: 1, G_TYPE_STRING);
6135 filtered = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
6136 gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filtered),
6137 func: specific_bug_549287_visible_func,
6138 NULL, NULL);
6139
6140 view = gtk_tree_view_new_with_model (model: filtered);
6141
6142 for (i = 0; i < 4; i++)
6143 {
6144 if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), iter: &iter))
6145 {
6146 parent = gtk_tree_iter_copy (iter: &iter);
6147 child = gtk_tree_iter_copy (iter: &iter);
6148
6149 while (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (store),
6150 iter: child, parent, n: 0))
6151 {
6152
6153 swap = parent;
6154 parent = child;
6155 child = swap;
6156 }
6157
6158 gtk_tree_store_append (tree_store: store, iter: child, parent);
6159 gtk_tree_store_set (tree_store: store, iter: child,
6160 0, "Something",
6161 -1);
6162
6163 gtk_tree_iter_free (iter: parent);
6164 gtk_tree_iter_free (iter: child);
6165 }
6166 else
6167 {
6168 gtk_tree_store_append (tree_store: store, iter: &iter, NULL);
6169 gtk_tree_store_set (tree_store: store, iter: &iter,
6170 0, "Something",
6171 -1);
6172 }
6173
6174 /* since we inserted something, we changed the visibility conditions: */
6175 gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (filtered));
6176 }
6177}
6178
6179static gboolean
6180specific_bug_621076_visible_func (GtkTreeModel *model,
6181 GtkTreeIter *iter,
6182 gpointer data)
6183{
6184 gboolean visible = FALSE;
6185 char *str = NULL;
6186
6187 gtk_tree_model_get (tree_model: model, iter, 0, &str, -1);
6188 if (str != NULL && g_str_has_prefix (str, prefix: "visible"))
6189 {
6190 visible = TRUE;
6191 }
6192 else
6193 {
6194 GtkTreeIter child_iter;
6195 gboolean valid;
6196
6197 /* Recursively check if we have a visible child */
6198 for (valid = gtk_tree_model_iter_children (tree_model: model, iter: &child_iter, parent: iter);
6199 valid; valid = gtk_tree_model_iter_next (tree_model: model, iter: &child_iter))
6200 {
6201 if (specific_bug_621076_visible_func (model, iter: &child_iter, data))
6202 {
6203 visible = TRUE;
6204 break;
6205 }
6206 }
6207 }
6208
6209 g_free (mem: str);
6210
6211 return visible;
6212}
6213
6214static void
6215specific_bug_621076 (void)
6216{
6217 /* Test case for GNOME Bugzilla bug 621076, provided by Xavier Claessens */
6218
6219 /* This test case differs from has-child-filter and root-has-child-filter
6220 * in that the visible function both filters on content and model
6221 * structure. Also, it is recursive.
6222 */
6223
6224 GtkTreeStore *store;
6225 GtkTreeModel *filter;
6226 GtkWidget *view;
6227 GtkTreeIter group_iter;
6228 GtkTreeIter item_iter;
6229 SignalMonitor *monitor;
6230
6231 /*http://bugzilla.gnome.org/show_bug.cgi?id=621076 */
6232
6233 store = gtk_tree_store_new (n_columns: 1, G_TYPE_STRING);
6234 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
6235 gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
6236 func: specific_bug_621076_visible_func,
6237 NULL, NULL);
6238
6239 view = gtk_tree_view_new_with_model (model: filter);
6240 g_object_ref_sink (view);
6241
6242 monitor = signal_monitor_new (client: filter);
6243
6244 signal_monitor_append_signal (m: monitor, signal: ROW_INSERTED, path_string: "0");
6245 gtk_tree_store_insert_with_values (tree_store: store, iter: &item_iter, NULL, position: -1,
6246 0, "visible-group-0",
6247 -1);
6248 signal_monitor_assert_is_empty (m: monitor);
6249
6250 /* visible-group-0 is not expanded, so ROW_INSERTED should not be emitted
6251 * for its children. However, ROW_HAS_CHILD_TOGGLED should be emitted on
6252 * visible-group-0 to tell the view that row can be expanded. */
6253 signal_monitor_append_signal (m: monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "0");
6254 signal_monitor_append_signal (m: monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "0");
6255 group_iter = item_iter;
6256 gtk_tree_store_insert_with_values (tree_store: store, iter: &item_iter, parent: &group_iter, position: -1,
6257 0, "visible-0:0",
6258 -1);
6259 signal_monitor_assert_is_empty (m: monitor);
6260
6261 signal_monitor_append_signal (m: monitor, signal: ROW_INSERTED, path_string: "1");
6262 gtk_tree_store_insert_with_values (tree_store: store, iter: &item_iter, NULL, position: -1,
6263 0, "visible-group-1",
6264 -1);
6265 signal_monitor_assert_is_empty (m: monitor);
6266
6267 /* We are adding an hidden item inside visible-group-1, so
6268 * ROW_HAS_CHILD_TOGGLED should not be emitted. It is emitted though,
6269 * because the signal originating at TreeStore will be propagated,
6270 * as well a generated signal because the state of the parent *could*
6271 * change by a change in the model.
6272 */
6273 signal_monitor_append_signal (m: monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "1");
6274 signal_monitor_append_signal (m: monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "1");
6275 group_iter = item_iter;
6276 gtk_tree_store_insert_with_values (tree_store: store, iter: &item_iter, parent: &group_iter, position: -1,
6277 0, "group-1:0",
6278 -1);
6279 signal_monitor_assert_is_empty (m: monitor);
6280
6281 /* This group is invisible and its parent too. Nothing should be emitted */
6282 group_iter = item_iter;
6283 gtk_tree_store_insert_with_values (tree_store: store, iter: &item_iter, parent: &group_iter, position: -1,
6284 0, "group-1:0:0",
6285 -1);
6286 signal_monitor_assert_is_empty (m: monitor);
6287
6288 /* Adding a visible item in this group hierarchy will make all nodes
6289 * in this path visible. The first level should simply tell the view
6290 * that it now has a child, and the view will load the tree if needed
6291 * (depends on the expanded state).
6292 */
6293 signal_monitor_append_signal (m: monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "1");
6294 group_iter = item_iter;
6295 gtk_tree_store_insert_with_values (tree_store: store, iter: &item_iter, parent: &group_iter, position: -1,
6296 0, "visible-1:0:0:0",
6297 -1);
6298 signal_monitor_assert_is_empty (m: monitor);
6299
6300 check_level_length (GTK_TREE_MODEL_FILTER (filter), level: "1", expected_length: 1);
6301
6302 gtk_tree_store_insert_with_values (tree_store: store, iter: &item_iter, NULL, position: -1,
6303 0, "group-2",
6304 -1);
6305 signal_monitor_assert_is_empty (m: monitor);
6306
6307 /* Parent is invisible, and adding this invisible item won't change that,
6308 * so no signal should be emitted. */
6309 group_iter = item_iter;
6310 gtk_tree_store_insert_with_values (tree_store: store, NULL, parent: &group_iter, position: -1,
6311 0, "invisible-2:0",
6312 -1);
6313 signal_monitor_assert_is_empty (m: monitor);
6314
6315 /* This makes group-2 visible, so it gets inserted and tells it has
6316 * children.
6317 */
6318 signal_monitor_append_signal (m: monitor, signal: ROW_INSERTED, path_string: "2");
6319 signal_monitor_append_signal (m: monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "2");
6320 gtk_tree_store_insert_with_values (tree_store: store, NULL, parent: &group_iter, position: -1,
6321 0, "visible-2:1",
6322 -1);
6323 signal_monitor_assert_is_empty (m: monitor);
6324
6325 /* group-2 is already visible, so this time it is a normal insertion */
6326 gtk_tree_store_insert_with_values (tree_store: store, NULL, parent: &group_iter, position: -1,
6327 0, "visible-2:2",
6328 -1);
6329 signal_monitor_assert_is_empty (m: monitor);
6330
6331
6332 gtk_tree_store_insert_with_values (tree_store: store, iter: &item_iter, NULL, position: -1,
6333 0, "group-3",
6334 -1);
6335 signal_monitor_assert_is_empty (m: monitor);
6336
6337 /* Parent is invisible, and adding this invisible item won't change that,
6338 * so no signal should be emitted. */
6339 group_iter = item_iter;
6340 gtk_tree_store_insert_with_values (tree_store: store, NULL, parent: &group_iter, position: -1,
6341 0, "invisible-3:0",
6342 -1);
6343 signal_monitor_assert_is_empty (m: monitor);
6344
6345 gtk_tree_store_insert_with_values (tree_store: store, iter: &item_iter, parent: &group_iter, position: -1,
6346 0, "invisible-3:1",
6347 -1);
6348 signal_monitor_assert_is_empty (m: monitor);
6349
6350 /* This will make group 3 visible. */
6351 signal_monitor_append_signal (m: monitor, signal: ROW_INSERTED, path_string: "3");
6352 signal_monitor_append_signal (m: monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "3");
6353 signal_monitor_append_signal (m: monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "3");
6354 gtk_tree_store_set (tree_store: store, iter: &item_iter, 0, "visible-3:1", -1);
6355 signal_monitor_assert_is_empty (m: monitor);
6356
6357 /* Make sure all groups are expanded, so the filter has the tree cached */
6358 gtk_tree_view_expand_all (GTK_TREE_VIEW (view));
6359 while (g_main_context_pending (NULL))
6360 g_main_context_iteration (NULL, TRUE);
6361
6362 /* Should only yield a row-changed */
6363 signal_monitor_append_signal (m: monitor, signal: ROW_CHANGED, path_string: "3:0");
6364 gtk_tree_store_set (tree_store: store, iter: &item_iter, 0, "visible-3:1", -1);
6365 signal_monitor_assert_is_empty (m: monitor);
6366
6367 /* Now remove/hide some items. If a group loses its last item, the group
6368 * should be deleted instead of the item.
6369 */
6370
6371 signal_monitor_append_signal (m: monitor, signal: ROW_DELETED, path_string: "2:1");
6372 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (store), iter: &item_iter, path_string: "2:2");
6373 gtk_tree_store_remove (tree_store: store, iter: &item_iter);
6374 signal_monitor_assert_is_empty (m: monitor);
6375
6376 signal_monitor_append_signal (m: monitor, signal: ROW_DELETED, path_string: "2:0");
6377 signal_monitor_append_signal (m: monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "2");
6378 signal_monitor_append_signal (m: monitor, signal: ROW_DELETED, path_string: "2");
6379 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (store), iter: &item_iter, path_string: "2:1");
6380 gtk_tree_store_set (tree_store: store, iter: &item_iter, 0, "invisible-2:1", -1);
6381 signal_monitor_assert_is_empty (m: monitor);
6382
6383 signal_monitor_append_signal (m: monitor, signal: ROW_DELETED, path_string: "1:0:0:0");
6384 signal_monitor_append_signal (m: monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "1:0:0");
6385 signal_monitor_append_signal (m: monitor, signal: ROW_DELETED, path_string: "1:0");
6386 signal_monitor_append_signal (m: monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "1");
6387 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (store), iter: &item_iter, path_string: "1:0:0:0");
6388 gtk_tree_store_remove (tree_store: store, iter: &item_iter);
6389 signal_monitor_assert_is_empty (m: monitor);
6390
6391 /* Hide a group using row-changed instead of row-deleted */
6392 /* Caution: group 2 is gone, so offsets of the signals have moved. */
6393 signal_monitor_append_signal (m: monitor, signal: ROW_DELETED, path_string: "2:0");
6394 signal_monitor_append_signal (m: monitor, signal: ROW_HAS_CHILD_TOGGLED, path_string: "2");
6395 signal_monitor_append_signal (m: monitor, signal: ROW_DELETED, path_string: "2");
6396 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (store), iter: &item_iter,
6397 path_string: "3:1");
6398 gtk_tree_store_set (tree_store: store, iter: &item_iter, 0, "invisible-3:1", -1);
6399 signal_monitor_assert_is_empty (m: monitor);
6400
6401 /* Cleanup */
6402 signal_monitor_free (m: monitor);
6403 g_object_unref (object: view);
6404 g_object_unref (object: store);
6405 g_object_unref (object: filter);
6406}
6407
6408static void
6409specific_bug_657353_related (void)
6410{
6411 GtkTreeIter node1, node2, node3, node4;
6412 GtkTreeModel *model;
6413 GtkTreeModelRefCount *ref_model;
6414 GtkTreeModel *filter_model;
6415 GtkWidget *tree_view;
6416 GType column_types[] = { G_TYPE_BOOLEAN };
6417
6418 /* gtk_tree_model_filter_rows_reordered() used to have a problem to
6419 * not properly transfer the first ref count when the first node in
6420 * the level does not have elt->offset == 0. This test checks for
6421 * that. This bug could cause the faulty condition
6422 * elt->ext_ref_count > elt->ref_count
6423 * to raise.
6424 */
6425
6426 model = gtk_tree_model_ref_count_new ();
6427 ref_model = GTK_TREE_MODEL_REF_COUNT (model);
6428
6429 gtk_tree_store_set_column_types (GTK_TREE_STORE (model), n_columns: 1,
6430 types: column_types);
6431
6432 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &node1, NULL);
6433 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &node2, NULL);
6434 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &node3, NULL);
6435 gtk_tree_store_append (GTK_TREE_STORE (model), iter: &node4, NULL);
6436
6437 /* Hide the first node */
6438 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &node1, 0, FALSE, -1);
6439 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &node2, 0, TRUE, -1);
6440 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &node3, 0, TRUE, -1);
6441 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &node4, 0, TRUE, -1);
6442
6443 filter_model = gtk_tree_model_filter_new (child_model: model, NULL);
6444 gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), column: 0);
6445 tree_view = gtk_tree_view_new_with_model (model: filter_model);
6446
6447 assert_node_ref_count (ref_model, iter: &node1, ref_count: 0);
6448 assert_node_ref_count (ref_model, iter: &node2, ref_count: 2);
6449 assert_node_ref_count (ref_model, iter: &node3, ref_count: 1);
6450 assert_node_ref_count (ref_model, iter: &node4, ref_count: 1);
6451
6452 /* Swap nodes 2 and 3 */
6453
6454 /* gtk_tree_store_swap() will emit rows-reordered */
6455 gtk_tree_store_swap (GTK_TREE_STORE (model),
6456 a: &node2, b: &node3);
6457
6458 assert_node_ref_count (ref_model, iter: &node1, ref_count: 0);
6459 assert_node_ref_count (ref_model, iter: &node3, ref_count: 2);
6460 assert_node_ref_count (ref_model, iter: &node2, ref_count: 1);
6461 assert_node_ref_count (ref_model, iter: &node4, ref_count: 1);
6462
6463 /* Hide node 3 */
6464 gtk_tree_store_set (GTK_TREE_STORE (model), iter: &node3, 0, FALSE, -1);
6465
6466 assert_node_ref_count (ref_model, iter: &node1, ref_count: 0);
6467 assert_node_ref_count (ref_model, iter: &node3, ref_count: 0);
6468 assert_node_ref_count (ref_model, iter: &node2, ref_count: 2);
6469 assert_node_ref_count (ref_model, iter: &node4, ref_count: 1);
6470
6471 g_object_unref (g_object_ref_sink (tree_view));
6472 g_object_unref (object: filter_model);
6473 g_object_unref (object: ref_model);
6474}
6475
6476static gboolean
6477specific_bug_657353_visible_func (GtkTreeModel *model,
6478 GtkTreeIter *iter,
6479 gpointer data)
6480{
6481 char *str;
6482 gboolean ret = FALSE;
6483
6484 gtk_tree_model_get (tree_model: model, iter, 0, &str, -1);
6485 ret = strstr (haystack: str, needle: "hidden") ? FALSE : TRUE;
6486 g_free (mem: str);
6487
6488 return ret;
6489}
6490
6491static void
6492specific_bug_657353 (void)
6493{
6494 GtkListStore *store;
6495 GtkTreeModel *sort_model;
6496 GtkTreeModel *filter_model;
6497 GtkTreeIter iter, iter_a, iter_b, iter_c;
6498 GtkWidget *tree_view;
6499
6500 /* This is a very carefully crafted test case that is triggering the
6501 * situation described in bug 657353.
6502 *
6503 * GtkListStore acts like EphyCompletionModel
6504 * GtkTreeModelSort acts like the sort model added in
6505 * ephy_location_entry_set_completion.
6506 * GtkTreeModelFilter acts like the filter model in
6507 * GtkEntryCompletion.
6508 */
6509
6510 /* Set up a model that's wrapped in a GtkTreeModelSort. The first item
6511 * will be hidden.
6512 */
6513 store = gtk_list_store_new (n_columns: 1, G_TYPE_STRING);
6514 gtk_list_store_insert_with_values (list_store: store, iter: &iter_b, position: 0, 0, "BBB hidden", -1);
6515 gtk_list_store_insert_with_values (list_store: store, iter: &iter, position: 1, 0, "EEE", -1);
6516 gtk_list_store_insert_with_values (list_store: store, iter: &iter, position: 2, 0, "DDD", -1);
6517 gtk_list_store_insert_with_values (list_store: store, iter: &iter_c, position: 3, 0, "CCC", -1);
6518
6519 sort_model = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (store));
6520
6521 filter_model = gtk_tree_model_filter_new (child_model: sort_model, NULL);
6522 gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter_model),
6523 func: specific_bug_657353_visible_func,
6524 data: filter_model, NULL);
6525
6526 tree_view = gtk_tree_view_new_with_model (model: filter_model);
6527
6528 /* This triggers emission of rows-reordered. The elt with offset == 0
6529 * is hidden, which used to cause misbehavior. (The first reference should
6530 * have moved to CCC, which did not happen).
6531 */
6532 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sort_model),
6533 sort_column_id: 0, order: GTK_SORT_ASCENDING);
6534
6535 /* By inserting another item that will appear at the first position, a
6536 * reference transfer is done from CCC (which failed to get this reference
6537 * earlier) to AAA. At this point, the rule
6538 * elt->ref_count >= elt->ext_ref_count is broken for CCC.
6539 */
6540 gtk_list_store_insert_with_values (list_store: store, iter: &iter_a, position: 6, 0, "AAA", -1);
6541
6542 /* When we hide CCC, the references cannot be correctly released, because
6543 * CCC failed to get a reference during rows-reordered. The faulty condition
6544 * only manifests itself here with MODEL_FILTER_DEBUG disabled (as is usual
6545 * in production).
6546 */
6547 gtk_list_store_set (list_store: store, iter: &iter_c, 0, "CCC hidden", -1);
6548
6549 g_object_unref (g_object_ref_sink (tree_view));
6550 g_object_unref (object: filter_model);
6551 g_object_unref (object: sort_model);
6552 g_object_unref (object: store);
6553}
6554
6555static void
6556specific_bug_658696 (void)
6557{
6558 GtkTreeStore *store;
6559 GtkTreeModel *filter;
6560 GtkTreePath *vroot;
6561 GtkTreeIter iter;
6562
6563 store = create_tree_store (depth: 4, TRUE);
6564
6565 vroot = gtk_tree_path_new_from_indices (first_index: 0, 0, -1);
6566 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), root: vroot);
6567 gtk_tree_path_free (path: vroot);
6568
6569 /* This used to cause a crash in gtk_tree_model_filter_check_ancestors() */
6570 gtk_tree_store_append (tree_store: store, iter: &iter, NULL);
6571
6572 g_object_unref (object: store);
6573 g_object_unref (object: filter);
6574}
6575
6576static gboolean
6577specific_bug_659022_visible_func (GtkTreeModel *model,
6578 GtkTreeIter *iter,
6579 gpointer data)
6580{
6581 GtkTreeIter tmp;
6582
6583 if (!gtk_tree_model_iter_parent (tree_model: model, iter: &tmp, child: iter))
6584 {
6585 if (gtk_tree_model_iter_n_children (tree_model: model, iter) >= 2)
6586 return TRUE;
6587 else
6588 return FALSE;
6589 }
6590
6591 return TRUE;
6592}
6593
6594static void
6595specific_bug_659022_row_changed_emission (void)
6596{
6597 GtkTreeModel *filter;
6598 GtkTreeModel *model;
6599 GtkTreeIter parent, child, child2;
6600 GtkTreePath *path;
6601 GtkWidget *tree_view;
6602
6603 model = gtk_tree_model_ref_count_new ();
6604
6605 filter = gtk_tree_model_filter_new (child_model: model, NULL);
6606 gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
6607 func: specific_bug_659022_visible_func,
6608 NULL, NULL);
6609
6610 tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (filter));
6611
6612 gtk_tree_store_insert (GTK_TREE_STORE (model), iter: &parent, NULL, position: 0);
6613 gtk_tree_store_insert (GTK_TREE_STORE (model), iter: &child, parent: &parent, position: 0);
6614 gtk_tree_store_insert (GTK_TREE_STORE (model), iter: &child2, parent: &parent, position: 0);
6615
6616 gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
6617
6618 gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (filter));
6619
6620 gtk_tree_store_remove (GTK_TREE_STORE (model), iter: &child2);
6621
6622 gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (filter));
6623
6624 path = gtk_tree_model_get_path (tree_model: model, iter: &child);
6625 gtk_tree_model_row_changed (tree_model: model, path, iter: &child);
6626 gtk_tree_path_free (path);
6627
6628 g_object_unref (g_object_ref_sink (tree_view));
6629 g_object_unref (object: filter);
6630 g_object_unref (object: model);
6631}
6632
6633static void
6634specific_bug_659022_row_deleted_node_invisible (void)
6635{
6636 GtkTreeModel *filter;
6637 GtkTreeModel *model;
6638 GtkTreeIter parent, child;
6639 GtkTreeIter parent2, child2, child3;
6640 GtkWidget *tree_view;
6641
6642 model = gtk_tree_model_ref_count_new ();
6643
6644 filter = gtk_tree_model_filter_new (child_model: model, NULL);
6645 gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
6646 func: specific_bug_659022_visible_func,
6647 NULL, NULL);
6648
6649 tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (filter));
6650
6651 gtk_tree_store_insert (GTK_TREE_STORE (model), iter: &parent, NULL, position: 0);
6652 gtk_tree_store_insert (GTK_TREE_STORE (model), iter: &child, parent: &parent, position: 0);
6653
6654 gtk_tree_store_insert (GTK_TREE_STORE (model), iter: &parent2, NULL, position: 0);
6655 gtk_tree_store_insert (GTK_TREE_STORE (model), iter: &child2, parent: &parent2, position: 0);
6656 gtk_tree_store_insert (GTK_TREE_STORE (model), iter: &child3, parent: &parent2, position: 0);
6657
6658 gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
6659
6660 gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (filter));
6661
6662 gtk_tree_store_remove (GTK_TREE_STORE (model), iter: &parent);
6663
6664 g_object_unref (g_object_ref_sink (tree_view));
6665 g_object_unref (object: filter);
6666 g_object_unref (object: model);
6667}
6668
6669static void
6670specific_bug_659022_row_deleted_free_level (void)
6671{
6672 GtkTreeModel *filter;
6673 GtkTreeModel *model;
6674 GtkTreeModelRefCount *ref_model;
6675 GtkTreeIter parent, child;
6676 GtkTreeIter parent2, child2, child3;
6677 GtkWidget *tree_view;
6678
6679 model = gtk_tree_model_ref_count_new ();
6680 ref_model = GTK_TREE_MODEL_REF_COUNT (model);
6681
6682 filter = gtk_tree_model_filter_new (child_model: model, NULL);
6683 gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
6684 func: specific_bug_659022_visible_func,
6685 NULL, NULL);
6686
6687 tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (filter));
6688
6689 /* Carefully construct a model */
6690 gtk_tree_store_insert (GTK_TREE_STORE (model), iter: &parent, NULL, position: 0);
6691 gtk_tree_store_insert (GTK_TREE_STORE (model), iter: &child, parent: &parent, position: 0);
6692
6693 gtk_tree_store_insert (GTK_TREE_STORE (model), iter: &parent2, NULL, position: 0);
6694 gtk_tree_store_insert (GTK_TREE_STORE (model), iter: &child2, parent: &parent2, position: 0);
6695 gtk_tree_store_insert (GTK_TREE_STORE (model), iter: &child3, parent: &parent2, position: 0);
6696
6697 /* Only parent2 is visible, child3 holds first ref count for that level
6698 * (Note that above, both child2 as child3 are inserted at position 0).
6699 */
6700 assert_node_ref_count (ref_model, iter: &parent, ref_count: 0);
6701 assert_node_ref_count (ref_model, iter: &child, ref_count: 0);
6702 assert_node_ref_count (ref_model, iter: &parent2, ref_count: 3);
6703 assert_node_ref_count (ref_model, iter: &child3, ref_count: 1);
6704 assert_node_ref_count (ref_model, iter: &child2, ref_count: 0);
6705
6706 /* Make sure child level is cached */
6707 gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
6708
6709 assert_node_ref_count (ref_model, iter: &parent, ref_count: 0);
6710 assert_node_ref_count (ref_model, iter: &child, ref_count: 0);
6711 assert_node_ref_count (ref_model, iter: &parent2, ref_count: 3);
6712 assert_node_ref_count (ref_model, iter: &child3, ref_count: 2);
6713 assert_node_ref_count (ref_model, iter: &child2, ref_count: 1);
6714
6715 gtk_tree_view_collapse_all (GTK_TREE_VIEW (tree_view));
6716
6717 assert_node_ref_count (ref_model, iter: &parent, ref_count: 0);
6718 assert_node_ref_count (ref_model, iter: &child, ref_count: 0);
6719 assert_node_ref_count (ref_model, iter: &parent2, ref_count: 3);
6720 assert_node_ref_count (ref_model, iter: &child3, ref_count: 1);
6721 assert_node_ref_count (ref_model, iter: &child2, ref_count: 0);
6722
6723 /* Remove node with longer child level first */
6724 gtk_tree_store_remove (GTK_TREE_STORE (model), iter: &parent2);
6725 gtk_tree_store_remove (GTK_TREE_STORE (model), iter: &parent);
6726
6727 g_object_unref (g_object_ref_sink (tree_view));
6728 g_object_unref (object: filter);
6729 g_object_unref (object: model);
6730}
6731
6732static void
6733specific_bug_679910 (void)
6734{
6735 GtkTreeModel *filter;
6736 GtkListStore *store;
6737 GtkTreeIter iter, nil_iter;
6738 GtkTreeIter filter_iter;
6739
6740 store = gtk_list_store_new (n_columns: 1, G_TYPE_POINTER);
6741 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
6742
6743 gtk_list_store_append (list_store: store, iter: &nil_iter);
6744 gtk_list_store_append (list_store: store, iter: &iter);
6745 gtk_list_store_append (list_store: store, iter: &nil_iter);
6746
6747 gtk_tree_model_filter_convert_child_iter_to_iter (GTK_TREE_MODEL_FILTER (filter),
6748 filter_iter: &filter_iter,
6749 child_iter: &iter);
6750 iter = filter_iter;
6751 g_assert_true (gtk_tree_model_iter_next (filter, &iter));
6752 iter = filter_iter;
6753 g_assert_true (gtk_tree_model_iter_previous (filter, &iter));
6754
6755 g_object_unref (object: filter);
6756 g_object_unref (object: store);
6757}
6758
6759static int row_changed_count;
6760static int filter_row_changed_count;
6761
6762static void
6763row_changed (GtkTreeModel *model,
6764 GtkTreePath *path,
6765 GtkTreeIter *iter,
6766 gpointer data)
6767{
6768 int *count = data;
6769
6770 (*count)++;
6771}
6772
6773static void
6774test_row_changed (void)
6775{
6776 GtkTreeModel *filter;
6777 GtkListStore *store;
6778 GtkTreeIter iter1, iter2, iter3;
6779 GtkTreeIter fiter1, fiter2, fiter3;
6780
6781 store = gtk_list_store_new (n_columns: 1, G_TYPE_INT);
6782 filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
6783
6784 gtk_list_store_append (list_store: store, iter: &iter1);
6785 gtk_list_store_append (list_store: store, iter: &iter2);
6786 gtk_list_store_append (list_store: store, iter: &iter3);
6787
6788 gtk_tree_model_filter_convert_child_iter_to_iter (GTK_TREE_MODEL_FILTER (filter), filter_iter: &fiter1, child_iter: &iter1);
6789 gtk_tree_model_filter_convert_child_iter_to_iter (GTK_TREE_MODEL_FILTER (filter), filter_iter: &fiter2, child_iter: &iter2);
6790 gtk_tree_model_filter_convert_child_iter_to_iter (GTK_TREE_MODEL_FILTER (filter), filter_iter: &fiter3, child_iter: &iter3);
6791
6792 g_signal_connect (store, "row-changed", G_CALLBACK (row_changed), &row_changed_count);
6793 g_signal_connect (filter, "row-changed", G_CALLBACK (row_changed), &filter_row_changed_count);
6794
6795 row_changed_count = 0;
6796 filter_row_changed_count = 0;
6797
6798 gtk_list_store_set (list_store: store, iter: &iter1, 0, 1, -1);
6799 gtk_list_store_set (list_store: store, iter: &iter2, 0, 1, -1);
6800 gtk_list_store_set (list_store: store, iter: &iter3, 0, 1, -1);
6801
6802 g_assert_cmpint (row_changed_count, ==, 3);
6803 g_assert_cmpint (filter_row_changed_count, ==, 0);
6804
6805 row_changed_count = 0;
6806 filter_row_changed_count = 0;
6807
6808 gtk_tree_model_ref_node (tree_model: filter, iter: &fiter1);
6809 gtk_tree_model_ref_node (tree_model: filter, iter: &fiter2);
6810 gtk_tree_model_ref_node (tree_model: filter, iter: &fiter3);
6811
6812 gtk_list_store_set (list_store: store, iter: &iter1, 0, 2, -1);
6813 gtk_list_store_set (list_store: store, iter: &iter2, 0, 2, -1);
6814 gtk_list_store_set (list_store: store, iter: &iter3, 0, 2, -1);
6815
6816 g_assert_cmpint (row_changed_count, ==, 3);
6817 g_assert_cmpint (filter_row_changed_count, ==, 3);
6818
6819 gtk_tree_model_unref_node (tree_model: filter, iter: &fiter1);
6820 gtk_tree_model_unref_node (tree_model: filter, iter: &fiter2);
6821 gtk_tree_model_unref_node (tree_model: filter, iter: &fiter3);
6822
6823 g_object_unref (object: filter);
6824 g_object_unref (object: store);
6825}
6826
6827
6828/* main */
6829
6830void
6831register_filter_model_tests (void)
6832{
6833 g_test_add ("/TreeModelFilter/self/verify-test-suite",
6834 FilterTest, NULL,
6835 filter_test_setup,
6836 verify_test_suite,
6837 filter_test_teardown);
6838
6839 g_test_add ("/TreeModelFilter/self/verify-test-suite/vroot/depth-1",
6840 FilterTest, gtk_tree_path_new_from_indices (2, -1),
6841 filter_test_setup,
6842 verify_test_suite_vroot,
6843 filter_test_teardown);
6844 g_test_add ("/TreeModelFilter/self/verify-test-suite/vroot/depth-2",
6845 FilterTest, gtk_tree_path_new_from_indices (2, 3, -1),
6846 filter_test_setup,
6847 verify_test_suite_vroot,
6848 filter_test_teardown);
6849
6850
6851 g_test_add ("/TreeModelFilter/filled/hide-root-level",
6852 FilterTest, NULL,
6853 filter_test_setup,
6854 filled_hide_root_level,
6855 filter_test_teardown);
6856 g_test_add ("/TreeModelFilter/filled/hide-child-levels",
6857 FilterTest, NULL,
6858 filter_test_setup,
6859 filled_hide_child_levels,
6860 filter_test_teardown);
6861 g_test_add ("/TreeModelFilter/filled/hide-child-levels/root-expanded",
6862 FilterTest, NULL,
6863 filter_test_setup,
6864 filled_hide_child_levels_root_expanded,
6865 filter_test_teardown);
6866
6867 g_test_add ("/TreeModelFilter/filled/hide-root-level/vroot",
6868 FilterTest, gtk_tree_path_new_from_indices (2, -1),
6869 filter_test_setup,
6870 filled_vroot_hide_root_level,
6871 filter_test_teardown);
6872 g_test_add ("/TreeModelFilter/filled/hide-child-levels/vroot",
6873 FilterTest, gtk_tree_path_new_from_indices (2, -1),
6874 filter_test_setup,
6875 filled_vroot_hide_child_levels,
6876 filter_test_teardown);
6877 g_test_add ("/TreeModelFilter/filled/hide-child-levels/vroot-root-expanded",
6878 FilterTest, gtk_tree_path_new_from_indices (2, -1),
6879 filter_test_setup,
6880 filled_vroot_hide_child_levels_root_expanded,
6881 filter_test_teardown);
6882
6883
6884 g_test_add ("/TreeModelFilter/empty/show-nodes",
6885 FilterTest, NULL,
6886 filter_test_setup_empty,
6887 empty_show_nodes,
6888 filter_test_teardown);
6889 g_test_add ("/TreeModelFilter/empty/show-multiple-nodes",
6890 FilterTest, NULL,
6891 filter_test_setup_empty,
6892 empty_show_multiple_nodes,
6893 filter_test_teardown);
6894
6895 g_test_add ("/TreeModelFilter/empty/show-nodes/vroot",
6896 FilterTest, gtk_tree_path_new_from_indices (2, -1),
6897 filter_test_setup_empty,
6898 empty_vroot_show_nodes,
6899 filter_test_teardown);
6900 g_test_add ("/TreeModelFilter/empty/show-multiple-nodes/vroot",
6901 FilterTest, gtk_tree_path_new_from_indices (2, -1),
6902 filter_test_setup_empty,
6903 empty_vroot_show_multiple_nodes,
6904 filter_test_teardown);
6905
6906
6907 g_test_add ("/TreeModelFilter/unfiltered/hide-single",
6908 FilterTest, NULL,
6909 filter_test_setup_unfiltered,
6910 unfiltered_hide_single,
6911 filter_test_teardown);
6912 g_test_add ("/TreeModelFilter/unfiltered/hide-single/root-expanded",
6913 FilterTest, NULL,
6914 filter_test_setup_unfiltered_root_expanded,
6915 unfiltered_hide_single_root_expanded,
6916 filter_test_teardown);
6917 g_test_add ("/TreeModelFilter/unfiltered/hide-single-child",
6918 FilterTest, NULL,
6919 filter_test_setup_unfiltered,
6920 unfiltered_hide_single_child,
6921 filter_test_teardown);
6922 g_test_add ("/TreeModelFilter/unfiltered/hide-single-child/root-expanded",
6923 FilterTest, NULL,
6924 filter_test_setup_unfiltered_root_expanded,
6925 unfiltered_hide_single_child_root_expanded,
6926 filter_test_teardown);
6927 g_test_add ("/TreeModelFilter/unfiltered/hide-single-multi-level",
6928 FilterTest, NULL,
6929 filter_test_setup_unfiltered,
6930 unfiltered_hide_single_multi_level,
6931 filter_test_teardown);
6932 g_test_add ("/TreeModelFilter/unfiltered/hide-single-multi-level/root-expanded",
6933 FilterTest, NULL,
6934 filter_test_setup_unfiltered_root_expanded,
6935 unfiltered_hide_single_multi_level_root_expanded,
6936 filter_test_teardown);
6937
6938 g_test_add ("/TreeModelFilter/unfiltered/hide-single/vroot",
6939 FilterTest, gtk_tree_path_new_from_indices (2, -1),
6940 filter_test_setup_unfiltered,
6941 unfiltered_vroot_hide_single,
6942 filter_test_teardown);
6943 g_test_add ("/TreeModelFilter/unfiltered/hide-single-child/vroot",
6944 FilterTest, gtk_tree_path_new_from_indices (2, -1),
6945 filter_test_setup_unfiltered,
6946 unfiltered_vroot_hide_single_child,
6947 filter_test_teardown);
6948 g_test_add ("/TreeModelFilter/unfiltered/hide-single-child/vroot/root-expanded",
6949 FilterTest, gtk_tree_path_new_from_indices (2, -1),
6950 filter_test_setup_unfiltered_root_expanded,
6951 unfiltered_vroot_hide_single_child_root_expanded,
6952 filter_test_teardown);
6953 g_test_add ("/TreeModelFilter/unfiltered/hide-single-multi-level/vroot",
6954 FilterTest, gtk_tree_path_new_from_indices (2, -1),
6955 filter_test_setup_unfiltered,
6956 unfiltered_vroot_hide_single_multi_level,
6957 filter_test_teardown);
6958 g_test_add ("/TreeModelFilter/unfiltered/hide-single-multi-level/vroot/root-expanded",
6959 FilterTest, gtk_tree_path_new_from_indices (2, -1),
6960 filter_test_setup_unfiltered_root_expanded,
6961 unfiltered_vroot_hide_single_multi_level_root_expanded,
6962 filter_test_teardown);
6963
6964
6965
6966 g_test_add ("/TreeModelFilter/unfiltered/show-single",
6967 FilterTest, NULL,
6968 filter_test_setup_empty_unfiltered,
6969 unfiltered_show_single,
6970 filter_test_teardown);
6971 g_test_add ("/TreeModelFilter/unfiltered/show-single-child",
6972 FilterTest, NULL,
6973 filter_test_setup_empty_unfiltered,
6974 unfiltered_show_single_child,
6975 filter_test_teardown);
6976 g_test_add ("/TreeModelFilter/unfiltered/show-single-child/root-expanded",
6977 FilterTest, NULL,
6978 filter_test_setup_empty_unfiltered_root_expanded,
6979 unfiltered_show_single_child_root_expanded,
6980 filter_test_teardown);
6981 g_test_add ("/TreeModelFilter/unfiltered/show-single-multi-level",
6982 FilterTest, NULL,
6983 filter_test_setup_empty_unfiltered,
6984 unfiltered_show_single_multi_level,
6985 filter_test_teardown);
6986 g_test_add ("/TreeModelFilter/unfiltered/show-single-multi-level/root-expanded",
6987 FilterTest, NULL,
6988 filter_test_setup_empty_unfiltered_root_expanded,
6989 unfiltered_show_single_multi_level_root_expanded,
6990 filter_test_teardown);
6991
6992 g_test_add ("/TreeModelFilter/unfiltered/show-single/vroot",
6993 FilterTest, gtk_tree_path_new_from_indices (2, -1),
6994 filter_test_setup_empty_unfiltered,
6995 unfiltered_vroot_show_single,
6996 filter_test_teardown);
6997 g_test_add ("/TreeModelFilter/unfiltered/show-single-child/vroot",
6998 FilterTest, gtk_tree_path_new_from_indices (2, -1),
6999 filter_test_setup_empty_unfiltered,
7000 unfiltered_vroot_show_single_child,
7001 filter_test_teardown);
7002 g_test_add ("/TreeModelFilter/unfiltered/show-single-child/vroot/root-expanded",
7003 FilterTest, gtk_tree_path_new_from_indices (2, -1),
7004 filter_test_setup_empty_unfiltered_root_expanded,
7005 unfiltered_vroot_show_single_child_root_expanded,
7006 filter_test_teardown);
7007 g_test_add ("/TreeModelFilter/unfiltered/show-single-multi-level/vroot",
7008 FilterTest, gtk_tree_path_new_from_indices (2, -1),
7009 filter_test_setup_empty_unfiltered,
7010 unfiltered_vroot_show_single_multi_level,
7011 filter_test_teardown);
7012 g_test_add ("/TreeModelFilter/unfiltered/show-single-multi-level/vroot/root-expanded",
7013 FilterTest, gtk_tree_path_new_from_indices (2, -1),
7014 filter_test_setup_empty_unfiltered_root_expanded,
7015 unfiltered_vroot_show_single_multi_level_root_expanded,
7016 filter_test_teardown);
7017
7018
7019 g_test_add ("/TreeModelFilter/unfiltered/rows-reordered/root-level",
7020 FilterTest, NULL,
7021 filter_test_setup_unfiltered,
7022 unfiltered_rows_reordered_root_level,
7023 filter_test_teardown);
7024 g_test_add ("/TreeModelFilter/unfiltered/rows-reordered/child-level",
7025 FilterTest, NULL,
7026 filter_test_setup_unfiltered,
7027 unfiltered_rows_reordered_child_level,
7028 filter_test_teardown);
7029
7030 g_test_add ("/TreeModelFilter/filtered/rows-reordered/root-level/first-hidden",
7031 FilterTest, NULL,
7032 filter_test_setup,
7033 filtered_rows_reordered_root_level_first_hidden,
7034 filter_test_teardown);
7035 g_test_add ("/TreeModelFilter/filtered/rows-reordered/root-level/middle-hidden",
7036 FilterTest, NULL,
7037 filter_test_setup,
7038 filtered_rows_reordered_root_level_middle_hidden,
7039 filter_test_teardown);
7040 g_test_add ("/TreeModelFilter/filtered/rows-reordered/child-level/first-hidden",
7041 FilterTest, NULL,
7042 filter_test_setup,
7043 filtered_rows_reordered_child_level_first_hidden,
7044 filter_test_teardown);
7045 g_test_add ("/TreeModelFilter/filtered/rows-reordered/child-level/middle-hidden",
7046 FilterTest, NULL,
7047 filter_test_setup,
7048 filtered_rows_reordered_child_level_middle_hidden,
7049 filter_test_teardown);
7050 g_test_add ("/TreeModelFilter/filtered/rows-reordered/child-level/4-hidden",
7051 FilterTest, NULL,
7052 filter_test_setup,
7053 filtered_rows_reordered_child_level_4_hidden,
7054 filter_test_teardown);
7055 g_test_add ("/TreeModelFilter/filtered/rows-reordered/child-level/all-hidden",
7056 FilterTest, NULL,
7057 filter_test_setup,
7058 filtered_rows_reordered_child_level_all_hidden,
7059 filter_test_teardown);
7060
7061 /* Inserts in child models after creation of filter model */
7062 g_test_add_func (testpath: "/TreeModelFilter/insert/before",
7063 test_func: insert_before);
7064 g_test_add_func (testpath: "/TreeModelFilter/insert/child",
7065 test_func: insert_child);
7066
7067 /* Removals from child model after creating of filter model */
7068 g_test_add_func (testpath: "/TreeModelFilter/remove/node",
7069 test_func: remove_node);
7070 g_test_add_func (testpath: "/TreeModelFilter/remove/node-vroot",
7071 test_func: remove_node_vroot);
7072 g_test_add_func (testpath: "/TreeModelFilter/remove/vroot-ancestor",
7073 test_func: remove_vroot_ancestor);
7074
7075 /* Reference counting */
7076 g_test_add_func (testpath: "/TreeModelFilter/ref-count/single-level",
7077 test_func: ref_count_single_level);
7078 g_test_add_func (testpath: "/TreeModelFilter/ref-count/two-levels",
7079 test_func: ref_count_two_levels);
7080 g_test_add_func (testpath: "/TreeModelFilter/ref-count/three-levels",
7081 test_func: ref_count_three_levels);
7082 g_test_add_func (testpath: "/TreeModelFilter/ref-count/delete-row",
7083 test_func: ref_count_delete_row);
7084 g_test_add_func (testpath: "/TreeModelFilter/ref-count/filter-row/length-1",
7085 test_func: ref_count_filter_row_length_1);
7086 g_test_add_func (testpath: "/TreeModelFilter/ref-count/filter-row/length-1-remove-in-root-level",
7087 test_func: ref_count_filter_row_length_1_remove_in_root_level);
7088 g_test_add_func (testpath: "/TreeModelFilter/ref-count/filter-row/length-1-remove-in-child-level",
7089 test_func: ref_count_filter_row_length_1_remove_in_child_level);
7090 g_test_add_func (testpath: "/TreeModelFilter/ref-count/filter-row/length-gt-1",
7091 test_func: ref_count_filter_row_length_gt_1);
7092 g_test_add_func (testpath: "/TreeModelFilter/ref-count/filter-row/length-gt-1-visible-children",
7093 test_func: ref_count_filter_row_length_gt_1_visible_children);
7094 g_test_add_func (testpath: "/TreeModelFilter/ref-count/cleanup",
7095 test_func: ref_count_cleanup);
7096 g_test_add_func (testpath: "/TreeModelFilter/ref-count/row-ref",
7097 test_func: ref_count_row_ref);
7098
7099 /* Reference counting, transfer of first reference on
7100 * first node in level. This is a GtkTreeModelFilter-specific
7101 * feature.
7102 */
7103 g_test_add_func (testpath: "/TreeModelFilter/ref-count/transfer/root-level/insert",
7104 test_func: ref_count_transfer_root_level_insert);
7105 g_test_add_func (testpath: "/TreeModelFilter/ref-count/transfer/root-level/remove",
7106 test_func: ref_count_transfer_root_level_remove);
7107 g_test_add_func (testpath: "/TreeModelFilter/ref-count/transfer/root-level/remove/filtered",
7108 test_func: ref_count_transfer_root_level_remove_filtered);
7109 g_test_add_func (testpath: "/TreeModelFilter/ref-count/transfer/root-level/reordered",
7110 test_func: ref_count_transfer_root_level_reordered);
7111 g_test_add_func (testpath: "/TreeModelFilter/ref-count/transfer/root-level/reordered/filtered",
7112 test_func: ref_count_transfer_root_level_reordered_filtered);
7113 g_test_add_func (testpath: "/TreeModelFilter/ref-count/transfer/root-level/filter",
7114 test_func: ref_count_transfer_root_level_filter);
7115 g_test_add_func (testpath: "/TreeModelFilter/ref-count/transfer/child-level/insert",
7116 test_func: ref_count_transfer_child_level_insert);
7117 g_test_add_func (testpath: "/TreeModelFilter/ref-count/transfer/child-level/remove",
7118 test_func: ref_count_transfer_child_level_remove);
7119 g_test_add_func (testpath: "/TreeModelFilter/ref-count/transfer/child-level/remove/filtered",
7120 test_func: ref_count_transfer_child_level_remove_filtered);
7121 g_test_add_func (testpath: "/TreeModelFilter/ref-count/transfer/child-level/reordered",
7122 test_func: ref_count_transfer_child_level_reordered);
7123 g_test_add_func (testpath: "/TreeModelFilter/ref-count/transfer/child-level/reordered/filtered",
7124 test_func: ref_count_transfer_child_level_reordered_filtered);
7125 g_test_add_func (testpath: "/TreeModelFilter/ref-count/transfer/child-level/filter",
7126 test_func: ref_count_transfer_child_level_filter);
7127
7128 g_test_add_func (testpath: "/TreeModelFilter/specific/path-dependent-filter",
7129 test_func: specific_path_dependent_filter);
7130 g_test_add_func (testpath: "/TreeModelFilter/specific/append-after-collapse",
7131 test_func: specific_append_after_collapse);
7132 g_test_add_func (testpath: "/TreeModelFilter/specific/sort-filter-remove-node",
7133 test_func: specific_sort_filter_remove_node);
7134 g_test_add_func (testpath: "/TreeModelFilter/specific/sort-filter-remove-root",
7135 test_func: specific_sort_filter_remove_root);
7136 g_test_add_func (testpath: "/TreeModelFilter/specific/root-mixed-visibility",
7137 test_func: specific_root_mixed_visibility);
7138 g_test_add_func (testpath: "/TreeModelFilter/specific/has-child-filter",
7139 test_func: specific_has_child_filter);
7140 g_test_add_func (testpath: "/TreeModelFilter/specific/has-child-filter-on-sort-model",
7141 test_func: specific_has_child_filter_on_sort_model);
7142 g_test_add_func (testpath: "/TreeModelFilter/specific/at-least-2-children-filter",
7143 test_func: specific_at_least_2_children_filter);
7144 g_test_add_func (testpath: "/TreeModelFilter/specific/at-least-2-children-filter-on-sort-model",
7145 test_func: specific_at_least_2_children_filter_on_sort_model);
7146 g_test_add_func (testpath: "/TreeModelFilter/specific/root-has-child-filter",
7147 test_func: specific_root_has_child_filter);
7148 g_test_add_func (testpath: "/TreeModelFilter/specific/filter-add-child",
7149 test_func: specific_filter_add_child);
7150 g_test_add_func (testpath: "/TreeModelFilter/specific/list-store-clear",
7151 test_func: specific_list_store_clear);
7152 g_test_add_func (testpath: "/TreeModelFilter/specific/sort-ref-leaf-and-remove-ancestor",
7153 test_func: specific_sort_ref_leaf_and_remove_ancestor);
7154 g_test_add_func (testpath: "/TreeModelFilter/specific/ref-leaf-and-remove-ancestor",
7155 test_func: specific_ref_leaf_and_remove_ancestor);
7156 g_test_add_func (testpath: "/TreeModelFilter/specific/virtual-ref-leaf-and-remove-ancestor",
7157 test_func: specific_virtual_ref_leaf_and_remove_ancestor);
7158
7159 g_test_add_func (testpath: "/TreeModelFilter/specific/bug-301558",
7160 test_func: specific_bug_301558);
7161 g_test_add_func (testpath: "/TreeModelFilter/specific/bug-311955",
7162 test_func: specific_bug_311955);
7163 g_test_add_func (testpath: "/TreeModelFilter/specific/bug-311955-clean",
7164 test_func: specific_bug_311955_clean);
7165 g_test_add_func (testpath: "/TreeModelFilter/specific/bug-346800",
7166 test_func: specific_bug_346800);
7167 g_test_add_func (testpath: "/TreeModelFilter/specific/bug-464173",
7168 test_func: specific_bug_464173);
7169 g_test_add_func (testpath: "/TreeModelFilter/specific/bug-540201",
7170 test_func: specific_bug_540201);
7171 g_test_add_func (testpath: "/TreeModelFilter/specific/bug-549287",
7172 test_func: specific_bug_549287);
7173 g_test_add_func (testpath: "/TreeModelFilter/specific/bug-621076",
7174 test_func: specific_bug_621076);
7175 g_test_add_func (testpath: "/TreeModelFilter/specific/bug-657353-related",
7176 test_func: specific_bug_657353_related);
7177 g_test_add_func (testpath: "/TreeModelFilter/specific/bug-657353",
7178 test_func: specific_bug_657353);
7179 g_test_add_func (testpath: "/TreeModelFilter/specific/bug-658696",
7180 test_func: specific_bug_658696);
7181 g_test_add_func (testpath: "/TreeModelFilter/specific/bug-659022/row-changed-emission",
7182 test_func: specific_bug_659022_row_changed_emission);
7183 g_test_add_func (testpath: "/TreeModelFilter/specific/bug-659022/row-deleted-node-invisible",
7184 test_func: specific_bug_659022_row_deleted_node_invisible);
7185 g_test_add_func (testpath: "/TreeModelFilter/specific/bug-659022/row-deleted-free-level",
7186 test_func: specific_bug_659022_row_deleted_free_level);
7187 g_test_add_func (testpath: "/TreeModelFilter/specific/bug-679910",
7188 test_func: specific_bug_679910);
7189
7190 g_test_add_func (testpath: "/TreeModelFilter/signal/row-changed", test_func: test_row_changed);
7191}
7192

source code of gtk/testsuite/gtk/filtermodel.c