Branch data Line data Source code
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 [type@Gio.MenuModel] 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 [type@GLib.Variant] 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 [type@GLib.Variant]. 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_action_enabled()` method.
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 [method@Gio.ActionGroup.has_action]
80 : : * @list_actions: the virtual function pointer for [method@Gio.ActionGroup.list_actions]
81 : : * @get_action_parameter_type: the virtual function pointer for [method@Gio.ActionGroup.get_action_parameter_type]
82 : : * @get_action_state_type: the virtual function pointer for [method@Gio.ActionGroup.get_action_state_type]
83 : : * @get_action_state_hint: the virtual function pointer for [method@Gio.ActionGroup.get_action_state_hint]
84 : : * @get_action_enabled: the virtual function pointer for [method@Gio.ActionGroup.get_action_enabled]
85 : : * @get_action_state: the virtual function pointer for [method@Gio.ActionGroup.get_action_state]
86 : : * @change_action_state: the virtual function pointer for [method@Gio.ActionGroup.change_action_state]
87 : : * @activate_action: the virtual function pointer for [method@Gio.ActionGroup.activate_action]
88 : : * @action_added: the class closure for the [signal@Gio.ActionGroup::action-added] signal
89 : : * @action_removed: the class closure for the [signal@Gio.ActionGroup::action-removed] signal
90 : : * @action_enabled_changed: the class closure for the [signal@Gio.ActionGroup::action-enabled-changed] signal
91 : : * @action_state_changed: the class closure for the [signal@Gio.ActionGroup::action-enabled-changed] signal
92 : : * @query_action: the virtual function pointer for [method@Gio.ActionGroup.query_action]
93 : : *
94 : : * The virtual function table for [type@Gio.ActionGroup].
95 : : *
96 : : * Since: 2.28
97 : : **/
98 : :
99 : 201235 : 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 : 4 : g_action_group_real_has_action (GActionGroup *action_group,
114 : : const gchar *action_name)
115 : : {
116 : 4 : return g_action_group_query_action (action_group, action_name, NULL, NULL, NULL, NULL, NULL);
117 : : }
118 : :
119 : : static gboolean
120 : 19 : g_action_group_real_get_action_enabled (GActionGroup *action_group,
121 : : const gchar *action_name)
122 : : {
123 : : gboolean enabled;
124 : :
125 : 19 : if (!g_action_group_query_action (action_group, action_name, &enabled, NULL, NULL, NULL, NULL))
126 : 0 : return FALSE;
127 : :
128 : 19 : return enabled;
129 : : }
130 : :
131 : : static const GVariantType *
132 : 17 : g_action_group_real_get_action_parameter_type (GActionGroup *action_group,
133 : : const gchar *action_name)
134 : : {
135 : : const GVariantType *type;
136 : :
137 : 17 : if (!g_action_group_query_action (action_group, action_name, NULL, &type, NULL, NULL, NULL))
138 : 0 : return NULL;
139 : :
140 : 17 : return type;
141 : : }
142 : :
143 : : static const GVariantType *
144 : 2 : g_action_group_real_get_action_state_type (GActionGroup *action_group,
145 : : const gchar *action_name)
146 : : {
147 : : const GVariantType *type;
148 : :
149 : 2 : if (!g_action_group_query_action (action_group, action_name, NULL, NULL, &type, NULL, NULL))
150 : 0 : return NULL;
151 : :
152 : 2 : return type;
153 : : }
154 : :
155 : : static GVariant *
156 : 2 : g_action_group_real_get_action_state_hint (GActionGroup *action_group,
157 : : const gchar *action_name)
158 : : {
159 : : GVariant *hint;
160 : :
161 : 2 : if (!g_action_group_query_action (action_group, action_name, NULL, NULL, NULL, &hint, NULL))
162 : 0 : return NULL;
163 : :
164 : 2 : return hint;
165 : : }
166 : :
167 : : static GVariant *
168 : 55 : g_action_group_real_get_action_state (GActionGroup *action_group,
169 : : const gchar *action_name)
170 : : {
171 : : GVariant *state;
172 : :
173 : 55 : if (!g_action_group_query_action (action_group, action_name, NULL, NULL, NULL, NULL, &state))
174 : 0 : return NULL;
175 : :
176 : 55 : return state;
177 : : }
178 : :
179 : : static gboolean
180 : 0 : 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 : 0 : 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 : 0 : 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 : 0 : 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 : 0 : return FALSE;
207 : : }
208 : :
209 : 0 : if (!(* iface->has_action) (action_group, action_name))
210 : 0 : return FALSE;
211 : :
212 : 0 : if (enabled != NULL)
213 : 0 : *enabled = (* iface->get_action_enabled) (action_group, action_name);
214 : :
215 : 0 : if (parameter_type != NULL)
216 : 0 : *parameter_type = (* iface->get_action_parameter_type) (action_group, action_name);
217 : :
218 : 0 : if (state_type != NULL)
219 : 0 : *state_type = (* iface->get_action_state_type) (action_group, action_name);
220 : :
221 : 0 : if (state_hint != NULL)
222 : 0 : *state_hint = (* iface->get_action_state_hint) (action_group, action_name);
223 : :
224 : 0 : if (state != NULL)
225 : 0 : *state = (* iface->get_action_state) (action_group, action_name);
226 : :
227 : 0 : return TRUE;
228 : : }
229 : :
230 : : static void
231 : 13 : g_action_group_default_init (GActionGroupInterface *iface)
232 : : {
233 : 13 : iface->has_action = g_action_group_real_has_action;
234 : 13 : iface->get_action_enabled = g_action_group_real_get_action_enabled;
235 : 13 : iface->get_action_parameter_type = g_action_group_real_get_action_parameter_type;
236 : 13 : iface->get_action_state_type = g_action_group_real_get_action_state_type;
237 : 13 : iface->get_action_state_hint = g_action_group_real_get_action_state_hint;
238 : 13 : iface->get_action_state = g_action_group_real_get_action_state;
239 : 13 : iface->query_action = g_action_group_real_query_action;
240 : :
241 : : /**
242 : : * GActionGroup::action-added:
243 : : * @action_group: the [type@Gio.ActionGroup] 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 : : *
248 : : * This signal is emitted after the action has been added
249 : : * and is now visible.
250 : : *
251 : : * Since: 2.28
252 : : **/
253 : 13 : g_action_group_signals[SIGNAL_ACTION_ADDED] =
254 : 13 : g_signal_new (I_("action-added"),
255 : : G_TYPE_ACTION_GROUP,
256 : : G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
257 : : G_STRUCT_OFFSET (GActionGroupInterface, action_added),
258 : : NULL, NULL,
259 : : NULL,
260 : : G_TYPE_NONE, 1,
261 : : G_TYPE_STRING);
262 : :
263 : : /**
264 : : * GActionGroup::action-removed:
265 : : * @action_group: the [type@Gio.ActionGroup] that changed
266 : : * @action_name: the name of the action in @action_group
267 : : *
268 : : * Signals that an action is just about to be removed from the group.
269 : : *
270 : : * This signal is emitted before the action is removed, so the action
271 : : * is still visible and can be queried from the signal handler.
272 : : *
273 : : * Since: 2.28
274 : : **/
275 : 13 : g_action_group_signals[SIGNAL_ACTION_REMOVED] =
276 : 13 : g_signal_new (I_("action-removed"),
277 : : G_TYPE_ACTION_GROUP,
278 : : G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
279 : : G_STRUCT_OFFSET (GActionGroupInterface, action_removed),
280 : : NULL, NULL,
281 : : NULL,
282 : : G_TYPE_NONE, 1,
283 : : G_TYPE_STRING);
284 : :
285 : : /**
286 : : * GActionGroup::action-enabled-changed:
287 : : * @action_group: the [type@Gio.ActionGroup] that changed
288 : : * @action_name: the name of the action in @action_group
289 : : * @enabled: whether the action is enabled
290 : : *
291 : : * Signals that the enabled status of the named action has changed.
292 : : *
293 : : * Since: 2.28
294 : : **/
295 : 13 : g_action_group_signals[SIGNAL_ACTION_ENABLED_CHANGED] =
296 : 13 : g_signal_new (I_("action-enabled-changed"),
297 : : G_TYPE_ACTION_GROUP,
298 : : G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
299 : : G_STRUCT_OFFSET (GActionGroupInterface,
300 : : action_enabled_changed),
301 : : NULL, NULL,
302 : : _g_cclosure_marshal_VOID__STRING_BOOLEAN,
303 : : G_TYPE_NONE, 2,
304 : : G_TYPE_STRING,
305 : : G_TYPE_BOOLEAN);
306 : 13 : g_signal_set_va_marshaller (g_action_group_signals[SIGNAL_ACTION_ENABLED_CHANGED],
307 : : G_TYPE_FROM_INTERFACE (iface),
308 : : _g_cclosure_marshal_VOID__STRING_BOOLEANv);
309 : :
310 : : /**
311 : : * GActionGroup::action-state-changed:
312 : : * @action_group: the [type@Gio.ActionGroup] that changed
313 : : * @action_name: the name of the action in @action_group
314 : : * @value: the new value of the state
315 : : *
316 : : * Signals that the state of the named action has changed.
317 : : *
318 : : * Since: 2.28
319 : : **/
320 : 13 : g_action_group_signals[SIGNAL_ACTION_STATE_CHANGED] =
321 : 13 : g_signal_new (I_("action-state-changed"),
322 : : G_TYPE_ACTION_GROUP,
323 : : G_SIGNAL_RUN_LAST |
324 : : G_SIGNAL_DETAILED |
325 : : G_SIGNAL_MUST_COLLECT,
326 : : G_STRUCT_OFFSET (GActionGroupInterface,
327 : : action_state_changed),
328 : : NULL, NULL,
329 : : _g_cclosure_marshal_VOID__STRING_VARIANT,
330 : : G_TYPE_NONE, 2,
331 : : G_TYPE_STRING,
332 : : G_TYPE_VARIANT);
333 : 13 : g_signal_set_va_marshaller (g_action_group_signals[SIGNAL_ACTION_STATE_CHANGED],
334 : : G_TYPE_FROM_INTERFACE (iface),
335 : : _g_cclosure_marshal_VOID__STRING_VARIANTv);
336 : 13 : }
337 : :
338 : : /**
339 : : * g_action_group_list_actions:
340 : : * @action_group: a [type@Gio.ActionGroup]
341 : : *
342 : : * Lists the actions contained within @action_group.
343 : : *
344 : : * The caller is responsible for freeing the list with [func@GLib.strfreev] when
345 : : * it is no longer required.
346 : : *
347 : : * Returns: (transfer full) (array zero-terminated=1): a `NULL`-terminated array
348 : : * of the names of the actions in the group
349 : : *
350 : : * Since: 2.28
351 : : **/
352 : : gchar **
353 : 33 : g_action_group_list_actions (GActionGroup *action_group)
354 : : {
355 : 33 : g_return_val_if_fail (G_IS_ACTION_GROUP (action_group), NULL);
356 : :
357 : 33 : return G_ACTION_GROUP_GET_IFACE (action_group)
358 : 33 : ->list_actions (action_group);
359 : : }
360 : :
361 : : /**
362 : : * g_action_group_has_action:
363 : : * @action_group: a [type@Gio.ActionGroup]
364 : : * @action_name: the name of the action to check for
365 : : *
366 : : * Checks if the named action exists within @action_group.
367 : : *
368 : : * Returns: whether the named action exists
369 : : *
370 : : * Since: 2.28
371 : : **/
372 : : gboolean
373 : 4 : g_action_group_has_action (GActionGroup *action_group,
374 : : const gchar *action_name)
375 : : {
376 : 4 : g_return_val_if_fail (G_IS_ACTION_GROUP (action_group), FALSE);
377 : :
378 : 4 : return G_ACTION_GROUP_GET_IFACE (action_group)
379 : 4 : ->has_action (action_group, action_name);
380 : : }
381 : :
382 : : /**
383 : : * g_action_group_get_action_parameter_type:
384 : : * @action_group: a [type@Gio.ActionGroup]
385 : : * @action_name: the name of the action to query
386 : : *
387 : : * Queries the type of the parameter that must be given when activating
388 : : * the named action within @action_group.
389 : : *
390 : : * When activating the action using [method@Gio.ActionGroup.activate_action],
391 : : * the [type@GLib.Variant] given to that function must be of the type returned
392 : : * by this function.
393 : : *
394 : : * In the case that this function returns `NULL`, you must not give any
395 : : * [type@GLib.Variant], but `NULL` instead.
396 : : *
397 : : * The parameter type of a particular action will never change but it is
398 : : * possible for an action to be removed and for a new action to be added
399 : : * with the same name but a different parameter type.
400 : : *
401 : : * Returns: (nullable): the parameter type
402 : : *
403 : : * Since: 2.28
404 : : **/
405 : : const GVariantType *
406 : 17 : g_action_group_get_action_parameter_type (GActionGroup *action_group,
407 : : const gchar *action_name)
408 : : {
409 : 17 : g_return_val_if_fail (G_IS_ACTION_GROUP (action_group), NULL);
410 : :
411 : 17 : return G_ACTION_GROUP_GET_IFACE (action_group)
412 : 17 : ->get_action_parameter_type (action_group, action_name);
413 : : }
414 : :
415 : : /**
416 : : * g_action_group_get_action_state_type:
417 : : * @action_group: a [type@Gio.ActionGroup]
418 : : * @action_name: the name of the action to query
419 : : *
420 : : * Queries the type of the state of the named action within
421 : : * @action_group.
422 : : *
423 : : * If the action is stateful then this function returns the
424 : : * [type@GLib.VariantType] of the state. All calls to
425 : : * [method@Gio.ActionGroup.change_action_state] must give a [type@GLib.Variant] of this
426 : : * type and [method@Gio.ActionGroup.get_action_state] will return a [type@GLib.Variant]
427 : : * of the same type.
428 : : *
429 : : * If the action is not stateful then this function will return `NULL`.
430 : : * In that case, [method@Gio.ActionGroup.get_action_state] will return `NULL`
431 : : * and you must not call [method@Gio.ActionGroup.change_action_state].
432 : : *
433 : : * The state type of a particular action will never change but it is
434 : : * possible for an action to be removed and for a new action to be added
435 : : * with the same name but a different state type.
436 : : *
437 : : * Returns: (nullable): the state type, if the action is stateful
438 : : *
439 : : * Since: 2.28
440 : : **/
441 : : const GVariantType *
442 : 2 : g_action_group_get_action_state_type (GActionGroup *action_group,
443 : : const gchar *action_name)
444 : : {
445 : 2 : g_return_val_if_fail (G_IS_ACTION_GROUP (action_group), NULL);
446 : :
447 : 2 : return G_ACTION_GROUP_GET_IFACE (action_group)
448 : 2 : ->get_action_state_type (action_group, action_name);
449 : : }
450 : :
451 : : /**
452 : : * g_action_group_get_action_state_hint:
453 : : * @action_group: a [type@Gio.ActionGroup]
454 : : * @action_name: the name of the action to query
455 : : *
456 : : * Requests a hint about the valid range of values for the state of the
457 : : * named action within @action_group.
458 : : *
459 : : * If `NULL` is returned it either means that the action is not stateful
460 : : * or that there is no hint about the valid range of values for the
461 : : * state of the action.
462 : : *
463 : : * If a [type@GLib.Variant] array is returned then each item in the array is a
464 : : * possible value for the state. If a [type@GLib.Variant] pair (ie: two-tuple) is
465 : : * returned then the tuple specifies the inclusive lower and upper bound
466 : : * of valid values for the state.
467 : : *
468 : : * In any case, the information is merely a hint. It may be possible to
469 : : * have a state value outside of the hinted range and setting a value
470 : : * within the range may fail.
471 : : *
472 : : * The return value (if non-`NULL`) should be freed with
473 : : * [method@GLib.Variant.unref] when it is no longer required.
474 : : *
475 : : * Returns: (nullable) (transfer full): the state range hint
476 : : *
477 : : * Since: 2.28
478 : : **/
479 : : GVariant *
480 : 2 : g_action_group_get_action_state_hint (GActionGroup *action_group,
481 : : const gchar *action_name)
482 : : {
483 : 2 : g_return_val_if_fail (G_IS_ACTION_GROUP (action_group), NULL);
484 : :
485 : 2 : return G_ACTION_GROUP_GET_IFACE (action_group)
486 : 2 : ->get_action_state_hint (action_group, action_name);
487 : : }
488 : :
489 : : /**
490 : : * g_action_group_get_action_enabled:
491 : : * @action_group: a [type@Gio.ActionGroup]
492 : : * @action_name: the name of the action to query
493 : : *
494 : : * Checks if the named action within @action_group is currently enabled.
495 : : *
496 : : * An action must be enabled in order to be activated or in order to
497 : : * have its state changed from outside callers.
498 : : *
499 : : * Returns: whether the action is currently enabled
500 : : *
501 : : * Since: 2.28
502 : : **/
503 : : gboolean
504 : 19 : g_action_group_get_action_enabled (GActionGroup *action_group,
505 : : const gchar *action_name)
506 : : {
507 : 19 : g_return_val_if_fail (G_IS_ACTION_GROUP (action_group), FALSE);
508 : :
509 : 19 : return G_ACTION_GROUP_GET_IFACE (action_group)
510 : 19 : ->get_action_enabled (action_group, action_name);
511 : : }
512 : :
513 : : /**
514 : : * g_action_group_get_action_state:
515 : : * @action_group: a [type@Gio.ActionGroup]
516 : : * @action_name: the name of the action to query
517 : : *
518 : : * Queries the current state of the named action within @action_group.
519 : : *
520 : : * If the action is not stateful then `NULL` will be returned. If the
521 : : * action is stateful then the type of the return value is the type
522 : : * given by [method@Gio.ActionGroup.get_action_state_type].
523 : : *
524 : : * The return value (if non-`NULL`) should be freed with
525 : : * [method@GLib.Variant.unref] when it is no longer required.
526 : : *
527 : : * Returns: (nullable) (transfer full): the current state of the action
528 : : *
529 : : * Since: 2.28
530 : : **/
531 : : GVariant *
532 : 55 : g_action_group_get_action_state (GActionGroup *action_group,
533 : : const gchar *action_name)
534 : : {
535 : 55 : g_return_val_if_fail (G_IS_ACTION_GROUP (action_group), NULL);
536 : :
537 : 55 : return G_ACTION_GROUP_GET_IFACE (action_group)
538 : 55 : ->get_action_state (action_group, action_name);
539 : : }
540 : :
541 : : /**
542 : : * g_action_group_change_action_state:
543 : : * @action_group: a [type@Gio.ActionGroup]
544 : : * @action_name: the name of the action to request the change on
545 : : * @value: the new state
546 : : *
547 : : * Request for the state of the named action within @action_group to be
548 : : * changed to @value.
549 : : *
550 : : * The action must be stateful and @value must be of the correct type.
551 : : * See [method@Gio.ActionGroup.get_action_state_type].
552 : : *
553 : : * This call merely requests a change. The action may refuse to change
554 : : * its state or may change its state to something other than @value.
555 : : * See [method@Gio.ActionGroup.get_action_state_hint].
556 : : *
557 : : * If the @value GVariant is floating, it is consumed.
558 : : *
559 : : * Since: 2.28
560 : : **/
561 : : void
562 : 13 : g_action_group_change_action_state (GActionGroup *action_group,
563 : : const gchar *action_name,
564 : : GVariant *value)
565 : : {
566 : 13 : g_return_if_fail (G_IS_ACTION_GROUP (action_group));
567 : 13 : g_return_if_fail (action_name != NULL);
568 : 13 : g_return_if_fail (value != NULL);
569 : :
570 : 13 : G_ACTION_GROUP_GET_IFACE (action_group)
571 : 13 : ->change_action_state (action_group, action_name, value);
572 : : }
573 : :
574 : : /**
575 : : * g_action_group_activate_action:
576 : : * @action_group: a [type@Gio.ActionGroup]
577 : : * @action_name: the name of the action to activate
578 : : * @parameter: (nullable): parameters to the activation
579 : : *
580 : : * Activate the named action within @action_group.
581 : : *
582 : : * If the action is expecting a parameter, then the correct type of
583 : : * parameter must be given as @parameter. If the action is expecting no
584 : : * parameters then @parameter must be `NULL`. See
585 : : * [method@Gio.ActionGroup.get_action_parameter_type].
586 : : *
587 : : * If the [type@Gio.ActionGroup] implementation supports asynchronous remote
588 : : * activation over D-Bus, this call may return before the relevant
589 : : * D-Bus traffic has been sent, or any replies have been received. In
590 : : * order to block on such asynchronous activation calls,
591 : : * [method@Gio.DBusConnection.flush] should be called prior to the code, which
592 : : * depends on the result of the action activation. Without flushing
593 : : * the D-Bus connection, there is no guarantee that the action would
594 : : * have been activated.
595 : : *
596 : : * The following code which runs in a remote app instance, shows an
597 : : * example of a ‘quit’ action being activated on the primary app
598 : : * instance over D-Bus. Here [method@Gio.DBusConnection.flush] is called
599 : : * before `exit()`. Without `g_dbus_connection_flush()`, the ‘quit’ action
600 : : * may fail to be activated on the primary instance.
601 : : *
602 : : * ```c
603 : : * // call ‘quit’ action on primary instance
604 : : * g_action_group_activate_action (G_ACTION_GROUP (app), "quit", NULL);
605 : : *
606 : : * // make sure the action is activated now
607 : : * g_dbus_connection_flush (…);
608 : : *
609 : : * g_debug ("Application has been terminated. Exiting.");
610 : : *
611 : : * exit (0);
612 : : * ```
613 : : *
614 : : * Since: 2.28
615 : : **/
616 : : void
617 : 32 : g_action_group_activate_action (GActionGroup *action_group,
618 : : const gchar *action_name,
619 : : GVariant *parameter)
620 : : {
621 : 32 : g_return_if_fail (G_IS_ACTION_GROUP (action_group));
622 : 32 : g_return_if_fail (action_name != NULL);
623 : :
624 : 32 : G_ACTION_GROUP_GET_IFACE (action_group)
625 : 32 : ->activate_action (action_group, action_name, parameter);
626 : : }
627 : :
628 : : /**
629 : : * g_action_group_action_added:
630 : : * @action_group: a [type@Gio.ActionGroup]
631 : : * @action_name: the name of an action in the group
632 : : *
633 : : * Emits the [signal@Gio.ActionGroup::action-added] signal on @action_group.
634 : : *
635 : : * This function should only be called by [type@Gio.ActionGroup] implementations.
636 : : *
637 : : * Since: 2.28
638 : : **/
639 : : void
640 : 167 : g_action_group_action_added (GActionGroup *action_group,
641 : : const gchar *action_name)
642 : : {
643 : 167 : g_return_if_fail (G_IS_ACTION_GROUP (action_group));
644 : 167 : g_return_if_fail (action_name != NULL);
645 : :
646 : 167 : g_signal_emit (action_group,
647 : : g_action_group_signals[SIGNAL_ACTION_ADDED],
648 : : g_quark_try_string (action_name),
649 : : action_name);
650 : : }
651 : :
652 : : /**
653 : : * g_action_group_action_removed:
654 : : * @action_group: a [type@Gio.ActionGroup]
655 : : * @action_name: the name of an action in the group
656 : : *
657 : : * Emits the [signal@Gio.ActionGroup::action-removed] signal on @action_group.
658 : : *
659 : : * This function should only be called by [type@Gio.ActionGroup] implementations.
660 : : *
661 : : * Since: 2.28
662 : : **/
663 : : void
664 : 12 : g_action_group_action_removed (GActionGroup *action_group,
665 : : const gchar *action_name)
666 : : {
667 : 12 : g_return_if_fail (G_IS_ACTION_GROUP (action_group));
668 : 12 : g_return_if_fail (action_name != NULL);
669 : :
670 : 12 : g_signal_emit (action_group,
671 : : g_action_group_signals[SIGNAL_ACTION_REMOVED],
672 : : g_quark_try_string (action_name),
673 : : action_name);
674 : : }
675 : :
676 : : /**
677 : : * g_action_group_action_enabled_changed:
678 : : * @action_group: a [type@Gio.ActionGroup]
679 : : * @action_name: the name of an action in the group
680 : : * @enabled: whether the action is now enabled
681 : : *
682 : : * Emits the [signal@Gio.ActionGroup::action-enabled-changed] signal on @action_group.
683 : : *
684 : : * This function should only be called by [type@Gio.ActionGroup] implementations.
685 : : *
686 : : * Since: 2.28
687 : : **/
688 : : void
689 : 100003 : g_action_group_action_enabled_changed (GActionGroup *action_group,
690 : : const gchar *action_name,
691 : : gboolean enabled)
692 : : {
693 : 100003 : g_return_if_fail (G_IS_ACTION_GROUP (action_group));
694 : 100003 : g_return_if_fail (action_name != NULL);
695 : :
696 : 100003 : enabled = !!enabled;
697 : :
698 : 100003 : g_signal_emit (action_group,
699 : : g_action_group_signals[SIGNAL_ACTION_ENABLED_CHANGED],
700 : : g_quark_try_string (action_name),
701 : : action_name,
702 : : enabled);
703 : : }
704 : :
705 : : /**
706 : : * g_action_group_action_state_changed:
707 : : * @action_group: a [type@Gio.ActionGroup]
708 : : * @action_name: the name of an action in the group
709 : : * @state: the new state of the named action
710 : : *
711 : : * Emits the [signal@Gio.ActionGroup::action-state-changed] signal on @action_group.
712 : : *
713 : : * This function should only be called by [type@Gio.ActionGroup] implementations.
714 : : *
715 : : * Since: 2.28
716 : : **/
717 : : void
718 : 31 : g_action_group_action_state_changed (GActionGroup *action_group,
719 : : const gchar *action_name,
720 : : GVariant *state)
721 : : {
722 : 31 : g_return_if_fail (G_IS_ACTION_GROUP (action_group));
723 : 31 : g_return_if_fail (action_name != NULL);
724 : :
725 : 31 : g_signal_emit (action_group,
726 : : g_action_group_signals[SIGNAL_ACTION_STATE_CHANGED],
727 : : g_quark_try_string (action_name),
728 : : action_name,
729 : : state);
730 : : }
731 : :
732 : : /**
733 : : * g_action_group_query_action:
734 : : * @action_group: a [type@Gio.ActionGroup]
735 : : * @action_name: the name of an action in the group
736 : : * @enabled: (out): if the action is presently enabled
737 : : * @parameter_type: (out) (transfer none) (optional): the parameter type, or `NULL` if none needed
738 : : * @state_type: (out) (transfer none) (optional): the state type, or `NULL` if stateless
739 : : * @state_hint: (out) (optional): the state hint, or `NULL` if none
740 : : * @state: (out) (optional): the current state, or `NULL` if stateless
741 : : *
742 : : * Queries all aspects of the named action within an @action_group.
743 : : *
744 : : * This function acquires the information available from
745 : : * [method@Gio.ActionGroup.has_action], [method@Gio.ActionGroup.get_action_enabled],
746 : : * [method@Gio.ActionGroup.get_action_parameter_type],
747 : : * [method@Gio.ActionGroup.get_action_state_type],
748 : : * [method@Gio.ActionGroup.get_action_state_hint] and
749 : : * [method@Gio.ActionGroup.get_action_state] with a single function call.
750 : : *
751 : : * This provides two main benefits.
752 : : *
753 : : * The first is the improvement in efficiency that comes with not having
754 : : * to perform repeated lookups of the action in order to discover
755 : : * different things about it. The second is that implementing
756 : : * [type@Gio.ActionGroup] can now be done by only overriding this one virtual
757 : : * function.
758 : : *
759 : : * The interface provides a default implementation of this function that
760 : : * calls the individual functions, as required, to fetch the
761 : : * information. The interface also provides default implementations of
762 : : * those functions that call this function. All implementations,
763 : : * therefore, must override either this function or all of the others.
764 : : *
765 : : * If the action exists, `TRUE` is returned and any of the requested
766 : : * fields (as indicated by having a non-`NULL` reference passed in) are
767 : : * filled. If the action doesn’t exist, `FALSE` is returned and the
768 : : * fields may or may not have been modified.
769 : : *
770 : : * Returns: `TRUE` if the action exists, else `FALSE`
771 : : *
772 : : * Since: 2.32
773 : : **/
774 : : gboolean
775 : 262 : g_action_group_query_action (GActionGroup *action_group,
776 : : const gchar *action_name,
777 : : gboolean *enabled,
778 : : const GVariantType **parameter_type,
779 : : const GVariantType **state_type,
780 : : GVariant **state_hint,
781 : : GVariant **state)
782 : : {
783 : 262 : return G_ACTION_GROUP_GET_IFACE (action_group)
784 : 262 : ->query_action (action_group, action_name, enabled, parameter_type, state_type, state_hint, state);
785 : : }
|