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, see <http://www.gnu.org/licenses/>.
17 * Author: Ryan Lortie <desrt@desrt.ca>
32 * @short_description: A simple implementation of GMenuModel
35 * #GMenu is a simple implementation of #GMenuModel.
36 * You populate a #GMenu by adding #GMenuItem instances to it.
38 * There are some convenience functions to allow you to directly
39 * add items (avoiding #GMenuItem) for the common cases. To add
40 * a regular item, use g_menu_insert(). To add a section, use
41 * g_menu_insert_section(). To add a submenu, use
42 * g_menu_insert_submenu().
48 * #GMenu is an opaque structure type. You must access it using the
57 * #GMenuItem is an opaque structure type. You must access it using the
65 GObject parent_instance
;
67 GHashTable
*attributes
;
72 typedef GObjectClass GMenuItemClass
;
76 GMenuModel parent_instance
;
82 typedef GMenuModelClass GMenuClass
;
84 G_DEFINE_TYPE (GMenu
, g_menu
, G_TYPE_MENU_MODEL
)
85 G_DEFINE_TYPE (GMenuItem
, g_menu_item
, G_TYPE_OBJECT
)
89 GHashTable
*attributes
;
94 g_menu_is_mutable (GMenuModel
*model
)
96 GMenu
*menu
= G_MENU (model
);
102 g_menu_get_n_items (GMenuModel
*model
)
104 GMenu
*menu
= G_MENU (model
);
106 return menu
->items
->len
;
110 g_menu_get_item_attributes (GMenuModel
*model
,
114 GMenu
*menu
= G_MENU (model
);
116 *table
= g_hash_table_ref (g_array_index (menu
->items
, struct item
, position
).attributes
);
120 g_menu_get_item_links (GMenuModel
*model
,
124 GMenu
*menu
= G_MENU (model
);
126 *table
= g_hash_table_ref (g_array_index (menu
->items
, struct item
, position
).links
);
130 * g_menu_insert_item:
132 * @position: the position at which to insert the item
133 * @item: the #GMenuItem to insert
135 * Inserts @item into @menu.
137 * The "insertion" is actually done by copying all of the attribute and
138 * link values of @item and using them to form a new item within @menu.
139 * As such, @item itself is not really inserted, but rather, a menu item
140 * that is exactly the same as the one presently described by @item.
142 * This means that @item is essentially useless after the insertion
143 * occurs. Any changes you make to it are ignored unless it is inserted
144 * again (at which point its updated values will be copied).
146 * You should probably just free @item once you're done.
148 * There are many convenience functions to take care of common cases.
149 * See g_menu_insert(), g_menu_insert_section() and
150 * g_menu_insert_submenu() as well as "prepend" and "append" variants of
151 * each of these functions.
156 g_menu_insert_item (GMenu
*menu
,
160 struct item new_item
;
162 g_return_if_fail (G_IS_MENU (menu
));
163 g_return_if_fail (G_IS_MENU_ITEM (item
));
165 if (position
< 0 || position
> menu
->items
->len
)
166 position
= menu
->items
->len
;
168 new_item
.attributes
= g_hash_table_ref (item
->attributes
);
169 new_item
.links
= g_hash_table_ref (item
->links
);
172 g_array_insert_val (menu
->items
, position
, new_item
);
173 g_menu_model_items_changed (G_MENU_MODEL (menu
), position
, 0, 1);
177 * g_menu_prepend_item:
179 * @item: a #GMenuItem to prepend
181 * Prepends @item to the start of @menu.
183 * See g_menu_insert_item() for more information.
188 g_menu_prepend_item (GMenu
*menu
,
191 g_menu_insert_item (menu
, 0, item
);
195 * g_menu_append_item:
197 * @item: a #GMenuItem to append
199 * Appends @item to the end of @menu.
201 * See g_menu_insert_item() for more information.
206 g_menu_append_item (GMenu
*menu
,
209 g_menu_insert_item (menu
, -1, item
);
216 * Marks @menu as frozen.
218 * After the menu is frozen, it is an error to attempt to make any
219 * changes to it. In effect this means that the #GMenu API must no
222 * This function causes g_menu_model_is_mutable() to begin returning
223 * %FALSE, which has some positive performance implications.
228 g_menu_freeze (GMenu
*menu
)
230 g_return_if_fail (G_IS_MENU (menu
));
232 menu
->mutable = FALSE
;
238 * Creates a new #GMenu.
240 * The new menu has no items.
242 * Returns: a new #GMenu
249 return g_object_new (G_TYPE_MENU
, NULL
);
255 * @position: the position at which to insert the item
256 * @label: (nullable): the section label, or %NULL
257 * @detailed_action: (nullable): the detailed action string, or %NULL
259 * Convenience function for inserting a normal menu item into @menu.
260 * Combine g_menu_item_new() and g_menu_insert_item() for a more flexible
266 g_menu_insert (GMenu
*menu
,
269 const gchar
*detailed_action
)
271 GMenuItem
*menu_item
;
273 menu_item
= g_menu_item_new (label
, detailed_action
);
274 g_menu_insert_item (menu
, position
, menu_item
);
275 g_object_unref (menu_item
);
281 * @label: (nullable): the section label, or %NULL
282 * @detailed_action: (nullable): the detailed action string, or %NULL
284 * Convenience function for prepending a normal menu item to the start
285 * of @menu. Combine g_menu_item_new() and g_menu_insert_item() for a more
286 * flexible alternative.
291 g_menu_prepend (GMenu
*menu
,
293 const gchar
*detailed_action
)
295 g_menu_insert (menu
, 0, label
, detailed_action
);
301 * @label: (nullable): the section label, or %NULL
302 * @detailed_action: (nullable): the detailed action string, or %NULL
304 * Convenience function for appending a normal menu item to the end of
305 * @menu. Combine g_menu_item_new() and g_menu_insert_item() for a more
306 * flexible alternative.
311 g_menu_append (GMenu
*menu
,
313 const gchar
*detailed_action
)
315 g_menu_insert (menu
, -1, label
, detailed_action
);
319 * g_menu_insert_section:
321 * @position: the position at which to insert the item
322 * @label: (nullable): the section label, or %NULL
323 * @section: a #GMenuModel with the items of the section
325 * Convenience function for inserting a section menu item into @menu.
326 * Combine g_menu_item_new_section() and g_menu_insert_item() for a more
327 * flexible alternative.
332 g_menu_insert_section (GMenu
*menu
,
337 GMenuItem
*menu_item
;
339 menu_item
= g_menu_item_new_section (label
, section
);
340 g_menu_insert_item (menu
, position
, menu_item
);
341 g_object_unref (menu_item
);
346 * g_menu_prepend_section:
348 * @label: (nullable): the section label, or %NULL
349 * @section: a #GMenuModel with the items of the section
351 * Convenience function for prepending a section menu item to the start
352 * of @menu. Combine g_menu_item_new_section() and g_menu_insert_item() for
353 * a more flexible alternative.
358 g_menu_prepend_section (GMenu
*menu
,
362 g_menu_insert_section (menu
, 0, label
, section
);
366 * g_menu_append_section:
368 * @label: (nullable): the section label, or %NULL
369 * @section: a #GMenuModel with the items of the section
371 * Convenience function for appending a section menu item to the end of
372 * @menu. Combine g_menu_item_new_section() and g_menu_insert_item() for a
373 * more flexible alternative.
378 g_menu_append_section (GMenu
*menu
,
382 g_menu_insert_section (menu
, -1, label
, section
);
386 * g_menu_insert_submenu:
388 * @position: the position at which to insert the item
389 * @label: (nullable): the section label, or %NULL
390 * @submenu: a #GMenuModel with the items of the submenu
392 * Convenience function for inserting a submenu menu item into @menu.
393 * Combine g_menu_item_new_submenu() and g_menu_insert_item() for a more
394 * flexible alternative.
399 g_menu_insert_submenu (GMenu
*menu
,
404 GMenuItem
*menu_item
;
406 menu_item
= g_menu_item_new_submenu (label
, submenu
);
407 g_menu_insert_item (menu
, position
, menu_item
);
408 g_object_unref (menu_item
);
412 * g_menu_prepend_submenu:
414 * @label: (nullable): the section label, or %NULL
415 * @submenu: a #GMenuModel with the items of the submenu
417 * Convenience function for prepending a submenu menu item to the start
418 * of @menu. Combine g_menu_item_new_submenu() and g_menu_insert_item() for
419 * a more flexible alternative.
424 g_menu_prepend_submenu (GMenu
*menu
,
428 g_menu_insert_submenu (menu
, 0, label
, submenu
);
432 * g_menu_append_submenu:
434 * @label: (nullable): the section label, or %NULL
435 * @submenu: a #GMenuModel with the items of the submenu
437 * Convenience function for appending a submenu menu item to the end of
438 * @menu. Combine g_menu_item_new_submenu() and g_menu_insert_item() for a
439 * more flexible alternative.
444 g_menu_append_submenu (GMenu
*menu
,
448 g_menu_insert_submenu (menu
, -1, label
, submenu
);
452 g_menu_clear_item (struct item
*item
)
454 if (item
->attributes
!= NULL
)
455 g_hash_table_unref (item
->attributes
);
456 if (item
->links
!= NULL
)
457 g_hash_table_unref (item
->links
);
463 * @position: the position of the item to remove
465 * Removes an item from the menu.
467 * @position gives the index of the item to remove.
469 * It is an error if position is not in range the range from 0 to one
470 * less than the number of items in the menu.
472 * It is not possible to remove items by identity since items are added
473 * to the menu simply by copying their links and attributes (ie:
474 * identity of the item itself is not preserved).
479 g_menu_remove (GMenu
*menu
,
482 g_return_if_fail (G_IS_MENU (menu
));
483 g_return_if_fail (0 <= position
&& position
< menu
->items
->len
);
485 g_menu_clear_item (&g_array_index (menu
->items
, struct item
, position
));
486 g_array_remove_index (menu
->items
, position
);
487 g_menu_model_items_changed (G_MENU_MODEL (menu
), position
, 1, 0);
494 * Removes all items in the menu.
499 g_menu_remove_all (GMenu
*menu
)
503 g_return_if_fail (G_IS_MENU (menu
));
504 n
= menu
->items
->len
;
506 for (i
= 0; i
< n
; i
++)
507 g_menu_clear_item (&g_array_index (menu
->items
, struct item
, i
));
508 g_array_set_size (menu
->items
, 0);
510 g_menu_model_items_changed (G_MENU_MODEL (menu
), 0, n
, 0);
514 g_menu_finalize (GObject
*object
)
516 GMenu
*menu
= G_MENU (object
);
521 n_items
= menu
->items
->len
;
522 items
= (struct item
*) g_array_free (menu
->items
, FALSE
);
523 for (i
= 0; i
< n_items
; i
++)
524 g_menu_clear_item (&items
[i
]);
527 G_OBJECT_CLASS (g_menu_parent_class
)
532 g_menu_init (GMenu
*menu
)
534 menu
->items
= g_array_new (FALSE
, FALSE
, sizeof (struct item
));
535 menu
->mutable = TRUE
;
539 g_menu_class_init (GMenuClass
*class)
541 GMenuModelClass
*model_class
= G_MENU_MODEL_CLASS (class);
542 GObjectClass
*object_class
= G_OBJECT_CLASS (class);
544 object_class
->finalize
= g_menu_finalize
;
546 model_class
->is_mutable
= g_menu_is_mutable
;
547 model_class
->get_n_items
= g_menu_get_n_items
;
548 model_class
->get_item_attributes
= g_menu_get_item_attributes
;
549 model_class
->get_item_links
= g_menu_get_item_links
;
554 g_menu_item_clear_cow (GMenuItem
*menu_item
)
563 new = g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, (GDestroyNotify
) g_variant_unref
);
564 g_hash_table_iter_init (&iter
, menu_item
->attributes
);
565 while (g_hash_table_iter_next (&iter
, &key
, &val
))
566 g_hash_table_insert (new, g_strdup (key
), g_variant_ref (val
));
567 g_hash_table_unref (menu_item
->attributes
);
568 menu_item
->attributes
= new;
570 new = g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, (GDestroyNotify
) g_object_unref
);
571 g_hash_table_iter_init (&iter
, menu_item
->links
);
572 while (g_hash_table_iter_next (&iter
, &key
, &val
))
573 g_hash_table_insert (new, g_strdup (key
), g_object_ref (val
));
574 g_hash_table_unref (menu_item
->links
);
575 menu_item
->links
= new;
577 menu_item
->cow
= FALSE
;
582 g_menu_item_finalize (GObject
*object
)
584 GMenuItem
*menu_item
= G_MENU_ITEM (object
);
586 g_hash_table_unref (menu_item
->attributes
);
587 g_hash_table_unref (menu_item
->links
);
589 G_OBJECT_CLASS (g_menu_item_parent_class
)
594 g_menu_item_init (GMenuItem
*menu_item
)
596 menu_item
->attributes
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, (GDestroyNotify
) g_variant_unref
);
597 menu_item
->links
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, g_object_unref
);
598 menu_item
->cow
= FALSE
;
602 g_menu_item_class_init (GMenuItemClass
*class)
604 class->finalize
= g_menu_item_finalize
;
607 /* We treat attribute names the same as GSettings keys:
608 * - only lowercase ascii, digits and '-'
609 * - must start with lowercase
610 * - must not end with '-'
611 * - no consecutive '-'
612 * - not longer than 1024 chars
615 valid_attribute_name (const gchar
*name
)
619 if (!g_ascii_islower (name
[0]))
622 for (i
= 1; name
[i
]; i
++)
624 if (name
[i
] != '-' &&
625 !g_ascii_islower (name
[i
]) &&
626 !g_ascii_isdigit (name
[i
]))
629 if (name
[i
] == '-' && name
[i
+ 1] == '-')
633 if (name
[i
- 1] == '-')
643 * g_menu_item_set_attribute_value:
644 * @menu_item: a #GMenuItem
645 * @attribute: the attribute to set
646 * @value: (nullable): a #GVariant to use as the value, or %NULL
648 * Sets or unsets an attribute on @menu_item.
650 * The attribute to set or unset is specified by @attribute. This
651 * can be one of the standard attribute names %G_MENU_ATTRIBUTE_LABEL,
652 * %G_MENU_ATTRIBUTE_ACTION, %G_MENU_ATTRIBUTE_TARGET, or a custom
654 * Attribute names are restricted to lowercase characters, numbers
655 * and '-'. Furthermore, the names must begin with a lowercase character,
656 * must not end with a '-', and must not contain consecutive dashes.
658 * must consist only of lowercase
659 * ASCII characters, digits and '-'.
661 * If @value is non-%NULL then it is used as the new value for the
662 * attribute. If @value is %NULL then the attribute is unset. If
663 * the @value #GVariant is floating, it is consumed.
665 * See also g_menu_item_set_attribute() for a more convenient way to do
671 g_menu_item_set_attribute_value (GMenuItem
*menu_item
,
672 const gchar
*attribute
,
675 g_return_if_fail (G_IS_MENU_ITEM (menu_item
));
676 g_return_if_fail (attribute
!= NULL
);
677 g_return_if_fail (valid_attribute_name (attribute
));
679 g_menu_item_clear_cow (menu_item
);
682 g_hash_table_insert (menu_item
->attributes
, g_strdup (attribute
), g_variant_ref_sink (value
));
684 g_hash_table_remove (menu_item
->attributes
, attribute
);
688 * g_menu_item_set_attribute:
689 * @menu_item: a #GMenuItem
690 * @attribute: the attribute to set
691 * @format_string: (nullable): a #GVariant format string, or %NULL
692 * @...: positional parameters, as per @format_string
694 * Sets or unsets an attribute on @menu_item.
696 * The attribute to set or unset is specified by @attribute. This
697 * can be one of the standard attribute names %G_MENU_ATTRIBUTE_LABEL,
698 * %G_MENU_ATTRIBUTE_ACTION, %G_MENU_ATTRIBUTE_TARGET, or a custom
700 * Attribute names are restricted to lowercase characters, numbers
701 * and '-'. Furthermore, the names must begin with a lowercase character,
702 * must not end with a '-', and must not contain consecutive dashes.
704 * If @format_string is non-%NULL then the proper position parameters
705 * are collected to create a #GVariant instance to use as the attribute
706 * value. If it is %NULL then the positional parameterrs are ignored
707 * and the named attribute is unset.
709 * See also g_menu_item_set_attribute_value() for an equivalent call
710 * that directly accepts a #GVariant.
715 g_menu_item_set_attribute (GMenuItem
*menu_item
,
716 const gchar
*attribute
,
717 const gchar
*format_string
,
722 if (format_string
!= NULL
)
726 va_start (ap
, format_string
);
727 value
= g_variant_new_va (format_string
, NULL
, &ap
);
733 g_menu_item_set_attribute_value (menu_item
, attribute
, value
);
737 * g_menu_item_set_link:
738 * @menu_item: a #GMenuItem
739 * @link: type of link to establish or unset
740 * @model: (nullable): the #GMenuModel to link to (or %NULL to unset)
742 * Creates a link from @menu_item to @model if non-%NULL, or unsets it.
744 * Links are used to establish a relationship between a particular menu
745 * item and another menu. For example, %G_MENU_LINK_SUBMENU is used to
746 * associate a submenu with a particular menu item, and %G_MENU_LINK_SECTION
747 * is used to create a section. Other types of link can be used, but there
748 * is no guarantee that clients will be able to make sense of them.
749 * Link types are restricted to lowercase characters, numbers
750 * and '-'. Furthermore, the names must begin with a lowercase character,
751 * must not end with a '-', and must not contain consecutive dashes.
756 g_menu_item_set_link (GMenuItem
*menu_item
,
760 g_return_if_fail (G_IS_MENU_ITEM (menu_item
));
761 g_return_if_fail (link
!= NULL
);
762 g_return_if_fail (valid_attribute_name (link
));
764 g_menu_item_clear_cow (menu_item
);
767 g_hash_table_insert (menu_item
->links
, g_strdup (link
), g_object_ref (model
));
769 g_hash_table_remove (menu_item
->links
, link
);
773 * g_menu_item_get_attribute_value:
774 * @menu_item: a #GMenuItem
775 * @attribute: the attribute name to query
776 * @expected_type: (nullable): the expected type of the attribute
778 * Queries the named @attribute on @menu_item.
780 * If @expected_type is specified and the attribute does not have this
781 * type, %NULL is returned. %NULL is also returned if the attribute
782 * simply does not exist.
784 * Returns: (transfer full): the attribute value, or %NULL
789 g_menu_item_get_attribute_value (GMenuItem
*menu_item
,
790 const gchar
*attribute
,
791 const GVariantType
*expected_type
)
795 g_return_val_if_fail (G_IS_MENU_ITEM (menu_item
), NULL
);
796 g_return_val_if_fail (attribute
!= NULL
, NULL
);
798 value
= g_hash_table_lookup (menu_item
->attributes
, attribute
);
802 if (expected_type
== NULL
|| g_variant_is_of_type (value
, expected_type
))
803 g_variant_ref (value
);
812 * g_menu_item_get_attribute:
813 * @menu_item: a #GMenuItem
814 * @attribute: the attribute name to query
815 * @format_string: a #GVariant format string
816 * @...: positional parameters, as per @format_string
818 * Queries the named @attribute on @menu_item.
820 * If the attribute exists and matches the #GVariantType corresponding
821 * to @format_string then @format_string is used to deconstruct the
822 * value into the positional parameters and %TRUE is returned.
824 * If the attribute does not exist, or it does exist but has the wrong
825 * type, then the positional parameters are ignored and %FALSE is
828 * Returns: %TRUE if the named attribute was found with the expected
834 g_menu_item_get_attribute (GMenuItem
*menu_item
,
835 const gchar
*attribute
,
836 const gchar
*format_string
,
842 g_return_val_if_fail (G_IS_MENU_ITEM (menu_item
), FALSE
);
843 g_return_val_if_fail (attribute
!= NULL
, FALSE
);
844 g_return_val_if_fail (format_string
!= NULL
, FALSE
);
846 value
= g_hash_table_lookup (menu_item
->attributes
, attribute
);
851 if (!g_variant_check_format_string (value
, format_string
, FALSE
))
854 va_start (ap
, format_string
);
855 g_variant_get_va (value
, format_string
, NULL
, &ap
);
862 * g_menu_item_get_link:
863 * @menu_item: a #GMenuItem
864 * @link: the link name to query
866 * Queries the named @link on @menu_item.
868 * Returns: (transfer full): the link, or %NULL
873 g_menu_item_get_link (GMenuItem
*menu_item
,
878 g_return_val_if_fail (G_IS_MENU_ITEM (menu_item
), NULL
);
879 g_return_val_if_fail (link
!= NULL
, NULL
);
880 g_return_val_if_fail (valid_attribute_name (link
), NULL
);
882 model
= g_hash_table_lookup (menu_item
->links
, link
);
885 g_object_ref (model
);
891 * g_menu_item_set_label:
892 * @menu_item: a #GMenuItem
893 * @label: (nullable): the label to set, or %NULL to unset
895 * Sets or unsets the "label" attribute of @menu_item.
897 * If @label is non-%NULL it is used as the label for the menu item. If
898 * it is %NULL then the label attribute is unset.
903 g_menu_item_set_label (GMenuItem
*menu_item
,
909 value
= g_variant_new_string (label
);
913 g_menu_item_set_attribute_value (menu_item
, G_MENU_ATTRIBUTE_LABEL
, value
);
917 * g_menu_item_set_submenu:
918 * @menu_item: a #GMenuItem
919 * @submenu: (nullable): a #GMenuModel, or %NULL
921 * Sets or unsets the "submenu" link of @menu_item to @submenu.
923 * If @submenu is non-%NULL, it is linked to. If it is %NULL then the
926 * The effect of having one menu appear as a submenu of another is
927 * exactly as it sounds.
932 g_menu_item_set_submenu (GMenuItem
*menu_item
,
935 g_menu_item_set_link (menu_item
, G_MENU_LINK_SUBMENU
, submenu
);
939 * g_menu_item_set_section:
940 * @menu_item: a #GMenuItem
941 * @section: (nullable): a #GMenuModel, or %NULL
943 * Sets or unsets the "section" link of @menu_item to @section.
945 * The effect of having one menu appear as a section of another is
946 * exactly as it sounds: the items from @section become a direct part of
947 * the menu that @menu_item is added to. See g_menu_item_new_section()
948 * for more information about what it means for a menu item to be a
954 g_menu_item_set_section (GMenuItem
*menu_item
,
957 g_menu_item_set_link (menu_item
, G_MENU_LINK_SECTION
, section
);
961 * g_menu_item_set_action_and_target_value:
962 * @menu_item: a #GMenuItem
963 * @action: (nullable): the name of the action for this item
964 * @target_value: (nullable): a #GVariant to use as the action target
966 * Sets or unsets the "action" and "target" attributes of @menu_item.
968 * If @action is %NULL then both the "action" and "target" attributes
969 * are unset (and @target_value is ignored).
971 * If @action is non-%NULL then the "action" attribute is set. The
972 * "target" attribute is then set to the value of @target_value if it is
973 * non-%NULL or unset otherwise.
975 * Normal menu items (ie: not submenu, section or other custom item
976 * types) are expected to have the "action" attribute set to identify
977 * the action that they are associated with. The state type of the
978 * action help to determine the disposition of the menu item. See
979 * #GAction and #GActionGroup for an overview of actions.
981 * In general, clicking on the menu item will result in activation of
982 * the named action with the "target" attribute given as the parameter
983 * to the action invocation. If the "target" attribute is not set then
984 * the action is invoked with no parameter.
986 * If the action has no state then the menu item is usually drawn as a
987 * plain menu item (ie: with no additional decoration).
989 * If the action has a boolean state then the menu item is usually drawn
990 * as a toggle menu item (ie: with a checkmark or equivalent
991 * indication). The item should be marked as 'toggled' or 'checked'
992 * when the boolean state is %TRUE.
994 * If the action has a string state then the menu item is usually drawn
995 * as a radio menu item (ie: with a radio bullet or equivalent
996 * indication). The item should be marked as 'selected' when the string
997 * state is equal to the value of the @target property.
999 * See g_menu_item_set_action_and_target() or
1000 * g_menu_item_set_detailed_action() for two equivalent calls that are
1001 * probably more convenient for most uses.
1006 g_menu_item_set_action_and_target_value (GMenuItem
*menu_item
,
1007 const gchar
*action
,
1008 GVariant
*target_value
)
1010 GVariant
*action_value
;
1014 action_value
= g_variant_new_string (action
);
1018 action_value
= NULL
;
1019 target_value
= NULL
;
1022 g_menu_item_set_attribute_value (menu_item
, G_MENU_ATTRIBUTE_ACTION
, action_value
);
1023 g_menu_item_set_attribute_value (menu_item
, G_MENU_ATTRIBUTE_TARGET
, target_value
);
1027 * g_menu_item_set_action_and_target:
1028 * @menu_item: a #GMenuItem
1029 * @action: (nullable): the name of the action for this item
1030 * @format_string: (nullable): a GVariant format string
1031 * @...: positional parameters, as per @format_string
1033 * Sets or unsets the "action" and "target" attributes of @menu_item.
1035 * If @action is %NULL then both the "action" and "target" attributes
1036 * are unset (and @format_string is ignored along with the positional
1039 * If @action is non-%NULL then the "action" attribute is set.
1040 * @format_string is then inspected. If it is non-%NULL then the proper
1041 * position parameters are collected to create a #GVariant instance to
1042 * use as the target value. If it is %NULL then the positional
1043 * parameters are ignored and the "target" attribute is unset.
1045 * See also g_menu_item_set_action_and_target_value() for an equivalent
1046 * call that directly accepts a #GVariant. See
1047 * g_menu_item_set_detailed_action() for a more convenient version that
1048 * works with string-typed targets.
1050 * See also g_menu_item_set_action_and_target_value() for a
1051 * description of the semantics of the action and target attributes.
1056 g_menu_item_set_action_and_target (GMenuItem
*menu_item
,
1057 const gchar
*action
,
1058 const gchar
*format_string
,
1063 if (format_string
!= NULL
)
1067 va_start (ap
, format_string
);
1068 value
= g_variant_new_va (format_string
, NULL
, &ap
);
1074 g_menu_item_set_action_and_target_value (menu_item
, action
, value
);
1078 * g_menu_item_set_detailed_action:
1079 * @menu_item: a #GMenuItem
1080 * @detailed_action: the "detailed" action string
1082 * Sets the "action" and possibly the "target" attribute of @menu_item.
1084 * The format of @detailed_action is the same format parsed by
1085 * g_action_parse_detailed_name().
1087 * See g_menu_item_set_action_and_target() or
1088 * g_menu_item_set_action_and_target_value() for more flexible (but
1089 * slightly less convenient) alternatives.
1091 * See also g_menu_item_set_action_and_target_value() for a description of
1092 * the semantics of the action and target attributes.
1097 g_menu_item_set_detailed_action (GMenuItem
*menu_item
,
1098 const gchar
*detailed_action
)
1100 GError
*error
= NULL
;
1104 if (!g_action_parse_detailed_name (detailed_action
, &name
, &target
, &error
))
1105 g_error ("g_menu_item_set_detailed_action: %s", error
->message
);
1107 g_menu_item_set_action_and_target_value (menu_item
, name
, target
);
1109 g_variant_unref (target
);
1115 * @label: (nullable): the section label, or %NULL
1116 * @detailed_action: (nullable): the detailed action string, or %NULL
1118 * Creates a new #GMenuItem.
1120 * If @label is non-%NULL it is used to set the "label" attribute of the
1123 * If @detailed_action is non-%NULL it is used to set the "action" and
1124 * possibly the "target" attribute of the new item. See
1125 * g_menu_item_set_detailed_action() for more information.
1127 * Returns: a new #GMenuItem
1132 g_menu_item_new (const gchar
*label
,
1133 const gchar
*detailed_action
)
1135 GMenuItem
*menu_item
;
1137 menu_item
= g_object_new (G_TYPE_MENU_ITEM
, NULL
);
1140 g_menu_item_set_label (menu_item
, label
);
1142 if (detailed_action
!= NULL
)
1143 g_menu_item_set_detailed_action (menu_item
, detailed_action
);
1149 * g_menu_item_new_submenu:
1150 * @label: (nullable): the section label, or %NULL
1151 * @submenu: a #GMenuModel with the items of the submenu
1153 * Creates a new #GMenuItem representing a submenu.
1155 * This is a convenience API around g_menu_item_new() and
1156 * g_menu_item_set_submenu().
1158 * Returns: a new #GMenuItem
1163 g_menu_item_new_submenu (const gchar
*label
,
1164 GMenuModel
*submenu
)
1166 GMenuItem
*menu_item
;
1168 menu_item
= g_object_new (G_TYPE_MENU_ITEM
, NULL
);
1171 g_menu_item_set_label (menu_item
, label
);
1173 g_menu_item_set_submenu (menu_item
, submenu
);
1179 * g_menu_item_new_section:
1180 * @label: (nullable): the section label, or %NULL
1181 * @section: a #GMenuModel with the items of the section
1183 * Creates a new #GMenuItem representing a section.
1185 * This is a convenience API around g_menu_item_new() and
1186 * g_menu_item_set_section().
1188 * The effect of having one menu appear as a section of another is
1189 * exactly as it sounds: the items from @section become a direct part of
1190 * the menu that @menu_item is added to.
1192 * Visual separation is typically displayed between two non-empty
1193 * sections. If @label is non-%NULL then it will be encorporated into
1194 * this visual indication. This allows for labeled subsections of a
1197 * As a simple example, consider a typical "Edit" menu from a simple
1198 * program. It probably contains an "Undo" and "Redo" item, followed by
1199 * a separator, followed by "Cut", "Copy" and "Paste".
1201 * This would be accomplished by creating three #GMenu instances. The
1202 * first would be populated with the "Undo" and "Redo" items, and the
1203 * second with the "Cut", "Copy" and "Paste" items. The first and
1204 * second menus would then be added as submenus of the third. In XML
1205 * format, this would look something like the following:
1207 * <menu id='edit-menu'>
1209 * <item label='Undo'/>
1210 * <item label='Redo'/>
1213 * <item label='Cut'/>
1214 * <item label='Copy'/>
1215 * <item label='Paste'/>
1220 * The following example is exactly equivalent. It is more illustrative
1221 * of the exact relationship between the menus and items (keeping in
1222 * mind that the 'link' element defines a new menu that is linked to the
1223 * containing one). The style of the second example is more verbose and
1224 * difficult to read (and therefore not recommended except for the
1225 * purpose of understanding what is really going on).
1227 * <menu id='edit-menu'>
1229 * <link name='section'>
1230 * <item label='Undo'/>
1231 * <item label='Redo'/>
1235 * <link name='section'>
1236 * <item label='Cut'/>
1237 * <item label='Copy'/>
1238 * <item label='Paste'/>
1244 * Returns: a new #GMenuItem
1249 g_menu_item_new_section (const gchar
*label
,
1250 GMenuModel
*section
)
1252 GMenuItem
*menu_item
;
1254 menu_item
= g_object_new (G_TYPE_MENU_ITEM
, NULL
);
1257 g_menu_item_set_label (menu_item
, label
);
1259 g_menu_item_set_section (menu_item
, section
);
1265 * g_menu_item_new_from_model:
1266 * @model: a #GMenuModel
1267 * @item_index: the index of an item in @model
1269 * Creates a #GMenuItem as an exact copy of an existing menu item in a
1272 * @item_index must be valid (ie: be sure to call
1273 * g_menu_model_get_n_items() first).
1275 * Returns: a new #GMenuItem.
1280 g_menu_item_new_from_model (GMenuModel
*model
,
1283 GMenuModelClass
*class = G_MENU_MODEL_GET_CLASS (model
);
1284 GMenuItem
*menu_item
;
1286 menu_item
= g_object_new (G_TYPE_MENU_ITEM
, NULL
);
1288 /* With some trickery we can be pretty efficient.
1290 * A GMenuModel must either implement iterate_item_attributes() or
1291 * get_item_attributes(). If it implements get_item_attributes() then
1292 * we are in luck -- we can just take a reference on the returned
1293 * hashtable and mark ourselves as copy-on-write.
1295 * In the case that the model is based on get_item_attributes (which
1296 * is the case for both GMenu and GDBusMenuModel) then this is
1297 * basically just g_hash_table_ref().
1299 if (class->get_item_attributes
)
1301 GHashTable
*attributes
= NULL
;
1303 class->get_item_attributes (model
, item_index
, &attributes
);
1306 g_hash_table_unref (menu_item
->attributes
);
1307 menu_item
->attributes
= attributes
;
1308 menu_item
->cow
= TRUE
;
1313 GMenuAttributeIter
*iter
;
1314 const gchar
*attribute
;
1317 iter
= g_menu_model_iterate_item_attributes (model
, item_index
);
1318 while (g_menu_attribute_iter_get_next (iter
, &attribute
, &value
))
1319 g_hash_table_insert (menu_item
->attributes
, g_strdup (attribute
), value
);
1320 g_object_unref (iter
);
1323 /* Same story for the links... */
1324 if (class->get_item_links
)
1326 GHashTable
*links
= NULL
;
1328 class->get_item_links (model
, item_index
, &links
);
1331 g_hash_table_unref (menu_item
->links
);
1332 menu_item
->links
= links
;
1333 menu_item
->cow
= TRUE
;
1338 GMenuLinkIter
*iter
;
1342 iter
= g_menu_model_iterate_item_links (model
, item_index
);
1343 while (g_menu_link_iter_get_next (iter
, &link
, &value
))
1344 g_hash_table_insert (menu_item
->links
, g_strdup (link
), value
);
1345 g_object_unref (iter
);
1352 * g_menu_item_set_icon:
1353 * @menu_item: a #GMenuItem
1354 * @icon: a #GIcon, or %NULL
1356 * Sets (or unsets) the icon on @menu_item.
1358 * This call is the same as calling g_icon_serialize() and using the
1359 * result as the value to g_menu_item_set_attribute_value() for
1360 * %G_MENU_ATTRIBUTE_ICON.
1362 * This API is only intended for use with "noun" menu items; things like
1363 * bookmarks or applications in an "Open With" menu. Don't use it on
1364 * menu items corresponding to verbs (eg: stock icons for 'Save' or
1367 * If @icon is %NULL then the icon is unset.
1372 g_menu_item_set_icon (GMenuItem
*menu_item
,
1377 g_return_if_fail (G_IS_MENU_ITEM (menu_item
));
1378 g_return_if_fail (icon
== NULL
|| G_IS_ICON (icon
));
1381 value
= g_icon_serialize (icon
);
1385 g_menu_item_set_attribute_value (menu_item
, G_MENU_ATTRIBUTE_ICON
, value
);
1387 g_variant_unref (value
);