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>
34 * @short_description: A simple implementation of GMenuModel
37 * #GMenu is a simple implementation of #GMenuModel.
38 * You populate a #GMenu by adding #GMenuItem instances to it.
40 * There are some convenience functions to allow you to directly
41 * add items (avoiding #GMenuItem) for the common cases. To add
42 * a regular item, use g_menu_insert(). To add a section, use
43 * g_menu_insert_section(). To add a submenu, use
44 * g_menu_insert_submenu().
50 * #GMenu is an opaque structure type. You must access it using the
59 * #GMenuItem is an opaque structure type. You must access it using the
67 GObject parent_instance;
69 GHashTable *attributes;
74 typedef GObjectClass GMenuItemClass;
78 GMenuModel parent_instance;
84 typedef GMenuModelClass GMenuClass;
86 G_DEFINE_TYPE (GMenu, g_menu, G_TYPE_MENU_MODEL)
87 G_DEFINE_TYPE (GMenuItem, g_menu_item, G_TYPE_OBJECT)
91 GHashTable *attributes;
96 g_menu_is_mutable (GMenuModel *model)
98 GMenu *menu = G_MENU (model);
100 return menu->mutable;
104 g_menu_get_n_items (GMenuModel *model)
106 GMenu *menu = G_MENU (model);
108 return menu->items->len;
112 g_menu_get_item_attributes (GMenuModel *model,
116 GMenu *menu = G_MENU (model);
118 *table = g_hash_table_ref (g_array_index (menu->items, struct item, position).attributes);
122 g_menu_get_item_links (GMenuModel *model,
126 GMenu *menu = G_MENU (model);
128 *table = g_hash_table_ref (g_array_index (menu->items, struct item, position).links);
132 * g_menu_insert_item:
134 * @position: the position at which to insert the item
135 * @item: the #GMenuItem to insert
137 * Inserts @item into @menu.
139 * The "insertion" is actually done by copying all of the attribute and
140 * link values of @item and using them to form a new item within @menu.
141 * As such, @item itself is not really inserted, but rather, a menu item
142 * that is exactly the same as the one presently described by @item.
144 * This means that @item is essentially useless after the insertion
145 * occurs. Any changes you make to it are ignored unless it is inserted
146 * again (at which point its updated values will be copied).
148 * You should probably just free @item once you're done.
150 * There are many convenience functions to take care of common cases.
151 * See g_menu_insert(), g_menu_insert_section() and
152 * g_menu_insert_submenu() as well as "prepend" and "append" variants of
153 * each of these functions.
158 g_menu_insert_item (GMenu *menu,
162 struct item new_item;
164 g_return_if_fail (G_IS_MENU (menu));
165 g_return_if_fail (G_IS_MENU_ITEM (item));
167 if (position < 0 || position > menu->items->len)
168 position = menu->items->len;
170 new_item.attributes = g_hash_table_ref (item->attributes);
171 new_item.links = g_hash_table_ref (item->links);
174 g_array_insert_val (menu->items, position, new_item);
175 g_menu_model_items_changed (G_MENU_MODEL (menu), position, 0, 1);
179 * g_menu_prepend_item:
181 * @item: a #GMenuItem to prepend
183 * Prepends @item to the start of @menu.
185 * See g_menu_insert_item() for more information.
190 g_menu_prepend_item (GMenu *menu,
193 g_menu_insert_item (menu, 0, item);
197 * g_menu_append_item:
199 * @item: a #GMenuItem to append
201 * Appends @item to the end of @menu.
203 * See g_menu_insert_item() for more information.
208 g_menu_append_item (GMenu *menu,
211 g_menu_insert_item (menu, -1, item);
218 * Marks @menu as frozen.
220 * After the menu is frozen, it is an error to attempt to make any
221 * changes to it. In effect this means that the #GMenu API must no
224 * This function causes g_menu_model_is_mutable() to begin returning
225 * %FALSE, which has some positive performance implications.
230 g_menu_freeze (GMenu *menu)
232 g_return_if_fail (G_IS_MENU (menu));
234 menu->mutable = FALSE;
240 * Creates a new #GMenu.
242 * The new menu has no items.
244 * Returns: a new #GMenu
251 return g_object_new (G_TYPE_MENU, NULL);
257 * @position: the position at which to insert the item
258 * @label: (allow-none): the section label, or %NULL
259 * @detailed_action: (allow-none): the detailed action string, or %NULL
261 * Convenience function for inserting a normal menu item into @menu.
262 * Combine g_menu_item_new() and g_menu_insert_item() for a more flexible
268 g_menu_insert (GMenu *menu,
271 const gchar *detailed_action)
273 GMenuItem *menu_item;
275 menu_item = g_menu_item_new (label, detailed_action);
276 g_menu_insert_item (menu, position, menu_item);
277 g_object_unref (menu_item);
283 * @label: (allow-none): the section label, or %NULL
284 * @detailed_action: (allow-none): the detailed action string, or %NULL
286 * Convenience function for prepending a normal menu item to the start
287 * of @menu. Combine g_menu_item_new() and g_menu_insert_item() for a more
288 * flexible alternative.
293 g_menu_prepend (GMenu *menu,
295 const gchar *detailed_action)
297 g_menu_insert (menu, 0, label, detailed_action);
303 * @label: (allow-none): the section label, or %NULL
304 * @detailed_action: (allow-none): the detailed action string, or %NULL
306 * Convenience function for appending a normal menu item to the end of
307 * @menu. Combine g_menu_item_new() and g_menu_insert_item() for a more
308 * flexible alternative.
313 g_menu_append (GMenu *menu,
315 const gchar *detailed_action)
317 g_menu_insert (menu, -1, label, detailed_action);
321 * g_menu_insert_section:
323 * @position: the position at which to insert the item
324 * @label: (allow-none): the section label, or %NULL
325 * @section: a #GMenuModel with the items of the section
327 * Convenience function for inserting a section menu item into @menu.
328 * Combine g_menu_item_new_section() and g_menu_insert_item() for a more
329 * flexible alternative.
334 g_menu_insert_section (GMenu *menu,
339 GMenuItem *menu_item;
341 menu_item = g_menu_item_new_section (label, section);
342 g_menu_insert_item (menu, position, menu_item);
343 g_object_unref (menu_item);
348 * g_menu_prepend_section:
350 * @label: (allow-none): the section label, or %NULL
351 * @section: a #GMenuModel with the items of the section
353 * Convenience function for prepending a section menu item to the start
354 * of @menu. Combine g_menu_item_new_section() and g_menu_insert_item() for
355 * a more flexible alternative.
360 g_menu_prepend_section (GMenu *menu,
364 g_menu_insert_section (menu, 0, label, section);
368 * g_menu_append_section:
370 * @label: (allow-none): the section label, or %NULL
371 * @section: a #GMenuModel with the items of the section
373 * Convenience function for appending a section menu item to the end of
374 * @menu. Combine g_menu_item_new_section() and g_menu_insert_item() for a
375 * more flexible alternative.
380 g_menu_append_section (GMenu *menu,
384 g_menu_insert_section (menu, -1, label, section);
388 * g_menu_insert_submenu:
390 * @position: the position at which to insert the item
391 * @label: (allow-none): the section label, or %NULL
392 * @submenu: a #GMenuModel with the items of the submenu
394 * Convenience function for inserting a submenu menu item into @menu.
395 * Combine g_menu_item_new_submenu() and g_menu_insert_item() for a more
396 * flexible alternative.
401 g_menu_insert_submenu (GMenu *menu,
406 GMenuItem *menu_item;
408 menu_item = g_menu_item_new_submenu (label, submenu);
409 g_menu_insert_item (menu, position, menu_item);
410 g_object_unref (menu_item);
414 * g_menu_prepend_submenu:
416 * @label: (allow-none): the section label, or %NULL
417 * @submenu: a #GMenuModel with the items of the submenu
419 * Convenience function for prepending a submenu menu item to the start
420 * of @menu. Combine g_menu_item_new_submenu() and g_menu_insert_item() for
421 * a more flexible alternative.
426 g_menu_prepend_submenu (GMenu *menu,
430 g_menu_insert_submenu (menu, 0, label, submenu);
434 * g_menu_append_submenu:
436 * @label: (allow-none): the section label, or %NULL
437 * @submenu: a #GMenuModel with the items of the submenu
439 * Convenience function for appending a submenu menu item to the end of
440 * @menu. Combine g_menu_item_new_submenu() and g_menu_insert_item() for a
441 * more flexible alternative.
446 g_menu_append_submenu (GMenu *menu,
450 g_menu_insert_submenu (menu, -1, label, submenu);
454 g_menu_clear_item (struct item *item)
456 if (item->attributes != NULL)
457 g_hash_table_unref (item->attributes);
458 if (item->links != NULL)
459 g_hash_table_unref (item->links);
465 * @position: the position of the item to remove
467 * Removes an item from the menu.
469 * @position gives the index of the item to remove.
471 * It is an error if position is not in range the range from 0 to one
472 * less than the number of items in the menu.
474 * It is not possible to remove items by identity since items are added
475 * to the menu simply by copying their links and attributes (ie:
476 * identity of the item itself is not preserved).
481 g_menu_remove (GMenu *menu,
484 g_return_if_fail (G_IS_MENU (menu));
485 g_return_if_fail (0 <= position && position < menu->items->len);
487 g_menu_clear_item (&g_array_index (menu->items, struct item, position));
488 g_array_remove_index (menu->items, position);
489 g_menu_model_items_changed (G_MENU_MODEL (menu), position, 1, 0);
496 * Removes all items in the menu.
501 g_menu_remove_all (GMenu *menu)
505 g_return_if_fail (G_IS_MENU (menu));
506 n = menu->items->len;
508 for (i = 0; i < n; i++)
509 g_menu_clear_item (&g_array_index (menu->items, struct item, i));
510 g_array_set_size (menu->items, 0);
512 g_menu_model_items_changed (G_MENU_MODEL (menu), 0, n, 0);
516 g_menu_finalize (GObject *object)
518 GMenu *menu = G_MENU (object);
523 n_items = menu->items->len;
524 items = (struct item *) g_array_free (menu->items, FALSE);
525 for (i = 0; i < n_items; i++)
526 g_menu_clear_item (&items[i]);
529 G_OBJECT_CLASS (g_menu_parent_class)
534 g_menu_init (GMenu *menu)
536 menu->items = g_array_new (FALSE, FALSE, sizeof (struct item));
537 menu->mutable = TRUE;
541 g_menu_class_init (GMenuClass *class)
543 GMenuModelClass *model_class = G_MENU_MODEL_CLASS (class);
544 GObjectClass *object_class = G_OBJECT_CLASS (class);
546 object_class->finalize = g_menu_finalize;
548 model_class->is_mutable = g_menu_is_mutable;
549 model_class->get_n_items = g_menu_get_n_items;
550 model_class->get_item_attributes = g_menu_get_item_attributes;
551 model_class->get_item_links = g_menu_get_item_links;
556 g_menu_item_clear_cow (GMenuItem *menu_item)
565 new = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_variant_unref);
566 g_hash_table_iter_init (&iter, menu_item->attributes);
567 while (g_hash_table_iter_next (&iter, &key, &val))
568 g_hash_table_insert (new, g_strdup (key), g_variant_ref (val));
569 g_hash_table_unref (menu_item->attributes);
570 menu_item->attributes = new;
572 new = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_object_unref);
573 g_hash_table_iter_init (&iter, menu_item->links);
574 while (g_hash_table_iter_next (&iter, &key, &val))
575 g_hash_table_insert (new, g_strdup (key), g_object_ref (val));
576 g_hash_table_unref (menu_item->links);
577 menu_item->links = new;
579 menu_item->cow = FALSE;
584 g_menu_item_finalize (GObject *object)
586 GMenuItem *menu_item = G_MENU_ITEM (object);
588 g_hash_table_unref (menu_item->attributes);
589 g_hash_table_unref (menu_item->links);
591 G_OBJECT_CLASS (g_menu_item_parent_class)
596 g_menu_item_init (GMenuItem *menu_item)
598 menu_item->attributes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_variant_unref);
599 menu_item->links = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
600 menu_item->cow = FALSE;
604 g_menu_item_class_init (GMenuItemClass *class)
606 class->finalize = g_menu_item_finalize;
609 /* We treat attribute names the same as GSettings keys:
610 * - only lowercase ascii, digits and '-'
611 * - must start with lowercase
612 * - must not end with '-'
613 * - no consecutive '-'
614 * - not longer than 1024 chars
617 valid_attribute_name (const gchar *name)
621 if (!g_ascii_islower (name[0]))
624 for (i = 1; name[i]; i++)
626 if (name[i] != '-' &&
627 !g_ascii_islower (name[i]) &&
628 !g_ascii_isdigit (name[i]))
631 if (name[i] == '-' && name[i + 1] == '-')
635 if (name[i - 1] == '-')
645 * g_menu_item_set_attribute_value:
646 * @menu_item: a #GMenuItem
647 * @attribute: the attribute to set
648 * @value: (allow-none): a #GVariant to use as the value, or %NULL
650 * Sets or unsets an attribute on @menu_item.
652 * The attribute to set or unset is specified by @attribute. This
653 * can be one of the standard attribute names %G_MENU_ATTRIBUTE_LABEL,
654 * %G_MENU_ATTRIBUTE_ACTION, %G_MENU_ATTRIBUTE_TARGET, or a custom
656 * Attribute names are restricted to lowercase characters, numbers
657 * and '-'. Furthermore, the names must begin with a lowercase character,
658 * must not end with a '-', and must not contain consecutive dashes.
660 * must consist only of lowercase
661 * ASCII characters, digits and '-'.
663 * If @value is non-%NULL then it is used as the new value for the
664 * attribute. If @value is %NULL then the attribute is unset. If
665 * the @value #GVariant is floating, it is consumed.
667 * See also g_menu_item_set_attribute() for a more convenient way to do
673 g_menu_item_set_attribute_value (GMenuItem *menu_item,
674 const gchar *attribute,
677 g_return_if_fail (G_IS_MENU_ITEM (menu_item));
678 g_return_if_fail (attribute != NULL);
679 g_return_if_fail (valid_attribute_name (attribute));
681 g_menu_item_clear_cow (menu_item);
684 g_hash_table_insert (menu_item->attributes, g_strdup (attribute), g_variant_ref_sink (value));
686 g_hash_table_remove (menu_item->attributes, attribute);
690 * g_menu_item_set_attribute:
691 * @menu_item: a #GMenuItem
692 * @attribute: the attribute to set
693 * @format_string: (allow-none): a #GVariant format string, or %NULL
694 * @...: positional parameters, as per @format_string
696 * Sets or unsets an attribute on @menu_item.
698 * The attribute to set or unset is specified by @attribute. This
699 * can be one of the standard attribute names %G_MENU_ATTRIBUTE_LABEL,
700 * %G_MENU_ATTRIBUTE_ACTION, %G_MENU_ATTRIBUTE_TARGET, or a custom
702 * Attribute names are restricted to lowercase characters, numbers
703 * and '-'. Furthermore, the names must begin with a lowercase character,
704 * must not end with a '-', and must not contain consecutive dashes.
706 * If @format_string is non-%NULL then the proper position parameters
707 * are collected to create a #GVariant instance to use as the attribute
708 * value. If it is %NULL then the positional parameterrs are ignored
709 * and the named attribute is unset.
711 * See also g_menu_item_set_attribute_value() for an equivalent call
712 * that directly accepts a #GVariant.
717 g_menu_item_set_attribute (GMenuItem *menu_item,
718 const gchar *attribute,
719 const gchar *format_string,
724 if (format_string != NULL)
728 va_start (ap, format_string);
729 value = g_variant_new_va (format_string, NULL, &ap);
735 g_menu_item_set_attribute_value (menu_item, attribute, value);
739 * g_menu_item_set_link:
740 * @menu_item: a #GMenuItem
741 * @link: type of link to establish or unset
742 * @model: (allow-none): the #GMenuModel to link to (or %NULL to unset)
744 * Creates a link from @menu_item to @model if non-%NULL, or unsets it.
746 * Links are used to establish a relationship between a particular menu
747 * item and another menu. For example, %G_MENU_LINK_SUBMENU is used to
748 * associate a submenu with a particular menu item, and %G_MENU_LINK_SECTION
749 * is used to create a section. Other types of link can be used, but there
750 * is no guarantee that clients will be able to make sense of them.
751 * Link types are restricted to lowercase characters, numbers
752 * and '-'. Furthermore, the names must begin with a lowercase character,
753 * must not end with a '-', and must not contain consecutive dashes.
758 g_menu_item_set_link (GMenuItem *menu_item,
762 g_return_if_fail (G_IS_MENU_ITEM (menu_item));
763 g_return_if_fail (link != NULL);
764 g_return_if_fail (valid_attribute_name (link));
766 g_menu_item_clear_cow (menu_item);
769 g_hash_table_insert (menu_item->links, g_strdup (link), g_object_ref (model));
771 g_hash_table_remove (menu_item->links, link);
775 * g_menu_item_get_attribute_value:
776 * @menu_item: a #GMenuItem
777 * @attribute: the attribute name to query
778 * @expected_type: (allow-none): the expected type of the attribute
780 * Queries the named @attribute on @menu_item.
782 * If @expected_type is specified and the attribute does not have this
783 * type, %NULL is returned. %NULL is also returned if the attribute
784 * simply does not exist.
786 * Returns: (transfer full): the attribute value, or %NULL
791 g_menu_item_get_attribute_value (GMenuItem *menu_item,
792 const gchar *attribute,
793 const GVariantType *expected_type)
797 g_return_val_if_fail (G_IS_MENU_ITEM (menu_item), NULL);
798 g_return_val_if_fail (attribute != NULL, NULL);
800 value = g_hash_table_lookup (menu_item->attributes, attribute);
804 if (expected_type == NULL || g_variant_is_of_type (value, expected_type))
805 g_variant_ref (value);
814 * g_menu_item_get_attribute:
815 * @menu_item: a #GMenuItem
816 * @attribute: the attribute name to query
817 * @format_string: a #GVariant format string
818 * @...: positional parameters, as per @format_string
820 * Queries the named @attribute on @menu_item.
822 * If the attribute exists and matches the #GVariantType corresponding
823 * to @format_string then @format_string is used to deconstruct the
824 * value into the positional parameters and %TRUE is returned.
826 * If the attribute does not exist, or it does exist but has the wrong
827 * type, then the positional parameters are ignored and %FALSE is
830 * Returns: %TRUE if the named attribute was found with the expected
836 g_menu_item_get_attribute (GMenuItem *menu_item,
837 const gchar *attribute,
838 const gchar *format_string,
844 g_return_val_if_fail (G_IS_MENU_ITEM (menu_item), FALSE);
845 g_return_val_if_fail (attribute != NULL, FALSE);
846 g_return_val_if_fail (format_string != NULL, FALSE);
848 value = g_hash_table_lookup (menu_item->attributes, attribute);
853 if (!g_variant_check_format_string (value, format_string, FALSE))
856 va_start (ap, format_string);
857 g_variant_get_va (value, format_string, NULL, &ap);
864 * g_menu_item_get_link:
865 * @menu_item: a #GMenuItem
866 * @link: the link name to query
868 * Queries the named @link on @menu_item.
870 * Returns: (transfer full): the link, or %NULL
875 g_menu_item_get_link (GMenuItem *menu_item,
880 g_return_val_if_fail (G_IS_MENU_ITEM (menu_item), NULL);
881 g_return_val_if_fail (link != NULL, NULL);
882 g_return_val_if_fail (valid_attribute_name (link), NULL);
884 model = g_hash_table_lookup (menu_item->links, link);
887 g_object_ref (model);
893 * g_menu_item_set_label:
894 * @menu_item: a #GMenuItem
895 * @label: (allow-none): the label to set, or %NULL to unset
897 * Sets or unsets the "label" attribute of @menu_item.
899 * If @label is non-%NULL it is used as the label for the menu item. If
900 * it is %NULL then the label attribute is unset.
905 g_menu_item_set_label (GMenuItem *menu_item,
911 value = g_variant_new_string (label);
915 g_menu_item_set_attribute_value (menu_item, G_MENU_ATTRIBUTE_LABEL, value);
919 * g_menu_item_set_submenu:
920 * @menu_item: a #GMenuItem
921 * @submenu: (allow-none): a #GMenuModel, or %NULL
923 * Sets or unsets the "submenu" link of @menu_item to @submenu.
925 * If @submenu is non-%NULL, it is linked to. If it is %NULL then the
928 * The effect of having one menu appear as a submenu of another is
929 * exactly as it sounds.
934 g_menu_item_set_submenu (GMenuItem *menu_item,
937 g_menu_item_set_link (menu_item, G_MENU_LINK_SUBMENU, submenu);
941 * g_menu_item_set_section:
942 * @menu_item: a #GMenuItem
943 * @section: (allow-none): a #GMenuModel, or %NULL
945 * Sets or unsets the "section" link of @menu_item to @section.
947 * The effect of having one menu appear as a section of another is
948 * exactly as it sounds: the items from @section become a direct part of
949 * the menu that @menu_item is added to. See g_menu_item_new_section()
950 * for more information about what it means for a menu item to be a
956 g_menu_item_set_section (GMenuItem *menu_item,
959 g_menu_item_set_link (menu_item, G_MENU_LINK_SECTION, section);
963 * g_menu_item_set_action_and_target_value:
964 * @menu_item: a #GMenuItem
965 * @action: (allow-none): the name of the action for this item
966 * @target_value: (allow-none): a #GVariant to use as the action target
968 * Sets or unsets the "action" and "target" attributes of @menu_item.
970 * If @action is %NULL then both the "action" and "target" attributes
971 * are unset (and @target_value is ignored).
973 * If @action is non-%NULL then the "action" attribute is set. The
974 * "target" attribute is then set to the value of @target_value if it is
975 * non-%NULL or unset otherwise.
977 * Normal menu items (ie: not submenu, section or other custom item
978 * types) are expected to have the "action" attribute set to identify
979 * the action that they are associated with. The state type of the
980 * action help to determine the disposition of the menu item. See
981 * #GAction and #GActionGroup for an overview of actions.
983 * In general, clicking on the menu item will result in activation of
984 * the named action with the "target" attribute given as the parameter
985 * to the action invocation. If the "target" attribute is not set then
986 * the action is invoked with no parameter.
988 * If the action has no state then the menu item is usually drawn as a
989 * plain menu item (ie: with no additional decoration).
991 * If the action has a boolean state then the menu item is usually drawn
992 * as a toggle menu item (ie: with a checkmark or equivalent
993 * indication). The item should be marked as 'toggled' or 'checked'
994 * when the boolean state is %TRUE.
996 * If the action has a string state then the menu item is usually drawn
997 * as a radio menu item (ie: with a radio bullet or equivalent
998 * indication). The item should be marked as 'selected' when the string
999 * state is equal to the value of the @target property.
1001 * See g_menu_item_set_action_and_target() or
1002 * g_menu_item_set_detailed_action() for two equivalent calls that are
1003 * probably more convenient for most uses.
1008 g_menu_item_set_action_and_target_value (GMenuItem *menu_item,
1009 const gchar *action,
1010 GVariant *target_value)
1012 GVariant *action_value;
1016 action_value = g_variant_new_string (action);
1020 action_value = NULL;
1021 target_value = NULL;
1024 g_menu_item_set_attribute_value (menu_item, G_MENU_ATTRIBUTE_ACTION, action_value);
1025 g_menu_item_set_attribute_value (menu_item, G_MENU_ATTRIBUTE_TARGET, target_value);
1029 * g_menu_item_set_action_and_target:
1030 * @menu_item: a #GMenuItem
1031 * @action: (allow-none): the name of the action for this item
1032 * @format_string: (allow-none): a GVariant format string
1033 * @...: positional parameters, as per @format_string
1035 * Sets or unsets the "action" and "target" attributes of @menu_item.
1037 * If @action is %NULL then both the "action" and "target" attributes
1038 * are unset (and @format_string is ignored along with the positional
1041 * If @action is non-%NULL then the "action" attribute is set.
1042 * @format_string is then inspected. If it is non-%NULL then the proper
1043 * position parameters are collected to create a #GVariant instance to
1044 * use as the target value. If it is %NULL then the positional
1045 * parameters are ignored and the "target" attribute is unset.
1047 * See also g_menu_item_set_action_and_target_value() for an equivalent
1048 * call that directly accepts a #GVariant. See
1049 * g_menu_item_set_detailed_action() for a more convenient version that
1050 * works with string-typed targets.
1052 * See also g_menu_item_set_action_and_target_value() for a
1053 * description of the semantics of the action and target attributes.
1058 g_menu_item_set_action_and_target (GMenuItem *menu_item,
1059 const gchar *action,
1060 const gchar *format_string,
1065 if (format_string != NULL)
1069 va_start (ap, format_string);
1070 value = g_variant_new_va (format_string, NULL, &ap);
1076 g_menu_item_set_action_and_target_value (menu_item, action, value);
1080 * g_menu_item_set_detailed_action:
1081 * @menu_item: a #GMenuItem
1082 * @detailed_action: the "detailed" action string
1084 * Sets the "action" and possibly the "target" attribute of @menu_item.
1086 * The format of @detailed_action is the same format parsed by
1087 * g_action_parse_detailed_name().
1089 * See g_menu_item_set_action_and_target() or
1090 * g_menu_item_set_action_and_target_value() for more flexible (but
1091 * slightly less convenient) alternatives.
1093 * See also g_menu_item_set_action_and_target_value() for a description of
1094 * the semantics of the action and target attributes.
1099 g_menu_item_set_detailed_action (GMenuItem *menu_item,
1100 const gchar *detailed_action)
1102 GError *error = NULL;
1106 if (!g_action_parse_detailed_name (detailed_action, &name, &target, &error))
1107 g_error ("g_menu_item_set_detailed_action: %s", error->message);
1109 g_menu_item_set_action_and_target_value (menu_item, name, target);
1111 g_variant_unref (target);
1117 * @label: (allow-none): the section label, or %NULL
1118 * @detailed_action: (allow-none): the detailed action string, or %NULL
1120 * Creates a new #GMenuItem.
1122 * If @label is non-%NULL it is used to set the "label" attribute of the
1125 * If @detailed_action is non-%NULL it is used to set the "action" and
1126 * possibly the "target" attribute of the new item. See
1127 * g_menu_item_set_detailed_action() for more information.
1129 * Returns: a new #GMenuItem
1134 g_menu_item_new (const gchar *label,
1135 const gchar *detailed_action)
1137 GMenuItem *menu_item;
1139 menu_item = g_object_new (G_TYPE_MENU_ITEM, NULL);
1142 g_menu_item_set_label (menu_item, label);
1144 if (detailed_action != NULL)
1145 g_menu_item_set_detailed_action (menu_item, detailed_action);
1151 * g_menu_item_new_submenu:
1152 * @label: (allow-none): the section label, or %NULL
1153 * @submenu: a #GMenuModel with the items of the submenu
1155 * Creates a new #GMenuItem representing a submenu.
1157 * This is a convenience API around g_menu_item_new() and
1158 * g_menu_item_set_submenu().
1160 * Returns: a new #GMenuItem
1165 g_menu_item_new_submenu (const gchar *label,
1166 GMenuModel *submenu)
1168 GMenuItem *menu_item;
1170 menu_item = g_object_new (G_TYPE_MENU_ITEM, NULL);
1173 g_menu_item_set_label (menu_item, label);
1175 g_menu_item_set_submenu (menu_item, submenu);
1181 * g_menu_item_new_section:
1182 * @label: (allow-none): the section label, or %NULL
1183 * @section: a #GMenuModel with the items of the section
1185 * Creates a new #GMenuItem representing a section.
1187 * This is a convenience API around g_menu_item_new() and
1188 * g_menu_item_set_section().
1190 * The effect of having one menu appear as a section of another is
1191 * exactly as it sounds: the items from @section become a direct part of
1192 * the menu that @menu_item is added to.
1194 * Visual separation is typically displayed between two non-empty
1195 * sections. If @label is non-%NULL then it will be encorporated into
1196 * this visual indication. This allows for labeled subsections of a
1199 * As a simple example, consider a typical "Edit" menu from a simple
1200 * program. It probably contains an "Undo" and "Redo" item, followed by
1201 * a separator, followed by "Cut", "Copy" and "Paste".
1203 * This would be accomplished by creating three #GMenu instances. The
1204 * first would be populated with the "Undo" and "Redo" items, and the
1205 * second with the "Cut", "Copy" and "Paste" items. The first and
1206 * second menus would then be added as submenus of the third. In XML
1207 * format, this would look something like the following:
1209 * <informalexample><programlisting><![CDATA[
1210 * <menu id='edit-menu'>
1212 * <item label='Undo'/>
1213 * <item label='Redo'/>
1216 * <item label='Cut'/>
1217 * <item label='Copy'/>
1218 * <item label='Paste'/>
1221 * ]]></programlisting></informalexample>
1223 * The following example is exactly equivalent. It is more illustrative
1224 * of the exact relationship between the menus and items (keeping in
1225 * mind that the 'link' element defines a new menu that is linked to the
1226 * containing one). The style of the second example is more verbose and
1227 * difficult to read (and therefore not recommended except for the
1228 * purpose of understanding what is really going on).
1230 * <informalexample><programlisting><![CDATA[
1231 * <menu id='edit-menu'>
1233 * <link name='section'>
1234 * <item label='Undo'/>
1235 * <item label='Redo'/>
1239 * <link name='section'>
1240 * <item label='Cut'/>
1241 * <item label='Copy'/>
1242 * <item label='Paste'/>
1246 * ]]></programlisting></informalexample>
1248 * Returns: a new #GMenuItem
1253 g_menu_item_new_section (const gchar *label,
1254 GMenuModel *section)
1256 GMenuItem *menu_item;
1258 menu_item = g_object_new (G_TYPE_MENU_ITEM, NULL);
1261 g_menu_item_set_label (menu_item, label);
1263 g_menu_item_set_section (menu_item, section);
1269 * g_menu_item_new_from_model:
1270 * @model: a #GMenuModel
1271 * @item_index: the index of an item in @model
1273 * Creates a #GMenuItem as an exact copy of an existing menu item in a
1276 * @item_index must be valid (ie: be sure to call
1277 * g_menu_model_get_n_items() first).
1279 * Returns: a new #GMenuItem.
1284 g_menu_item_new_from_model (GMenuModel *model,
1287 GMenuModelClass *class = G_MENU_MODEL_GET_CLASS (model);
1288 GMenuItem *menu_item;
1290 menu_item = g_object_new (G_TYPE_MENU_ITEM, NULL);
1292 /* With some trickery we can be pretty efficient.
1294 * A GMenuModel must either implement iterate_item_attributes() or
1295 * get_item_attributes(). If it implements get_item_attributes() then
1296 * we are in luck -- we can just take a reference on the returned
1297 * hashtable and mark ourselves as copy-on-write.
1299 * In the case that the model is based on get_item_attributes (which
1300 * is the case for both GMenu and GDBusMenuModel) then this is
1301 * basically just g_hash_table_ref().
1303 if (class->get_item_attributes)
1305 GHashTable *attributes = NULL;
1307 class->get_item_attributes (model, item_index, &attributes);
1310 g_hash_table_unref (menu_item->attributes);
1311 menu_item->attributes = attributes;
1312 menu_item->cow = TRUE;
1317 GMenuAttributeIter *iter;
1318 const gchar *attribute;
1321 iter = g_menu_model_iterate_item_attributes (model, item_index);
1322 while (g_menu_attribute_iter_get_next (iter, &attribute, &value))
1323 g_hash_table_insert (menu_item->attributes, g_strdup (attribute), value);
1324 g_object_unref (iter);
1327 /* Same story for the links... */
1328 if (class->get_item_links)
1330 GHashTable *links = NULL;
1332 class->get_item_links (model, item_index, &links);
1335 g_hash_table_unref (menu_item->links);
1336 menu_item->links = links;
1337 menu_item->cow = TRUE;
1342 GMenuLinkIter *iter;
1346 iter = g_menu_model_iterate_item_links (model, item_index);
1347 while (g_menu_link_iter_get_next (iter, &link, &value))
1348 g_hash_table_insert (menu_item->links, g_strdup (link), value);
1349 g_object_unref (iter);
1356 * g_menu_item_set_icon:
1357 * @menu_item: a #GMenuItem
1358 * @icon: a #GIcon, or %NULL
1360 * Sets (or unsets) the icon on @menu_item.
1362 * This call is the same as calling g_icon_serialize() and using the
1363 * result as the value to g_menu_item_set_attribute_value() for
1364 * %G_MENU_ATTRIBUTE_ICON.
1366 * This API is only intended for use with "noun" menu items; things like
1367 * bookmarks or applications in an "Open With" menu. Don't use it on
1368 * menu items corresponding to verbs (eg: stock icons for 'Save' or
1371 * If @icon is %NULL then the icon is unset.
1376 g_menu_item_set_icon (GMenuItem *menu_item,
1381 g_return_if_fail (G_IS_MENU_ITEM (menu_item));
1382 g_return_if_fail (G_IS_ICON (icon));
1385 value = g_icon_serialize (icon);
1389 g_menu_item_set_attribute_value (menu_item, G_MENU_ATTRIBUTE_ICON, value);
1391 g_variant_unref (value);