2 * Copyright © 2010 Codethink Limited
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as published
6 * by the Free Software Foundation; either version 2 of the licence or (at
7 * your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but 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
15 * Public License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
17 * Boston, MA 02111-1307, USA.
19 * Authors: Ryan Lortie <desrt@desrt.ca>
23 #include "gactiongroup.h"
28 * SECTION:gactiongroup
29 * @title: GActionGroup
30 * @short_description: A group of actions
34 * #GActionGroup represents a group of actions. Actions can be used to
35 * expose functionality in a structured way, either from one part of a
36 * program to another, or to the outside world. Action groups are often
37 * used together with a #GMenuModel that provides additional
38 * representation data for displaying the actions to the user, e.g. in
41 * The main way to interact with the actions in a GActionGroup is to
42 * activate them with g_action_group_activate_action(). Activating an
43 * action may require a #GVariant parameter. The required type of the
44 * parameter can be inquired with g_action_group_get_action_parameter_type().
45 * Actions may be disabled, see g_action_group_get_action_enabled().
46 * Activating a disabled action has no effect.
48 * Actions may optionally have a state in the form of a #GVariant. The
49 * current state of an action can be inquired with
50 * g_action_group_get_action_state(). Activating a stateful action may
51 * change its state, but it is also possible to set the state by calling
52 * g_action_group_change_action_state().
54 * As typical example, consider a text editing application which has an
55 * option to change the current font to 'bold'. A good way to represent
56 * this would be a stateful action, with a boolean state. Activating the
57 * action would toggle the state.
59 * Each action in the group has a unique name (which is a string). All
60 * method calls, except g_action_group_list_actions() take the name of
61 * an action as an argument.
63 * The #GActionGroup API is meant to be the 'public' API to the action
64 * group. The calls here are exactly the interaction that 'external
65 * forces' (eg: UI, incoming D-Bus messages, etc.) are supposed to have
66 * with actions. 'Internal' APIs (ie: ones meant only to be accessed by
67 * the action group implementation) are found on subclasses. This is
68 * why you will find - for example - g_action_group_get_action_enabled()
69 * but not an equivalent <function>set()</function> call.
71 * Signals are emitted on the action group in response to state changes
72 * on individual actions.
74 * Implementations of #GActionGroup should provide implementations for
75 * the virtual functions g_action_group_list_actions() and
76 * g_action_group_query_action(). The other virtual functions should
77 * not be implemented - their "wrappers" are actually implemented with
78 * calls to g_action_group_query_action().
82 * GActionGroupInterface:
83 * @has_action: the virtual function pointer for g_action_group_has_action()
84 * @list_actions: the virtual function pointer for g_action_group_list_actions()
85 * @get_action_parameter_type: the virtual function pointer for g_action_group_get_action_parameter_type()
86 * @get_action_state_type: the virtual function pointer for g_action_group_get_action_state_type()
87 * @get_action_state_hint: the virtual function pointer for g_action_group_get_action_state_hint()
88 * @get_action_enabled: the virtual function pointer for g_action_group_get_action_enabled()
89 * @get_action_state: the virtual function pointer for g_action_group_get_action_state()
90 * @change_action_state: the virtual function pointer for g_action_group_change_action_state()
91 * @query_action: the virtual function pointer for g_action_group_query_action()
92 * @activate_action: the virtual function pointer for g_action_group_activate_action()
93 * @change_action_state: the virtual function pointer for g_action_group_change_action_state()
94 * @action_added: the class closure for the #GActionGroup::action-added signal
95 * @action_removed: the class closure for the #GActionGroup::action-removed signal
96 * @action_enabled_changed: the class closure for the #GActionGroup::action-enabled-changed signal
97 * @action_state_changed: the class closure for the #GActionGroup::action-enabled-changed signal
99 * The virtual function table for #GActionGroup.
104 G_DEFINE_INTERFACE (GActionGroup, g_action_group, G_TYPE_OBJECT)
109 SIGNAL_ACTION_REMOVED,
110 SIGNAL_ACTION_ENABLED_CHANGED,
111 SIGNAL_ACTION_STATE_CHANGED,
115 static guint g_action_group_signals[NR_SIGNALS];
118 g_action_group_real_has_action (GActionGroup *action_group,
119 const gchar *action_name)
121 return g_action_group_query_action (action_group, action_name, NULL, NULL, NULL, NULL, NULL);
125 g_action_group_real_get_action_enabled (GActionGroup *action_group,
126 const gchar *action_name)
128 gboolean enabled = FALSE;
130 g_action_group_query_action (action_group, action_name, &enabled, NULL, NULL, NULL, NULL);
135 static const GVariantType *
136 g_action_group_real_get_action_parameter_type (GActionGroup *action_group,
137 const gchar *action_name)
139 const GVariantType *type = NULL;
141 g_action_group_query_action (action_group, action_name, NULL, &type, NULL, NULL, NULL);
146 static const GVariantType *
147 g_action_group_real_get_action_state_type (GActionGroup *action_group,
148 const gchar *action_name)
150 const GVariantType *type = NULL;
152 g_action_group_query_action (action_group, action_name, NULL, NULL, &type, NULL, NULL);
158 g_action_group_real_get_action_state_hint (GActionGroup *action_group,
159 const gchar *action_name)
161 GVariant *hint = NULL;
163 g_action_group_query_action (action_group, action_name, NULL, NULL, NULL, &hint, NULL);
169 g_action_group_real_get_action_state (GActionGroup *action_group,
170 const gchar *action_name)
172 GVariant *state = NULL;
174 g_action_group_query_action (action_group, action_name, NULL, NULL, NULL, NULL, &state);
180 g_action_group_real_query_action (GActionGroup *action_group,
181 const gchar *action_name,
183 const GVariantType **parameter_type,
184 const GVariantType **state_type,
185 GVariant **state_hint,
188 GActionGroupInterface *iface = G_ACTION_GROUP_GET_IFACE (action_group);
190 /* we expect implementations to override this method, but we also
191 * allow for implementations that existed before this method was
192 * introduced to override the individual accessors instead.
194 * detect the case that neither has happened and report it.
196 if G_UNLIKELY (iface->has_action == g_action_group_real_has_action ||
197 iface->get_action_enabled == g_action_group_real_get_action_enabled ||
198 iface->get_action_parameter_type == g_action_group_real_get_action_parameter_type ||
199 iface->get_action_state_type == g_action_group_real_get_action_state_type ||
200 iface->get_action_state_hint == g_action_group_real_get_action_state_hint ||
201 iface->get_action_state == g_action_group_real_get_action_state)
203 g_critical ("Class '%s' implements GActionGroup interface without overriding "
204 "query_action() method -- bailing out to avoid infinite recursion.",
205 G_OBJECT_TYPE_NAME (action_group));
209 if (!(* iface->has_action) (action_group, action_name))
213 *enabled = (* iface->get_action_enabled) (action_group, action_name);
215 if (parameter_type != NULL)
216 *parameter_type = (* iface->get_action_parameter_type) (action_group, action_name);
218 if (state_type != NULL)
219 *state_type = (* iface->get_action_state_type) (action_group, action_name);
221 if (state_hint != NULL)
222 *state_hint = (* iface->get_action_state_hint) (action_group, action_name);
225 *state = (* iface->get_action_state) (action_group, action_name);
231 g_action_group_default_init (GActionGroupInterface *iface)
233 iface->has_action = g_action_group_real_has_action;
234 iface->get_action_enabled = g_action_group_real_get_action_enabled;
235 iface->get_action_parameter_type = g_action_group_real_get_action_parameter_type;
236 iface->get_action_state_type = g_action_group_real_get_action_state_type;
237 iface->get_action_state_hint = g_action_group_real_get_action_state_hint;
238 iface->get_action_state = g_action_group_real_get_action_state;
239 iface->query_action = g_action_group_real_query_action;
242 * GActionGroup::action-added:
243 * @action_group: the #GActionGroup that changed
244 * @action_name: the name of the action in @action_group
246 * Signals that a new action was just added to the group.
247 * This signal is emitted after the action has been added
248 * and is now visible.
252 g_action_group_signals[SIGNAL_ACTION_ADDED] =
253 g_signal_new (I_("action-added"),
255 G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
256 G_STRUCT_OFFSET (GActionGroupInterface, action_added),
258 g_cclosure_marshal_VOID__STRING,
263 * GActionGroup::action-removed:
264 * @action_group: the #GActionGroup that changed
265 * @action_name: the name of the action in @action_group
267 * Signals that an action is just about to be removed from the group.
268 * This signal is emitted before the action is removed, so the action
269 * is still visible and can be queried from the signal handler.
273 g_action_group_signals[SIGNAL_ACTION_REMOVED] =
274 g_signal_new (I_("action-removed"),
276 G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
277 G_STRUCT_OFFSET (GActionGroupInterface, action_removed),
279 g_cclosure_marshal_VOID__STRING,
285 * GActionGroup::action-enabled-changed:
286 * @action_group: the #GActionGroup that changed
287 * @action_name: the name of the action in @action_group
288 * @enabled: whether the action is enabled or not
290 * Signals that the enabled status of the named action has changed.
294 g_action_group_signals[SIGNAL_ACTION_ENABLED_CHANGED] =
295 g_signal_new (I_("action-enabled-changed"),
297 G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
298 G_STRUCT_OFFSET (GActionGroupInterface,
299 action_enabled_changed),
307 * GActionGroup::action-state-changed:
308 * @action_group: the #GActionGroup that changed
309 * @action_name: the name of the action in @action_group
310 * @value: the new value of the state
312 * Signals that the state of the named action has changed.
316 g_action_group_signals[SIGNAL_ACTION_STATE_CHANGED] =
317 g_signal_new (I_("action-state-changed"),
321 G_SIGNAL_MUST_COLLECT,
322 G_STRUCT_OFFSET (GActionGroupInterface,
323 action_state_changed),
332 * g_action_group_list_actions:
333 * @action_group: a #GActionGroup
335 * Lists the actions contained within @action_group.
337 * The caller is responsible for freeing the list with g_strfreev() when
338 * it is no longer required.
340 * Returns: (transfer full): a %NULL-terminated array of the names of the
341 * actions in the groupb
346 g_action_group_list_actions (GActionGroup *action_group)
348 g_return_val_if_fail (G_IS_ACTION_GROUP (action_group), NULL);
350 return G_ACTION_GROUP_GET_IFACE (action_group)
351 ->list_actions (action_group);
355 * g_action_group_has_action:
356 * @action_group: a #GActionGroup
357 * @action_name: the name of the action to check for
359 * Checks if the named action exists within @action_group.
361 * Returns: whether the named action exists
366 g_action_group_has_action (GActionGroup *action_group,
367 const gchar *action_name)
369 g_return_val_if_fail (G_IS_ACTION_GROUP (action_group), FALSE);
371 return G_ACTION_GROUP_GET_IFACE (action_group)
372 ->has_action (action_group, action_name);
376 * g_action_group_get_action_parameter_type:
377 * @action_group: a #GActionGroup
378 * @action_name: the name of the action to query
380 * Queries the type of the parameter that must be given when activating
381 * the named action within @action_group.
383 * When activating the action using g_action_group_activate_action(),
384 * the #GVariant given to that function must be of the type returned
387 * In the case that this function returns %NULL, you must not give any
388 * #GVariant, but %NULL instead.
390 * The parameter type of a particular action will never change but it is
391 * possible for an action to be removed and for a new action to be added
392 * with the same name but a different parameter type.
394 * Return value: the parameter type
399 g_action_group_get_action_parameter_type (GActionGroup *action_group,
400 const gchar *action_name)
402 g_return_val_if_fail (G_IS_ACTION_GROUP (action_group), NULL);
404 return G_ACTION_GROUP_GET_IFACE (action_group)
405 ->get_action_parameter_type (action_group, action_name);
409 * g_action_group_get_action_state_type:
410 * @action_group: a #GActionGroup
411 * @action_name: the name of the action to query
413 * Queries the type of the state of the named action within
416 * If the action is stateful then this function returns the
417 * #GVariantType of the state. All calls to
418 * g_action_group_change_action_state() must give a #GVariant of this
419 * type and g_action_group_get_action_state() will return a #GVariant
422 * If the action is not stateful then this function will return %NULL.
423 * In that case, g_action_group_get_action_state() will return %NULL
424 * and you must not call g_action_group_change_action_state().
426 * The state type of a particular action will never change but it is
427 * possible for an action to be removed and for a new action to be added
428 * with the same name but a different state type.
430 * Returns: (transfer full): the state type, if the action is stateful
435 g_action_group_get_action_state_type (GActionGroup *action_group,
436 const gchar *action_name)
438 g_return_val_if_fail (G_IS_ACTION_GROUP (action_group), NULL);
440 return G_ACTION_GROUP_GET_IFACE (action_group)
441 ->get_action_state_type (action_group, action_name);
445 * g_action_group_get_action_state_hint:
446 * @action_group: a #GActionGroup
447 * @action_name: the name of the action to query
449 * Requests a hint about the valid range of values for the state of the
450 * named action within @action_group.
452 * If %NULL is returned it either means that the action is not stateful
453 * or that there is no hint about the valid range of values for the
454 * state of the action.
456 * If a #GVariant array is returned then each item in the array is a
457 * possible value for the state. If a #GVariant pair (ie: two-tuple) is
458 * returned then the tuple specifies the inclusive lower and upper bound
459 * of valid values for the state.
461 * In any case, the information is merely a hint. It may be possible to
462 * have a state value outside of the hinted range and setting a value
463 * within the range may fail.
465 * The return value (if non-%NULL) should be freed with
466 * g_variant_unref() when it is no longer required.
468 * Return value: (transfer full): the state range hint
473 g_action_group_get_action_state_hint (GActionGroup *action_group,
474 const gchar *action_name)
476 g_return_val_if_fail (G_IS_ACTION_GROUP (action_group), NULL);
478 return G_ACTION_GROUP_GET_IFACE (action_group)
479 ->get_action_state_hint (action_group, action_name);
483 * g_action_group_get_action_enabled:
484 * @action_group: a #GActionGroup
485 * @action_name: the name of the action to query
487 * Checks if the named action within @action_group is currently enabled.
489 * An action must be enabled in order to be activated or in order to
490 * have its state changed from outside callers.
492 * Return value: whether or not the action is currently enabled
497 g_action_group_get_action_enabled (GActionGroup *action_group,
498 const gchar *action_name)
500 g_return_val_if_fail (G_IS_ACTION_GROUP (action_group), FALSE);
502 return G_ACTION_GROUP_GET_IFACE (action_group)
503 ->get_action_enabled (action_group, action_name);
507 * g_action_group_get_action_state:
508 * @action_group: a #GActionGroup
509 * @action_name: the name of the action to query
511 * Queries the current state of the named action within @action_group.
513 * If the action is not stateful then %NULL will be returned. If the
514 * action is stateful then the type of the return value is the type
515 * given by g_action_group_get_action_state_type().
517 * The return value (if non-%NULL) should be freed with
518 * g_variant_unref() when it is no longer required.
520 * Return value: (allow-none): the current state of the action
525 g_action_group_get_action_state (GActionGroup *action_group,
526 const gchar *action_name)
528 g_return_val_if_fail (G_IS_ACTION_GROUP (action_group), NULL);
530 return G_ACTION_GROUP_GET_IFACE (action_group)
531 ->get_action_state (action_group, action_name);
535 * g_action_group_change_action_state:
536 * @action_group: a #GActionGroup
537 * @action_name: the name of the action to request the change on
538 * @value: the new state
540 * Request for the state of the named action within @action_group to be
543 * The action must be stateful and @value must be of the correct type.
544 * See g_action_group_get_action_state_type().
546 * This call merely requests a change. The action may refuse to change
547 * its state or may change its state to something other than @value.
548 * See g_action_group_get_action_state_hint().
550 * If the @value GVariant is floating, it is consumed.
555 g_action_group_change_action_state (GActionGroup *action_group,
556 const gchar *action_name,
559 g_return_if_fail (G_IS_ACTION_GROUP (action_group));
560 g_return_if_fail (action_name != NULL);
561 g_return_if_fail (value != NULL);
563 G_ACTION_GROUP_GET_IFACE (action_group)
564 ->change_action_state (action_group, action_name, value);
568 * g_action_group_activate_action:
569 * @action_group: a #GActionGroup
570 * @action_name: the name of the action to activate
571 * @parameter: (allow-none): parameters to the activation
573 * Activate the named action within @action_group.
575 * If the action is expecting a parameter, then the correct type of
576 * parameter must be given as @parameter. If the action is expecting no
577 * parameters then @parameter must be %NULL. See
578 * g_action_group_get_action_parameter_type().
583 g_action_group_activate_action (GActionGroup *action_group,
584 const gchar *action_name,
587 g_return_if_fail (G_IS_ACTION_GROUP (action_group));
588 g_return_if_fail (action_name != NULL);
590 G_ACTION_GROUP_GET_IFACE (action_group)
591 ->activate_action (action_group, action_name, parameter);
595 * g_action_group_action_added:
596 * @action_group: a #GActionGroup
597 * @action_name: the name of an action in the group
599 * Emits the #GActionGroup::action-added signal on @action_group.
601 * This function should only be called by #GActionGroup implementations.
606 g_action_group_action_added (GActionGroup *action_group,
607 const gchar *action_name)
609 g_return_if_fail (G_IS_ACTION_GROUP (action_group));
610 g_return_if_fail (action_name != NULL);
612 g_signal_emit (action_group,
613 g_action_group_signals[SIGNAL_ACTION_ADDED],
614 g_quark_try_string (action_name),
619 * g_action_group_action_removed:
620 * @action_group: a #GActionGroup
621 * @action_name: the name of an action in the group
623 * Emits the #GActionGroup::action-removed signal on @action_group.
625 * This function should only be called by #GActionGroup implementations.
630 g_action_group_action_removed (GActionGroup *action_group,
631 const gchar *action_name)
633 g_return_if_fail (G_IS_ACTION_GROUP (action_group));
634 g_return_if_fail (action_name != NULL);
636 g_signal_emit (action_group,
637 g_action_group_signals[SIGNAL_ACTION_REMOVED],
638 g_quark_try_string (action_name),
643 * g_action_group_action_enabled_changed:
644 * @action_group: a #GActionGroup
645 * @action_name: the name of an action in the group
646 * @enabled: whether or not the action is now enabled
648 * Emits the #GActionGroup::action-enabled-changed signal on @action_group.
650 * This function should only be called by #GActionGroup implementations.
655 g_action_group_action_enabled_changed (GActionGroup *action_group,
656 const gchar *action_name,
659 g_return_if_fail (G_IS_ACTION_GROUP (action_group));
660 g_return_if_fail (action_name != NULL);
664 g_signal_emit (action_group,
665 g_action_group_signals[SIGNAL_ACTION_ENABLED_CHANGED],
666 g_quark_try_string (action_name),
672 * g_action_group_action_state_changed:
673 * @action_group: a #GActionGroup
674 * @action_name: the name of an action in the group
675 * @state: the new state of the named action
677 * Emits the #GActionGroup::action-state-changed signal on @action_group.
679 * This function should only be called by #GActionGroup implementations.
684 g_action_group_action_state_changed (GActionGroup *action_group,
685 const gchar *action_name,
688 g_return_if_fail (G_IS_ACTION_GROUP (action_group));
689 g_return_if_fail (action_name != NULL);
691 g_signal_emit (action_group,
692 g_action_group_signals[SIGNAL_ACTION_STATE_CHANGED],
693 g_quark_try_string (action_name),
699 * g_action_group_query_action:
700 * @action_group: a #GActionGroup
701 * @action_name: the name of an action in the group
702 * @enabled: (out): if the action is presently enabled
703 * @parameter_type: (out) (allow-none): the parameter type, or %NULL if none needed
704 * @state_type: (out) (allow-none): the state type, or %NULL if stateless
705 * @state_hint: (out) (allow-none): the state hint, or %NULL if none
706 * @state: (out) (allow-none): the current state, or %NULL if stateless
708 * Queries all aspects of the named action within an @action_group.
710 * This function acquires the information available from
711 * g_action_group_has_action(), g_action_group_get_action_enabled(),
712 * g_action_group_get_action_parameter_type(),
713 * g_action_group_get_action_state_type(),
714 * g_action_group_get_action_state_hint() and
715 * g_action_group_get_action_state() with a single function call.
717 * This provides two main benefits.
719 * The first is the improvement in efficiency that comes with not having
720 * to perform repeated lookups of the action in order to discover
721 * different things about it. The second is that implementing
722 * #GActionGroup can now be done by only overriding this one virtual
725 * The interface provides a default implementation of this function that
726 * calls the individual functions, as required, to fetch the
727 * information. The interface also provides default implementations of
728 * those functions that call this function. All implementations,
729 * therefore, must override either this function or all of the others.
731 * If the action exists, %TRUE is returned and any of the requested
732 * fields (as indicated by having a non-%NULL reference passed in) are
733 * filled. If the action doesn't exist, %FALSE is returned and the
734 * fields may or may not have been modified.
736 * Returns: %TRUE if the action exists, else %FALSE
741 g_action_group_query_action (GActionGroup *action_group,
742 const gchar *action_name,
744 const GVariantType **parameter_type,
745 const GVariantType **state_type,
746 GVariant **state_hint,
749 return G_ACTION_GROUP_GET_IFACE (action_group)
750 ->query_action (action_group, action_name, enabled, parameter_type, state_type, state_hint, state);