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,
19 * Author: Ryan Lortie <desrt@desrt.ca>
32 * @short_description: A simple implementation of GMenuModel
34 * #GMenu is a simple implementation of #GMenuModel.
35 * You populate a #GMenu by adding #GMenuItem instances to it.
37 * There are some convenience functions to allow you to directly
38 * add items (avoiding #GMenuItem) for the common cases. To add
39 * a regular item, use g_menu_insert(). To add a section, use
40 * g_menu_insert_section(). To add a submenu, use
41 * g_menu_insert_submenu().
47 * #GMenu is an opaque structure type. You must access it using the
56 * #GMenuItem is an opaque structure type. You must access it using the
64 GObject parent_instance;
66 GHashTable *attributes;
71 typedef GObjectClass GMenuItemClass;
75 GMenuModel parent_instance;
81 typedef GMenuModelClass GMenuClass;
83 G_DEFINE_TYPE (GMenu, g_menu, G_TYPE_MENU_MODEL)
84 G_DEFINE_TYPE (GMenuItem, g_menu_item, G_TYPE_OBJECT)
88 GHashTable *attributes;
93 g_menu_is_mutable (GMenuModel *model)
95 GMenu *menu = G_MENU (model);
101 g_menu_get_n_items (GMenuModel *model)
103 GMenu *menu = G_MENU (model);
105 return menu->items->len;
109 g_menu_get_item_attributes (GMenuModel *model,
113 GMenu *menu = G_MENU (model);
115 *table = g_hash_table_ref (g_array_index (menu->items, struct item, position).attributes);
119 g_menu_get_item_links (GMenuModel *model,
123 GMenu *menu = G_MENU (model);
125 *table = g_hash_table_ref (g_array_index (menu->items, struct item, position).links);
129 * g_menu_insert_item:
131 * @position: the position at which to insert the item
132 * @item: the #GMenuItem to insert
134 * Inserts @item into @menu.
136 * The "insertion" is actually done by copying all of the attribute and
137 * link values of @item and using them to form a new item within @menu.
138 * As such, @item itself is not really inserted, but rather, a menu item
139 * that is exactly the same as the one presently described by @item.
141 * This means that @item is essentially useless after the insertion
142 * occurs. Any changes you make to it are ignored unless it is inserted
143 * again (at which point its updated values will be copied).
145 * You should probably just free @item once you're done.
147 * There are many convenience functions to take care of common cases.
148 * See g_menu_insert(), g_menu_insert_section() and
149 * g_menu_insert_submenu() as well as "prepend" and "append" variants of
150 * each of these functions.
155 g_menu_insert_item (GMenu *menu,
159 struct item new_item;
161 g_return_if_fail (G_IS_MENU (menu));
162 g_return_if_fail (G_IS_MENU_ITEM (item));
164 if (position < 0 || position > menu->items->len)
165 position = menu->items->len;
167 new_item.attributes = g_hash_table_ref (item->attributes);
168 new_item.links = g_hash_table_ref (item->links);
171 g_array_insert_val (menu->items, position, new_item);
172 g_menu_model_items_changed (G_MENU_MODEL (menu), position, 0, 1);
176 * g_menu_prepend_item:
178 * @item: a #GMenuItem to prepend
180 * Prepends @item to the start of @menu.
182 * See g_menu_insert_item() for more information.
187 g_menu_prepend_item (GMenu *menu,
190 g_menu_insert_item (menu, 0, item);
194 * g_menu_append_item:
196 * @item: a #GMenuItem to append
198 * Appends @item to the end of @menu.
200 * See g_menu_insert_item() for more information.
205 g_menu_append_item (GMenu *menu,
208 g_menu_insert_item (menu, -1, item);
215 * Marks @menu as frozen.
217 * After the menu is frozen, it is an error to attempt to make any
218 * changes to it. In effect this means that the #GMenu API must no
221 * This function causes g_menu_model_is_mutable() to begin returning
222 * %FALSE, which has some positive performance implications.
227 g_menu_freeze (GMenu *menu)
229 g_return_if_fail (G_IS_MENU (menu));
231 menu->mutable = FALSE;
237 * Creates a new #GMenu.
239 * The new menu has no items.
241 * Returns: a new #GMenu
248 return g_object_new (G_TYPE_MENU, NULL);
254 * @position: the position at which to insert the item
255 * @label: (allow-none): the section label, or %NULL
256 * @detailed_action: (allow-none): the detailed action string, or %NULL
258 * Convenience function for inserting a normal menu item into @menu.
259 * Combine g_menu_item_new() and g_menu_insert_item() for a more flexible
265 g_menu_insert (GMenu *menu,
268 const gchar *detailed_action)
270 GMenuItem *menu_item;
272 menu_item = g_menu_item_new (label, detailed_action);
273 g_menu_insert_item (menu, position, menu_item);
274 g_object_unref (menu_item);
280 * @label: (allow-none): the section label, or %NULL
281 * @detailed_action: (allow-none): the detailed action string, or %NULL
283 * Convenience function for prepending a normal menu item to the start
284 * of @menu. Combine g_menu_item_new() and g_menu_insert_item() for a more
285 * flexible alternative.
290 g_menu_prepend (GMenu *menu,
292 const gchar *detailed_action)
294 g_menu_insert (menu, 0, label, detailed_action);
300 * @label: (allow-none): the section label, or %NULL
301 * @detailed_action: (allow-none): the detailed action string, or %NULL
303 * Convenience function for appending a normal menu item to the end of
304 * @menu. Combine g_menu_item_new() and g_menu_insert_item() for a more
305 * flexible alternative.
310 g_menu_append (GMenu *menu,
312 const gchar *detailed_action)
314 g_menu_insert (menu, -1, label, detailed_action);
318 * g_menu_insert_section:
320 * @position: the position at which to insert the item
321 * @label: (allow-none): the section label, or %NULL
322 * @section: a #GMenuModel with the items of the section
324 * Convenience function for inserting a section menu item into @menu.
325 * Combine g_menu_item_new_section() and g_menu_insert_item() for a more
326 * flexible alternative.
331 g_menu_insert_section (GMenu *menu,
336 GMenuItem *menu_item;
338 menu_item = g_menu_item_new_section (label, section);
339 g_menu_insert_item (menu, position, menu_item);
340 g_object_unref (menu_item);
345 * g_menu_prepend_section:
347 * @label: (allow-none): the section label, or %NULL
348 * @section: a #GMenuModel with the items of the section
350 * Convenience function for prepending a section menu item to the start
351 * of @menu. Combine g_menu_item_new_section() and g_menu_insert_item() for
352 * a more flexible alternative.
357 g_menu_prepend_section (GMenu *menu,
361 g_menu_insert_section (menu, 0, label, section);
365 * g_menu_append_section:
367 * @label: (allow-none): the section label, or %NULL
368 * @section: a #GMenuModel with the items of the section
370 * Convenience function for appending a section menu item to the end of
371 * @menu. Combine g_menu_item_new_section() and g_menu_insert_item() for a
372 * more flexible alternative.
377 g_menu_append_section (GMenu *menu,
381 g_menu_insert_section (menu, -1, label, section);
385 * g_menu_insert_submenu:
387 * @position: the position at which to insert the item
388 * @label: (allow-none): the section label, or %NULL
389 * @submenu: a #GMenuModel with the items of the submenu
391 * Convenience function for inserting a submenu menu item into @menu.
392 * Combine g_menu_item_new_submenu() and g_menu_insert_item() for a more
393 * flexible alternative.
398 g_menu_insert_submenu (GMenu *menu,
403 GMenuItem *menu_item;
405 menu_item = g_menu_item_new_submenu (label, submenu);
406 g_menu_insert_item (menu, position, menu_item);
407 g_object_unref (menu_item);
411 * g_menu_prepend_submenu:
413 * @label: (allow-none): the section label, or %NULL
414 * @submenu: a #GMenuModel with the items of the submenu
416 * Convenience function for prepending a submenu menu item to the start
417 * of @menu. Combine g_menu_item_new_submenu() and g_menu_insert_item() for
418 * a more flexible alternative.
423 g_menu_prepend_submenu (GMenu *menu,
427 g_menu_insert_submenu (menu, 0, label, submenu);
431 * g_menu_append_submenu:
433 * @label: (allow-none): the section label, or %NULL
434 * @submenu: a #GMenuModel with the items of the submenu
436 * Convenience function for appending a submenu menu item to the end of
437 * @menu. Combine g_menu_item_new_submenu() and g_menu_insert_item() for a
438 * more flexible alternative.
443 g_menu_append_submenu (GMenu *menu,
447 g_menu_insert_submenu (menu, -1, label, submenu);
451 g_menu_clear_item (struct item *item)
453 if (item->attributes != NULL)
454 g_hash_table_unref (item->attributes);
455 if (item->links != NULL)
456 g_hash_table_unref (item->links);
462 * @position: the position of the item to remove
464 * Removes an item from the menu.
466 * @position gives the index of the item to remove.
468 * It is an error if position is not in range the range from 0 to one
469 * less than the number of items in the menu.
471 * It is not possible to remove items by identity since items are added
472 * to the menu simply by copying their links and attributes (ie:
473 * identity of the item itself is not preserved).
478 g_menu_remove (GMenu *menu,
481 g_return_if_fail (G_IS_MENU (menu));
482 g_return_if_fail (0 <= position && position < menu->items->len);
484 g_menu_clear_item (&g_array_index (menu->items, struct item, position));
485 g_array_remove_index (menu->items, position);
486 g_menu_model_items_changed (G_MENU_MODEL (menu), position, 1, 0);
490 g_menu_finalize (GObject *object)
492 GMenu *menu = G_MENU (object);
497 n_items = menu->items->len;
498 items = (struct item *) g_array_free (menu->items, FALSE);
499 for (i = 0; i < n_items; i++)
500 g_menu_clear_item (&items[i]);
503 G_OBJECT_CLASS (g_menu_parent_class)
508 g_menu_init (GMenu *menu)
510 menu->items = g_array_new (FALSE, FALSE, sizeof (struct item));
511 menu->mutable = TRUE;
515 g_menu_class_init (GMenuClass *class)
517 GMenuModelClass *model_class = G_MENU_MODEL_CLASS (class);
518 GObjectClass *object_class = G_OBJECT_CLASS (class);
520 object_class->finalize = g_menu_finalize;
522 model_class->is_mutable = g_menu_is_mutable;
523 model_class->get_n_items = g_menu_get_n_items;
524 model_class->get_item_attributes = g_menu_get_item_attributes;
525 model_class->get_item_links = g_menu_get_item_links;
530 g_menu_item_clear_cow (GMenuItem *menu_item)
539 new = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_variant_unref);
540 g_hash_table_iter_init (&iter, menu_item->attributes);
541 while (g_hash_table_iter_next (&iter, &key, &val))
542 g_hash_table_insert (new, g_strdup (key), g_variant_ref (val));
543 g_hash_table_unref (menu_item->attributes);
544 menu_item->attributes = new;
546 new = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_object_unref);
547 g_hash_table_iter_init (&iter, menu_item->links);
548 while (g_hash_table_iter_next (&iter, &key, &val))
549 g_hash_table_insert (new, g_strdup (key), g_object_ref (val));
550 g_hash_table_unref (menu_item->links);
551 menu_item->links = new;
553 menu_item->cow = FALSE;
558 g_menu_item_finalize (GObject *object)
560 GMenuItem *menu_item = G_MENU_ITEM (object);
562 g_hash_table_unref (menu_item->attributes);
563 g_hash_table_unref (menu_item->links);
565 G_OBJECT_CLASS (g_menu_item_parent_class)
570 g_menu_item_init (GMenuItem *menu_item)
572 menu_item->attributes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_variant_unref);
573 menu_item->links = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
574 menu_item->cow = FALSE;
578 g_menu_item_class_init (GMenuItemClass *class)
580 class->finalize = g_menu_item_finalize;
583 /* We treat attribute names the same as GSettings keys:
584 * - only lowercase ascii, digits and '-'
585 * - must start with lowercase
586 * - must not end with '-'
587 * - no consecutive '-'
588 * - not longer than 1024 chars
591 valid_attribute_name (const gchar *name)
595 if (!g_ascii_islower (name[0]))
598 for (i = 1; name[i]; i++)
600 if (name[i] != '-' &&
601 !g_ascii_islower (name[i]) &&
602 !g_ascii_isdigit (name[i]))
605 if (name[i] == '-' && name[i + 1] == '-')
609 if (name[i - 1] == '-')
619 * g_menu_item_set_attribute_value:
620 * @menu_item: a #GMenuItem
621 * @attribute: the attribute to set
622 * @value: (allow-none): a #GVariant to use as the value, or %NULL
624 * Sets or unsets an attribute on @menu_item.
626 * The attribute to set or unset is specified by @attribute. This
627 * can be one of the standard attribute names %G_MENU_ATTRIBUTE_LABEL,
628 * %G_MENU_ATTRIBUTE_ACTION, %G_MENU_ATTRIBUTE_TARGET, or a custom
630 * Attribute names are restricted to lowercase characters, numbers
631 * and '-'. Furthermore, the names must begin with a lowercase character,
632 * must not end with a '-', and must not contain consecutive dashes.
634 * must consist only of lowercase
635 * ASCII characters, digits and '-'.
637 * If @value is non-%NULL then it is used as the new value for the
638 * attribute. If @value is %NULL then the attribute is unset. If
639 * the @value #GVariant is floating, it is consumed.
641 * See also g_menu_item_set_attribute() for a more convenient way to do
647 g_menu_item_set_attribute_value (GMenuItem *menu_item,
648 const gchar *attribute,
651 g_return_if_fail (G_IS_MENU_ITEM (menu_item));
652 g_return_if_fail (attribute != NULL);
653 g_return_if_fail (valid_attribute_name (attribute));
655 g_menu_item_clear_cow (menu_item);
658 g_hash_table_insert (menu_item->attributes, g_strdup (attribute), g_variant_ref_sink (value));
660 g_hash_table_remove (menu_item->attributes, attribute);
664 * g_menu_item_set_attribute:
665 * @menu_item: a #GMenuItem
666 * @attribute: the attribute to set
667 * @format_string: (allow-none): a #GVariant format string, or %NULL
668 * @...: positional parameters, as per @format_string
670 * Sets or unsets an attribute on @menu_item.
672 * The attribute to set or unset is specified by @attribute. This
673 * can be one of the standard attribute names %G_MENU_ATTRIBUTE_LABEL,
674 * %G_MENU_ATTRIBUTE_ACTION, %G_MENU_ATTRIBUTE_TARGET, or a custom
676 * Attribute names are restricted to lowercase characters, numbers
677 * and '-'. Furthermore, the names must begin with a lowercase character,
678 * must not end with a '-', and must not contain consecutive dashes.
680 * If @format_string is non-%NULL then the proper position parameters
681 * are collected to create a #GVariant instance to use as the attribute
682 * value. If it is %NULL then the positional parameterrs are ignored
683 * and the named attribute is unset.
685 * See also g_menu_item_set_attribute_value() for an equivalent call
686 * that directly accepts a #GVariant.
691 g_menu_item_set_attribute (GMenuItem *menu_item,
692 const gchar *attribute,
693 const gchar *format_string,
698 if (format_string != NULL)
702 va_start (ap, format_string);
703 value = g_variant_new_va (format_string, NULL, &ap);
709 g_menu_item_set_attribute_value (menu_item, attribute, value);
713 * g_menu_item_set_link:
714 * @menu_item: a #GMenuItem
715 * @link: type of link to establish or unset
716 * @model: (allow-none): the #GMenuModel to link to (or %NULL to unset)
718 * Creates a link from @menu_item to @model if non-%NULL, or unsets it.
720 * Links are used to establish a relationship between a particular menu
721 * item and another menu. For example, %G_MENU_LINK_SUBMENU is used to
722 * associate a submenu with a particular menu item, and %G_MENU_LINK_SECTION
723 * is used to create a section. Other types of link can be used, but there
724 * is no guarantee that clients will be able to make sense of them.
725 * Link types are restricted to lowercase characters, numbers
726 * and '-'. Furthermore, the names must begin with a lowercase character,
727 * must not end with a '-', and must not contain consecutive dashes.
732 g_menu_item_set_link (GMenuItem *menu_item,
736 g_return_if_fail (G_IS_MENU_ITEM (menu_item));
737 g_return_if_fail (link != NULL);
738 g_return_if_fail (valid_attribute_name (link));
740 g_menu_item_clear_cow (menu_item);
743 g_hash_table_insert (menu_item->links, g_strdup (link), g_object_ref (model));
745 g_hash_table_remove (menu_item->links, link);
749 * g_menu_item_get_attribute_value:
750 * @menu_item: a #GMenuItem
751 * @attribute: the attribute name to query
752 * @expected_type: (allow-none): the expected type of the attribute
754 * Queries the named @attribute on @menu_item.
756 * If @expected_type is specified and the attribute does not have this
757 * type, %NULL is returned. %NULL is also returned if the attribute
758 * simply does not exist.
760 * Returns: (transfer full): the attribute value, or %NULL
765 g_menu_item_get_attribute_value (GMenuItem *menu_item,
766 const gchar *attribute,
767 const GVariantType *expected_type)
771 g_return_val_if_fail (G_IS_MENU_ITEM (menu_item), NULL);
772 g_return_val_if_fail (attribute != NULL, NULL);
774 value = g_hash_table_lookup (menu_item->attributes, attribute);
778 if (expected_type == NULL || g_variant_is_of_type (value, expected_type))
779 g_variant_ref (value);
788 * g_menu_item_get_attribute:
789 * @menu_item: a #GMenuItem
790 * @attribute: the attribute name to query
791 * @format_string: a #GVariant format string
792 * @...: positional parameters, as per @format_string
794 * Queries the named @attribute on @menu_item.
796 * If the attribute exists and matches the #GVariantType corresponding
797 * to @format_string then @format_string is used to deconstruct the
798 * value into the positional parameters and %TRUE is returned.
800 * If the attribute does not exist, or it does exist but has the wrong
801 * type, then the positional parameters are ignored and %FALSE is
804 * Returns: %TRUE if the named attribute was found with the expected
810 g_menu_item_get_attribute (GMenuItem *menu_item,
811 const gchar *attribute,
812 const gchar *format_string,
818 g_return_val_if_fail (G_IS_MENU_ITEM (menu_item), FALSE);
819 g_return_val_if_fail (attribute != NULL, FALSE);
820 g_return_val_if_fail (format_string != NULL, FALSE);
822 value = g_hash_table_lookup (menu_item->attributes, attribute);
827 if (!g_variant_check_format_string (value, format_string, FALSE))
830 va_start (ap, format_string);
831 g_variant_get_va (value, format_string, NULL, &ap);
838 * g_menu_item_get_link:
839 * @menu_item: a #GMenuItem
840 * @link: the link name to query
842 * Queries the named @link on @menu_item.
844 * Returns: (transfer full): the link, or %NULL
849 g_menu_item_get_link (GMenuItem *menu_item,
854 g_return_val_if_fail (G_IS_MENU_ITEM (menu_item), NULL);
855 g_return_val_if_fail (link != NULL, NULL);
856 g_return_val_if_fail (valid_attribute_name (link), NULL);
858 model = g_hash_table_lookup (menu_item->links, link);
861 g_object_ref (model);
867 * g_menu_item_set_label:
868 * @menu_item: a #GMenuItem
869 * @label: (allow-none): the label to set, or %NULL to unset
871 * Sets or unsets the "label" attribute of @menu_item.
873 * If @label is non-%NULL it is used as the label for the menu item. If
874 * it is %NULL then the label attribute is unset.
879 g_menu_item_set_label (GMenuItem *menu_item,
885 value = g_variant_new_string (label);
889 g_menu_item_set_attribute_value (menu_item, G_MENU_ATTRIBUTE_LABEL, value);
893 * g_menu_item_set_submenu:
894 * @menu_item: a #GMenuItem
895 * @submenu: (allow-none): a #GMenuModel, or %NULL
897 * Sets or unsets the "submenu" link of @menu_item to @submenu.
899 * If @submenu is non-%NULL, it is linked to. If it is %NULL then the
902 * The effect of having one menu appear as a submenu of another is
903 * exactly as it sounds.
908 g_menu_item_set_submenu (GMenuItem *menu_item,
911 g_menu_item_set_link (menu_item, G_MENU_LINK_SUBMENU, submenu);
915 * g_menu_item_set_section:
916 * @menu_item: a #GMenuItem
917 * @section: (allow-none): a #GMenuModel, or %NULL
919 * Sets or unsets the "section" link of @menu_item to @section.
921 * The effect of having one menu appear as a section of another is
922 * exactly as it sounds: the items from @section become a direct part of
923 * the menu that @menu_item is added to. See g_menu_item_new_section()
924 * for more information about what it means for a menu item to be a
930 g_menu_item_set_section (GMenuItem *menu_item,
933 g_menu_item_set_link (menu_item, G_MENU_LINK_SECTION, section);
937 * g_menu_item_set_action_and_target_value:
938 * @menu_item: a #GMenuItem
939 * @action: (allow-none): the name of the action for this item
940 * @target_value: (allow-none): a #GVariant to use as the action target
942 * Sets or unsets the "action" and "target" attributes of @menu_item.
944 * If @action is %NULL then both the "action" and "target" attributes
945 * are unset (and @target_value is ignored).
947 * If @action is non-%NULL then the "action" attribute is set. The
948 * "target" attribute is then set to the value of @target_value if it is
949 * non-%NULL or unset otherwise.
951 * Normal menu items (ie: not submenu, section or other custom item
952 * types) are expected to have the "action" attribute set to identify
953 * the action that they are associated with. The state type of the
954 * action help to determine the disposition of the menu item. See
955 * #GAction and #GActionGroup for an overview of actions.
957 * In general, clicking on the menu item will result in activation of
958 * the named action with the "target" attribute given as the parameter
959 * to the action invocation. If the "target" attribute is not set then
960 * the action is invoked with no parameter.
962 * If the action has no state then the menu item is usually drawn as a
963 * plain menu item (ie: with no additional decoration).
965 * If the action has a boolean state then the menu item is usually drawn
966 * as a toggle menu item (ie: with a checkmark or equivalent
967 * indication). The item should be marked as 'toggled' or 'checked'
968 * when the boolean state is %TRUE.
970 * If the action has a string state then the menu item is usually drawn
971 * as a radio menu item (ie: with a radio bullet or equivalent
972 * indication). The item should be marked as 'selected' when the string
973 * state is equal to the value of the @target property.
975 * See g_menu_item_set_action_and_target() or
976 * g_menu_item_set_detailed_action() for two equivalent calls that are
977 * probably more convenient for most uses.
982 g_menu_item_set_action_and_target_value (GMenuItem *menu_item,
984 GVariant *target_value)
986 GVariant *action_value;
990 action_value = g_variant_new_string (action);
998 g_menu_item_set_attribute_value (menu_item, G_MENU_ATTRIBUTE_ACTION, action_value);
999 g_menu_item_set_attribute_value (menu_item, G_MENU_ATTRIBUTE_TARGET, target_value);
1003 * g_menu_item_set_action_and_target:
1004 * @menu_item: a #GMenuItem
1005 * @action: (allow-none): the name of the action for this item
1006 * @format_string: (allow-none): a GVariant format string
1007 * @...: positional parameters, as per @format_string
1009 * Sets or unsets the "action" and "target" attributes of @menu_item.
1011 * If @action is %NULL then both the "action" and "target" attributes
1012 * are unset (and @format_string is ignored along with the positional
1015 * If @action is non-%NULL then the "action" attribute is set.
1016 * @format_string is then inspected. If it is non-%NULL then the proper
1017 * position parameters are collected to create a #GVariant instance to
1018 * use as the target value. If it is %NULL then the positional
1019 * parameters are ignored and the "target" attribute is unset.
1021 * See also g_menu_item_set_action_and_target_value() for an equivalent
1022 * call that directly accepts a #GVariant. See
1023 * g_menu_item_set_detailed_action() for a more convenient version that
1024 * works with string-typed targets.
1026 * See also g_menu_item_set_action_and_target_value() for a
1027 * description of the semantics of the action and target attributes.
1032 g_menu_item_set_action_and_target (GMenuItem *menu_item,
1033 const gchar *action,
1034 const gchar *format_string,
1039 if (format_string != NULL)
1043 va_start (ap, format_string);
1044 value = g_variant_new_va (format_string, NULL, &ap);
1050 g_menu_item_set_action_and_target_value (menu_item, action, value);
1054 * g_menu_item_set_detailed_action:
1055 * @menu_item: a #GMenuItem
1056 * @detailed_action: the "detailed" action string
1058 * Sets the "action" and possibly the "target" attribute of @menu_item.
1060 * The format of @detailed_action is the same format parsed by
1061 * g_action_parse_detailed_name().
1063 * See g_menu_item_set_action_and_target() or
1064 * g_menu_item_set_action_and_target_value() for more flexible (but
1065 * slightly less convenient) alternatives.
1067 * See also g_menu_item_set_action_and_target_value() for a description of
1068 * the semantics of the action and target attributes.
1073 g_menu_item_set_detailed_action (GMenuItem *menu_item,
1074 const gchar *detailed_action)
1076 GError *error = NULL;
1080 if (!g_action_parse_detailed_name (detailed_action, &name, &target, &error))
1081 g_error ("g_menu_item_set_detailed_action: %s", error->message);
1083 g_menu_item_set_action_and_target_value (menu_item, name, target);
1085 g_variant_unref (target);
1091 * @label: (allow-none): the section label, or %NULL
1092 * @detailed_action: (allow-none): the detailed action string, or %NULL
1094 * Creates a new #GMenuItem.
1096 * If @label is non-%NULL it is used to set the "label" attribute of the
1099 * If @detailed_action is non-%NULL it is used to set the "action" and
1100 * possibly the "target" attribute of the new item. See
1101 * g_menu_item_set_detailed_action() for more information.
1103 * Returns: a new #GMenuItem
1108 g_menu_item_new (const gchar *label,
1109 const gchar *detailed_action)
1111 GMenuItem *menu_item;
1113 menu_item = g_object_new (G_TYPE_MENU_ITEM, NULL);
1116 g_menu_item_set_label (menu_item, label);
1118 if (detailed_action != NULL)
1119 g_menu_item_set_detailed_action (menu_item, detailed_action);
1125 * g_menu_item_new_submenu:
1126 * @label: (allow-none): the section label, or %NULL
1127 * @submenu: a #GMenuModel with the items of the submenu
1129 * Creates a new #GMenuItem representing a submenu.
1131 * This is a convenience API around g_menu_item_new() and
1132 * g_menu_item_set_submenu().
1134 * Returns: a new #GMenuItem
1139 g_menu_item_new_submenu (const gchar *label,
1140 GMenuModel *submenu)
1142 GMenuItem *menu_item;
1144 menu_item = g_object_new (G_TYPE_MENU_ITEM, NULL);
1147 g_menu_item_set_label (menu_item, label);
1149 g_menu_item_set_submenu (menu_item, submenu);
1155 * g_menu_item_new_section:
1156 * @label: (allow-none): the section label, or %NULL
1157 * @section: a #GMenuModel with the items of the section
1159 * Creates a new #GMenuItem representing a section.
1161 * This is a convenience API around g_menu_item_new() and
1162 * g_menu_item_set_section().
1164 * The effect of having one menu appear as a section of another is
1165 * exactly as it sounds: the items from @section become a direct part of
1166 * the menu that @menu_item is added to.
1168 * Visual separation is typically displayed between two non-empty
1169 * sections. If @label is non-%NULL then it will be encorporated into
1170 * this visual indication. This allows for labeled subsections of a
1173 * As a simple example, consider a typical "Edit" menu from a simple
1174 * program. It probably contains an "Undo" and "Redo" item, followed by
1175 * a separator, followed by "Cut", "Copy" and "Paste".
1177 * This would be accomplished by creating three #GMenu instances. The
1178 * first would be populated with the "Undo" and "Redo" items, and the
1179 * second with the "Cut", "Copy" and "Paste" items. The first and
1180 * second menus would then be added as submenus of the third. In XML
1181 * format, this would look something like the following:
1183 * <informalexample><programlisting><![CDATA[
1184 * <menu id='edit-menu'>
1186 * <item label='Undo'/>
1187 * <item label='Redo'/>
1190 * <item label='Cut'/>
1191 * <item label='Copy'/>
1192 * <item label='Paste'/>
1195 * ]]></programlisting></informalexample>
1197 * The following example is exactly equivalent. It is more illustrative
1198 * of the exact relationship between the menus and items (keeping in
1199 * mind that the 'link' element defines a new menu that is linked to the
1200 * containing one). The style of the second example is more verbose and
1201 * difficult to read (and therefore not recommended except for the
1202 * purpose of understanding what is really going on).
1204 * <informalexample><programlisting><![CDATA[
1205 * <menu id='edit-menu'>
1207 * <link name='section'>
1208 * <item label='Undo'/>
1209 * <item label='Redo'/>
1213 * <link name='section'>
1214 * <item label='Cut'/>
1215 * <item label='Copy'/>
1216 * <item label='Paste'/>
1220 * ]]></programlisting></informalexample>
1222 * Returns: a new #GMenuItem
1227 g_menu_item_new_section (const gchar *label,
1228 GMenuModel *section)
1230 GMenuItem *menu_item;
1232 menu_item = g_object_new (G_TYPE_MENU_ITEM, NULL);
1235 g_menu_item_set_label (menu_item, label);
1237 g_menu_item_set_section (menu_item, section);
1243 * g_menu_item_new_from_model:
1244 * @model: a #GMenuModel
1245 * @item_index: the index of an item in @model
1247 * Creates a #GMenuItem as an exact copy of an existing menu item in a
1250 * @item_index must be valid (ie: be sure to call
1251 * g_menu_model_get_n_items() first).
1253 * Returns: a new #GMenuItem.
1258 g_menu_item_new_from_model (GMenuModel *model,
1261 GMenuModelClass *class = G_MENU_MODEL_GET_CLASS (model);
1262 GMenuItem *menu_item;
1264 menu_item = g_object_new (G_TYPE_MENU_ITEM, NULL);
1266 /* With some trickery we can be pretty efficient.
1268 * A GMenuModel must either implement iterate_item_attributes() or
1269 * get_item_attributes(). If it implements get_item_attributes() then
1270 * we are in luck -- we can just take a reference on the returned
1271 * hashtable and mark ourselves as copy-on-write.
1273 * In the case that the model is based on get_item_attributes (which
1274 * is the case for both GMenu and GDBusMenuModel) then this is
1275 * basically just g_hash_table_ref().
1277 if (class->get_item_attributes)
1279 GHashTable *attributes = NULL;
1281 class->get_item_attributes (model, item_index, &attributes);
1284 g_hash_table_unref (menu_item->attributes);
1285 menu_item->attributes = attributes;
1286 menu_item->cow = TRUE;
1291 GMenuAttributeIter *iter;
1292 const gchar *attribute;
1295 iter = g_menu_model_iterate_item_attributes (model, item_index);
1296 while (g_menu_attribute_iter_get_next (iter, &attribute, &value))
1297 g_hash_table_insert (menu_item->attributes, g_strdup (attribute), value);
1298 g_object_unref (iter);
1301 /* Same story for the links... */
1302 if (class->get_item_links)
1304 GHashTable *links = NULL;
1306 class->get_item_links (model, item_index, &links);
1309 g_hash_table_unref (menu_item->links);
1310 menu_item->links = links;
1311 menu_item->cow = TRUE;
1316 GMenuLinkIter *iter;
1320 iter = g_menu_model_iterate_item_links (model, item_index);
1321 while (g_menu_link_iter_get_next (iter, &link, &value))
1322 g_hash_table_insert (menu_item->links, g_strdup (link), value);
1323 g_object_unref (iter);