GMenuModel exporter: remove workaround
[glib.git] / gio / gmenu.c
bloba4131ed0e1a6bdf74e2b80bd417222189a52d520
1 /*
2 * Copyright © 2011 Canonical Ltd.
4 * This library is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * licence, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
17 * USA.
19 * Author: Ryan Lortie <desrt@desrt.ca>
22 #include "config.h"
24 #include "gmenu.h"
26 #include <string.h>
28 /**
29 * SECTION:gmenu
30 * @title: GMenu
31 * @short_description: A simple implementation of GMenuModel
33 * #GMenu is a simple implementation of #GMenuModel.
34 * You populate a #GMenu by adding #GMenuItem instances to it.
36 * There are some convenience functions to allow you to directly
37 * add items (avoiding #GMenuItem) for the common cases. To add
38 * a regular item, use g_menu_insert(). To add a section, use
39 * g_menu_insert_section(). To add a submenu, use
40 * g_menu_insert_submenu().
42 * Often it is more convenient to create a #GMenu from an XML
43 * fragment, using <link linkend="gio-GMenu-Markup">GMenu Markup</link>.
46 /**
47 * GMenu:
49 * #GMenu is an opaque structure type. You must access it using the
50 * functions below.
51 **/
53 /**
54 * GMenuItem:
56 * #GMenuItem is an opaque structure type. You must access it using the
57 * functions below.
58 **/
60 struct _GMenuItem
62 GObject parent_instance;
64 GHashTable *attributes;
65 GHashTable *links;
66 gboolean cow;
69 typedef GObjectClass GMenuItemClass;
71 struct _GMenu
73 GMenuModel parent_instance;
75 GArray *items;
76 gboolean mutable;
79 typedef GMenuModelClass GMenuClass;
81 G_DEFINE_TYPE (GMenu, g_menu, G_TYPE_MENU_MODEL)
82 G_DEFINE_TYPE (GMenuItem, g_menu_item, G_TYPE_OBJECT)
84 struct item
86 GHashTable *attributes;
87 GHashTable *links;
90 static gboolean
91 g_menu_is_mutable (GMenuModel *model)
93 GMenu *menu = G_MENU (model);
95 return menu->mutable;
98 static gint
99 g_menu_get_n_items (GMenuModel *model)
101 GMenu *menu = G_MENU (model);
103 return menu->items->len;
106 static void
107 g_menu_get_item_attributes (GMenuModel *model,
108 gint position,
109 GHashTable **table)
111 GMenu *menu = G_MENU (model);
113 *table = g_hash_table_ref (g_array_index (menu->items, struct item, position).attributes);
116 static void
117 g_menu_get_item_links (GMenuModel *model,
118 gint position,
119 GHashTable **table)
121 GMenu *menu = G_MENU (model);
123 *table = g_hash_table_ref (g_array_index (menu->items, struct item, position).links);
127 * g_menu_insert_item:
128 * @menu: a #GMenu
129 * @position: the position at which to insert the item
130 * @item: the #GMenuItem to insert
132 * Inserts @item into @menu.
134 * The "insertion" is actually done by copying all of the attribute and
135 * link values of @item and using them to form a new item within @menu.
136 * As such, @item itself is not really inserted, but rather, a menu item
137 * that is exactly the same as the one presently described by @item.
139 * This means that @item is essentially useless after the insertion
140 * occurs. Any changes you make to it are ignored unless it is inserted
141 * again (at which point its updated values will be copied).
143 * You should probably just free @item once you're done.
145 * There are many convenience functions to take care of common cases.
146 * See g_menu_insert(), g_menu_insert_section() and
147 * g_menu_insert_submenu() as well as "prepend" and "append" variants of
148 * each of these functions.
150 void
151 g_menu_insert_item (GMenu *menu,
152 gint position,
153 GMenuItem *item)
155 struct item new_item;
157 g_return_if_fail (G_IS_MENU (menu));
158 g_return_if_fail (G_IS_MENU_ITEM (item));
160 if (position < 0 || position > menu->items->len)
161 position = menu->items->len;
163 new_item.attributes = g_hash_table_ref (item->attributes);
164 new_item.links = g_hash_table_ref (item->links);
165 item->cow = TRUE;
167 g_array_insert_val (menu->items, position, new_item);
168 g_menu_model_items_changed (G_MENU_MODEL (menu), position, 0, 1);
172 * g_menu_prepend_item:
173 * @menu: a #GMenu
174 * @item: a #GMenuItem to prepend
176 * Prepends @item to the start of @menu.
178 * See g_menu_insert_item() for more information.
180 void
181 g_menu_prepend_item (GMenu *menu,
182 GMenuItem *item)
184 g_menu_insert_item (menu, 0, item);
188 * g_menu_append_item:
189 * @menu: a #GMenu
190 * @item: a #GMenuItem to append
192 * Appends @item to the end of @menu.
194 * See g_menu_insert_item() for more information.
196 void
197 g_menu_append_item (GMenu *menu,
198 GMenuItem *item)
200 g_menu_insert_item (menu, -1, item);
204 * g_menu_freeze:
205 * @menu: a #GMenu
207 * Marks @menu as frozen.
209 * After the menu is frozen, it is an error to attempt to make any
210 * changes to it. In effect this means that the #GMenu API must no
211 * longer be used.
213 * This function causes g_menu_model_is_mutable() to begin returning
214 * %FALSE, which has some positive performance implications.
216 void
217 g_menu_freeze (GMenu *menu)
219 g_return_if_fail (G_IS_MENU (menu));
221 menu->mutable = FALSE;
225 * g_menu_new:
227 * Creates a new #GMenu.
229 * The new menu has no items.
231 * Returns: a new #GMenu
233 GMenu *
234 g_menu_new (void)
236 return g_object_new (G_TYPE_MENU, NULL);
240 * g_menu_insert:
241 * @menu: a #GMenu
242 * @position: the position at which to insert the item
243 * @label: (allow-none): the section label, or %NULL
244 * @detailed_action: (allow-none): the detailed action string, or %NULL
246 * Convenience function for inserting a normal menu item into @menu.
247 * Combine g_menu_new() and g_menu_insert_item() for a more flexible
248 * alternative.
250 void
251 g_menu_insert (GMenu *menu,
252 gint position,
253 const gchar *label,
254 const gchar *detailed_action)
256 GMenuItem *menu_item;
258 menu_item = g_menu_item_new (label, detailed_action);
259 g_menu_insert_item (menu, position, menu_item);
260 g_object_unref (menu_item);
264 * g_menu_prepend:
265 * @menu: a #GMenu
266 * @label: (allow-none): the section label, or %NULL
267 * @detailed_action: (allow-none): the detailed action string, or %NULL
269 * Convenience function for prepending a normal menu item to the start
270 * of @menu. Combine g_menu_new() and g_menu_insert_item() for a more
271 * flexible alternative.
273 void
274 g_menu_prepend (GMenu *menu,
275 const gchar *label,
276 const gchar *detailed_action)
278 g_menu_insert (menu, 0, label, detailed_action);
282 * g_menu_append:
283 * @menu: a #GMenu
284 * @label: (allow-none): the section label, or %NULL
285 * @detailed_action: (allow-none): the detailed action string, or %NULL
287 * Convenience function for appending a normal menu item to the end of
288 * @menu. Combine g_menu_new() and g_menu_insert_item() for a more
289 * flexible alternative.
291 void
292 g_menu_append (GMenu *menu,
293 const gchar *label,
294 const gchar *detailed_action)
296 g_menu_insert (menu, -1, label, detailed_action);
300 * g_menu_insert_section:
301 * @menu: a #GMenu
302 * @position: the position at which to insert the item
303 * @label: (allow-none): the section label, or %NULL
304 * @section: a #GMenuModel with the items of the section
306 * Convenience function for inserting a section menu item into @menu.
307 * Combine g_menu_new_section() and g_menu_insert_item() for a more
308 * flexible alternative.
310 void
311 g_menu_insert_section (GMenu *menu,
312 gint position,
313 const gchar *label,
314 GMenuModel *section)
316 GMenuItem *menu_item;
318 menu_item = g_menu_item_new_section (label, section);
319 g_menu_insert_item (menu, position, menu_item);
320 g_object_unref (menu_item);
325 * g_menu_prepend_section:
326 * @menu: a #GMenu
327 * @label: (allow-none): the section label, or %NULL
328 * @section: a #GMenuModel with the items of the section
330 * Convenience function for prepending a section menu item to the start
331 * of @menu. Combine g_menu_new_section() and g_menu_insert_item() for
332 * a more flexible alternative.
334 void
335 g_menu_prepend_section (GMenu *menu,
336 const gchar *label,
337 GMenuModel *section)
339 g_menu_insert_section (menu, 0, label, section);
343 * g_menu_append_section:
344 * @menu: a #GMenu
345 * @label: (allow-none): the section label, or %NULL
346 * @section: a #GMenuModel with the items of the section
348 * Convenience function for appending a section menu item to the end of
349 * @menu. Combine g_menu_new_section() and g_menu_insert_item() for a
350 * more flexible alternative.
352 void
353 g_menu_append_section (GMenu *menu,
354 const gchar *label,
355 GMenuModel *section)
357 g_menu_insert_section (menu, -1, label, section);
361 * g_menu_insert_submenu:
362 * @menu: a #GMenu
363 * @position: the position at which to insert the item
364 * @label: (allow-none): the section label, or %NULL
365 * @submenu: a #GMenuModel with the items of the submenu
367 * Convenience function for inserting a submenu menu item into @menu.
368 * Combine g_menu_new_submenu() and g_menu_insert_item() for a more
369 * flexible alternative.
371 void
372 g_menu_insert_submenu (GMenu *menu,
373 gint position,
374 const gchar *label,
375 GMenuModel *submenu)
377 GMenuItem *menu_item;
379 menu_item = g_menu_item_new_submenu (label, submenu);
380 g_menu_insert_item (menu, position, menu_item);
381 g_object_unref (menu_item);
385 * g_menu_prepend_submenu:
386 * @menu: a #GMenu
387 * @label: (allow-none): the section label, or %NULL
388 * @submenu: a #GMenuModel with the items of the submenu
390 * Convenience function for prepending a submenu menu item to the start
391 * of @menu. Combine g_menu_new_submenu() and g_menu_insert_item() for
392 * a more flexible alternative.
394 void
395 g_menu_prepend_submenu (GMenu *menu,
396 const gchar *label,
397 GMenuModel *submenu)
399 g_menu_insert_submenu (menu, 0, label, submenu);
403 * g_menu_append_submenu:
404 * @menu: a #GMenu
405 * @label: (allow-none): the section label, or %NULL
406 * @submenu: a #GMenuModel with the items of the submenu
408 * Convenience function for appending a submenu menu item to the end of
409 * @menu. Combine g_menu_new_submenu() and g_menu_insert_item() for a
410 * more flexible alternative.
412 void
413 g_menu_append_submenu (GMenu *menu,
414 const gchar *label,
415 GMenuModel *submenu)
417 g_menu_insert_submenu (menu, -1, label, submenu);
420 static void
421 g_menu_clear_item (struct item *item)
423 if (item->attributes != NULL)
424 g_hash_table_unref (item->attributes);
425 if (item->links != NULL);
426 g_hash_table_unref (item->links);
430 * g_menu_remove:
431 * @menu: a #GMenu
432 * @position: the position of the item to remove
434 * Removes an item from the menu.
436 * @position gives the index of the item to remove.
438 * It is an error if position is not in range the range from 0 to one
439 * less than the number of items in the menu.
441 * It is not possible to remove items by identity since items are added
442 * to the menu simply by copying their links and attributes (ie:
443 * identity of the item itself is not preserved).
445 void
446 g_menu_remove (GMenu *menu,
447 gint position)
449 g_return_if_fail (G_IS_MENU (menu));
450 g_return_if_fail (0 <= position && position < menu->items->len);
452 g_menu_clear_item (&g_array_index (menu->items, struct item, position));
453 g_array_remove_index (menu->items, position);
454 g_menu_model_items_changed (G_MENU_MODEL (menu), position, 1, 0);
457 static void
458 g_menu_finalize (GObject *object)
460 GMenu *menu = G_MENU (object);
461 struct item *items;
462 gint n_items;
463 gint i;
465 n_items = menu->items->len;
466 items = (struct item *) g_array_free (menu->items, FALSE);
467 for (i = 0; i < n_items; i++)
468 g_menu_clear_item (&items[i]);
469 g_free (items);
471 G_OBJECT_CLASS (g_menu_parent_class)
472 ->finalize (object);
475 static void
476 g_menu_init (GMenu *menu)
478 menu->items = g_array_new (FALSE, FALSE, sizeof (struct item));
479 menu->mutable = TRUE;
482 static void
483 g_menu_class_init (GMenuClass *class)
485 GMenuModelClass *model_class = G_MENU_MODEL_CLASS (class);
486 GObjectClass *object_class = G_OBJECT_CLASS (class);
488 object_class->finalize = g_menu_finalize;
490 model_class->is_mutable = g_menu_is_mutable;
491 model_class->get_n_items = g_menu_get_n_items;
492 model_class->get_item_attributes = g_menu_get_item_attributes;
493 model_class->get_item_links = g_menu_get_item_links;
497 static void
498 g_menu_item_clear_cow (GMenuItem *menu_item)
500 if (menu_item->cow)
502 GHashTableIter iter;
503 GHashTable *new;
504 gpointer key;
505 gpointer val;
507 new = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_variant_unref);
508 g_hash_table_iter_init (&iter, menu_item->attributes);
509 while (g_hash_table_iter_next (&iter, &key, &val))
510 g_hash_table_insert (new, g_strdup (key), g_variant_ref (val));
511 g_hash_table_unref (menu_item->attributes);
512 menu_item->attributes = new;
514 new = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_object_unref);
515 g_hash_table_iter_init (&iter, menu_item->links);
516 while (g_hash_table_iter_next (&iter, &key, &val))
517 g_hash_table_insert (new, g_strdup (key), g_object_ref (val));
518 g_hash_table_unref (menu_item->links);
519 menu_item->links = new;
521 menu_item->cow = FALSE;
525 static void
526 g_menu_item_finalize (GObject *object)
528 GMenuItem *menu_item = G_MENU_ITEM (object);
530 g_hash_table_unref (menu_item->attributes);
531 g_hash_table_unref (menu_item->links);
533 G_OBJECT_CLASS (g_menu_item_parent_class)
534 ->finalize (object);
537 static void
538 g_menu_item_init (GMenuItem *menu_item)
540 menu_item->attributes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_variant_unref);
541 menu_item->links = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
542 menu_item->cow = FALSE;
545 static void
546 g_menu_item_class_init (GMenuItemClass *class)
548 class->finalize = g_menu_item_finalize;
551 /* We treat attribute names the same as GSettings keys:
552 * - only lowercase ascii, digits and '-'
553 * - must start with lowercase
554 * - must not end with '-'
555 * - no consecutive '-'
556 * - not longer than 1024 chars
558 static gboolean
559 valid_attribute_name (const gchar *name)
561 gint i;
563 if (!g_ascii_islower (name[0]))
564 return FALSE;
566 for (i = 1; name[i]; i++)
568 if (name[i] != '-' &&
569 !g_ascii_islower (name[i]) &&
570 !g_ascii_isdigit (name[i]))
571 return FALSE;
573 if (name[i] == '-' && name[i + 1] == '-')
574 return FALSE;
577 if (name[i - 1] == '-')
578 return FALSE;
580 if (i > 1024)
581 return FALSE;
583 return TRUE;
587 * g_menu_item_set_attribute_value:
588 * @menu_item: a #GMenuItem
589 * @attribute: the attribute to set
590 * @value: (allow-none): a #GVariant to use as the value, or %NULL
592 * Sets or unsets an attribute on @menu_item.
594 * The attribute to set or unset is specified by @attribute. This
595 * can be one of the standard attribute names %G_MENU_ATTRIBUTE_LABEL,
596 * %G_MENU_ATTRIBUTE_ACTION, %G_MENU_ATTRIBUTE_TARGET, or a custom
597 * attribute name.
598 * Attribute names are restricted to lowercase characters, numbers
599 * and '-'. Furthermore, the names must begin with a lowercase character,
600 * must not end with a '-', and must not contain consecutive dashes.
602 * must consist only of lowercase
603 * ASCII characters, digits and '-'.
605 * If @value is non-%NULL then it is used as the new value for the
606 * attribute. If @value is %NULL then the attribute is unset. If
607 * the @value #GVariant is floating, it is consumed.
609 * See also g_menu_item_set_attribute() for a more convenient way to do
610 * the same.
612 void
613 g_menu_item_set_attribute_value (GMenuItem *menu_item,
614 const gchar *attribute,
615 GVariant *value)
617 g_return_if_fail (G_IS_MENU_ITEM (menu_item));
618 g_return_if_fail (attribute != NULL);
619 g_return_if_fail (valid_attribute_name (attribute));
621 g_menu_item_clear_cow (menu_item);
623 if (value != NULL)
624 g_hash_table_insert (menu_item->attributes, g_strdup (attribute), g_variant_ref_sink (value));
625 else
626 g_hash_table_remove (menu_item->attributes, attribute);
630 * g_menu_item_set_attribute:
631 * @menu_item: a #GMenuItem
632 * @attribute: the attribute to set
633 * @format_string: (allow-none): a #GVariant format string, or %NULL
634 * @...: positional parameters, as per @format_string
636 * Sets or unsets an attribute on @menu_item.
638 * The attribute to set or unset is specified by @attribute. This
639 * can be one of the standard attribute names %G_MENU_ATTRIBUTE_LABEL,
640 * %G_MENU_ATTRIBUTE_ACTION, %G_MENU_ATTRIBUTE_TARGET, or a custom
641 * attribute name.
642 * Attribute names are restricted to lowercase characters, numbers
643 * and '-'. Furthermore, the names must begin with a lowercase character,
644 * must not end with a '-', and must not contain consecutive dashes.
646 * If @format_string is non-%NULL then the proper position parameters
647 * are collected to create a #GVariant instance to use as the attribute
648 * value. If it is %NULL then the positional parameterrs are ignored
649 * and the named attribute is unset.
651 * See also g_menu_item_set_attribute_value() for an equivalent call
652 * that directly accepts a #GVariant.
654 void
655 g_menu_item_set_attribute (GMenuItem *menu_item,
656 const gchar *attribute,
657 const gchar *format_string,
658 ...)
660 GVariant *value;
662 if (format_string != NULL)
664 va_list ap;
666 va_start (ap, format_string);
667 value = g_variant_new_va (format_string, NULL, &ap);
668 va_end (ap);
670 else
671 value = NULL;
673 g_menu_item_set_attribute_value (menu_item, attribute, value);
677 * g_menu_item_set_link:
678 * @menu_item: a #GMenuItem
679 * @link: type of link to establish or unset
680 * @model: (allow-none): the #GMenuModel to link to (or %NULL to unset)
682 * Creates a link from @menu_item to @model if non-%NULL, or unsets it.
684 * Links are used to establish a relationship between a particular menu
685 * item and another menu. For example, %G_MENU_LINK_SUBMENU is used to
686 * associate a submenu with a particular menu item, and %G_MENU_LINK_SECTION
687 * is used to create a section. Other types of link can be used, but there
688 * is no guarantee that clients will be able to make sense of them.
689 * Link types are restricted to lowercase characters, numbers
690 * and '-'. Furthermore, the names must begin with a lowercase character,
691 * must not end with a '-', and must not contain consecutive dashes.
693 void
694 g_menu_item_set_link (GMenuItem *menu_item,
695 const gchar *link,
696 GMenuModel *model)
698 g_return_if_fail (G_IS_MENU_ITEM (menu_item));
699 g_return_if_fail (link != NULL);
700 g_return_if_fail (valid_attribute_name (link));
702 g_menu_item_clear_cow (menu_item);
704 if (model != NULL)
705 g_hash_table_insert (menu_item->links, g_strdup (link), g_object_ref (model));
706 else
707 g_hash_table_remove (menu_item->links, link);
711 * g_menu_item_set_label:
712 * @menu_item: a #GMenuItem
713 * @label: (allow-none): the label to set, or %NULL to unset
715 * Sets or unsets the "label" attribute of @menu_item.
717 * If @label is non-%NULL it is used as the label for the menu item. If
718 * it is %NULL then the label attribute is unset.
720 void
721 g_menu_item_set_label (GMenuItem *menu_item,
722 const gchar *label)
724 GVariant *value;
726 if (label != NULL)
727 value = g_variant_new_string (label);
728 else
729 value = NULL;
731 g_menu_item_set_attribute_value (menu_item, G_MENU_ATTRIBUTE_LABEL, value);
735 * g_menu_item_set_submenu:
736 * @menu_item: a #GMenuItem
737 * @submenu: (allow-none): a #GMenuModel, or %NULL
739 * Sets or unsets the "submenu" link of @menu_item to @submenu.
741 * If @submenu is non-%NULL, it is linked to. If it is %NULL then the
742 * link is unset.
744 * The effect of having one menu appear as a submenu of another is
745 * exactly as it sounds.
747 void
748 g_menu_item_set_submenu (GMenuItem *menu_item,
749 GMenuModel *submenu)
751 g_menu_item_set_link (menu_item, G_MENU_LINK_SUBMENU, submenu);
755 * g_menu_item_set_section:
756 * @menu_item: a #GMenuItem
757 * @section: (allow-none): a #GMenuModel, or %NULL
759 * Sets or unsets the "section" link of @menu_item to @section.
761 * The effect of having one menu appear as a section of another is
762 * exactly as it sounds: the items from @section become a direct part of
763 * the menu that @menu_item is added to. See g_menu_item_new_section()
764 * for more information about what it means for a menu item to be a
765 * section.
767 void
768 g_menu_item_set_section (GMenuItem *menu_item,
769 GMenuModel *section)
771 g_menu_item_set_link (menu_item, G_MENU_LINK_SECTION, section);
775 * g_menu_item_set_action_and_target_value:
776 * @menu_item: a #GMenuItem
777 * @action: (allow-none): the name of the action for this item
778 * @target_value: (allow-none): a #GVariant to use as the action target
780 * Sets or unsets the "action" and "target" attributes of @menu_item.
782 * If @action is %NULL then both the "action" and "target" attributes
783 * are unset (and @target_value is ignored).
785 * If @action is non-%NULL then the "action" attribute is set. The
786 * "target" attribute is then set to the value of @target_value if it is
787 * non-%NULL or unset otherwise.
789 * Normal menu items (ie: not submenu, section or other custom item
790 * types) are expected to have the "action" attribute set to identify
791 * the action that they are associated with. The state type of the
792 * action help to determine the disposition of the menu item. See
793 * #GAction and #GActionGroup for an overview of actions.
795 * In general, clicking on the menu item will result in activation of
796 * the named action with the "target" attribute given as the parameter
797 * to the action invocation. If the "target" attribute is not set then
798 * the action is invoked with no parameter.
800 * If the action has no state then the menu item is usually drawn as a
801 * plain menu item (ie: with no additional decoration).
803 * If the action has a boolean state then the menu item is usually drawn
804 * as a toggle menu item (ie: with a checkmark or equivalent
805 * indication). The item should be marked as 'toggled' or 'checked'
806 * when the boolean state is %TRUE.
808 * If the action has a string state then the menu item is usually drawn
809 * as a radio menu item (ie: with a radio bullet or equivalent
810 * indication). The item should be marked as 'selected' when the string
811 * state is equal to the value of the @target property.
813 * See g_menu_item_set_action_and_target() or
814 * g_menu_item_set_detailed_action() for two equivalent calls that are
815 * probably more convenient for most uses.
817 void
818 g_menu_item_set_action_and_target_value (GMenuItem *menu_item,
819 const gchar *action,
820 GVariant *target_value)
822 GVariant *action_value;
824 if (action != NULL)
826 action_value = g_variant_new_string (action);
828 else
830 action_value = NULL;
831 target_value = NULL;
834 g_menu_item_set_attribute_value (menu_item, G_MENU_ATTRIBUTE_ACTION, action_value);
835 g_menu_item_set_attribute_value (menu_item, G_MENU_ATTRIBUTE_TARGET, target_value);
839 * g_menu_item_set_action_and_target:
840 * @menu_item: a #GMenuItem
841 * @action: (allow-none): the name of the action for this item
842 * @format_string: (allow-none): a GVariant format string
843 * @...: positional parameters, as per @format_string
845 * Sets or unsets the "action" and "target" attributes of @menu_item.
847 * If @action is %NULL then both the "action" and "target" attributes
848 * are unset (and @format_string is ignored along with the positional
849 * parameters).
851 * If @action is non-%NULL then the "action" attribute is set.
852 * @format_string is then inspected. If it is non-%NULL then the proper
853 * position parameters are collected to create a #GVariant instance to
854 * use as the target value. If it is %NULL then the positional
855 * parameters are ignored and the "target" attribute is unset.
857 * See also g_menu_item_set_action_and_target_value() for an equivalent
858 * call that directly accepts a #GVariant. See
859 * g_menu_item_set_detailed_action() for a more convenient version that
860 * works with string-typed targets.
862 * See also g_menu_item_set_action_and_target_value() for a
863 * description of the semantics of the action and target attributes.
865 void
866 g_menu_item_set_action_and_target (GMenuItem *menu_item,
867 const gchar *action,
868 const gchar *format_string,
869 ...)
871 GVariant *value;
873 if (format_string != NULL)
875 va_list ap;
877 va_start (ap, format_string);
878 value = g_variant_new_va (format_string, NULL, &ap);
879 va_end (ap);
881 else
882 value = NULL;
884 g_menu_item_set_action_and_target_value (menu_item, action, value);
888 * g_menu_item_set_detailed_action:
889 * @menu_item: a #GMenuItem
890 * @detailed_action: the "detailed" action string
892 * Sets the "action" and possibly the "target" attribute of @menu_item.
894 * If @detailed_action contains a double colon ("::") then it is used as
895 * a separator between an action name and a target string. In this
896 * case, this call is equivalent to calling
897 * g_menu_item_set_action_and_target() with the part before the "::" and
898 * g_menu_item_set_target_value() with a string-type #GVariant
899 * containing the part following the "::".
901 * If @detailed_action doesn't contain "::" then the action is set to
902 * the given string (verbatim) and the target value is unset.
904 * See g_menu_item_set_action_and_target() or
905 * g_menu_item_set_action_and_target_value() for more flexible (but
906 * slightly less convenient) alternatives.
908 * See also g_menu_set_action_and_target_value() for a description of
909 * the semantics of the action and target attributes.
911 void
912 g_menu_item_set_detailed_action (GMenuItem *menu_item,
913 const gchar *detailed_action)
915 const gchar *sep;
917 sep = strstr (detailed_action, "::");
919 if (sep != NULL)
921 gchar *action;
923 action = g_strndup (detailed_action, sep - detailed_action);
924 g_menu_item_set_action_and_target (menu_item, action, "s", sep + 2);
925 g_free (action);
928 else
929 g_menu_item_set_action_and_target_value (menu_item, detailed_action, NULL);
933 * g_menu_item_new:
934 * @label: (allow-none): the section label, or %NULL
935 * @detailed_action: (allow-none): the detailed action string, or %NULL
937 * Creates a new #GMenuItem.
939 * If @label is non-%NULL it is used to set the "label" attribute of the
940 * new item.
942 * If @detailed_action is non-%NULL it is used to set the "action" and
943 * possibly the "target" attribute of the new item. See
944 * g_menu_item_set_detailed_action() for more information.
946 * Returns: a new #GMenuItem
948 GMenuItem *
949 g_menu_item_new (const gchar *label,
950 const gchar *detailed_action)
952 GMenuItem *menu_item;
954 menu_item = g_object_new (G_TYPE_MENU_ITEM, NULL);
956 if (label != NULL)
957 g_menu_item_set_label (menu_item, label);
959 if (detailed_action != NULL)
960 g_menu_item_set_detailed_action (menu_item, detailed_action);
962 return menu_item;
966 * g_menu_item_new_submenu:
967 * @label: (allow-none): the section label, or %NULL
968 * @submenu: a #GMenuModel with the items of the submenu
970 * Creates a new #GMenuItem representing a submenu.
972 * This is a convenience API around g_menu_item_new() and
973 * g_menu_item_set_submenu().
975 * Returns: a new #GMenuItem
977 GMenuItem *
978 g_menu_item_new_submenu (const gchar *label,
979 GMenuModel *submenu)
981 GMenuItem *menu_item;
983 menu_item = g_object_new (G_TYPE_MENU_ITEM, NULL);
985 if (label != NULL)
986 g_menu_item_set_label (menu_item, label);
988 g_menu_item_set_submenu (menu_item, submenu);
990 return menu_item;
994 * g_menu_item_new_section:
995 * @label: (allow-none): the section label, or %NULL
996 * @section: a #GMenuModel with the items of the section
998 * Creates a new #GMenuItem representing a section.
1000 * This is a convenience API around g_menu_item_new() and
1001 * g_menu_item_set_section().
1003 * The effect of having one menu appear as a section of another is
1004 * exactly as it sounds: the items from @section become a direct part of
1005 * the menu that @menu_item is added to.
1007 * Visual separation is typically displayed between two non-empty
1008 * sections. If @label is non-%NULL then it will be encorporated into
1009 * this visual indication. This allows for labeled subsections of a
1010 * menu.
1012 * As a simple example, consider a typical "Edit" menu from a simple
1013 * program. It probably contains an "Undo" and "Redo" item, followed by
1014 * a separator, followed by "Cut", "Copy" and "Paste".
1016 * This would be accomplished by creating three #GMenu instances. The
1017 * first would be populated with the "Undo" and "Redo" items, and the
1018 * second with the "Cut", "Copy" and "Paste" items. The first and
1019 * second menus would then be added as submenus of the third. In XML
1020 * format, this would look something like the following:
1022 * <informalexample><programlisting><![CDATA[
1023 * <menu id='edit-menu'>
1024 * <section>
1025 * <item label='Undo'/>
1026 * <item label='Redo'/>
1027 * </section>
1028 * <section>
1029 * <item label='Cut'/>
1030 * <item label='Copy'/>
1031 * <item label='Paste'/>
1032 * </section>
1033 * </menu>
1034 * ]]></programlisting></informalexample>
1036 * The following example is exactly equivalent. It is more illustrative
1037 * of the exact relationship between the menus and items (keeping in
1038 * mind that the 'link' element defines a new menu that is linked to the
1039 * containing one). The style of the second example is more verbose and
1040 * difficult to read (and therefore not recommended except for the
1041 * purpose of understanding what is really going on).
1043 * <informalexample><programlisting><![CDATA[
1044 * <menu id='edit-menu'>
1045 * <item>
1046 * <link name='section'>
1047 * <item label='Undo'/>
1048 * <item label='Redo'/>
1049 * </link>
1050 * </item>
1051 * <item>
1052 * <link name='section'>
1053 * <item label='Cut'/>
1054 * <item label='Copy'/>
1055 * <item label='Paste'/>
1056 * </link>
1057 * </item>
1058 * </menu>
1059 * ]]></programlisting></informalexample>
1061 * Returns: a new #GMenuItem
1063 GMenuItem *
1064 g_menu_item_new_section (const gchar *label,
1065 GMenuModel *section)
1067 GMenuItem *menu_item;
1069 menu_item = g_object_new (G_TYPE_MENU_ITEM, NULL);
1071 if (label != NULL)
1072 g_menu_item_set_label (menu_item, label);
1074 g_menu_item_set_section (menu_item, section);
1076 return menu_item;