Coverage Report

Created: 2025-07-23 08:13

/src/pango/subprojects/glib/gio/gactiongroup.c
Line
Count
Source (jump to first uncovered line)
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
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
0
{
116
0
  return g_action_group_query_action (action_group, action_name, NULL, NULL, NULL, NULL, NULL);
117
0
}
118
119
static gboolean
120
g_action_group_real_get_action_enabled (GActionGroup *action_group,
121
                                        const gchar  *action_name)
122
0
{
123
0
  gboolean enabled;
124
125
0
  if (!g_action_group_query_action (action_group, action_name, &enabled, NULL, NULL, NULL, NULL))
126
0
    return FALSE;
127
128
0
  return enabled;
129
0
}
130
131
static const GVariantType *
132
g_action_group_real_get_action_parameter_type (GActionGroup *action_group,
133
                                               const gchar  *action_name)
134
0
{
135
0
  const GVariantType *type;
136
137
0
  if (!g_action_group_query_action (action_group, action_name, NULL, &type, NULL, NULL, NULL))
138
0
    return NULL;
139
140
0
  return type;
141
0
}
142
143
static const GVariantType *
144
g_action_group_real_get_action_state_type (GActionGroup *action_group,
145
                                           const gchar  *action_name)
146
0
{
147
0
  const GVariantType *type;
148
149
0
  if (!g_action_group_query_action (action_group, action_name, NULL, NULL, &type, NULL, NULL))
150
0
    return NULL;
151
152
0
  return type;
153
0
}
154
155
static GVariant *
156
g_action_group_real_get_action_state_hint (GActionGroup *action_group,
157
                                           const gchar  *action_name)
158
0
{
159
0
  GVariant *hint;
160
161
0
  if (!g_action_group_query_action (action_group, action_name, NULL, NULL, NULL, &hint, NULL))
162
0
    return NULL;
163
164
0
  return hint;
165
0
}
166
167
static GVariant *
168
g_action_group_real_get_action_state (GActionGroup *action_group,
169
                                      const gchar  *action_name)
170
0
{
171
0
  GVariant *state;
172
173
0
  if (!g_action_group_query_action (action_group, action_name, NULL, NULL, NULL, NULL, &state))
174
0
    return NULL;
175
176
0
  return state;
177
0
}
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
0
{
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
0
                 iface->get_action_enabled == g_action_group_real_get_action_enabled ||
198
0
                 iface->get_action_parameter_type == g_action_group_real_get_action_parameter_type ||
199
0
                 iface->get_action_state_type == g_action_group_real_get_action_state_type ||
200
0
                 iface->get_action_state_hint == g_action_group_real_get_action_state_hint ||
201
0
                 iface->get_action_state == g_action_group_real_get_action_state)
