1 /*
2 * Copyright © 2010 Codethink Limited
3 *
4 * SPDX-License-Identifier: LGPL-2.1-or-later
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General
17 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 *
19 * Authors: Ryan Lortie <desrt@desrt.ca>
20 */
21
22 #include "config.h"
23 #include "gactiongroup.h"
24 #include "gaction.h"
25 #include "glibintl.h"
26 #include "gmarshal-internal.h"
27
28 /**
29 * GActionGroup:
30 *
31 * `GActionGroup` represents a group of actions.
32 *
33 * Actions can be used to expose functionality in a structured way, either
34 * from one part of a program to another, or to the outside world. Action
35 * groups are often used together with a `GMenuModel` that provides additional
36 * representation data for displaying the actions to the user, e.g. in a menu.
37 *
38 * The main way to interact with the actions in a `GActionGroup` is to
39 * activate them with [method@Gio.ActionGroup.activate_action]. Activating an
40 * action may require a `GVariant` parameter. The required type of the
41 * parameter can be inquired with [method@Gio.ActionGroup.get_action_parameter_type].
42 * Actions may be disabled, see [method@Gio.ActionGroup.get_action_enabled].
43 * Activating a disabled action has no effect.
44 *
45 * Actions may optionally have a state in the form of a #GVariant. The current
46 * state of an action can be inquired with [method@Gio.ActionGroup.get_action_state].
47 * Activating a stateful action may change its state, but it is also possible to
48 * set the state by calling [method@Gio.ActionGroup.change_action_state].
49 *
50 * As typical example, consider a text editing application which has an
51 * option to change the current font to 'bold'. A good way to represent
52 * this would be a stateful action, with a boolean state. Activating the
53 * action would toggle the state.
54 *
55 * Each action in the group has a unique name (which is a string). All
56 * method calls, except [method@Gio.ActionGroup.list_actions] take the name of
57 * an action as an argument.
58 *
59 * The `GActionGroup` API is meant to be the 'public' API to the action
60 * group. The calls here are exactly the interaction that 'external
61 * forces' (eg: UI, incoming D-Bus messages, etc.) are supposed to have
62 * with actions. 'Internal' APIs (ie: ones meant only to be accessed by
63 * the action group implementation) are found on subclasses. This is
64 * why you will find - for example - [method@Gio.ActionGroup.get_action_enabled]
65 * but not an equivalent set() call.
66 *
67 * Signals are emitted on the action group in response to state changes
68 * on individual actions.
69 *
70 * Implementations of `GActionGroup` should provide implementations for
71 * the virtual functions [method@Gio.ActionGroup.list_actions] and
72 * [method@Gio.ActionGroup.query_action]. The other virtual functions should
73 * not be implemented - their "wrappers" are actually implemented with
74 * calls to [method@Gio.ActionGroup.query_action].
75 */
76
77 /**
78 * GActionGroupInterface:
79 * @has_action: the virtual function pointer for g_action_group_has_action()
80 * @list_actions: the virtual function pointer for g_action_group_list_actions()
81 * @get_action_parameter_type: the virtual function pointer for g_action_group_get_action_parameter_type()
82 * @get_action_state_type: the virtual function pointer for g_action_group_get_action_state_type()
83 * @get_action_state_hint: the virtual function pointer for g_action_group_get_action_state_hint()
84 * @get_action_enabled: the virtual function pointer for g_action_group_get_action_enabled()
85 * @get_action_state: the virtual function pointer for g_action_group_get_action_state()
86 * @change_action_state: the virtual function pointer for g_action_group_change_action_state()
87 * @activate_action: the virtual function pointer for g_action_group_activate_action()
88 * @action_added: the class closure for the #GActionGroup::action-added signal
89 * @action_removed: the class closure for the #GActionGroup::action-removed signal
90 * @action_enabled_changed: the class closure for the #GActionGroup::action-enabled-changed signal
91 * @action_state_changed: the class closure for the #GActionGroup::action-enabled-changed signal
92 * @query_action: the virtual function pointer for g_action_group_query_action()
93 *
94 * The virtual function table for #GActionGroup.
95 *
96 * Since: 2.28
97 **/
98
99 G_DEFINE_INTERFACE (GActionGroup, g_action_group, G_TYPE_OBJECT)
100
101 enum
102 {
103 SIGNAL_ACTION_ADDED,
104 SIGNAL_ACTION_REMOVED,
105 SIGNAL_ACTION_ENABLED_CHANGED,
106 SIGNAL_ACTION_STATE_CHANGED,
107 NR_SIGNALS
108 };
109
110 static guint g_action_group_signals[NR_SIGNALS];
111
112 static gboolean
113 g_action_group_real_has_action (GActionGroup *action_group,
114 const gchar *action_name)
115 {
116 return g_action_group_query_action (action_group, action_name, NULL, NULL, NULL, NULL, NULL);
117 }
118
119 static gboolean
120 g_action_group_real_get_action_enabled (GActionGroup *action_group,
121 const gchar *action_name)
122 {
123 gboolean enabled;
124
125 if (!g_action_group_query_action (action_group, action_name, &enabled, NULL, NULL, NULL, NULL))
126 return FALSE;
127
128 return enabled;
129 }
130
131 static const GVariantType *
132 g_action_group_real_get_action_parameter_type (GActionGroup *action_group,
133 const gchar *action_name)
134 {
135 const GVariantType *type;
136
137 if (!g_action_group_query_action (action_group, action_name, NULL, &type, NULL, NULL, NULL))
138 return NULL;
139
140 return type;
141 }
142
143 static const GVariantType *
144 g_action_group_real_get_action_state_type (GActionGroup *action_group,
145 const gchar *action_name)
146 {
147 const GVariantType *type;
148
149 if (!g_action_group_query_action (action_group, action_name, NULL, NULL, &type, NULL, NULL))
150 return NULL;
151
152 return type;
153 }
154
155 static GVariant *
156 g_action_group_real_get_action_state_hint (GActionGroup *action_group,
157 const gchar *action_name)
158 {
159 GVariant *hint;
160
161 if (!g_action_group_query_action (action_group, action_name, NULL, NULL, NULL, &hint, NULL))
162 return NULL;
163
164 return hint;
165 }
166
167 static GVariant *
168 g_action_group_real_get_action_state (GActionGroup *action_group,
169 const gchar *action_name)
170 {
171 GVariant *state;
172
173 if (!g_action_group_query_action (action_group, action_name, NULL, NULL, NULL, NULL, &state))
174 return NULL;
175
176 return state;
177 }
178
179 static gboolean
180 g_action_group_real_query_action (GActionGroup *action_group,
181 const gchar *action_name,
182 gboolean *enabled,
183 const GVariantType **parameter_type,
184 const GVariantType **state_type,
185 GVariant **state_hint,
186 GVariant **state)
187 {
188 GActionGroupInterface *iface = G_ACTION_GROUP_GET_IFACE (action_group);
189
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.
193 *
194 * detect the case that neither has happened and report it.
195 */
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)
202 {
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));
206 return FALSE;
207 }
208
209 if (!(* iface->has_action) (action_group, action_name))
210 return FALSE;
211
212 if (enabled != NULL)
213 *enabled = (* iface->get_action_enabled) (action_group, action_name);
214
215 if (parameter_type != NULL)
216 *parameter_type = (* iface->get_action_parameter_type) (action_group, action_name);
217
218 if (state_type != NULL)
219 *state_type = (* iface->get_action_state_type) (action_group, action_name);
220
221 if (state_hint != NULL)
222 *state_hint = (* iface->get_action_state_hint) (action_group, action_name);
223
224 if (state != NULL)
225 *state = (* iface->get_action_state) (action_group, action_name);
226
227 return TRUE;
228 }
229
230 static void
231 g_action_group_default_init (GActionGroupInterface *iface)
232 {
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;
240
241 /**
242 * GActionGroup::action-added:
243 * @action_group: the #GActionGroup that changed
244 * @action_name: the name of the action in @action_group
245 *
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.
249 *
250 * Since: 2.28
251 **/
252 g_action_group_signals[SIGNAL_ACTION_ADDED] =
253 g_signal_new (I_("action-added"),
254 G_TYPE_ACTION_GROUP,
255 G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
256 G_STRUCT_OFFSET (GActionGroupInterface, action_added),
257 NULL, NULL,
258 NULL,
259 G_TYPE_NONE, 1,
260 G_TYPE_STRING);
261
262 /**
263 * GActionGroup::action-removed:
264 * @action_group: the #GActionGroup that changed
265 * @action_name: the name of the action in @action_group
266 *
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.
270 *
271 * Since: 2.28
272 **/
273 g_action_group_signals[SIGNAL_ACTION_REMOVED] =
274 g_signal_new (I_("action-removed"),
275 G_TYPE_ACTION_GROUP,
276 G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
277 G_STRUCT_OFFSET (GActionGroupInterface, action_removed),
278 NULL, NULL,
279 NULL,
280 G_TYPE_NONE, 1,
281 G_TYPE_STRING);
282
283
284 /**
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
289 *
290 * Signals that the enabled status of the named action has changed.
291 *
292 * Since: 2.28
293 **/
294 g_action_group_signals[SIGNAL_ACTION_ENABLED_CHANGED] =
295 g_signal_new (I_("action-enabled-changed"),
296 G_TYPE_ACTION_GROUP,
297 G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
298 G_STRUCT_OFFSET (GActionGroupInterface,
299 action_enabled_changed),
300 NULL, NULL,
301 _g_cclosure_marshal_VOID__STRING_BOOLEAN,
302 G_TYPE_NONE, 2,
303 G_TYPE_STRING,
304 G_TYPE_BOOLEAN);
305 g_signal_set_va_marshaller (g_action_group_signals[SIGNAL_ACTION_ENABLED_CHANGED],
306 G_TYPE_FROM_INTERFACE (iface),
307 _g_cclosure_marshal_VOID__STRING_BOOLEANv);
308
309 /**
310 * GActionGroup::action-state-changed:
311 * @action_group: the #GActionGroup that changed
312 * @action_name: the name of the action in @action_group
313 * @value: the new value of the state
314 *
315 * Signals that the state of the named action has changed.
316 *
317 * Since: 2.28
318 **/
319 g_action_group_signals[SIGNAL_ACTION_STATE_CHANGED] =
320 g_signal_new (I_("action-state-changed"),
321 G_TYPE_ACTION_GROUP,
322 G_SIGNAL_RUN_LAST |
323 G_SIGNAL_DETAILED |
324 G_SIGNAL_MUST_COLLECT,
325 G_STRUCT_OFFSET (GActionGroupInterface,
326 action_state_changed),
327 NULL, NULL,
328 _g_cclosure_marshal_VOID__STRING_VARIANT,
329 G_TYPE_NONE, 2,
330 G_TYPE_STRING,
331 G_TYPE_VARIANT);
332 g_signal_set_va_marshaller (g_action_group_signals[SIGNAL_ACTION_STATE_CHANGED],
333 G_TYPE_FROM_INTERFACE (iface),
334 _g_cclosure_marshal_VOID__STRING_VARIANTv);
335 }
336
337 /**
338 * g_action_group_list_actions:
339 * @action_group: a #GActionGroup
340 *
341 * Lists the actions contained within @action_group.
342 *
343 * The caller is responsible for freeing the list with g_strfreev() when
344 * it is no longer required.
345 *
346 * Returns: (transfer full): a %NULL-terminated array of the names of the
347 * actions in the group
348 *
349 * Since: 2.28
350 **/
351 gchar **
352 g_action_group_list_actions (GActionGroup *action_group)
353 {
354 g_return_val_if_fail (G_IS_ACTION_GROUP (action_group), NULL);
355
356 return G_ACTION_GROUP_GET_IFACE (action_group)
357 ->list_actions (action_group);
358 }
359
360 /**
361 * g_action_group_has_action:
362 * @action_group: a #GActionGroup
363 * @action_name: the name of the action to check for
364 *
365 * Checks if the named action exists within @action_group.
366 *
367 * Returns: whether the named action exists
368 *
369 * Since: 2.28
370 **/
371 gboolean
372 g_action_group_has_action (GActionGroup *action_group,
373 const gchar *action_name)
374 {
375 g_return_val_if_fail (G_IS_ACTION_GROUP (action_group), FALSE);
376
377 return G_ACTION_GROUP_GET_IFACE (action_group)
378 ->has_action (action_group, action_name);
379 }
380
381 /**
382 * g_action_group_get_action_parameter_type:
383 * @action_group: a #GActionGroup
384 * @action_name: the name of the action to query
385 *
386 * Queries the type of the parameter that must be given when activating
387 * the named action within @action_group.
388 *
389 * When activating the action using g_action_group_activate_action(),
390 * the #GVariant given to that function must be of the type returned
391 * by this function.
392 *
393 * In the case that this function returns %NULL, you must not give any
394 * #GVariant, but %NULL instead.
395 *
396 * The parameter type of a particular action will never change but it is
397 * possible for an action to be removed and for a new action to be added
398 * with the same name but a different parameter type.
399 *
400 * Returns: (nullable): the parameter type
401 *
402 * Since: 2.28
403 **/
404 const GVariantType *
405 g_action_group_get_action_parameter_type (GActionGroup *action_group,
406 const gchar *action_name)
407 {
408 g_return_val_if_fail (G_IS_ACTION_GROUP (action_group), NULL);
409
410 return G_ACTION_GROUP_GET_IFACE (action_group)
411 ->get_action_parameter_type (action_group, action_name);
412 }
413
414 /**
415 * g_action_group_get_action_state_type:
416 * @action_group: a #GActionGroup
417 * @action_name: the name of the action to query
418 *
419 * Queries the type of the state of the named action within
420 * @action_group.
421 *
422 * If the action is stateful then this function returns the
423 * #GVariantType of the state. All calls to
424 * g_action_group_change_action_state() must give a #GVariant of this
425 * type and g_action_group_get_action_state() will return a #GVariant
426 * of the same type.
427 *
428 * If the action is not stateful then this function will return %NULL.
429 * In that case, g_action_group_get_action_state() will return %NULL
430 * and you must not call g_action_group_change_action_state().
431 *
432 * The state type of a particular action will never change but it is
433 * possible for an action to be removed and for a new action to be added
434 * with the same name but a different state type.
435 *
436 * Returns: (nullable): the state type, if the action is stateful
437 *
438 * Since: 2.28
439 **/
440 const GVariantType *
441 g_action_group_get_action_state_type (GActionGroup *action_group,
442 const gchar *action_name)
443 {
444 g_return_val_if_fail (G_IS_ACTION_GROUP (action_group), NULL);
445
446 return G_ACTION_GROUP_GET_IFACE (action_group)
447 ->get_action_state_type (action_group, action_name);
448 }
449
450 /**
451 * g_action_group_get_action_state_hint:
452 * @action_group: a #GActionGroup
453 * @action_name: the name of the action to query
454 *
455 * Requests a hint about the valid range of values for the state of the
456 * named action within @action_group.
457 *
458 * If %NULL is returned it either means that the action is not stateful
459 * or that there is no hint about the valid range of values for the
460 * state of the action.
461 *
462 * If a #GVariant array is returned then each item in the array is a
463 * possible value for the state. If a #GVariant pair (ie: two-tuple) is
464 * returned then the tuple specifies the inclusive lower and upper bound
465 * of valid values for the state.
466 *
467 * In any case, the information is merely a hint. It may be possible to
468 * have a state value outside of the hinted range and setting a value
469 * within the range may fail.
470 *
471 * The return value (if non-%NULL) should be freed with
472 * g_variant_unref() when it is no longer required.
473 *
474 * Returns: (nullable) (transfer full): the state range hint
475 *
476 * Since: 2.28
477 **/
478 GVariant *
479 g_action_group_get_action_state_hint (GActionGroup *action_group,
480 const gchar *action_name)
481 {
482 g_return_val_if_fail (G_IS_ACTION_GROUP (action_group), NULL);
483
484 return G_ACTION_GROUP_GET_IFACE (action_group)
485 ->get_action_state_hint (action_group, action_name);
486 }
487
488 /**
489 * g_action_group_get_action_enabled:
490 * @action_group: a #GActionGroup
491 * @action_name: the name of the action to query
492 *
493 * Checks if the named action within @action_group is currently enabled.
494 *
495 * An action must be enabled in order to be activated or in order to
496 * have its state changed from outside callers.
497 *
498 * Returns: whether or not the action is currently enabled
499 *
500 * Since: 2.28
501 **/
502 gboolean
503 g_action_group_get_action_enabled (GActionGroup *action_group,
504 const gchar *action_name)
505 {
506 g_return_val_if_fail (G_IS_ACTION_GROUP (action_group), FALSE);
507
508 return G_ACTION_GROUP_GET_IFACE (action_group)
509 ->get_action_enabled (action_group, action_name);
510 }
511
512 /**
513 * g_action_group_get_action_state:
514 * @action_group: a #GActionGroup
515 * @action_name: the name of the action to query
516 *
517 * Queries the current state of the named action within @action_group.
518 *
519 * If the action is not stateful then %NULL will be returned. If the
520 * action is stateful then the type of the return value is the type
521 * given by g_action_group_get_action_state_type().
522 *
523 * The return value (if non-%NULL) should be freed with
524 * g_variant_unref() when it is no longer required.
525 *
526 * Returns: (nullable) (transfer full): the current state of the action
527 *
528 * Since: 2.28
529 **/
530 GVariant *
531 g_action_group_get_action_state (GActionGroup *action_group,
532 const gchar *action_name)
533 {
534 g_return_val_if_fail (G_IS_ACTION_GROUP (action_group), NULL);
535
536 return G_ACTION_GROUP_GET_IFACE (action_group)
537 ->get_action_state (action_group, action_name);
538 }
539
540 /**
541 * g_action_group_change_action_state:
542 * @action_group: a #GActionGroup
543 * @action_name: the name of the action to request the change on
544 * @value: the new state
545 *
546 * Request for the state of the named action within @action_group to be
547 * changed to @value.
548 *
549 * The action must be stateful and @value must be of the correct type.
550 * See g_action_group_get_action_state_type().
551 *
552 * This call merely requests a change. The action may refuse to change
553 * its state or may change its state to something other than @value.
554 * See g_action_group_get_action_state_hint().
555 *
556 * If the @value GVariant is floating, it is consumed.
557 *
558 * Since: 2.28
559 **/
560 void
561 g_action_group_change_action_state (GActionGroup *action_group,
562 const gchar *action_name,
563 GVariant *value)
564 {
565 g_return_if_fail (G_IS_ACTION_GROUP (action_group));
566 g_return_if_fail (action_name != NULL);
567 g_return_if_fail (value != NULL);
568
569 G_ACTION_GROUP_GET_IFACE (action_group)
570 ->change_action_state (action_group, action_name, value);
571 }
572
573 /**
574 * g_action_group_activate_action:
575 * @action_group: a #GActionGroup
576 * @action_name: the name of the action to activate
577 * @parameter: (nullable): parameters to the activation
578 *
579 * Activate the named action within @action_group.
580 *
581 * If the action is expecting a parameter, then the correct type of
582 * parameter must be given as @parameter. If the action is expecting no
583 * parameters then @parameter must be %NULL. See
584 * g_action_group_get_action_parameter_type().
585 *
586 * If the #GActionGroup implementation supports asynchronous remote
587 * activation over D-Bus, this call may return before the relevant
588 * D-Bus traffic has been sent, or any replies have been received. In
589 * order to block on such asynchronous activation calls,
590 * g_dbus_connection_flush() should be called prior to the code, which
591 * depends on the result of the action activation. Without flushing
592 * the D-Bus connection, there is no guarantee that the action would
593 * have been activated.
594 *
595 * The following code which runs in a remote app instance, shows an
596 * example of a "quit" action being activated on the primary app
597 * instance over D-Bus. Here g_dbus_connection_flush() is called
598 * before `exit()`. Without g_dbus_connection_flush(), the "quit" action
599 * may fail to be activated on the primary instance.
600 *
601 * |[<!-- language="C" -->
602 * // call "quit" action on primary instance
603 * g_action_group_activate_action (G_ACTION_GROUP (app), "quit", NULL);
604 *
605 * // make sure the action is activated now
606 * g_dbus_connection_flush (...);
607 *
608 * g_debug ("application has been terminated. exiting.");
609 *
610 * exit (0);
611 * ]|
612 *
613 * Since: 2.28
614 **/
615 void
616 g_action_group_activate_action (GActionGroup *action_group,
617 const gchar *action_name,
618 GVariant *parameter)
619 {
620 g_return_if_fail (G_IS_ACTION_GROUP (action_group));
621 g_return_if_fail (action_name != NULL);
622
623 G_ACTION_GROUP_GET_IFACE (action_group)
624 ->activate_action (action_group, action_name, parameter);
625 }
626
627 /**
628 * g_action_group_action_added:
629 * @action_group: a #GActionGroup
630 * @action_name: the name of an action in the group
631 *
632 * Emits the #GActionGroup::action-added signal on @action_group.
633 *
634 * This function should only be called by #GActionGroup implementations.
635 *
636 * Since: 2.28
637 **/
638 void
639 g_action_group_action_added (GActionGroup *action_group,
640 const gchar *action_name)
641 {
642 g_return_if_fail (G_IS_ACTION_GROUP (action_group));
643 g_return_if_fail (action_name != NULL);
644
645 g_signal_emit (action_group,
646 g_action_group_signals[SIGNAL_ACTION_ADDED],
647 g_quark_try_string (action_name),
648 action_name);
649 }
650
651 /**
652 * g_action_group_action_removed:
653 * @action_group: a #GActionGroup
654 * @action_name: the name of an action in the group
655 *
656 * Emits the #GActionGroup::action-removed signal on @action_group.
657 *
658 * This function should only be called by #GActionGroup implementations.
659 *
660 * Since: 2.28
661 **/
662 void
663 g_action_group_action_removed (GActionGroup *action_group,
664 const gchar *action_name)
665 {
666 g_return_if_fail (G_IS_ACTION_GROUP (action_group));
667 g_return_if_fail (action_name != NULL);
668
669 g_signal_emit (action_group,
670 g_action_group_signals[SIGNAL_ACTION_REMOVED],
671 g_quark_try_string (action_name),
672 action_name);
673 }
674
675 /**
676 * g_action_group_action_enabled_changed:
677 * @action_group: a #GActionGroup
678 * @action_name: the name of an action in the group
679 * @enabled: whether or not the action is now enabled
680 *
681 * Emits the #GActionGroup::action-enabled-changed signal on @action_group.
682 *
683 * This function should only be called by #GActionGroup implementations.
684 *
685 * Since: 2.28
686 **/
687 void
688 g_action_group_action_enabled_changed (GActionGroup *action_group,
689 const gchar *action_name,
690 gboolean enabled)
691 {
692 g_return_if_fail (G_IS_ACTION_GROUP (action_group));
693 g_return_if_fail (action_name != NULL);
694
695 enabled = !!enabled;
696
697 g_signal_emit (action_group,
698 g_action_group_signals[SIGNAL_ACTION_ENABLED_CHANGED],
699 g_quark_try_string (action_name),
700 action_name,
701 enabled);
702 }
703
704 /**
705 * g_action_group_action_state_changed:
706 * @action_group: a #GActionGroup
707 * @action_name: the name of an action in the group
708 * @state: the new state of the named action
709 *
710 * Emits the #GActionGroup::action-state-changed signal on @action_group.
711 *
712 * This function should only be called by #GActionGroup implementations.
713 *
714 * Since: 2.28
715 **/
716 void
717 g_action_group_action_state_changed (GActionGroup *action_group,
718 const gchar *action_name,
719 GVariant *state)
720 {
721 g_return_if_fail (G_IS_ACTION_GROUP (action_group));
722 g_return_if_fail (action_name != NULL);
723
724 g_signal_emit (action_group,
725 g_action_group_signals[SIGNAL_ACTION_STATE_CHANGED],
726 g_quark_try_string (action_name),
727 action_name,
728 state);
729 }
730
731 /**
732 * g_action_group_query_action:
733 * @action_group: a #GActionGroup
734 * @action_name: the name of an action in the group
735 * @enabled: (out): if the action is presently enabled
736 * @parameter_type: (out) (transfer none) (optional): the parameter type, or %NULL if none needed
737 * @state_type: (out) (transfer none) (optional): the state type, or %NULL if stateless
738 * @state_hint: (out) (optional): the state hint, or %NULL if none
739 * @state: (out) (optional): the current state, or %NULL if stateless
740 *
741 * Queries all aspects of the named action within an @action_group.
742 *
743 * This function acquires the information available from
744 * g_action_group_has_action(), g_action_group_get_action_enabled(),
745 * g_action_group_get_action_parameter_type(),
746 * g_action_group_get_action_state_type(),
747 * g_action_group_get_action_state_hint() and
748 * g_action_group_get_action_state() with a single function call.
749 *
750 * This provides two main benefits.
751 *
752 * The first is the improvement in efficiency that comes with not having
753 * to perform repeated lookups of the action in order to discover
754 * different things about it. The second is that implementing
755 * #GActionGroup can now be done by only overriding this one virtual
756 * function.
757 *
758 * The interface provides a default implementation of this function that
759 * calls the individual functions, as required, to fetch the
760 * information. The interface also provides default implementations of
761 * those functions that call this function. All implementations,
762 * therefore, must override either this function or all of the others.
763 *
764 * If the action exists, %TRUE is returned and any of the requested
765 * fields (as indicated by having a non-%NULL reference passed in) are
766 * filled. If the action doesn't exist, %FALSE is returned and the
767 * fields may or may not have been modified.
768 *
769 * Returns: %TRUE if the action exists, else %FALSE
770 *
771 * Since: 2.32
772 **/
773 gboolean
774 g_action_group_query_action (GActionGroup *action_group,
775 const gchar *action_name,
776 gboolean *enabled,
777 const GVariantType **parameter_type,
778 const GVariantType **state_type,
779 GVariant **state_hint,
780 GVariant **state)
781 {
782 return G_ACTION_GROUP_GET_IFACE (action_group)
783 ->query_action (action_group, action_name, enabled, parameter_type, state_type, state_hint, state);
784 }