nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | #include <gio/gio.h> |
2 | |||
3 | #include "gdbus-sessionbus.h" |
||
4 | |||
5 | /* Markup printing {{{1 */ |
||
6 | |||
7 | /* This used to be part of GLib, but it was removed before the stable |
||
8 | * release because it wasn't generally useful. We want it here, though. |
||
9 | */ |
||
10 | static void |
||
11 | indent_string (GString *string, |
||
12 | gint indent) |
||
13 | { |
||
14 | while (indent--) |
||
15 | g_string_append_c (string, ' '); |
||
16 | } |
||
17 | |||
18 | static GString * |
||
19 | g_menu_markup_print_string (GString *string, |
||
20 | GMenuModel *model, |
||
21 | gint indent, |
||
22 | gint tabstop) |
||
23 | { |
||
24 | gboolean need_nl = FALSE; |
||
25 | gint i, n; |
||
26 | |||
27 | if G_UNLIKELY (string == NULL) |
||
28 | string = g_string_new (NULL); |
||
29 | |||
30 | n = g_menu_model_get_n_items (model); |
||
31 | |||
32 | for (i = 0; i < n; i++) |
||
33 | { |
||
34 | GMenuAttributeIter *attr_iter; |
||
35 | GMenuLinkIter *link_iter; |
||
36 | GString *contents; |
||
37 | GString *attrs; |
||
38 | |||
39 | attr_iter = g_menu_model_iterate_item_attributes (model, i); |
||
40 | link_iter = g_menu_model_iterate_item_links (model, i); |
||
41 | contents = g_string_new (NULL); |
||
42 | attrs = g_string_new (NULL); |
||
43 | |||
44 | while (g_menu_attribute_iter_next (attr_iter)) |
||
45 | { |
||
46 | const char *name = g_menu_attribute_iter_get_name (attr_iter); |
||
47 | GVariant *value = g_menu_attribute_iter_get_value (attr_iter); |
||
48 | |||
49 | if (g_variant_is_of_type (value, G_VARIANT_TYPE_STRING)) |
||
50 | { |
||
51 | gchar *str; |
||
52 | str = g_markup_printf_escaped (" %s='%s'", name, g_variant_get_string (value, NULL)); |
||
53 | g_string_append (attrs, str); |
||
54 | g_free (str); |
||
55 | } |
||
56 | |||
57 | else |
||
58 | { |
||
59 | gchar *printed; |
||
60 | gchar *str; |
||
61 | const gchar *type; |
||
62 | |||
63 | printed = g_variant_print (value, TRUE); |
||
64 | type = g_variant_type_peek_string (g_variant_get_type (value)); |
||
65 | str = g_markup_printf_escaped ("<attribute name='%s' type='%s'>%s</attribute>\n", name, type, printed); |
||
66 | indent_string (contents, indent + tabstop); |
||
67 | g_string_append (contents, str); |
||
68 | g_free (printed); |
||
69 | g_free (str); |
||
70 | } |
||
71 | |||
72 | g_variant_unref (value); |
||
73 | } |
||
74 | g_object_unref (attr_iter); |
||
75 | |||
76 | while (g_menu_link_iter_next (link_iter)) |
||
77 | { |
||
78 | const gchar *name = g_menu_link_iter_get_name (link_iter); |
||
79 | GMenuModel *menu = g_menu_link_iter_get_value (link_iter); |
||
80 | gchar *str; |
||
81 | |||
82 | if (contents->str[0]) |
||
83 | g_string_append_c (contents, '\n'); |
||
84 | |||
85 | str = g_markup_printf_escaped ("<link name='%s'>\n", name); |
||
86 | indent_string (contents, indent + tabstop); |
||
87 | g_string_append (contents, str); |
||
88 | g_free (str); |
||
89 | |||
90 | g_menu_markup_print_string (contents, menu, indent + 2 * tabstop, tabstop); |
||
91 | |||
92 | indent_string (contents, indent + tabstop); |
||
93 | g_string_append (contents, "</link>\n"); |
||
94 | g_object_unref (menu); |
||
95 | } |
||
96 | g_object_unref (link_iter); |
||
97 | |||
98 | if (contents->str[0]) |
||
99 | { |
||
100 | indent_string (string, indent); |
||
101 | g_string_append_printf (string, "<item%s>\n", attrs->str); |
||
102 | g_string_append (string, contents->str); |
||
103 | indent_string (string, indent); |
||
104 | g_string_append (string, "</item>\n"); |
||
105 | need_nl = TRUE; |
||
106 | } |
||
107 | |||
108 | else |
||
109 | { |
||
110 | if (need_nl) |
||
111 | g_string_append_c (string, '\n'); |
||
112 | |||
113 | indent_string (string, indent); |
||
114 | g_string_append_printf (string, "<item%s/>\n", attrs->str); |
||
115 | need_nl = FALSE; |
||
116 | } |
||
117 | |||
118 | g_string_free (contents, TRUE); |
||
119 | g_string_free (attrs, TRUE); |
||
120 | } |
||
121 | |||
122 | return string; |
||
123 | } |
||
124 | |||
125 | /* TestItem {{{1 */ |
||
126 | |||
127 | /* This utility struct is used by both the RandomMenu and MirrorMenu |
||
128 | * class implementations below. |
||
129 | */ |
||
130 | typedef struct { |
||
131 | GHashTable *attributes; |
||
132 | GHashTable *links; |
||
133 | } TestItem; |
||
134 | |||
135 | static TestItem * |
||
136 | test_item_new (GHashTable *attributes, |
||
137 | GHashTable *links) |
||
138 | { |
||
139 | TestItem *item; |
||
140 | |||
141 | item = g_slice_new (TestItem); |
||
142 | item->attributes = g_hash_table_ref (attributes); |
||
143 | item->links = g_hash_table_ref (links); |
||
144 | |||
145 | return item; |
||
146 | } |
||
147 | |||
148 | static void |
||
149 | test_item_free (gpointer data) |
||
150 | { |
||
151 | TestItem *item = data; |
||
152 | |||
153 | g_hash_table_unref (item->attributes); |
||
154 | g_hash_table_unref (item->links); |
||
155 | |||
156 | g_slice_free (TestItem, item); |
||
157 | } |
||
158 | |||
159 | /* RandomMenu {{{1 */ |
||
160 | #define MAX_ITEMS 5 |
||
161 | #define TOP_ORDER 4 |
||
162 | |||
163 | typedef struct { |
||
164 | GMenuModel parent_instance; |
||
165 | |||
166 | GSequence *items; |
||
167 | gint order; |
||
168 | } RandomMenu; |
||
169 | |||
170 | typedef GMenuModelClass RandomMenuClass; |
||
171 | |||
172 | static GType random_menu_get_type (void); |
||
173 | G_DEFINE_TYPE (RandomMenu, random_menu, G_TYPE_MENU_MODEL); |
||
174 | |||
175 | static gboolean |
||
176 | random_menu_is_mutable (GMenuModel *model) |
||
177 | { |
||
178 | return TRUE; |
||
179 | } |
||
180 | |||
181 | static gint |
||
182 | random_menu_get_n_items (GMenuModel *model) |
||
183 | { |
||
184 | RandomMenu *menu = (RandomMenu *) model; |
||
185 | |||
186 | return g_sequence_get_length (menu->items); |
||
187 | } |
||
188 | |||
189 | static void |
||
190 | random_menu_get_item_attributes (GMenuModel *model, |
||
191 | gint position, |
||
192 | GHashTable **table) |
||
193 | { |
||
194 | RandomMenu *menu = (RandomMenu *) model; |
||
195 | TestItem *item; |
||
196 | |||
197 | item = g_sequence_get (g_sequence_get_iter_at_pos (menu->items, position)); |
||
198 | *table = g_hash_table_ref (item->attributes); |
||
199 | } |
||
200 | |||
201 | static void |
||
202 | random_menu_get_item_links (GMenuModel *model, |
||
203 | gint position, |
||
204 | GHashTable **table) |
||
205 | { |
||
206 | RandomMenu *menu = (RandomMenu *) model; |
||
207 | TestItem *item; |
||
208 | |||
209 | item = g_sequence_get (g_sequence_get_iter_at_pos (menu->items, position)); |
||
210 | *table = g_hash_table_ref (item->links); |
||
211 | } |
||
212 | |||
213 | static void |
||
214 | random_menu_finalize (GObject *object) |
||
215 | { |
||
216 | RandomMenu *menu = (RandomMenu *) object; |
||
217 | |||
218 | g_sequence_free (menu->items); |
||
219 | |||
220 | G_OBJECT_CLASS (random_menu_parent_class) |
||
221 | ->finalize (object); |
||
222 | } |
||
223 | |||
224 | static void |
||
225 | random_menu_init (RandomMenu *menu) |
||
226 | { |
||
227 | } |
||
228 | |||
229 | static void |
||
230 | random_menu_class_init (GMenuModelClass *class) |
||
231 | { |
||
232 | GObjectClass *object_class = G_OBJECT_CLASS (class); |
||
233 | |||
234 | class->is_mutable = random_menu_is_mutable; |
||
235 | class->get_n_items = random_menu_get_n_items; |
||
236 | class->get_item_attributes = random_menu_get_item_attributes; |
||
237 | class->get_item_links = random_menu_get_item_links; |
||
238 | |||
239 | object_class->finalize = random_menu_finalize; |
||
240 | } |
||
241 | |||
242 | static RandomMenu * random_menu_new (GRand *rand, gint order); |
||
243 | |||
244 | static void |
||
245 | random_menu_change (RandomMenu *menu, |
||
246 | GRand *rand) |
||
247 | { |
||
248 | gint position, removes, adds; |
||
249 | GSequenceIter *point; |
||
250 | gint n_items; |
||
251 | gint i; |
||
252 | |||
253 | n_items = g_sequence_get_length (menu->items); |
||
254 | |||
255 | do |
||
256 | { |
||
257 | position = g_rand_int_range (rand, 0, n_items + 1); |
||
258 | removes = g_rand_int_range (rand, 0, n_items - position + 1); |
||
259 | adds = g_rand_int_range (rand, 0, MAX_ITEMS - (n_items - removes) + 1); |
||
260 | } |
||
261 | while (removes == 0 && adds == 0); |
||
262 | |||
263 | point = g_sequence_get_iter_at_pos (menu->items, position + removes); |
||
264 | |||
265 | if (removes) |
||
266 | { |
||
267 | GSequenceIter *start; |
||
268 | |||
269 | start = g_sequence_get_iter_at_pos (menu->items, position); |
||
270 | g_sequence_remove_range (start, point); |
||
271 | } |
||
272 | |||
273 | for (i = 0; i < adds; i++) |
||
274 | { |
||
275 | const gchar *label; |
||
276 | GHashTable *links; |
||
277 | GHashTable *attributes; |
||
278 | |||
279 | attributes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_variant_unref); |
||
280 | links = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_object_unref); |
||
281 | |||
282 | if (menu->order > 0 && g_rand_boolean (rand)) |
||
283 | { |
||
284 | RandomMenu *child; |
||
285 | const gchar *subtype; |
||
286 | |||
287 | child = random_menu_new (rand, menu->order - 1); |
||
288 | |||
289 | if (g_rand_boolean (rand)) |
||
290 | { |
||
291 | subtype = G_MENU_LINK_SECTION; |
||
292 | /* label some section headers */ |
||
293 | if (g_rand_boolean (rand)) |
||
294 | label = "Section"; |
||
295 | else |
||
296 | label = NULL; |
||
297 | } |
||
298 | else |
||
299 | { |
||
300 | /* label all submenus */ |
||
301 | subtype = G_MENU_LINK_SUBMENU; |
||
302 | label = "Submenu"; |
||
303 | } |
||
304 | |||
305 | g_hash_table_insert (links, g_strdup (subtype), child); |
||
306 | } |
||
307 | else |
||
308 | /* label all terminals */ |
||
309 | label = "Menu Item"; |
||
310 | |||
311 | if (label) |
||
312 | g_hash_table_insert (attributes, g_strdup ("label"), g_variant_ref_sink (g_variant_new_string (label))); |
||
313 | |||
314 | g_sequence_insert_before (point, test_item_new (attributes, links)); |
||
315 | g_hash_table_unref (links); |
||
316 | g_hash_table_unref (attributes); |
||
317 | } |
||
318 | |||
319 | g_menu_model_items_changed (G_MENU_MODEL (menu), position, removes, adds); |
||
320 | } |
||
321 | |||
322 | static RandomMenu * |
||
323 | random_menu_new (GRand *rand, |
||
324 | gint order) |
||
325 | { |
||
326 | RandomMenu *menu; |
||
327 | |||
328 | menu = g_object_new (random_menu_get_type (), NULL); |
||
329 | menu->items = g_sequence_new (test_item_free); |
||
330 | menu->order = order; |
||
331 | |||
332 | random_menu_change (menu, rand); |
||
333 | |||
334 | return menu; |
||
335 | } |
||
336 | |||
337 | /* MirrorMenu {{{1 */ |
||
338 | typedef struct { |
||
339 | GMenuModel parent_instance; |
||
340 | |||
341 | GMenuModel *clone_of; |
||
342 | GSequence *items; |
||
343 | gulong handler_id; |
||
344 | } MirrorMenu; |
||
345 | |||
346 | typedef GMenuModelClass MirrorMenuClass; |
||
347 | |||
348 | static GType mirror_menu_get_type (void); |
||
349 | G_DEFINE_TYPE (MirrorMenu, mirror_menu, G_TYPE_MENU_MODEL); |
||
350 | |||
351 | static gboolean |
||
352 | mirror_menu_is_mutable (GMenuModel *model) |
||
353 | { |
||
354 | MirrorMenu *menu = (MirrorMenu *) model; |
||
355 | |||
356 | return menu->handler_id != 0; |
||
357 | } |
||
358 | |||
359 | static gint |
||
360 | mirror_menu_get_n_items (GMenuModel *model) |
||
361 | { |
||
362 | MirrorMenu *menu = (MirrorMenu *) model; |
||
363 | |||
364 | return g_sequence_get_length (menu->items); |
||
365 | } |
||
366 | |||
367 | static void |
||
368 | mirror_menu_get_item_attributes (GMenuModel *model, |
||
369 | gint position, |
||
370 | GHashTable **table) |
||
371 | { |
||
372 | MirrorMenu *menu = (MirrorMenu *) model; |
||
373 | TestItem *item; |
||
374 | |||
375 | item = g_sequence_get (g_sequence_get_iter_at_pos (menu->items, position)); |
||
376 | *table = g_hash_table_ref (item->attributes); |
||
377 | } |
||
378 | |||
379 | static void |
||
380 | mirror_menu_get_item_links (GMenuModel *model, |
||
381 | gint position, |
||
382 | GHashTable **table) |
||
383 | { |
||
384 | MirrorMenu *menu = (MirrorMenu *) model; |
||
385 | TestItem *item; |
||
386 | |||
387 | item = g_sequence_get (g_sequence_get_iter_at_pos (menu->items, position)); |
||
388 | *table = g_hash_table_ref (item->links); |
||
389 | } |
||
390 | |||
391 | static void |
||
392 | mirror_menu_finalize (GObject *object) |
||
393 | { |
||
394 | MirrorMenu *menu = (MirrorMenu *) object; |
||
395 | |||
396 | if (menu->handler_id) |
||
397 | g_signal_handler_disconnect (menu->clone_of, menu->handler_id); |
||
398 | |||
399 | g_sequence_free (menu->items); |
||
400 | g_object_unref (menu->clone_of); |
||
401 | |||
402 | G_OBJECT_CLASS (mirror_menu_parent_class) |
||
403 | ->finalize (object); |
||
404 | } |
||
405 | |||
406 | static void |
||
407 | mirror_menu_init (MirrorMenu *menu) |
||
408 | { |
||
409 | } |
||
410 | |||
411 | static void |
||
412 | mirror_menu_class_init (GMenuModelClass *class) |
||
413 | { |
||
414 | GObjectClass *object_class = G_OBJECT_CLASS (class); |
||
415 | |||
416 | class->is_mutable = mirror_menu_is_mutable; |
||
417 | class->get_n_items = mirror_menu_get_n_items; |
||
418 | class->get_item_attributes = mirror_menu_get_item_attributes; |
||
419 | class->get_item_links = mirror_menu_get_item_links; |
||
420 | |||
421 | object_class->finalize = mirror_menu_finalize; |
||
422 | } |
||
423 | |||
424 | static MirrorMenu * mirror_menu_new (GMenuModel *clone_of); |
||
425 | |||
426 | static void |
||
427 | mirror_menu_changed (GMenuModel *model, |
||
428 | gint position, |
||
429 | gint removed, |
||
430 | gint added, |
||
431 | gpointer user_data) |
||
432 | { |
||
433 | MirrorMenu *menu = user_data; |
||
434 | GSequenceIter *point; |
||
435 | gint i; |
||
436 | |||
437 | g_assert (model == menu->clone_of); |
||
438 | |||
439 | point = g_sequence_get_iter_at_pos (menu->items, position + removed); |
||
440 | |||
441 | if (removed) |
||
442 | { |
||
443 | GSequenceIter *start; |
||
444 | |||
445 | start = g_sequence_get_iter_at_pos (menu->items, position); |
||
446 | g_sequence_remove_range (start, point); |
||
447 | } |
||
448 | |||
449 | for (i = position; i < position + added; i++) |
||
450 | { |
||
451 | GMenuAttributeIter *attr_iter; |
||
452 | GMenuLinkIter *link_iter; |
||
453 | GHashTable *links; |
||
454 | GHashTable *attributes; |
||
455 | const gchar *name; |
||
456 | GMenuModel *child; |
||
457 | GVariant *value; |
||
458 | |||
459 | attributes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_variant_unref); |
||
460 | links = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_object_unref); |
||
461 | |||
462 | attr_iter = g_menu_model_iterate_item_attributes (model, i); |
||
463 | while (g_menu_attribute_iter_get_next (attr_iter, &name, &value)) |
||
464 | { |
||
465 | g_hash_table_insert (attributes, g_strdup (name), value); |
||
466 | } |
||
467 | g_object_unref (attr_iter); |
||
468 | |||
469 | link_iter = g_menu_model_iterate_item_links (model, i); |
||
470 | while (g_menu_link_iter_get_next (link_iter, &name, &child)) |
||
471 | { |
||
472 | g_hash_table_insert (links, g_strdup (name), mirror_menu_new (child)); |
||
473 | g_object_unref (child); |
||
474 | } |
||
475 | g_object_unref (link_iter); |
||
476 | |||
477 | g_sequence_insert_before (point, test_item_new (attributes, links)); |
||
478 | g_hash_table_unref (attributes); |
||
479 | g_hash_table_unref (links); |
||
480 | } |
||
481 | |||
482 | g_menu_model_items_changed (G_MENU_MODEL (menu), position, removed, added); |
||
483 | } |
||
484 | |||
485 | static MirrorMenu * |
||
486 | mirror_menu_new (GMenuModel *clone_of) |
||
487 | { |
||
488 | MirrorMenu *menu; |
||
489 | |||
490 | menu = g_object_new (mirror_menu_get_type (), NULL); |
||
491 | menu->items = g_sequence_new (test_item_free); |
||
492 | menu->clone_of = g_object_ref (clone_of); |
||
493 | |||
494 | if (g_menu_model_is_mutable (clone_of)) |
||
495 | menu->handler_id = g_signal_connect (clone_of, "items-changed", G_CALLBACK (mirror_menu_changed), menu); |
||
496 | mirror_menu_changed (clone_of, 0, 0, g_menu_model_get_n_items (clone_of), menu); |
||
497 | |||
498 | return menu; |
||
499 | } |
||
500 | |||
501 | /* check_menus_equal(), assert_menus_equal() {{{1 */ |
||
502 | static gboolean |
||
503 | check_menus_equal (GMenuModel *a, |
||
504 | GMenuModel *b) |
||
505 | { |
||
506 | gboolean equal = TRUE; |
||
507 | gint a_n, b_n; |
||
508 | gint i; |
||
509 | |||
510 | a_n = g_menu_model_get_n_items (a); |
||
511 | b_n = g_menu_model_get_n_items (b); |
||
512 | |||
513 | if (a_n != b_n) |
||
514 | return FALSE; |
||
515 | |||
516 | for (i = 0; i < a_n; i++) |
||
517 | { |
||
518 | GMenuAttributeIter *attr_iter; |
||
519 | GVariant *a_value, *b_value; |
||
520 | GMenuLinkIter *link_iter; |
||
521 | GMenuModel *a_menu, *b_menu; |
||
522 | const gchar *name; |
||
523 | |||
524 | attr_iter = g_menu_model_iterate_item_attributes (a, i); |
||
525 | while (g_menu_attribute_iter_get_next (attr_iter, &name, &a_value)) |
||
526 | { |
||
527 | b_value = g_menu_model_get_item_attribute_value (b, i, name, NULL); |
||
528 | equal &= b_value && g_variant_equal (a_value, b_value); |
||
529 | if (b_value) |
||
530 | g_variant_unref (b_value); |
||
531 | g_variant_unref (a_value); |
||
532 | } |
||
533 | g_object_unref (attr_iter); |
||
534 | |||
535 | attr_iter = g_menu_model_iterate_item_attributes (b, i); |
||
536 | while (g_menu_attribute_iter_get_next (attr_iter, &name, &b_value)) |
||
537 | { |
||
538 | a_value = g_menu_model_get_item_attribute_value (a, i, name, NULL); |
||
539 | equal &= a_value && g_variant_equal (a_value, b_value); |
||
540 | if (a_value) |
||
541 | g_variant_unref (a_value); |
||
542 | g_variant_unref (b_value); |
||
543 | } |
||
544 | g_object_unref (attr_iter); |
||
545 | |||
546 | link_iter = g_menu_model_iterate_item_links (a, i); |
||
547 | while (g_menu_link_iter_get_next (link_iter, &name, &a_menu)) |
||
548 | { |
||
549 | b_menu = g_menu_model_get_item_link (b, i, name); |
||
550 | equal &= b_menu && check_menus_equal (a_menu, b_menu); |
||
551 | if (b_menu) |
||
552 | g_object_unref (b_menu); |
||
553 | g_object_unref (a_menu); |
||
554 | } |
||
555 | g_object_unref (link_iter); |
||
556 | |||
557 | link_iter = g_menu_model_iterate_item_links (b, i); |
||
558 | while (g_menu_link_iter_get_next (link_iter, &name, &b_menu)) |
||
559 | { |
||
560 | a_menu = g_menu_model_get_item_link (a, i, name); |
||
561 | equal &= a_menu && check_menus_equal (a_menu, b_menu); |
||
562 | if (a_menu) |
||
563 | g_object_unref (a_menu); |
||
564 | g_object_unref (b_menu); |
||
565 | } |
||
566 | g_object_unref (link_iter); |
||
567 | } |
||
568 | |||
569 | return equal; |
||
570 | } |
||
571 | |||
572 | static void |
||
573 | assert_menus_equal (GMenuModel *a, |
||
574 | GMenuModel *b) |
||
575 | { |
||
576 | if (!check_menus_equal (a, b)) |
||
577 | { |
||
578 | GString *string; |
||
579 | |||
580 | string = g_string_new ("\n <a>\n"); |
||
581 | g_menu_markup_print_string (string, G_MENU_MODEL (a), 4, 2); |
||
582 | g_string_append (string, " </a>\n\n-------------\n <b>\n"); |
||
583 | g_menu_markup_print_string (string, G_MENU_MODEL (b), 4, 2); |
||
584 | g_string_append (string, " </b>\n"); |
||
585 | g_error ("%s", string->str); |
||
586 | } |
||
587 | } |
||
588 | |||
589 | static void |
||
590 | assert_menuitem_equal (GMenuItem *item, |
||
591 | GMenuModel *model, |
||
592 | gint index) |
||
593 | { |
||
594 | GMenuAttributeIter *attr_iter; |
||
595 | GMenuLinkIter *link_iter; |
||
596 | const gchar *name; |
||
597 | GVariant *value; |
||
598 | GMenuModel *linked_model; |
||
599 | |||
600 | /* NOTE we can't yet test whether item has attributes or links that |
||
601 | * are not in the model, because there's no iterator API for menu |
||
602 | * items */ |
||
603 | |||
604 | attr_iter = g_menu_model_iterate_item_attributes (model, index); |
||
605 | while (g_menu_attribute_iter_get_next (attr_iter, &name, &value)) |
||
606 | { |
||
607 | GVariant *item_value; |
||
608 | |||
609 | item_value = g_menu_item_get_attribute_value (item, name, g_variant_get_type (value)); |
||
610 | g_assert (item_value && g_variant_equal (item_value, value)); |
||
611 | |||
612 | g_variant_unref (item_value); |
||
613 | g_variant_unref (value); |
||
614 | } |
||
615 | |||
616 | link_iter = g_menu_model_iterate_item_links (model, index); |
||
617 | while (g_menu_link_iter_get_next (link_iter, &name, &linked_model)) |
||
618 | { |
||
619 | GMenuModel *item_linked_model; |
||
620 | |||
621 | item_linked_model = g_menu_item_get_link (item, name); |
||
622 | g_assert (linked_model == item_linked_model); |
||
623 | |||
624 | g_object_unref (item_linked_model); |
||
625 | g_object_unref (linked_model); |
||
626 | } |
||
627 | |||
628 | g_object_unref (attr_iter); |
||
629 | g_object_unref (link_iter); |
||
630 | } |
||
631 | |||
632 | /* Test cases {{{1 */ |
||
633 | static void |
||
634 | test_equality (void) |
||
635 | { |
||
636 | GRand *randa, *randb; |
||
637 | guint32 seed; |
||
638 | gint i; |
||
639 | |||
640 | seed = g_test_rand_int (); |
||
641 | |||
642 | randa = g_rand_new_with_seed (seed); |
||
643 | randb = g_rand_new_with_seed (seed); |
||
644 | |||
645 | for (i = 0; i < 500; i++) |
||
646 | { |
||
647 | RandomMenu *a, *b; |
||
648 | |||
649 | a = random_menu_new (randa, TOP_ORDER); |
||
650 | b = random_menu_new (randb, TOP_ORDER); |
||
651 | assert_menus_equal (G_MENU_MODEL (a), G_MENU_MODEL (b)); |
||
652 | g_object_unref (b); |
||
653 | g_object_unref (a); |
||
654 | } |
||
655 | |||
656 | g_rand_int (randa); |
||
657 | |||
658 | for (i = 0; i < 500;) |
||
659 | { |
||
660 | RandomMenu *a, *b; |
||
661 | |||
662 | a = random_menu_new (randa, TOP_ORDER); |
||
663 | b = random_menu_new (randb, TOP_ORDER); |
||
664 | if (check_menus_equal (G_MENU_MODEL (a), G_MENU_MODEL (b))) |
||
665 | { |
||
666 | /* by chance, they may really be equal. double check. */ |
||
667 | GString *as, *bs; |
||
668 | |||
669 | as = g_menu_markup_print_string (NULL, G_MENU_MODEL (a), 4, 2); |
||
670 | bs = g_menu_markup_print_string (NULL, G_MENU_MODEL (b), 4, 2); |
||
671 | g_assert_cmpstr (as->str, ==, bs->str); |
||
672 | g_string_free (bs, TRUE); |
||
673 | g_string_free (as, TRUE); |
||
674 | |||
675 | /* we're here because randa and randb just generated equal |
||
676 | * menus. they may do it again, so throw away randb and make |
||
677 | * a fresh one. |
||
678 | */ |
||
679 | g_rand_free (randb); |
||
680 | randb = g_rand_new_with_seed (g_rand_int (randa)); |
||
681 | } |
||
682 | else |
||
683 | /* make sure we get enough unequals (ie: no GRand failure) */ |
||
684 | i++; |
||
685 | |||
686 | g_object_unref (b); |
||
687 | g_object_unref (a); |
||
688 | } |
||
689 | |||
690 | g_rand_free (randb); |
||
691 | g_rand_free (randa); |
||
692 | } |
||
693 | |||
694 | static void |
||
695 | test_random (void) |
||
696 | { |
||
697 | RandomMenu *random; |
||
698 | MirrorMenu *mirror; |
||
699 | GRand *rand; |
||
700 | gint i; |
||
701 | |||
702 | rand = g_rand_new_with_seed (g_test_rand_int ()); |
||
703 | random = random_menu_new (rand, TOP_ORDER); |
||
704 | mirror = mirror_menu_new (G_MENU_MODEL (random)); |
||
705 | |||
706 | for (i = 0; i < 500; i++) |
||
707 | { |
||
708 | assert_menus_equal (G_MENU_MODEL (random), G_MENU_MODEL (mirror)); |
||
709 | random_menu_change (random, rand); |
||
710 | } |
||
711 | |||
712 | g_object_unref (mirror); |
||
713 | g_object_unref (random); |
||
714 | |||
715 | g_rand_free (rand); |
||
716 | } |
||
717 | |||
718 | struct roundtrip_state |
||
719 | { |
||
720 | RandomMenu *random; |
||
721 | MirrorMenu *proxy_mirror; |
||
722 | GDBusMenuModel *proxy; |
||
723 | GMainLoop *loop; |
||
724 | GRand *rand; |
||
725 | gint success; |
||
726 | gint count; |
||
727 | }; |
||
728 | |||
729 | static gboolean |
||
730 | roundtrip_step (gpointer data) |
||
731 | { |
||
732 | struct roundtrip_state *state = data; |
||
733 | |||
734 | if (check_menus_equal (G_MENU_MODEL (state->random), G_MENU_MODEL (state->proxy)) && |
||
735 | check_menus_equal (G_MENU_MODEL (state->random), G_MENU_MODEL (state->proxy_mirror))) |
||
736 | { |
||
737 | state->success++; |
||
738 | state->count = 0; |
||
739 | |||
740 | if (state->success < 100) |
||
741 | random_menu_change (state->random, state->rand); |
||
742 | else |
||
743 | g_main_loop_quit (state->loop); |
||
744 | } |
||
745 | else if (state->count == 100) |
||
746 | { |
||
747 | assert_menus_equal (G_MENU_MODEL (state->random), G_MENU_MODEL (state->proxy)); |
||
748 | g_assert_not_reached (); |
||
749 | } |
||
750 | else |
||
751 | state->count++; |
||
752 | |||
753 | return G_SOURCE_CONTINUE; |
||
754 | } |
||
755 | |||
756 | static void |
||
757 | test_dbus_roundtrip (void) |
||
758 | { |
||
759 | struct roundtrip_state state; |
||
760 | GDBusConnection *bus; |
||
761 | guint export_id; |
||
762 | guint id; |
||
763 | |||
764 | bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL); |
||
765 | |||
766 | state.rand = g_rand_new_with_seed (g_test_rand_int ()); |
||
767 | |||
768 | state.random = random_menu_new (state.rand, 2); |
||
769 | export_id = g_dbus_connection_export_menu_model (bus, "/", G_MENU_MODEL (state.random), NULL); |
||
770 | state.proxy = g_dbus_menu_model_get (bus, g_dbus_connection_get_unique_name (bus), "/"); |
||
771 | state.proxy_mirror = mirror_menu_new (G_MENU_MODEL (state.proxy)); |
||
772 | state.count = 0; |
||
773 | state.success = 0; |
||
774 | |||
775 | id = g_timeout_add (10, roundtrip_step, &state); |
||
776 | |||
777 | state.loop = g_main_loop_new (NULL, FALSE); |
||
778 | g_main_loop_run (state.loop); |
||
779 | |||
780 | g_main_loop_unref (state.loop); |
||
781 | g_source_remove (id); |
||
782 | g_object_unref (state.proxy); |
||
783 | g_dbus_connection_unexport_menu_model (bus, export_id); |
||
784 | g_object_unref (state.random); |
||
785 | g_object_unref (state.proxy_mirror); |
||
786 | g_rand_free (state.rand); |
||
787 | g_object_unref (bus); |
||
788 | } |
||
789 | |||
790 | static gint items_changed_count; |
||
791 | |||
792 | static void |
||
793 | items_changed (GMenuModel *model, |
||
794 | gint position, |
||
795 | gint removed, |
||
796 | gint added, |
||
797 | gpointer data) |
||
798 | { |
||
799 | items_changed_count++; |
||
800 | } |
||
801 | |||
802 | static gboolean |
||
803 | stop_loop (gpointer data) |
||
804 | { |
||
805 | GMainLoop *loop = data; |
||
806 | |||
807 | g_main_loop_quit (loop); |
||
808 | |||
809 | return G_SOURCE_REMOVE; |
||
810 | } |
||
811 | |||
812 | static void |
||
813 | test_dbus_subscriptions (void) |
||
814 | { |
||
815 | GDBusConnection *bus; |
||
816 | GMenu *menu; |
||
817 | GDBusMenuModel *proxy; |
||
818 | GMainLoop *loop; |
||
819 | GError *error = NULL; |
||
820 | guint export_id; |
||
821 | |||
822 | loop = g_main_loop_new (NULL, FALSE); |
||
823 | |||
824 | bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL); |
||
825 | |||
826 | menu = g_menu_new (); |
||
827 | |||
828 | export_id = g_dbus_connection_export_menu_model (bus, "/", G_MENU_MODEL (menu), &error); |
||
829 | g_assert_no_error (error); |
||
830 | |||
831 | proxy = g_dbus_menu_model_get (bus, g_dbus_connection_get_unique_name (bus), "/"); |
||
832 | items_changed_count = 0; |
||
833 | g_signal_connect (proxy, "items-changed", |
||
834 | G_CALLBACK (items_changed), NULL); |
||
835 | |||
836 | g_menu_append (menu, "item1", NULL); |
||
837 | g_menu_append (menu, "item2", NULL); |
||
838 | g_menu_append (menu, "item3", NULL); |
||
839 | |||
840 | g_assert_cmpint (items_changed_count, ==, 0); |
||
841 | |||
842 | g_timeout_add (100, stop_loop, loop); |
||
843 | g_main_loop_run (loop); |
||
844 | |||
845 | g_menu_model_get_n_items (G_MENU_MODEL (proxy)); |
||
846 | |||
847 | g_timeout_add (100, stop_loop, loop); |
||
848 | g_main_loop_run (loop); |
||
849 | |||
850 | g_assert_cmpint (items_changed_count, ==, 1); |
||
851 | g_assert_cmpint (g_menu_model_get_n_items (G_MENU_MODEL (proxy)), ==, 3); |
||
852 | |||
853 | g_timeout_add (100, stop_loop, loop); |
||
854 | g_main_loop_run (loop); |
||
855 | |||
856 | g_menu_append (menu, "item4", NULL); |
||
857 | g_menu_append (menu, "item5", NULL); |
||
858 | g_menu_append (menu, "item6", NULL); |
||
859 | g_menu_remove (menu, 0); |
||
860 | g_menu_remove (menu, 0); |
||
861 | |||
862 | g_timeout_add (200, stop_loop, loop); |
||
863 | g_main_loop_run (loop); |
||
864 | |||
865 | g_assert_cmpint (items_changed_count, ==, 6); |
||
866 | |||
867 | g_assert_cmpint (g_menu_model_get_n_items (G_MENU_MODEL (proxy)), ==, 4); |
||
868 | g_object_unref (proxy); |
||
869 | |||
870 | g_timeout_add (100, stop_loop, loop); |
||
871 | g_main_loop_run (loop); |
||
872 | |||
873 | g_menu_remove (menu, 0); |
||
874 | g_menu_remove (menu, 0); |
||
875 | |||
876 | g_timeout_add (100, stop_loop, loop); |
||
877 | g_main_loop_run (loop); |
||
878 | |||
879 | g_assert_cmpint (items_changed_count, ==, 6); |
||
880 | |||
881 | g_dbus_connection_unexport_menu_model (bus, export_id); |
||
882 | g_object_unref (menu); |
||
883 | |||
884 | g_main_loop_unref (loop); |
||
885 | g_object_unref (bus); |
||
886 | } |
||
887 | |||
888 | static gpointer |
||
889 | do_modify (gpointer data) |
||
890 | { |
||
891 | RandomMenu *menu = data; |
||
892 | GRand *rand; |
||
893 | gint i; |
||
894 | |||
895 | rand = g_rand_new_with_seed (g_test_rand_int ()); |
||
896 | |||
897 | for (i = 0; i < 10000; i++) |
||
898 | { |
||
899 | random_menu_change (menu, rand); |
||
900 | } |
||
901 | |||
902 | return NULL; |
||
903 | } |
||
904 | |||
905 | static gpointer |
||
906 | do_export (gpointer data) |
||
907 | { |
||
908 | GMenuModel *menu = data; |
||
909 | gint i; |
||
910 | GDBusConnection *bus; |
||
911 | gchar *path; |
||
912 | GError *error = NULL; |
||
913 | guint id; |
||
914 | |||
915 | bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL); |
||
916 | path = g_strdup_printf ("/%p", data); |
||
917 | |||
918 | for (i = 0; i < 10000; i++) |
||
919 | { |
||
920 | id = g_dbus_connection_export_menu_model (bus, path, menu, &error); |
||
921 | g_assert_no_error (error); |
||
922 | g_dbus_connection_unexport_menu_model (bus, id); |
||
923 | while (g_main_context_iteration (NULL, FALSE)); |
||
924 | } |
||
925 | |||
926 | g_free (path); |
||
927 | |||
928 | g_object_unref (bus); |
||
929 | |||
930 | return NULL; |
||
931 | } |
||
932 | |||
933 | static void |
||
934 | test_dbus_threaded (void) |
||
935 | { |
||
936 | RandomMenu *menu[10]; |
||
937 | GThread *call[10]; |
||
938 | GThread *export[10]; |
||
939 | gint i; |
||
940 | |||
941 | for (i = 0; i < 10; i++) |
||
942 | { |
||
943 | menu[i] = random_menu_new (g_rand_new_with_seed (g_test_rand_int ()), 2); |
||
944 | call[i] = g_thread_new ("call", do_modify, menu[i]); |
||
945 | export[i] = g_thread_new ("export", do_export, menu[i]); |
||
946 | } |
||
947 | |||
948 | for (i = 0; i < 10; i++) |
||
949 | { |
||
950 | g_thread_join (call[i]); |
||
951 | g_thread_join (export[i]); |
||
952 | } |
||
953 | |||
954 | for (i = 0; i < 10; i++) |
||
955 | g_object_unref (menu[i]); |
||
956 | } |
||
957 | |||
958 | static void |
||
959 | test_attributes (void) |
||
960 | { |
||
961 | GMenu *menu; |
||
962 | GMenuItem *item; |
||
963 | GVariant *v; |
||
964 | |||
965 | menu = g_menu_new (); |
||
966 | |||
967 | item = g_menu_item_new ("test", NULL); |
||
968 | g_menu_item_set_attribute_value (item, "boolean", g_variant_new_boolean (FALSE)); |
||
969 | g_menu_item_set_attribute_value (item, "string", g_variant_new_string ("bla")); |
||
970 | |||
971 | g_menu_item_set_attribute (item, "double", "d", 1.5); |
||
972 | v = g_variant_new_parsed ("[('one', 1), ('two', %i), (%s, 3)]", 2, "three"); |
||
973 | g_menu_item_set_attribute_value (item, "complex", v); |
||
974 | g_menu_item_set_attribute_value (item, "test-123", g_variant_new_string ("test-123")); |
||
975 | |||
976 | g_menu_append_item (menu, item); |
||
977 | |||
978 | g_menu_item_set_attribute (item, "double", "d", G_PI); |
||
979 | |||
980 | g_assert_cmpint (g_menu_model_get_n_items (G_MENU_MODEL (menu)), ==, 1); |
||
981 | |||
982 | v = g_menu_model_get_item_attribute_value (G_MENU_MODEL (menu), 0, "boolean", NULL); |
||
983 | g_assert (g_variant_is_of_type (v, G_VARIANT_TYPE_BOOLEAN)); |
||
984 | g_variant_unref (v); |
||
985 | |||
986 | v = g_menu_model_get_item_attribute_value (G_MENU_MODEL (menu), 0, "string", NULL); |
||
987 | g_assert (g_variant_is_of_type (v, G_VARIANT_TYPE_STRING)); |
||
988 | g_variant_unref (v); |
||
989 | |||
990 | v = g_menu_model_get_item_attribute_value (G_MENU_MODEL (menu), 0, "double", NULL); |
||
991 | g_assert (g_variant_is_of_type (v, G_VARIANT_TYPE_DOUBLE)); |
||
992 | g_variant_unref (v); |
||
993 | |||
994 | v = g_menu_model_get_item_attribute_value (G_MENU_MODEL (menu), 0, "complex", NULL); |
||
995 | g_assert (g_variant_is_of_type (v, G_VARIANT_TYPE("a(si)"))); |
||
996 | g_variant_unref (v); |
||
997 | |||
998 | g_menu_remove_all (menu); |
||
999 | |||
1000 | g_object_unref (menu); |
||
1001 | g_object_unref (item); |
||
1002 | } |
||
1003 | |||
1004 | static void |
||
1005 | test_attribute_iter (void) |
||
1006 | { |
||
1007 | GMenu *menu; |
||
1008 | GMenuItem *item; |
||
1009 | const gchar *name; |
||
1010 | GVariant *v; |
||
1011 | GMenuAttributeIter *iter; |
||
1012 | GHashTable *found; |
||
1013 | |||
1014 | menu = g_menu_new (); |
||
1015 | |||
1016 | item = g_menu_item_new ("test", NULL); |
||
1017 | g_menu_item_set_attribute_value (item, "boolean", g_variant_new_boolean (FALSE)); |
||
1018 | g_menu_item_set_attribute_value (item, "string", g_variant_new_string ("bla")); |
||
1019 | |||
1020 | g_menu_item_set_attribute (item, "double", "d", 1.5); |
||
1021 | v = g_variant_new_parsed ("[('one', 1), ('two', %i), (%s, 3)]", 2, "three"); |
||
1022 | g_menu_item_set_attribute_value (item, "complex", v); |
||
1023 | g_menu_item_set_attribute_value (item, "test-123", g_variant_new_string ("test-123")); |
||
1024 | |||
1025 | g_menu_append_item (menu, item); |
||
1026 | |||
1027 | g_menu_item_set_attribute (item, "double", "d", G_PI); |
||
1028 | |||
1029 | g_assert_cmpint (g_menu_model_get_n_items (G_MENU_MODEL (menu)), ==, 1); |
||
1030 | |||
1031 | found = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify)g_variant_unref); |
||
1032 | |||
1033 | iter = g_menu_model_iterate_item_attributes (G_MENU_MODEL (menu), 0); |
||
1034 | while (g_menu_attribute_iter_get_next (iter, &name, &v)) |
||
1035 | g_hash_table_insert (found, g_strdup (name), v); |
||
1036 | |||
1037 | g_assert_cmpint (g_hash_table_size (found), ==, 6); |
||
1038 | |||
1039 | v = g_hash_table_lookup (found, "label"); |
||
1040 | g_assert (g_variant_is_of_type (v, G_VARIANT_TYPE_STRING)); |
||
1041 | |||
1042 | v = g_hash_table_lookup (found, "boolean"); |
||
1043 | g_assert (g_variant_is_of_type (v, G_VARIANT_TYPE_BOOLEAN)); |
||
1044 | |||
1045 | v = g_hash_table_lookup (found, "string"); |
||
1046 | g_assert (g_variant_is_of_type (v, G_VARIANT_TYPE_STRING)); |
||
1047 | |||
1048 | v = g_hash_table_lookup (found, "double"); |
||
1049 | g_assert (g_variant_is_of_type (v, G_VARIANT_TYPE_DOUBLE)); |
||
1050 | |||
1051 | v = g_hash_table_lookup (found, "complex"); |
||
1052 | g_assert (g_variant_is_of_type (v, G_VARIANT_TYPE("a(si)"))); |
||
1053 | |||
1054 | v = g_hash_table_lookup (found, "test-123"); |
||
1055 | g_assert (g_variant_is_of_type (v, G_VARIANT_TYPE_STRING)); |
||
1056 | |||
1057 | g_hash_table_unref (found); |
||
1058 | |||
1059 | g_menu_remove_all (menu); |
||
1060 | |||
1061 | g_object_unref (menu); |
||
1062 | g_object_unref (item); |
||
1063 | } |
||
1064 | |||
1065 | static void |
||
1066 | test_links (void) |
||
1067 | { |
||
1068 | GMenu *menu; |
||
1069 | GMenuModel *m; |
||
1070 | GMenuModel *x; |
||
1071 | GMenuItem *item; |
||
1072 | |||
1073 | m = G_MENU_MODEL (g_menu_new ()); |
||
1074 | g_menu_append (G_MENU (m), "test", NULL); |
||
1075 | |||
1076 | menu = g_menu_new (); |
||
1077 | |||
1078 | item = g_menu_item_new ("test2", NULL); |
||
1079 | g_menu_item_set_link (item, "submenu", m); |
||
1080 | g_menu_prepend_item (menu, item); |
||
1081 | |||
1082 | item = g_menu_item_new ("test1", NULL); |
||
1083 | g_menu_item_set_link (item, "section", m); |
||
1084 | g_menu_insert_item (menu, 0, item); |
||
1085 | |||
1086 | item = g_menu_item_new ("test3", NULL); |
||
1087 | g_menu_item_set_link (item, "wallet", m); |
||
1088 | g_menu_insert_item (menu, 1000, item); |
||
1089 | |||
1090 | item = g_menu_item_new ("test4", NULL); |
||
1091 | g_menu_item_set_link (item, "purse", m); |
||
1092 | g_menu_item_set_link (item, "purse", NULL); |
||
1093 | g_menu_append_item (menu, item); |
||
1094 | |||
1095 | g_assert_cmpint (g_menu_model_get_n_items (G_MENU_MODEL (menu)), ==, 4); |
||
1096 | |||
1097 | x = g_menu_model_get_item_link (G_MENU_MODEL (menu), 0, "section"); |
||
1098 | g_assert (x == m); |
||
1099 | g_object_unref (x); |
||
1100 | |||
1101 | x = g_menu_model_get_item_link (G_MENU_MODEL (menu), 1, "submenu"); |
||
1102 | g_assert (x == m); |
||
1103 | g_object_unref (x); |
||
1104 | |||
1105 | x = g_menu_model_get_item_link (G_MENU_MODEL (menu), 2, "wallet"); |
||
1106 | g_assert (x == m); |
||
1107 | g_object_unref (x); |
||
1108 | |||
1109 | x = g_menu_model_get_item_link (G_MENU_MODEL (menu), 3, "purse"); |
||
1110 | g_assert (x == NULL); |
||
1111 | |||
1112 | g_object_unref (m); |
||
1113 | g_object_unref (menu); |
||
1114 | } |
||
1115 | |||
1116 | static void |
||
1117 | test_mutable (void) |
||
1118 | { |
||
1119 | GMenu *menu; |
||
1120 | |||
1121 | menu = g_menu_new (); |
||
1122 | g_menu_append (menu, "test", "test"); |
||
1123 | |||
1124 | g_assert (g_menu_model_is_mutable (G_MENU_MODEL (menu))); |
||
1125 | g_menu_freeze (menu); |
||
1126 | g_assert (!g_menu_model_is_mutable (G_MENU_MODEL (menu))); |
||
1127 | |||
1128 | g_object_unref (menu); |
||
1129 | } |
||
1130 | |||
1131 | static void |
||
1132 | test_convenience (void) |
||
1133 | { |
||
1134 | GMenu *m1, *m2; |
||
1135 | GMenu *sub; |
||
1136 | GMenuItem *item; |
||
1137 | |||
1138 | m1 = g_menu_new (); |
||
1139 | m2 = g_menu_new (); |
||
1140 | sub = g_menu_new (); |
||
1141 | |||
1142 | g_menu_prepend (m1, "label1", "do::something"); |
||
1143 | g_menu_insert (m2, 0, "label1", "do::something"); |
||
1144 | |||
1145 | g_menu_append (m1, "label2", "do::somethingelse"); |
||
1146 | g_menu_insert (m2, -1, "label2", "do::somethingelse"); |
||
1147 | |||
1148 | g_menu_insert_section (m1, 10, "label3", G_MENU_MODEL (sub)); |
||
1149 | item = g_menu_item_new_section ("label3", G_MENU_MODEL (sub)); |
||
1150 | g_menu_insert_item (m2, 10, item); |
||
1151 | g_object_unref (item); |
||
1152 | |||
1153 | g_menu_prepend_section (m1, "label4", G_MENU_MODEL (sub)); |
||
1154 | g_menu_insert_section (m2, 0, "label4", G_MENU_MODEL (sub)); |
||
1155 | |||
1156 | g_menu_append_section (m1, "label5", G_MENU_MODEL (sub)); |
||
1157 | g_menu_insert_section (m2, -1, "label5", G_MENU_MODEL (sub)); |
||
1158 | |||
1159 | g_menu_insert_submenu (m1, 5, "label6", G_MENU_MODEL (sub)); |
||
1160 | item = g_menu_item_new_submenu ("label6", G_MENU_MODEL (sub)); |
||
1161 | g_menu_insert_item (m2, 5, item); |
||
1162 | g_object_unref (item); |
||
1163 | |||
1164 | g_menu_prepend_submenu (m1, "label7", G_MENU_MODEL (sub)); |
||
1165 | g_menu_insert_submenu (m2, 0, "label7", G_MENU_MODEL (sub)); |
||
1166 | |||
1167 | g_menu_append_submenu (m1, "label8", G_MENU_MODEL (sub)); |
||
1168 | g_menu_insert_submenu (m2, -1, "label8", G_MENU_MODEL (sub)); |
||
1169 | |||
1170 | assert_menus_equal (G_MENU_MODEL (m1), G_MENU_MODEL (m2)); |
||
1171 | |||
1172 | g_object_unref (m1); |
||
1173 | g_object_unref (m2); |
||
1174 | } |
||
1175 | |||
1176 | static void |
||
1177 | test_menuitem (void) |
||
1178 | { |
||
1179 | GMenu *menu; |
||
1180 | GMenu *submenu; |
||
1181 | GMenuItem *item; |
||
1182 | GIcon *icon; |
||
1183 | gboolean b; |
||
1184 | gchar *s; |
||
1185 | |||
1186 | menu = g_menu_new (); |
||
1187 | submenu = g_menu_new (); |
||
1188 | |||
1189 | item = g_menu_item_new ("label", "action"); |
||
1190 | g_menu_item_set_attribute (item, "attribute", "b", TRUE); |
||
1191 | g_menu_item_set_link (item, G_MENU_LINK_SUBMENU, G_MENU_MODEL (submenu)); |
||
1192 | g_menu_append_item (menu, item); |
||
1193 | |||
1194 | icon = g_themed_icon_new ("bla"); |
||
1195 | g_menu_item_set_icon (item, icon); |
||
1196 | g_object_unref (icon); |
||
1197 | |||
1198 | g_assert (g_menu_item_get_attribute (item, "attribute", "b", &b)); |
||
1199 | g_assert (b); |
||
1200 | |||
1201 | g_menu_item_set_action_and_target (item, "action", "(bs)", TRUE, "string"); |
||
1202 | g_assert (g_menu_item_get_attribute (item, "target", "(bs)", &b, &s)); |
||
1203 | g_assert (b); |
||
1204 | g_assert_cmpstr (s, ==, "string"); |
||
1205 | g_free (s); |
||
1206 | |||
1207 | g_object_unref (item); |
||
1208 | |||
1209 | item = g_menu_item_new_from_model (G_MENU_MODEL (menu), 0); |
||
1210 | assert_menuitem_equal (item, G_MENU_MODEL (menu), 0); |
||
1211 | g_object_unref (item); |
||
1212 | |||
1213 | g_object_unref (menu); |
||
1214 | g_object_unref (submenu); |
||
1215 | } |
||
1216 | |||
1217 | /* Epilogue {{{1 */ |
||
1218 | int |
||
1219 | main (int argc, char **argv) |
||
1220 | { |
||
1221 | gboolean ret; |
||
1222 | |||
1223 | g_test_init (&argc, &argv, NULL); |
||
1224 | |||
1225 | session_bus_up (); |
||
1226 | |||
1227 | g_test_add_func ("/gmenu/equality", test_equality); |
||
1228 | g_test_add_func ("/gmenu/random", test_random); |
||
1229 | g_test_add_func ("/gmenu/dbus/roundtrip", test_dbus_roundtrip); |
||
1230 | g_test_add_func ("/gmenu/dbus/subscriptions", test_dbus_subscriptions); |
||
1231 | g_test_add_func ("/gmenu/dbus/threaded", test_dbus_threaded); |
||
1232 | g_test_add_func ("/gmenu/attributes", test_attributes); |
||
1233 | g_test_add_func ("/gmenu/attributes/iterate", test_attribute_iter); |
||
1234 | g_test_add_func ("/gmenu/links", test_links); |
||
1235 | g_test_add_func ("/gmenu/mutable", test_mutable); |
||
1236 | g_test_add_func ("/gmenu/convenience", test_convenience); |
||
1237 | g_test_add_func ("/gmenu/menuitem", test_menuitem); |
||
1238 | |||
1239 | ret = g_test_run (); |
||
1240 | |||
1241 | session_bus_down (); |
||
1242 | |||
1243 | return ret; |
||
1244 | } |
||
1245 | /* vim:set foldmethod=marker: */ |