202
0
    {
203
0
      g_critical ("Class ‘%s’ implements GActionGroup interface without overriding "
204
0
                  "query_action() method. Bailing out to avoid infinite recursion.",
205
0
                  G_OBJECT_TYPE_NAME (action_group));
206
0
      return FALSE;
207
0
    }
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
0
}
229
230
static void
231
g_action_group_default_init (GActionGroupInterface *iface)
232
0
{
233
0
  iface->has_action = g_action_group_real_has_action;
234
0
  iface->get_action_enabled = g_action_group_real_get_action_enabled;
235
0
  iface->get_action_parameter_type = g_action_group_real_get_action_parameter_type;
236
0
  iface->get_action_state_type = g_action_group_real_get_action_state_type;
237
0
  iface->get_action_state_hint = g_action_group_real_get_action_state_hint;
238
0
  iface->get_action_state = g_action_group_real_get_action_state;
239
0
  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
0
  g_action_group_signals[SIGNAL_ACTION_ADDED] =
254
0
    g_signal_new (I_("action-added"),
255
0
                  G_TYPE_ACTION_GROUP,
256
0
                  G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
257
0
                  G_STRUCT_OFFSET (GActionGroupInterface, action_added),
258
0
                  NULL, NULL,
259
0
                  NULL,
260
0
                  G_TYPE_NONE, 1,
261
0
                  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
0
  g_action_group_signals[SIGNAL_ACTION_REMOVED] =
276
0
    g_signal_new (I_("action-removed"),
277
0
                  G_TYPE_ACTION_GROUP,
278
0
                  G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
279
0
                  G_STRUCT_OFFSET (GActionGroupInterface, action_removed),
280
0
                  NULL, NULL,
281
0
                  NULL,
282
0
                  G_TYPE_NONE, 1,
283
0
                  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
0
  g_action_group_signals[SIGNAL_ACTION_ENABLED_CHANGED] =
296
0
    g_signal_new (I_("action-enabled-changed"),
297
0
                  G_TYPE_ACTION_GROUP,
298
0
                  G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
299
0
                  G_STRUCT_OFFSET (GActionGroupInterface,
300
0
                                   action_enabled_changed),
301
0
                  NULL, NULL,
302
0
                  _g_cclosure_marshal_VOID__STRING_BOOLEAN,
303
0
                  G_TYPE_NONE, 2,
304
0
                  G_TYPE_STRING,
305
0
                  G_TYPE_BOOLEAN);
306
0
  g_signal_set_va_marshaller (g_action_group_signals[SIGNAL_ACTION_ENABLED_CHANGED],
307
0
                              G_TYPE_FROM_INTERFACE (iface),
308
0
                              _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
0
  g_action_group_signals[SIGNAL_ACTION_STATE_CHANGED] =
321
0
    g_signal_new (I_("action-state-changed"),
322
0
                  G_TYPE_ACTION_GROUP,
323
0
                  G_SIGNAL_RUN_LAST |
324
0
                  G_SIGNAL_DETAILED |
325
0
                  G_SIGNAL_MUST_COLLECT,
326
0
                  G_STRUCT_OFFSET (GActionGroupInterface,
327
0
                                   action_state_changed),
328
0
                  NULL, NULL,
329
0
                  _g_cclosure_marshal_VOID__STRING_VARIANT,
330
0
                  G_TYPE_NONE, 2,
331
0
                  G_TYPE_STRING,
332
0
                  G_TYPE_VARIANT);
333
0
  g_signal_set_va_marshaller (g_action_group_signals[SIGNAL_ACTION_STATE_CHANGED],
334
0
                              G_TYPE_FROM_INTERFACE (iface),
335
0
                              _g_cclosure_marshal_VOID__STRING_VARIANTv);
336
0
}
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
g_action_group_list_actions (GActionGroup *action_group)
354
0
{
355
0
  g_return_val_if_fail (G_IS_ACTION_GROUP (action_group), NULL);
356
357
0
  return G_ACTION_GROUP_GET_IFACE (action_group)
358
0
    ->list_actions (action_group);
359
0
}
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
g_action_group_has_action (GActionGroup *action_group,
374
                           const gchar  *action_name)
375
0
{
376
0
  g_return_val_if_fail (G_IS_ACTION_GROUP (action_group), FALSE);
377
378
0
  return G_ACTION_GROUP_GET_IFACE (action_group)
379
0
    ->has_action (action_group, action_name);
380
0
}
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
g_action_group_get_action_parameter_type (GActionGroup *action_group,
407
                                          const gchar  *action_name)
408
0
{
409
0
  g_return_val_if_fail (G_IS_ACTION_GROUP (action_group), NULL);
410
411
0
  return G_ACTION_GROUP_GET_IFACE (action_group)
412
0
    ->get_action_parameter_type (action_group, action_name);
413
0
}
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
g_action_group_get_action_state_type (GActionGroup *action_group,
443
                                      const gchar  *action_name)
444
0
{
445
0
  g_return_val_if_fail (G_IS_ACTION_GROUP (action_group), NULL);
446
447
0
  return G_ACTION_GROUP_GET_IFACE (action_group)
448
0
    ->get_action_state_type (action_group, action_name);
449
0
}
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
g_action_group_get_action_state_hint (GActionGroup *action_group,
481
                                      const gchar  *action_name)
482
0
{
483
0
  g_return_val_if_fail (G_IS_ACTION_GROUP (action_group), NULL);
484
485
0
  return G_ACTION_GROUP_GET_IFACE (action_group)
486
0
    ->get_action_state_hint (action_group, action_name);
487
0
}
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
g_action_group_get_action_enabled (GActionGroup *action_group,
505
                                   const gchar  *action_name)
506
0
{
507
0
  g_return_val_if_fail (G_IS_ACTION_GROUP (action_group), FALSE);
508
509
0
  return G_ACTION_GROUP_GET_IFACE (action_group)
510
0
    ->get_action_enabled (action_group, action_name);
511
0
}
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
g_action_group_get_action_state (GActionGroup *action_group,
533
                                 const gchar  *action_name)
534
0
{
535
0
  g_return_val_if_fail (G_IS_ACTION_GROUP (action_group), NULL);
536
537
0
  return G_ACTION_GROUP_GET_IFACE (action_group)
538
0
    ->get_action_state (action_group, action_name);
539
0
}
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
g_action_group_change_action_state (GActionGroup *action_group,
563
                                    const gchar  *action_name,
564
                                    GVariant     *value)
565
0
{
566
0
  g_return_if_fail (G_IS_ACTION_GROUP (action_group));
567
0
  g_return_if_fail (action_name != NULL);
568
0
  g_return_if_fail (value != NULL);
569
570
0
  G_ACTION_GROUP_GET_IFACE (action_group)
571
0
    ->change_action_state (action_group, action_name, value);
572
0
}
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
g_action_group_activate_action (GActionGroup *action_group,
618
                                const gchar  *action_name,
619
                                GVariant     *parameter)
620
0
{
621
0
  g_return_if_fail (G_IS_ACTION_GROUP (action_group));
622
0
  g_return_if_fail (action_name != NULL);
623
624
0
  G_ACTION_GROUP_GET_IFACE (action_group)
625
0
    ->activate_action (action_group, action_name, parameter);
626
0
}
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
g_action_group_action_added (GActionGroup *action_group,
641
                             const gchar  *action_name)
642
0
{
643
0
  g_return_if_fail (G_IS_ACTION_GROUP (action_group));
644
0
  g_return_if_fail (action_name != NULL);
645
646
0
  g_signal_emit (action_group,
647
0
                 g_action_group_signals[SIGNAL_ACTION_ADDED],
648
0
                 g_quark_try_string (action_name),
649
0
                 action_name);
650
0
}
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
g_action_group_action_removed (GActionGroup *action_group,
665
                               const gchar  *action_name)
666
0
{
667
0
  g_return_if_fail (G_IS_ACTION_GROUP (action_group));
668
0
  g_return_if_fail (action_name != NULL);
669
670
0
  g_signal_emit (action_group,
671
0
                 g_action_group_signals[SIGNAL_ACTION_REMOVED],
672
0
                 g_quark_try_string (action_name),
673
0
                 action_name);
674
0
}
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
g_action_group_action_enabled_changed (GActionGroup *action_group,
690
                                       const gchar  *action_name,
691
                                       gboolean      enabled)
692
0
{
693
0
  g_return_if_fail (G_IS_ACTION_GROUP (action_group));
694
0
  g_return_if_fail (action_name != NULL);
695
696
0
  enabled = !!enabled;
697
698
0
  g_signal_emit (action_group,
699
0
                 g_action_group_signals[SIGNAL_ACTION_ENABLED_CHANGED],
700
0
                 g_quark_try_string (action_name),
701
0
                 action_name,
702
0
                 enabled);
703
0
}
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
g_action_group_action_state_changed (GActionGroup *action_group,
719
                                     const gchar  *action_name,
720
                                     GVariant     *state)
721
0
{
722
0
  g_return_if_fail (G_IS_ACTION_GROUP (action_group));
723
0
  g_return_if_fail (action_name != NULL);
724
725
0
  g_signal_emit (action_group,
726
0
                 g_action_group_signals[SIGNAL_ACTION_STATE_CHANGED],
727
0
                 g_quark_try_string (action_name),
728
0
                 action_name,
729
0
                 state);
730
0
}
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
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
0
{
783
0
  return G_ACTION_GROUP_GET_IFACE (action_group)
784
0
    ->query_action (action_group, action_name, enabled, parameter_type, state_type, state_hint, state);
785
0
}