1/*
2 * Copyright (C) 2019, Red Hat, Inc.
3 * Authors: Matthias Clasen <mclasen@redhat.com>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <locale.h>
20
21#include <gtk/gtk.h>
22
23static GQuark number_quark;
24static GQuark changes_quark;
25static GQuark selection_quark;
26
27static guint
28get (GListModel *model,
29 guint position)
30{
31 guint number;
32 GObject *object = g_list_model_get_item (list: model, position);
33 g_assert_nonnull (object);
34 number = GPOINTER_TO_UINT (g_object_get_qdata (object, number_quark));
35 g_object_unref (object);
36 return number;
37}
38
39static char *
40model_to_string (GListModel *model)
41{
42 GString *string = g_string_new (NULL);
43 guint i;
44
45 for (i = 0; i < g_list_model_get_n_items (list: model); i++)
46 {
47 if (i > 0)
48 g_string_append (string, val: " ");
49 g_string_append_printf (string, format: "%u", get (model, position: i));
50 }
51
52 return g_string_free (string, FALSE);
53}
54
55static char *
56selection_to_string (GListModel *model)
57{
58 GString *string = g_string_new (NULL);
59 guint i;
60
61 for (i = 0; i < g_list_model_get_n_items (list: model); i++)
62 {
63 if (!gtk_selection_model_is_selected (model: GTK_SELECTION_MODEL (ptr: model), position: i))
64 continue;
65
66 if (string->len > 0)
67 g_string_append (string, val: " ");
68 g_string_append_printf (string, format: "%u", get (model, position: i));
69 }
70
71 return g_string_free (string, FALSE);
72}
73
74static GListStore *
75new_store (guint start,
76 guint end,
77 guint step);
78
79static GObject *
80make_object (guint number)
81{
82 GObject *object;
83
84 /* 0 cannot be differentiated from NULL, so don't use it */
85 g_assert_cmpint (number, !=, 0);
86
87 object = g_object_new (G_TYPE_OBJECT, NULL);
88 g_object_set_qdata (object, quark: number_quark, GUINT_TO_POINTER (number));
89
90 return object;
91}
92
93static void
94splice (GListStore *store,
95 guint pos,
96 guint removed,
97 guint *numbers,
98 guint added)
99{
100 GObject **objects = g_newa (GObject *, added);
101 guint i;
102
103 for (i = 0; i < added; i++)
104 objects[i] = make_object (number: numbers[i]);
105
106 g_list_store_splice (store, position: pos, n_removals: removed, additions: (gpointer *) objects, n_additions: added);
107
108 for (i = 0; i < added; i++)
109 g_object_unref (object: objects[i]);
110}
111
112static void
113add (GListStore *store,
114 guint number)
115{
116 GObject *object = make_object (number);
117 g_list_store_append (store, item: object);
118 g_object_unref (object);
119}
120
121static void
122insert (GListStore *store,
123 guint position,
124 guint number)
125{
126 GObject *object = make_object (number);
127 g_list_store_insert (store, position, item: object);
128 g_object_unref (object);
129}
130
131#define assert_model(model, expected) G_STMT_START{ \
132 char *s = model_to_string (G_LIST_MODEL (model)); \
133 if (!g_str_equal (s, expected)) \
134 g_assertion_message_cmpstr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
135 #model " == " #expected, s, "==", expected); \
136 g_free (s); \
137}G_STMT_END
138
139#define ignore_changes(model) G_STMT_START{ \
140 GString *changes = g_object_get_qdata (G_OBJECT (model), changes_quark); \
141 g_string_set_size (changes, 0); \
142}G_STMT_END
143
144#define assert_changes(model, expected) G_STMT_START{ \
145 GString *changes = g_object_get_qdata (G_OBJECT (model), changes_quark); \
146 if (!g_str_equal (changes->str, expected)) \
147 g_assertion_message_cmpstr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
148 #model " == " #expected, changes->str, "==", expected); \
149 g_string_set_size (changes, 0); \
150}G_STMT_END
151
152#define assert_selection(model, expected) G_STMT_START{ \
153 char *s = selection_to_string (G_LIST_MODEL (model)); \
154 if (!g_str_equal (s, expected)) \
155 g_assertion_message_cmpstr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
156 #model " == " #expected, s, "==", expected); \
157 g_free (s); \
158}G_STMT_END
159
160#define assert_selection_changes(model, expected) G_STMT_START{ \
161 GString *changes = g_object_get_qdata (G_OBJECT (model), selection_quark); \
162 if (!g_str_equal (changes->str, expected)) \
163 g_assertion_message_cmpstr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
164 #model " == " #expected, changes->str, "==", expected); \
165 g_string_set_size (changes, 0); \
166}G_STMT_END
167
168#define ignore_selection_changes(model) G_STMT_START{ \
169 GString *changes = g_object_get_qdata (G_OBJECT (model), selection_quark); \
170 g_string_set_size (changes, 0); \
171}G_STMT_END
172
173static GListStore *
174new_empty_store (void)
175{
176 return g_list_store_new (G_TYPE_OBJECT);
177}
178
179static GListStore *
180new_store (guint start,
181 guint end,
182 guint step)
183{
184 GListStore *store = new_empty_store ();
185 guint i;
186
187 for (i = start; i <= end; i += step)
188 add (store, number: i);
189
190 return store;
191}
192
193static void
194items_changed (GListModel *model,
195 guint position,
196 guint removed,
197 guint added,
198 GString *changes)
199{
200 g_assert_true (removed != 0 || added != 0);
201
202 if (changes->len)
203 g_string_append (string: changes, val: ", ");
204
205 if (removed == 1 && added == 0)
206 {
207 g_string_append_printf (string: changes, format: "-%u", position);
208 }
209 else if (removed == 0 && added == 1)
210 {
211 g_string_append_printf (string: changes, format: "+%u", position);
212 }
213 else
214 {
215 g_string_append_printf (string: changes, format: "%u", position);
216 if (removed > 0)
217 g_string_append_printf (string: changes, format: "-%u", removed);
218 if (added > 0)
219 g_string_append_printf (string: changes, format: "+%u", added);
220 }
221}
222
223static void
224selection_changed (GListModel *model,
225 guint position,
226 guint n_items,
227 GString *changes)
228{
229 if (changes->len)
230 g_string_append (string: changes, val: ", ");
231
232 g_string_append_printf (string: changes, format: "%u:%u", position, n_items);
233}
234
235static void
236free_changes (gpointer data)
237{
238 GString *changes = data;
239
240 /* all changes must have been checked via assert_changes() before */
241 g_assert_cmpstr (changes->str, ==, "");
242
243 g_string_free (string: changes, TRUE);
244}
245
246static GtkSelectionModel *
247new_model (GListStore *store, gboolean autoselect, gboolean can_unselect)
248{
249 GtkSelectionModel *result;
250 GString *changes;
251
252 result = GTK_SELECTION_MODEL (ptr: gtk_single_selection_new (g_object_ref (G_LIST_MODEL (store))));
253
254 /* We want to return an empty selection unless autoselect is true,
255 * so undo the initial selection due to autoselect defaulting to TRUE.
256 */
257 gtk_single_selection_set_autoselect (self: GTK_SINGLE_SELECTION (ptr: result), FALSE);
258 gtk_single_selection_set_can_unselect (self: GTK_SINGLE_SELECTION (ptr: result), TRUE);
259 gtk_selection_model_unselect_item (model: result, position: 0);
260 assert_selection (result, "");
261
262 gtk_single_selection_set_autoselect (self: GTK_SINGLE_SELECTION (ptr: result), autoselect);
263 gtk_single_selection_set_can_unselect (self: GTK_SINGLE_SELECTION (ptr: result), can_unselect);
264
265 changes = g_string_new (init: "");
266 g_object_set_qdata_full (G_OBJECT(result), quark: changes_quark, data: changes, destroy: free_changes);
267 g_signal_connect (result, "items-changed", G_CALLBACK (items_changed), changes);
268
269 changes = g_string_new (init: "");
270 g_object_set_qdata_full (G_OBJECT(result), quark: selection_quark, data: changes, destroy: free_changes);
271 g_signal_connect (result, "selection-changed", G_CALLBACK (selection_changed), changes);
272
273 return result;
274}
275
276static void
277test_create (void)
278{
279 GtkSelectionModel *selection;
280 GListStore *store;
281
282 if (glib_check_version (required_major: 2, required_minor: 59, required_micro: 0) != NULL)
283 {
284 g_test_skip (msg: "g_list_store_get_item() has overflow issues before GLIB 2.59.0");
285 return;
286 }
287
288 store = new_store (start: 1, end: 5, step: 2);
289 selection = new_model (store, FALSE, FALSE);
290 g_assert_false (gtk_single_selection_get_autoselect (GTK_SINGLE_SELECTION (selection)));
291
292 assert_model (selection, "1 3 5");
293 assert_changes (selection, "");
294 assert_selection (selection, "");
295 assert_selection_changes (selection, "");
296
297 g_object_unref (object: store);
298
299 assert_model (selection, "1 3 5");
300 assert_changes (selection, "");
301 assert_selection (selection, "");
302 assert_selection_changes (selection, "");
303
304 g_object_unref (object: selection);
305}
306
307static void
308test_create_empty (void)
309{
310 GtkSingleSelection *selection;
311
312 selection = gtk_single_selection_new (NULL);
313 g_assert_cmpint (g_list_model_get_n_items (G_LIST_MODEL (selection)), ==, 0);
314
315 g_object_unref (object: selection);
316}
317
318static void
319test_changes (void)
320{
321 GtkSelectionModel *selection;
322 GListStore *store;
323
324 if (glib_check_version (required_major: 2, required_minor: 58, required_micro: 0) != NULL)
325 {
326 g_test_skip (msg: "g_list_store_splice() is broken before GLIB 2.58.0");
327 return;
328 }
329
330 store = new_store (start: 1, end: 5, step: 1);
331 selection = new_model (store, FALSE, FALSE);
332 assert_model (selection, "1 2 3 4 5");
333 assert_changes (selection, "");
334 assert_selection (selection, "");
335 assert_selection_changes (selection, "");
336
337 g_list_store_remove (store, position: 3);
338 assert_model (selection, "1 2 3 5");
339 assert_changes (selection, "-3");
340 assert_selection (selection, "");
341 assert_selection_changes (selection, "");
342
343 insert (store, position: 3, number: 99);
344 assert_model (selection, "1 2 3 99 5");
345 assert_changes (selection, "+3");
346 assert_selection (selection, "");
347 assert_selection_changes (selection, "");
348
349 splice (store, pos: 3, removed: 2, numbers: (guint[]) { 97 }, added: 1);
350 assert_model (selection, "1 2 3 97");
351 assert_changes (selection, "3-2+1");
352 assert_selection (selection, "");
353 assert_selection_changes (selection, "");
354
355 g_object_unref (object: selection);
356 g_object_unref (object: store);
357}
358
359static void
360test_selection (void)
361{
362 GtkSelectionModel *selection;
363 GListStore *store;
364 gboolean ret;
365
366 if (glib_check_version (required_major: 2, required_minor: 59, required_micro: 0) != NULL)
367 {
368 g_test_skip (msg: "g_list_store_get_item() has overflow issues before GLIB 2.59.0");
369 return;
370 }
371
372 store = new_store (start: 1, end: 5, step: 1);
373 selection = new_model (store, TRUE, FALSE);
374 assert_selection (selection, "1");
375 assert_selection_changes (selection, "");
376
377 ret = gtk_selection_model_select_item (model: selection, position: 3, FALSE);
378 g_assert_true (ret);
379 assert_selection (selection, "4");
380 assert_selection_changes (selection, "0:4");
381
382 ret = gtk_selection_model_unselect_item (model: selection, position: 3);
383 g_assert_false (ret);
384 assert_selection (selection, "4");
385 assert_selection_changes (selection, "");
386
387 ret = gtk_selection_model_select_item (model: selection, position: 1, FALSE);
388 g_assert_true (ret);
389 assert_selection (selection, "2");
390 assert_selection_changes (selection, "1:3");
391
392 ret = gtk_selection_model_select_range (model: selection, position: 3, n_items: 2, FALSE);
393 g_assert_false (ret);
394 assert_selection (selection, "2");
395 assert_selection_changes (selection, "");
396
397 ret = gtk_selection_model_unselect_range (model: selection, position: 4, n_items: 2);
398 g_assert_false (ret);
399 assert_selection (selection, "2");
400 assert_selection_changes (selection, "");
401
402 ret = gtk_selection_model_select_all (model: selection);
403 g_assert_false (ret);
404 assert_selection (selection, "2");
405 assert_selection_changes (selection, "");
406
407 ret = gtk_selection_model_unselect_all (model: selection);
408 g_assert_false (ret);
409 assert_selection (selection, "2");
410 assert_selection_changes (selection, "");
411
412 g_object_unref (object: store);
413 g_object_unref (object: selection);
414}
415
416static void
417test_autoselect (void)
418{
419 GtkSelectionModel *selection;
420 GListStore *store;
421
422 if (glib_check_version (required_major: 2, required_minor: 59, required_micro: 0) != NULL)
423 {
424 g_test_skip (msg: "g_list_store_get_item() has overflow issues before GLIB 2.59.0");
425 return;
426 }
427
428 store = new_empty_store ();
429 selection = new_model (store, TRUE, FALSE);
430 assert_model (selection, "");
431 assert_changes (selection, "");
432 assert_selection (selection, "");
433 assert_selection_changes (selection, "");
434
435 add (store, number: 1);
436 assert_model (selection, "1");
437 assert_changes (selection, "+0");
438 assert_selection (selection, "1");
439 assert_selection_changes (selection, "");
440
441 splice (store, pos: 0, removed: 1, numbers: (guint[]) { 7, 8, 9 }, added: 3);
442 assert_model (selection, "7 8 9");
443 assert_changes (selection, "0-1+3");
444 assert_selection (selection, "7");
445 assert_selection_changes (selection, "");
446
447 splice (store, pos: 0, removed: 0, numbers: (guint[]) { 5, 6 }, added: 2);
448 assert_model (selection, "5 6 7 8 9");
449 assert_changes (selection, "0+2");
450 assert_selection (selection, "7");
451 assert_selection_changes (selection, "");
452
453 g_list_store_remove (store, position: 2);
454 assert_model (selection, "5 6 8 9");
455 assert_changes (selection, "2-2+1");
456 assert_selection (selection, "8");
457 assert_selection_changes (selection, "");
458
459 splice (store, pos: 2, removed: 2, NULL, added: 0);
460 assert_model (selection, "5 6");
461 assert_changes (selection, "1-3+1");
462 assert_selection (selection, "6");
463 assert_selection_changes (selection, "");
464
465 splice (store, pos: 0, removed: 2, numbers: (guint[]) { 1, 2 }, added: 2);
466 assert_model (selection, "1 2");
467 assert_changes (selection, "0-2+2");
468 assert_selection (selection, "2");
469 assert_selection_changes (selection, "");
470
471 g_list_store_remove (store, position: 0);
472 assert_model (selection, "2");
473 assert_changes (selection, "-0");
474 assert_selection (selection, "2");
475 assert_selection_changes (selection, "");
476
477 g_list_store_remove (store, position: 0);
478 assert_model (selection, "");
479 assert_changes (selection, "-0");
480 assert_selection (selection, "");
481 assert_selection_changes (selection, "");
482
483 g_object_unref (object: store);
484 g_object_unref (object: selection);
485}
486
487static void
488test_autoselect_toggle (void)
489{
490 GtkSelectionModel *selection;
491 GListStore *store;
492
493 if (glib_check_version (required_major: 2, required_minor: 59, required_micro: 0) != NULL)
494 {
495 g_test_skip (msg: "g_list_store_get_item() has overflow issues before GLIB 2.59.0");
496 return;
497 }
498
499 store = new_store (start: 1, end: 1, step: 1);
500 selection = new_model (store, TRUE, TRUE);
501 assert_model (selection, "1");
502 assert_changes (selection, "");
503 assert_selection (selection, "1");
504 assert_selection_changes (selection, "");
505
506 gtk_single_selection_set_autoselect (self: GTK_SINGLE_SELECTION (ptr: selection), FALSE);
507 assert_model (selection, "1");
508 assert_changes (selection, "");
509 assert_selection (selection, "1");
510 assert_selection_changes (selection, "");
511
512 gtk_selection_model_unselect_item (model: selection, position: 0);
513 assert_model (selection, "1");
514 assert_changes (selection, "");
515 assert_selection (selection, "");
516 assert_selection_changes (selection, "0:1");
517
518 gtk_single_selection_set_autoselect (self: GTK_SINGLE_SELECTION (ptr: selection), TRUE);
519 assert_model (selection, "1");
520 assert_changes (selection, "");
521 assert_selection (selection, "1");
522 assert_selection_changes (selection, "0:1");
523
524 g_object_unref (object: store);
525 g_object_unref (object: selection);
526}
527
528static void
529test_can_unselect (void)
530{
531 GtkSelectionModel *selection;
532 GListStore *store;
533 gboolean ret;
534
535 if (glib_check_version (required_major: 2, required_minor: 59, required_micro: 0) != NULL)
536 {
537 g_test_skip (msg: "g_list_store_get_item() has overflow issues before GLIB 2.59.0");
538 return;
539 }
540
541 store = new_store (start: 1, end: 5, step: 1);
542 selection = new_model (store, TRUE, FALSE);
543 assert_selection (selection, "1");
544 assert_selection_changes (selection, "");
545
546 ret = gtk_selection_model_unselect_item (model: selection, position: 0);
547 g_assert_false (ret);
548 assert_selection (selection, "1");
549 assert_selection_changes (selection, "");
550
551 gtk_single_selection_set_can_unselect (self: GTK_SINGLE_SELECTION (ptr: selection), TRUE);
552
553 assert_selection (selection, "1");
554 ret = gtk_selection_model_unselect_item (model: selection, position: 0);
555 g_assert_true (ret);
556 assert_selection (selection, "");
557 assert_selection_changes (selection, "0:1");
558
559 ignore_changes (selection);
560
561 g_object_unref (object: store);
562 g_object_unref (object: selection);
563}
564
565static int
566sort_inverse (gconstpointer a, gconstpointer b, gpointer data)
567{
568 int ia = GPOINTER_TO_UINT (g_object_get_qdata (G_OBJECT (a), number_quark));
569 int ib = GPOINTER_TO_UINT (g_object_get_qdata (G_OBJECT (b), number_quark));
570
571 return ib - ia;
572}
573
574static void
575test_persistence (void)
576{
577 GtkSelectionModel *selection;
578 GListStore *store;
579
580 if (glib_check_version (required_major: 2, required_minor: 59, required_micro: 0) != NULL)
581 {
582 g_test_skip (msg: "g_list_store_get_item() has overflow issues before GLIB 2.59.0");
583 return;
584 }
585
586 store = new_store (start: 1, end: 5, step: 1);
587 selection = new_model (store, TRUE, FALSE);
588 assert_selection (selection, "1");
589 assert_selection_changes (selection, "");
590 g_assert_true (gtk_selection_model_is_selected (selection, 0));
591 g_assert_false (gtk_selection_model_is_selected (selection, 4));
592
593 g_list_store_sort (store, compare_func: sort_inverse, NULL);
594
595 assert_selection (selection, "1");
596 assert_selection_changes (selection, "");
597 g_assert_false (gtk_selection_model_is_selected (selection, 0));
598 g_assert_true (gtk_selection_model_is_selected (selection, 4));
599
600 ignore_changes (selection);
601
602 g_object_unref (object: store);
603 g_object_unref (object: selection);
604}
605
606static void
607check_get_selection (GtkSelectionModel *selection)
608{
609 GtkBitset *set;
610 guint i, n_items;
611
612 set = gtk_selection_model_get_selection (model: selection);
613
614 n_items = g_list_model_get_n_items (list: G_LIST_MODEL (ptr: selection));
615 if (n_items == 0)
616 {
617 g_assert_true (gtk_bitset_is_empty (set));
618 }
619 else
620 {
621 for (i = 0; i < n_items; i++)
622 {
623 g_assert_cmpint (gtk_bitset_contains (set, i), ==, gtk_selection_model_is_selected (selection, i));
624 }
625
626 /* check that out-of-range has no bits set */
627 g_assert_cmpint (gtk_bitset_get_maximum (set), <, g_list_model_get_n_items (G_LIST_MODEL (selection)));
628 }
629
630 gtk_bitset_unref (self: set);
631}
632
633static void
634test_query_range (void)
635{
636 GtkSelectionModel *selection;
637 GListStore *store;
638
639 store = new_store (start: 1, end: 5, step: 1);
640 selection = new_model (store, TRUE, TRUE);
641 check_get_selection (selection);
642
643 gtk_selection_model_unselect_item (model: selection, position: 0);
644 check_get_selection (selection);
645
646 gtk_selection_model_select_item (model: selection, position: 2, TRUE);
647 check_get_selection (selection);
648
649 gtk_selection_model_select_item (model: selection, position: 4, TRUE);
650 check_get_selection (selection);
651
652 ignore_selection_changes (selection);
653
654 g_object_unref (object: store);
655 g_object_unref (object: selection);
656}
657
658static void
659test_set_model (void)
660{
661 GtkSelectionModel *selection;
662 GListStore *store;
663 GListModel *m1, *m2;
664
665 store = new_store (start: 1, end: 5, step: 1);
666 m1 = G_LIST_MODEL (ptr: store);
667 m2 = G_LIST_MODEL (ptr: gtk_slice_list_model_new (g_object_ref (m1), offset: 0, size: 3));
668 selection = new_model (store, TRUE, TRUE);
669 assert_selection (selection, "1");
670 assert_selection_changes (selection, "");
671
672 /* we retain the selected item across model changes */
673 gtk_single_selection_set_model (self: GTK_SINGLE_SELECTION (ptr: selection), model: m2);
674 assert_changes (selection, "0-5+3");
675 assert_selection (selection, "1");
676 assert_selection_changes (selection, "");
677
678 gtk_single_selection_set_model (self: GTK_SINGLE_SELECTION (ptr: selection), NULL);
679 assert_changes (selection, "0-3");
680 assert_selection (selection, "");
681 assert_selection_changes (selection, "");
682
683 gtk_single_selection_set_autoselect (self: GTK_SINGLE_SELECTION (ptr: selection), FALSE);
684 gtk_single_selection_set_model (self: GTK_SINGLE_SELECTION (ptr: selection), model: m2);
685 assert_changes (selection, "0+3");
686 assert_selection (selection, "");
687 assert_selection_changes (selection, "");
688
689 /* we retain no selected item across model changes */
690 gtk_single_selection_set_model (self: GTK_SINGLE_SELECTION (ptr: selection), model: m1);
691 assert_changes (selection, "0-3+5");
692 assert_selection (selection, "");
693 assert_selection_changes (selection, "");
694
695 gtk_single_selection_set_selected (self: GTK_SINGLE_SELECTION (ptr: selection), position: 4);
696 assert_selection (selection, "5");
697 assert_selection_changes (selection, "4:1");
698
699 gtk_single_selection_set_model (self: GTK_SINGLE_SELECTION (ptr: selection), model: m2);
700 assert_changes (selection, "0-5+3");
701 assert_selection (selection, "");
702 assert_selection_changes (selection, "");
703
704 g_object_unref (object: m2);
705 g_object_unref (object: m1);
706 g_object_unref (object: selection);
707}
708
709static void
710test_empty (void)
711{
712 GtkSingleSelection *selection;
713 GListStore *store;
714
715 selection = gtk_single_selection_new (NULL);
716
717 g_assert_cmpuint (g_list_model_get_n_items (G_LIST_MODEL (selection)), ==, 0);
718 g_assert_null (g_list_model_get_item (G_LIST_MODEL (selection), 11));
719
720 store = g_list_store_new (G_TYPE_OBJECT);
721 gtk_single_selection_set_model (self: selection, model: G_LIST_MODEL (ptr: store));
722 g_object_unref (object: store);
723
724 g_assert_cmpuint (g_list_model_get_n_items (G_LIST_MODEL (selection)), ==, 0);
725 g_assert_null (g_list_model_get_item (G_LIST_MODEL (selection), 11));
726
727 g_object_unref (object: selection);
728}
729
730int
731main (int argc, char *argv[])
732{
733 (g_test_init) (argc: &argc, argv: &argv, NULL);
734 setlocale (LC_ALL, locale: "C");
735
736 number_quark = g_quark_from_static_string (string: "Hell and fire was spawned to be released.");
737 changes_quark = g_quark_from_static_string (string: "What did I see? Can I believe what I saw?");
738 selection_quark = g_quark_from_static_string (string: "Mana mana, badibidibi");
739
740 g_test_add_func (testpath: "/singleselection/create", test_func: test_create);
741 g_test_add_func (testpath: "/singleselection/create-empty", test_func: test_create_empty);
742 g_test_add_func (testpath: "/singleselection/autoselect", test_func: test_autoselect);
743 g_test_add_func (testpath: "/singleselection/autoselect-toggle", test_func: test_autoselect_toggle);
744 g_test_add_func (testpath: "/singleselection/selection", test_func: test_selection);
745 g_test_add_func (testpath: "/singleselection/can-unselect", test_func: test_can_unselect);
746 g_test_add_func (testpath: "/singleselection/persistence", test_func: test_persistence);
747 g_test_add_func (testpath: "/singleselection/query-range", test_func: test_query_range);
748 g_test_add_func (testpath: "/singleselection/changes", test_func: test_changes);
749 g_test_add_func (testpath: "/singleselection/set-model", test_func: test_set_model);
750 g_test_add_func (testpath: "/singleselection/empty", test_func: test_empty);
751
752 return g_test_run ();
753}
754

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