3 /* Markup printing {{{1 */
5 /* This used to be part of GLib, but it was removed before the stable
6 * release because it wasn't generally useful. We want it here, though.
9 indent_string (GString
*string
,
13 g_string_append_c (string
, ' ');
17 g_menu_markup_print_string (GString
*string
,
22 gboolean need_nl
= FALSE
;
25 if G_UNLIKELY (string
== NULL
)
26 string
= g_string_new (NULL
);
28 n
= g_menu_model_get_n_items (model
);
30 for (i
= 0; i
< n
; i
++)
32 GMenuAttributeIter
*attr_iter
;
33 GMenuLinkIter
*link_iter
;
37 attr_iter
= g_menu_model_iterate_item_attributes (model
, i
);
38 link_iter
= g_menu_model_iterate_item_links (model
, i
);
39 contents
= g_string_new (NULL
);
40 attrs
= g_string_new (NULL
);
42 while (g_menu_attribute_iter_next (attr_iter
))
44 const char *name
= g_menu_attribute_iter_get_name (attr_iter
);
45 GVariant
*value
= g_menu_attribute_iter_get_value (attr_iter
);
47 if (g_variant_is_of_type (value
, G_VARIANT_TYPE_STRING
))
50 str
= g_markup_printf_escaped (" %s='%s'", name
, g_variant_get_string (value
, NULL
));
51 g_string_append (attrs
, str
);
61 printed
= g_variant_print (value
, TRUE
);
62 type
= g_variant_type_peek_string (g_variant_get_type (value
));
63 str
= g_markup_printf_escaped ("<attribute name='%s' type='%s'>%s</attribute>\n", name
, type
, printed
);
64 indent_string (contents
, indent
+ tabstop
);
65 g_string_append (contents
, str
);
70 g_variant_unref (value
);
72 g_object_unref (attr_iter
);
74 while (g_menu_link_iter_next (link_iter
))
76 const gchar
*name
= g_menu_link_iter_get_name (link_iter
);
77 GMenuModel
*menu
= g_menu_link_iter_get_value (link_iter
);
81 g_string_append_c (contents
, '\n');
83 str
= g_markup_printf_escaped ("<link name='%s'>\n", name
);
84 indent_string (contents
, indent
+ tabstop
);
85 g_string_append (contents
, str
);
88 g_menu_markup_print_string (contents
, menu
, indent
+ 2 * tabstop
, tabstop
);
90 indent_string (contents
, indent
+ tabstop
);
91 g_string_append (contents
, "</link>\n");
92 g_object_unref (menu
);
94 g_object_unref (link_iter
);
98 indent_string (string
, indent
);
99 g_string_append_printf (string
, "<item%s>\n", attrs
->str
);
100 g_string_append (string
, contents
->str
);
101 indent_string (string
, indent
);
102 g_string_append (string
, "</item>\n");
109 g_string_append_c (string
, '\n');
111 indent_string (string
, indent
);
112 g_string_append_printf (string
, "<item%s/>\n", attrs
->str
);
116 g_string_free (contents
, TRUE
);
117 g_string_free (attrs
, TRUE
);
125 /* This utility struct is used by both the RandomMenu and MirrorMenu
126 * class implementations below.
129 GHashTable
*attributes
;
134 test_item_new (GHashTable
*attributes
,
139 item
= g_slice_new (TestItem
);
140 item
->attributes
= g_hash_table_ref (attributes
);
141 item
->links
= g_hash_table_ref (links
);
147 test_item_free (gpointer data
)
149 TestItem
*item
= data
;
151 g_hash_table_unref (item
->attributes
);
152 g_hash_table_unref (item
->links
);
154 g_slice_free (TestItem
, item
);
157 /* RandomMenu {{{1 */
162 GMenuModel parent_instance
;
168 typedef GMenuModelClass RandomMenuClass
;
170 static GType
random_menu_get_type (void);
171 G_DEFINE_TYPE (RandomMenu
, random_menu
, G_TYPE_MENU_MODEL
);
174 random_menu_is_mutable (GMenuModel
*model
)
180 random_menu_get_n_items (GMenuModel
*model
)
182 RandomMenu
*menu
= (RandomMenu
*) model
;
184 return g_sequence_get_length (menu
->items
);
188 random_menu_get_item_attributes (GMenuModel
*model
,
192 RandomMenu
*menu
= (RandomMenu
*) model
;
195 item
= g_sequence_get (g_sequence_get_iter_at_pos (menu
->items
, position
));
196 *table
= g_hash_table_ref (item
->attributes
);
200 random_menu_get_item_links (GMenuModel
*model
,
204 RandomMenu
*menu
= (RandomMenu
*) model
;
207 item
= g_sequence_get (g_sequence_get_iter_at_pos (menu
->items
, position
));
208 *table
= g_hash_table_ref (item
->links
);
212 random_menu_finalize (GObject
*object
)
214 RandomMenu
*menu
= (RandomMenu
*) object
;
216 g_sequence_free (menu
->items
);
218 G_OBJECT_CLASS (random_menu_parent_class
)
223 random_menu_init (RandomMenu
*menu
)
228 random_menu_class_init (GMenuModelClass
*class)
230 GObjectClass
*object_class
= G_OBJECT_CLASS (class);
232 class->is_mutable
= random_menu_is_mutable
;
233 class->get_n_items
= random_menu_get_n_items
;
234 class->get_item_attributes
= random_menu_get_item_attributes
;
235 class->get_item_links
= random_menu_get_item_links
;
237 object_class
->finalize
= random_menu_finalize
;
240 static RandomMenu
* random_menu_new (GRand
*rand
, gint order
);
243 random_menu_change (RandomMenu
*menu
,
246 gint position
, removes
, adds
;
247 GSequenceIter
*point
;
251 n_items
= g_sequence_get_length (menu
->items
);
255 position
= g_rand_int_range (rand
, 0, n_items
+ 1);
256 removes
= g_rand_int_range (rand
, 0, n_items
- position
+ 1);
257 adds
= g_rand_int_range (rand
, 0, MAX_ITEMS
- (n_items
- removes
) + 1);
259 while (removes
== 0 && adds
== 0);
261 point
= g_sequence_get_iter_at_pos (menu
->items
, position
+ removes
);
265 GSequenceIter
*start
;
267 start
= g_sequence_get_iter_at_pos (menu
->items
, position
);
268 g_sequence_remove_range (start
, point
);
271 for (i
= 0; i
< adds
; i
++)
275 GHashTable
*attributes
;
277 attributes
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, (GDestroyNotify
) g_variant_unref
);
278 links
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, (GDestroyNotify
) g_object_unref
);
280 if (menu
->order
> 0 && g_rand_boolean (rand
))
283 const gchar
*subtype
;
285 child
= random_menu_new (rand
, menu
->order
- 1);
287 if (g_rand_boolean (rand
))
289 subtype
= G_MENU_LINK_SECTION
;
290 /* label some section headers */
291 if (g_rand_boolean (rand
))
298 /* label all submenus */
299 subtype
= G_MENU_LINK_SUBMENU
;
303 g_hash_table_insert (links
, g_strdup (subtype
), child
);
306 /* label all terminals */
310 g_hash_table_insert (attributes
, g_strdup ("label"), g_variant_ref_sink (g_variant_new_string (label
)));
312 g_sequence_insert_before (point
, test_item_new (attributes
, links
));
313 g_hash_table_unref (links
);
314 g_hash_table_unref (attributes
);
317 g_menu_model_items_changed (G_MENU_MODEL (menu
), position
, removes
, adds
);
321 random_menu_new (GRand
*rand
,
326 menu
= g_object_new (random_menu_get_type (), NULL
);
327 menu
->items
= g_sequence_new (test_item_free
);
330 random_menu_change (menu
, rand
);
335 /* MirrorMenu {{{1 */
337 GMenuModel parent_instance
;
339 GMenuModel
*clone_of
;
344 typedef GMenuModelClass MirrorMenuClass
;
346 static GType
mirror_menu_get_type (void);
347 G_DEFINE_TYPE (MirrorMenu
, mirror_menu
, G_TYPE_MENU_MODEL
);
350 mirror_menu_is_mutable (GMenuModel
*model
)
352 MirrorMenu
*menu
= (MirrorMenu
*) model
;
354 return menu
->handler_id
!= 0;
358 mirror_menu_get_n_items (GMenuModel
*model
)
360 MirrorMenu
*menu
= (MirrorMenu
*) model
;
362 return g_sequence_get_length (menu
->items
);
366 mirror_menu_get_item_attributes (GMenuModel
*model
,
370 MirrorMenu
*menu
= (MirrorMenu
*) model
;
373 item
= g_sequence_get (g_sequence_get_iter_at_pos (menu
->items
, position
));
374 *table
= g_hash_table_ref (item
->attributes
);
378 mirror_menu_get_item_links (GMenuModel
*model
,
382 MirrorMenu
*menu
= (MirrorMenu
*) model
;
385 item
= g_sequence_get (g_sequence_get_iter_at_pos (menu
->items
, position
));
386 *table
= g_hash_table_ref (item
->links
);
390 mirror_menu_finalize (GObject
*object
)
392 MirrorMenu
*menu
= (MirrorMenu
*) object
;
394 if (menu
->handler_id
)
395 g_signal_handler_disconnect (menu
->clone_of
, menu
->handler_id
);
397 g_sequence_free (menu
->items
);
398 g_object_unref (menu
->clone_of
);
400 G_OBJECT_CLASS (mirror_menu_parent_class
)
405 mirror_menu_init (MirrorMenu
*menu
)
410 mirror_menu_class_init (GMenuModelClass
*class)
412 GObjectClass
*object_class
= G_OBJECT_CLASS (class);
414 class->is_mutable
= mirror_menu_is_mutable
;
415 class->get_n_items
= mirror_menu_get_n_items
;
416 class->get_item_attributes
= mirror_menu_get_item_attributes
;
417 class->get_item_links
= mirror_menu_get_item_links
;
419 object_class
->finalize
= mirror_menu_finalize
;
422 static MirrorMenu
* mirror_menu_new (GMenuModel
*clone_of
);
425 mirror_menu_changed (GMenuModel
*model
,
431 MirrorMenu
*menu
= user_data
;
432 GSequenceIter
*point
;
435 g_assert (model
== menu
->clone_of
);
437 point
= g_sequence_get_iter_at_pos (menu
->items
, position
+ removed
);
441 GSequenceIter
*start
;
443 start
= g_sequence_get_iter_at_pos (menu
->items
, position
);
444 g_sequence_remove_range (start
, point
);
447 for (i
= position
; i
< position
+ added
; i
++)
449 GMenuAttributeIter
*attr_iter
;
450 GMenuLinkIter
*link_iter
;
452 GHashTable
*attributes
;
457 attributes
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, (GDestroyNotify
) g_variant_unref
);
458 links
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, (GDestroyNotify
) g_object_unref
);
460 attr_iter
= g_menu_model_iterate_item_attributes (model
, i
);
461 while (g_menu_attribute_iter_get_next (attr_iter
, &name
, &value
))
463 g_hash_table_insert (attributes
, g_strdup (name
), value
);
465 g_object_unref (attr_iter
);
467 link_iter
= g_menu_model_iterate_item_links (model
, i
);
468 while (g_menu_link_iter_get_next (link_iter
, &name
, &child
))
470 g_hash_table_insert (links
, g_strdup (name
), mirror_menu_new (child
));
471 g_object_unref (child
);
473 g_object_unref (link_iter
);
475 g_sequence_insert_before (point
, test_item_new (attributes
, links
));
476 g_hash_table_unref (attributes
);
477 g_hash_table_unref (links
);
480 g_menu_model_items_changed (G_MENU_MODEL (menu
), position
, removed
, added
);
484 mirror_menu_new (GMenuModel
*clone_of
)
488 menu
= g_object_new (mirror_menu_get_type (), NULL
);
489 menu
->items
= g_sequence_new (test_item_free
);
490 menu
->clone_of
= g_object_ref (clone_of
);
492 if (g_menu_model_is_mutable (clone_of
))
493 menu
->handler_id
= g_signal_connect (clone_of
, "items-changed", G_CALLBACK (mirror_menu_changed
), menu
);
494 mirror_menu_changed (clone_of
, 0, 0, g_menu_model_get_n_items (clone_of
), menu
);
499 /* check_menus_equal(), assert_menus_equal() {{{1 */
501 check_menus_equal (GMenuModel
*a
,
504 gboolean equal
= TRUE
;
508 a_n
= g_menu_model_get_n_items (a
);
509 b_n
= g_menu_model_get_n_items (b
);
514 for (i
= 0; i
< a_n
; i
++)
516 GMenuAttributeIter
*attr_iter
;
517 GVariant
*a_value
, *b_value
;
518 GMenuLinkIter
*link_iter
;
519 GMenuModel
*a_menu
, *b_menu
;
522 attr_iter
= g_menu_model_iterate_item_attributes (a
, i
);
523 while (g_menu_attribute_iter_get_next (attr_iter
, &name
, &a_value
))
525 b_value
= g_menu_model_get_item_attribute_value (b
, i
, name
, NULL
);
526 equal
&= b_value
&& g_variant_equal (a_value
, b_value
);
528 g_variant_unref (b_value
);
529 g_variant_unref (a_value
);
531 g_object_unref (attr_iter
);
533 attr_iter
= g_menu_model_iterate_item_attributes (b
, i
);
534 while (g_menu_attribute_iter_get_next (attr_iter
, &name
, &b_value
))
536 a_value
= g_menu_model_get_item_attribute_value (a
, i
, name
, NULL
);
537 equal
&= a_value
&& g_variant_equal (a_value
, b_value
);
539 g_variant_unref (a_value
);
540 g_variant_unref (b_value
);
542 g_object_unref (attr_iter
);
544 link_iter
= g_menu_model_iterate_item_links (a
, i
);
545 while (g_menu_link_iter_get_next (link_iter
, &name
, &a_menu
))
547 b_menu
= g_menu_model_get_item_link (b
, i
, name
);
548 equal
&= b_menu
&& check_menus_equal (a_menu
, b_menu
);
550 g_object_unref (b_menu
);
551 g_object_unref (a_menu
);
553 g_object_unref (link_iter
);
555 link_iter
= g_menu_model_iterate_item_links (b
, i
);
556 while (g_menu_link_iter_get_next (link_iter
, &name
, &b_menu
))
558 a_menu
= g_menu_model_get_item_link (a
, i
, name
);
559 equal
&= a_menu
&& check_menus_equal (a_menu
, b_menu
);
561 g_object_unref (a_menu
);
562 g_object_unref (b_menu
);
564 g_object_unref (link_iter
);
571 assert_menus_equal (GMenuModel
*a
,
574 if (!check_menus_equal (a
, b
))
578 string
= g_string_new ("\n <a>\n");
579 g_menu_markup_print_string (string
, G_MENU_MODEL (a
), 4, 2);
580 g_string_append (string
, " </a>\n\n-------------\n <b>\n");
581 g_menu_markup_print_string (string
, G_MENU_MODEL (b
), 4, 2);
582 g_string_append (string
, " </b>\n");
583 g_error ("%s", string
->str
);
587 /* Test cases {{{1 */
591 GRand
*randa
, *randb
;
595 seed
= g_test_rand_int ();
597 randa
= g_rand_new_with_seed (seed
);
598 randb
= g_rand_new_with_seed (seed
);
600 for (i
= 0; i
< 500; i
++)
604 a
= random_menu_new (randa
, TOP_ORDER
);
605 b
= random_menu_new (randb
, TOP_ORDER
);
606 assert_menus_equal (G_MENU_MODEL (a
), G_MENU_MODEL (b
));
613 for (i
= 0; i
< 500;)
617 a
= random_menu_new (randa
, TOP_ORDER
);
618 b
= random_menu_new (randb
, TOP_ORDER
);
619 if (check_menus_equal (G_MENU_MODEL (a
), G_MENU_MODEL (b
)))
621 /* by chance, they may really be equal. double check. */
624 as
= g_menu_markup_print_string (NULL
, G_MENU_MODEL (a
), 4, 2);
625 bs
= g_menu_markup_print_string (NULL
, G_MENU_MODEL (b
), 4, 2);
626 g_assert_cmpstr (as
->str
, ==, bs
->str
);
627 g_string_free (bs
, TRUE
);
628 g_string_free (as
, TRUE
);
630 /* we're here because randa and randb just generated equal
631 * menus. they may do it again, so throw away randb and make
635 randb
= g_rand_new_with_seed (g_rand_int (randa
));
638 /* make sure we get enough unequals (ie: no GRand failure) */
657 rand
= g_rand_new_with_seed (g_test_rand_int ());
658 random
= random_menu_new (rand
, TOP_ORDER
);
659 mirror
= mirror_menu_new (G_MENU_MODEL (random
));
661 for (i
= 0; i
< 500; i
++)
663 assert_menus_equal (G_MENU_MODEL (random
), G_MENU_MODEL (mirror
));
664 random_menu_change (random
, rand
);
667 g_object_unref (mirror
);
668 g_object_unref (random
);
673 struct roundtrip_state
676 MirrorMenu
*proxy_mirror
;
677 GDBusMenuModel
*proxy
;
685 roundtrip_step (gpointer data
)
687 struct roundtrip_state
*state
= data
;
689 if (check_menus_equal (G_MENU_MODEL (state
->random
), G_MENU_MODEL (state
->proxy
)) &&
690 check_menus_equal (G_MENU_MODEL (state
->random
), G_MENU_MODEL (state
->proxy_mirror
)))
695 if (state
->success
< 100)
696 random_menu_change (state
->random
, state
->rand
);
698 g_main_loop_quit (state
->loop
);
700 else if (state
->count
== 100)
702 assert_menus_equal (G_MENU_MODEL (state
->random
), G_MENU_MODEL (state
->proxy
));
703 g_assert_not_reached ();
708 return G_SOURCE_CONTINUE
;
712 test_dbus_roundtrip (void)
714 struct roundtrip_state state
;
715 GDBusConnection
*bus
;
719 bus
= g_bus_get_sync (G_BUS_TYPE_SESSION
, NULL
, NULL
);
721 state
.rand
= g_rand_new_with_seed (g_test_rand_int ());
723 state
.random
= random_menu_new (state
.rand
, 2);
724 export_id
= g_dbus_connection_export_menu_model (bus
, "/", G_MENU_MODEL (state
.random
), NULL
);
725 state
.proxy
= g_dbus_menu_model_get (bus
, g_dbus_connection_get_unique_name (bus
), "/");
726 state
.proxy_mirror
= mirror_menu_new (G_MENU_MODEL (state
.proxy
));
730 id
= g_timeout_add (10, roundtrip_step
, &state
);
732 state
.loop
= g_main_loop_new (NULL
, FALSE
);
733 g_main_loop_run (state
.loop
);
735 g_main_loop_unref (state
.loop
);
736 g_source_remove (id
);
737 g_object_unref (state
.proxy
);
738 g_dbus_connection_unexport_menu_model (bus
, export_id
);
739 g_object_unref (state
.random
);
740 g_object_unref (state
.proxy_mirror
);
741 g_rand_free (state
.rand
);
742 g_object_unref (bus
);
745 static gint items_changed_count
;
748 items_changed (GMenuModel
*model
,
754 items_changed_count
++;
758 stop_loop (gpointer data
)
760 GMainLoop
*loop
= data
;
762 g_main_loop_quit (loop
);
764 return G_SOURCE_REMOVE
;
768 test_dbus_subscriptions (void)
770 GDBusConnection
*bus
;
772 GDBusMenuModel
*proxy
;
774 GError
*error
= NULL
;
777 loop
= g_main_loop_new (NULL
, FALSE
);
779 bus
= g_bus_get_sync (G_BUS_TYPE_SESSION
, NULL
, NULL
);
781 menu
= g_menu_new ();
783 export_id
= g_dbus_connection_export_menu_model (bus
, "/", G_MENU_MODEL (menu
), &error
);
784 g_assert_no_error (error
);
786 proxy
= g_dbus_menu_model_get (bus
, g_dbus_connection_get_unique_name (bus
), "/");
787 items_changed_count
= 0;
788 g_signal_connect (proxy
, "items-changed",
789 G_CALLBACK (items_changed
), NULL
);
791 g_menu_append (menu
, "item1", NULL
);
792 g_menu_append (menu
, "item2", NULL
);
793 g_menu_append (menu
, "item3", NULL
);
795 g_assert_cmpint (items_changed_count
, ==, 0);
797 g_timeout_add (100, stop_loop
, loop
);
798 g_main_loop_run (loop
);
800 g_menu_model_get_n_items (G_MENU_MODEL (proxy
));
802 g_timeout_add (100, stop_loop
, loop
);
803 g_main_loop_run (loop
);
805 g_assert_cmpint (items_changed_count
, ==, 1);
806 g_assert_cmpint (g_menu_model_get_n_items (G_MENU_MODEL (proxy
)), ==, 3);
808 g_timeout_add (100, stop_loop
, loop
);
809 g_main_loop_run (loop
);
811 g_menu_append (menu
, "item4", NULL
);
812 g_menu_append (menu
, "item5", NULL
);
813 g_menu_append (menu
, "item6", NULL
);
814 g_menu_remove (menu
, 0);
815 g_menu_remove (menu
, 0);
817 g_timeout_add (200, stop_loop
, loop
);
818 g_main_loop_run (loop
);
820 g_assert_cmpint (items_changed_count
, ==, 6);
822 g_assert_cmpint (g_menu_model_get_n_items (G_MENU_MODEL (proxy
)), ==, 4);
823 g_object_unref (proxy
);
825 g_timeout_add (100, stop_loop
, loop
);
826 g_main_loop_run (loop
);
828 g_menu_remove (menu
, 0);
829 g_menu_remove (menu
, 0);
831 g_timeout_add (100, stop_loop
, loop
);
832 g_main_loop_run (loop
);
834 g_assert_cmpint (items_changed_count
, ==, 6);
836 g_dbus_connection_unexport_menu_model (bus
, export_id
);
837 g_object_unref (menu
);
839 g_main_loop_unref (loop
);
843 do_modify (gpointer data
)
845 RandomMenu
*menu
= data
;
849 rand
= g_rand_new_with_seed (g_test_rand_int ());
851 for (i
= 0; i
< 10000; i
++)
853 random_menu_change (menu
, rand
);
860 do_export (gpointer data
)
862 GMenuModel
*menu
= data
;
864 GDBusConnection
*bus
;
866 GError
*error
= NULL
;
869 bus
= g_bus_get_sync (G_BUS_TYPE_SESSION
, NULL
, NULL
);
870 path
= g_strdup_printf ("/%p", data
);
872 for (i
= 0; i
< 10000; i
++)
874 id
= g_dbus_connection_export_menu_model (bus
, path
, menu
, &error
);
875 g_assert_no_error (error
);
876 g_dbus_connection_unexport_menu_model (bus
, id
);
877 while (g_main_context_iteration (NULL
, FALSE
));
882 g_object_unref (bus
);
888 test_dbus_threaded (void)
890 RandomMenu
*menu
[10];
895 for (i
= 0; i
< 10; i
++)
897 menu
[i
] = random_menu_new (g_rand_new_with_seed (g_test_rand_int ()), 2);
898 call
[i
] = g_thread_new ("call", do_modify
, menu
[i
]);
899 export
[i
] = g_thread_new ("export", do_export
, menu
[i
]);
902 for (i
= 0; i
< 10; i
++)
904 g_thread_join (call
[i
]);
905 g_thread_join (export
[i
]);
908 for (i
= 0; i
< 10; i
++)
909 g_object_unref (menu
[i
]);
913 test_attributes (void)
919 menu
= g_menu_new ();
921 item
= g_menu_item_new ("test", NULL
);
922 g_menu_item_set_attribute_value (item
, "boolean", g_variant_new_boolean (FALSE
));
923 g_menu_item_set_attribute_value (item
, "string", g_variant_new_string ("bla"));
924 g_menu_item_set_attribute_value (item
, "double", g_variant_new_double (1.5));
925 v
= g_variant_new_parsed ("[('one', 1), ('two', %i), (%s, 3)]", 2, "three");
926 g_menu_item_set_attribute_value (item
, "complex", v
);
927 g_menu_item_set_attribute_value (item
, "test-123", g_variant_new_string ("test-123"));
929 g_menu_append_item (menu
, item
);
931 g_assert_cmpint (g_menu_model_get_n_items (G_MENU_MODEL (menu
)), ==, 1);
933 v
= g_menu_model_get_item_attribute_value (G_MENU_MODEL (menu
), 0, "boolean", NULL
);
934 g_assert (g_variant_is_of_type (v
, G_VARIANT_TYPE_BOOLEAN
));
937 v
= g_menu_model_get_item_attribute_value (G_MENU_MODEL (menu
), 0, "string", NULL
);
938 g_assert (g_variant_is_of_type (v
, G_VARIANT_TYPE_STRING
));
941 v
= g_menu_model_get_item_attribute_value (G_MENU_MODEL (menu
), 0, "double", NULL
);
942 g_assert (g_variant_is_of_type (v
, G_VARIANT_TYPE_DOUBLE
));
945 v
= g_menu_model_get_item_attribute_value (G_MENU_MODEL (menu
), 0, "complex", NULL
);
946 g_assert (g_variant_is_of_type (v
, G_VARIANT_TYPE("a(si)")));
949 g_object_unref (menu
);
960 m
= G_MENU_MODEL (g_menu_new ());
961 g_menu_append (G_MENU (m
), "test", NULL
);
963 menu
= g_menu_new ();
965 item
= g_menu_item_new ("test1", NULL
);
966 g_menu_item_set_link (item
, "section", m
);
967 g_menu_append_item (menu
, item
);
969 item
= g_menu_item_new ("test2", NULL
);
970 g_menu_item_set_link (item
, "submenu", m
);
971 g_menu_append_item (menu
, item
);
973 item
= g_menu_item_new ("test3", NULL
);
974 g_menu_item_set_link (item
, "wallet", m
);
975 g_menu_append_item (menu
, item
);
977 item
= g_menu_item_new ("test4", NULL
);
978 g_menu_item_set_link (item
, "purse", m
);
979 g_menu_item_set_link (item
, "purse", NULL
);
980 g_menu_append_item (menu
, item
);
982 g_assert_cmpint (g_menu_model_get_n_items (G_MENU_MODEL (menu
)), ==, 4);
984 x
= g_menu_model_get_item_link (G_MENU_MODEL (menu
), 0, "section");
988 x
= g_menu_model_get_item_link (G_MENU_MODEL (menu
), 1, "submenu");
992 x
= g_menu_model_get_item_link (G_MENU_MODEL (menu
), 2, "wallet");
996 x
= g_menu_model_get_item_link (G_MENU_MODEL (menu
), 3, "purse");
997 g_assert (x
== NULL
);
1000 g_object_unref (menu
);
1008 menu
= g_menu_new ();
1009 g_menu_append (menu
, "test", "test");
1011 g_assert (g_menu_model_is_mutable (G_MENU_MODEL (menu
)));
1012 g_menu_freeze (menu
);
1013 g_assert (!g_menu_model_is_mutable (G_MENU_MODEL (menu
)));
1015 g_object_unref (menu
);
1020 main (int argc
, char **argv
)
1022 g_test_init (&argc
, &argv
, NULL
);
1026 g_test_add_func ("/gmenu/equality", test_equality
);
1027 g_test_add_func ("/gmenu/random", test_random
);
1028 g_test_add_func ("/gmenu/dbus/roundtrip", test_dbus_roundtrip
);
1029 g_test_add_func ("/gmenu/dbus/subscriptions", test_dbus_subscriptions
);
1030 g_test_add_func ("/gmenu/dbus/threaded", test_dbus_threaded
);
1031 g_test_add_func ("/gmenu/attributes", test_attributes
);
1032 g_test_add_func ("/gmenu/links", test_links
);
1033 g_test_add_func ("/gmenu/mutable", test_mutable
);
1035 return g_test_run ();
1037 /* vim:set foldmethod=marker: */