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 "gaction.h"
24 : : #include "glibintl.h"
25 : :
26 : : #include <string.h>
27 : :
28 : 601978 : G_DEFINE_INTERFACE (GAction, g_action, G_TYPE_OBJECT)
29 : :
30 : : /**
31 : : * GAction:
32 : : *
33 : : * `GAction` represents a single named action.
34 : : *
35 : : * The main interface to an action is that it can be activated with
36 : : * [method@Gio.Action.activate]. This results in the 'activate' signal being
37 : : * emitted. An activation has a `GVariant` parameter (which may be
38 : : * `NULL`). The correct type for the parameter is determined by a static
39 : : * parameter type (which is given at construction time).
40 : : *
41 : : * An action may optionally have a state, in which case the state may be
42 : : * set with [method@Gio.Action.change_state]. This call takes a [type@GLib.Variant]. The
43 : : * correct type for the state is determined by a static state type
44 : : * (which is given at construction time).
45 : : *
46 : : * The state may have a hint associated with it, specifying its valid
47 : : * range.
48 : : *
49 : : * `GAction` is merely the interface to the concept of an action, as
50 : : * described above. Various implementations of actions exist, including
51 : : * [class@Gio.SimpleAction].
52 : : *
53 : : * In all cases, the implementing class is responsible for storing the
54 : : * name of the action, the parameter type, the enabled state, the optional
55 : : * state type and the state and emitting the appropriate signals when these
56 : : * change. The implementor is responsible for filtering calls to
57 : : * [method@Gio.Action.activate] and [method@Gio.Action.change_state]
58 : : * for type safety and for the state being enabled.
59 : : *
60 : : * Probably the only useful thing to do with a `GAction` is to put it
61 : : * inside of a [class@Gio.SimpleActionGroup].
62 : : **/
63 : :
64 : : /**
65 : : * GActionInterface:
66 : : * @get_name: the virtual function pointer for [method@Gio.Action.get_name]
67 : : * @get_parameter_type: the virtual function pointer for [method@Gio.Action.get_parameter_type]
68 : : * @get_state_type: the virtual function pointer for [method@Gio.Action.get_state_type]
69 : : * @get_state_hint: the virtual function pointer for [method@Gio.Action.get_state_hint]
70 : : * @get_enabled: the virtual function pointer for [method@Gio.Action.get_enabled]
71 : : * @get_state: the virtual function pointer for [method@Gio.Action.get_state]
72 : : * @change_state: the virtual function pointer for [method@Gio.Action.change_state]
73 : : * @activate: the virtual function pointer for [method@Gio.Action.activate]. Note that [type@Gio.Action] does not have an
74 : : * 'activate' signal but that implementations of it may have one.
75 : : *
76 : : * The virtual function table for [type@Gio.Action].
77 : : *
78 : : * Since: 2.28
79 : : */
80 : :
81 : : void
82 : 9 : g_action_default_init (GActionInterface *iface)
83 : : {
84 : : /**
85 : : * GAction:name:
86 : : *
87 : : * The name of the action. This is mostly meaningful for identifying
88 : : * the action once it has been added to a [type@Gio.ActionGroup]. It is immutable.
89 : : *
90 : : * Since: 2.28
91 : : **/
92 : 9 : g_object_interface_install_property (iface,
93 : : g_param_spec_string ("name", NULL, NULL,
94 : : NULL,
95 : : G_PARAM_READABLE |
96 : : G_PARAM_STATIC_STRINGS));
97 : :
98 : : /**
99 : : * GAction:parameter-type:
100 : : *
101 : : * The type of the parameter that must be given when activating the
102 : : * action. This is immutable, and may be `NULL` if no parameter is needed when
103 : : * activating the action.
104 : : *
105 : : * Since: 2.28
106 : : **/
107 : 9 : g_object_interface_install_property (iface,
108 : : g_param_spec_boxed ("parameter-type", NULL, NULL,
109 : : G_TYPE_VARIANT_TYPE,
110 : : G_PARAM_READABLE |
111 : : G_PARAM_STATIC_STRINGS));
112 : :
113 : : /**
114 : : * GAction:enabled:
115 : : *
116 : : * If @action is currently enabled.
117 : : *
118 : : * If the action is disabled then calls to [method@Gio.Action.activate] and
119 : : * [method@Gio.Action.change_state] have no effect.
120 : : *
121 : : * Since: 2.28
122 : : **/
123 : 9 : g_object_interface_install_property (iface,
124 : : g_param_spec_boolean ("enabled", NULL, NULL,
125 : : TRUE,
126 : : G_PARAM_READABLE |
127 : : G_PARAM_STATIC_STRINGS));
128 : :
129 : : /**
130 : : * GAction:state-type:
131 : : *
132 : : * The [type@GLib.VariantType] of the state that the action has, or `NULL` if the
133 : : * action is stateless. This is immutable.
134 : : *
135 : : * Since: 2.28
136 : : **/
137 : 9 : g_object_interface_install_property (iface,
138 : : g_param_spec_boxed ("state-type", NULL, NULL,
139 : : G_TYPE_VARIANT_TYPE,
140 : : G_PARAM_READABLE |
141 : : G_PARAM_STATIC_STRINGS));
142 : :
143 : : /**
144 : : * GAction:state:
145 : : *
146 : : * The state of the action, or `NULL` if the action is stateless.
147 : : *
148 : : * Since: 2.28
149 : : **/
150 : 9 : g_object_interface_install_property (iface,
151 : : g_param_spec_variant ("state", NULL, NULL,
152 : : G_VARIANT_TYPE_ANY,
153 : : NULL,
154 : : G_PARAM_READABLE |
155 : : G_PARAM_STATIC_STRINGS));
156 : 9 : }
157 : :
158 : : /**
159 : : * g_action_change_state:
160 : : * @action: a [type@Gio.Action]
161 : : * @value: the new state
162 : : *
163 : : * Request for the state of @action to be changed to @value.
164 : : *
165 : : * The action must be stateful and @value must be of the correct type.
166 : : * See [method@Gio.Action.get_state_type].
167 : : *
168 : : * This call merely requests a change. The action may refuse to change
169 : : * its state or may change its state to something other than @value.
170 : : * See [method@Gio.Action.get_state_hint].
171 : : *
172 : : * If the @value [type@GLib.Variant] is floating, it is consumed.
173 : : *
174 : : * Since: 2.30
175 : : **/
176 : : void
177 : 15 : g_action_change_state (GAction *action,
178 : : GVariant *value)
179 : : {
180 : : const GVariantType *state_type;
181 : :
182 : 15 : g_return_if_fail (G_IS_ACTION (action));
183 : 15 : g_return_if_fail (value != NULL);
184 : 15 : state_type = g_action_get_state_type (action);
185 : 15 : g_return_if_fail (state_type != NULL);
186 : 15 : g_return_if_fail (g_variant_is_of_type (value, state_type));
187 : :
188 : 15 : g_variant_ref_sink (value);
189 : :
190 : 15 : G_ACTION_GET_IFACE (action)
191 : 15 : ->change_state (action, value);
192 : :
193 : 15 : g_variant_unref (value);
194 : : }
195 : :
196 : : /**
197 : : * g_action_get_state:
198 : : * @action: a [type@Gio.Action]
199 : : *
200 : : * Queries the current state of @action.
201 : : *
202 : : * If the action is not stateful then `NULL` will be returned. If the
203 : : * action is stateful then the type of the return value is the type
204 : : * given by [method@Gio.Action.get_state_type].
205 : : *
206 : : * The return value (if non-`NULL`) should be freed with
207 : : * [method@GLib.Variant.unref] when it is no longer required.
208 : : *
209 : : * Returns: (nullable) (transfer full): the current state of the action
210 : : *
211 : : * Since: 2.28
212 : : **/
213 : : GVariant *
214 : 150 : g_action_get_state (GAction *action)
215 : : {
216 : 150 : g_return_val_if_fail (G_IS_ACTION (action), NULL);
217 : :
218 : 150 : return G_ACTION_GET_IFACE (action)
219 : 150 : ->get_state (action);
220 : : }
221 : :
222 : : /**
223 : : * g_action_get_name:
224 : : * @action: a [type@Gio.Action]
225 : : *
226 : : * Queries the name of @action.
227 : : *
228 : : * Returns: the name of the action
229 : : *
230 : : * Since: 2.28
231 : : **/
232 : : const gchar *
233 : 100247 : g_action_get_name (GAction *action)
234 : : {
235 : 100247 : g_return_val_if_fail (G_IS_ACTION (action), NULL);
236 : :
237 : 100247 : return G_ACTION_GET_IFACE (action)
238 : 100247 : ->get_name (action);
239 : : }
240 : :
241 : : /**
242 : : * g_action_get_parameter_type:
243 : : * @action: a [type@Gio.Action]
244 : : *
245 : : * Queries the type of the parameter that must be given when activating
246 : : * @action.
247 : : *
248 : : * When activating the action using [method@Gio.Action.activate], the
249 : : * [type@GLib.Variant] given to that function must be of the type returned by
250 : : * this function.
251 : : *
252 : : * In the case that this function returns `NULL`, you must not give any
253 : : * [type@GLib.Variant], but `NULL` instead.
254 : : *
255 : : * Returns: (nullable): the parameter type
256 : : *
257 : : * Since: 2.28
258 : : **/
259 : : const GVariantType *
260 : 108 : g_action_get_parameter_type (GAction *action)
261 : : {
262 : 108 : g_return_val_if_fail (G_IS_ACTION (action), NULL);
263 : :
264 : 108 : return G_ACTION_GET_IFACE (action)
265 : 108 : ->get_parameter_type (action);
266 : : }
267 : :
268 : : /**
269 : : * g_action_get_state_type:
270 : : * @action: a [type@Gio.Action]
271 : : *
272 : : * Queries the type of the state of @action.
273 : : *
274 : : * If the action is stateful (e.g. created with
275 : : * [ctor@Gio.SimpleAction.new_stateful]) then this function returns the
276 : : * [type@GLib.VariantType] of the state. This is the type of the initial value
277 : : * given as the state. All calls to [method@Gio.Action.change_state] must give a
278 : : * [type@GLib.Variant] of this type and [method@Gio.Action.get_state] will return a
279 : : * [type@GLib.Variant] of the same type.
280 : : *
281 : : * If the action is not stateful (e.g. created with [ctor@Gio.SimpleAction.new])
282 : : * then this function will return `NULL`. In that case, [method@Gio.Action.get_state]
283 : : * will return `NULL` and you must not call [method@Gio.Action.change_state].
284 : : *
285 : : * Returns: (nullable): the state type, if the action is stateful
286 : : *
287 : : * Since: 2.28
288 : : **/
289 : : const GVariantType *
290 : 187 : g_action_get_state_type (GAction *action)
291 : : {
292 : 187 : g_return_val_if_fail (G_IS_ACTION (action), NULL);
293 : :
294 : 187 : return G_ACTION_GET_IFACE (action)
295 : 187 : ->get_state_type (action);
296 : : }
297 : :
298 : : /**
299 : : * g_action_get_state_hint:
300 : : * @action: a [type@Gio.Action]
301 : : *
302 : : * Requests a hint about the valid range of values for the state of
303 : : * @action.
304 : : *
305 : : * If `NULL` is returned it either means that the action is not stateful
306 : : * or that there is no hint about the valid range of values for the
307 : : * state of the action.
308 : : *
309 : : * If a [type@GLib.Variant] array is returned then each item in the array is a
310 : : * possible value for the state. If a [type@GLib.Variant] pair (ie: two-tuple) is
311 : : * returned then the tuple specifies the inclusive lower and upper bound
312 : : * of valid values for the state.
313 : : *
314 : : * In any case, the information is merely a hint. It may be possible to
315 : : * have a state value outside of the hinted range and setting a value
316 : : * within the range may fail.
317 : : *
318 : : * The return value (if non-`NULL`) should be freed with
319 : : * [method@GLib.Variant.unref] when it is no longer required.
320 : : *
321 : : * Returns: (nullable) (transfer full): the state range hint
322 : : *
323 : : * Since: 2.28
324 : : **/
325 : : GVariant *
326 : 64 : g_action_get_state_hint (GAction *action)
327 : : {
328 : 64 : g_return_val_if_fail (G_IS_ACTION (action), NULL);
329 : :
330 : 64 : return G_ACTION_GET_IFACE (action)
331 : 64 : ->get_state_hint (action);
332 : : }
333 : :
334 : : /**
335 : : * g_action_get_enabled:
336 : : * @action: a [type@Gio.Action]
337 : : *
338 : : * Checks if @action is currently enabled.
339 : : *
340 : : * An action must be enabled in order to be activated or in order to
341 : : * have its state changed from outside callers.
342 : : *
343 : : * Returns: whether the action is enabled
344 : : *
345 : : * Since: 2.28
346 : : **/
347 : : gboolean
348 : 200083 : g_action_get_enabled (GAction *action)
349 : : {
350 : 200083 : g_return_val_if_fail (G_IS_ACTION (action), FALSE);
351 : :
352 : 200083 : return G_ACTION_GET_IFACE (action)
353 : 200083 : ->get_enabled (action);
354 : : }
355 : :
356 : : /**
357 : : * g_action_activate:
358 : : * @action: a [type@Gio.Action]
359 : : * @parameter: (nullable): the parameter to the activation
360 : : *
361 : : * Activates the action.
362 : : *
363 : : * @parameter must be the correct type of parameter for the action (ie:
364 : : * the parameter type given at construction time). If the parameter
365 : : * type was `NULL` then @parameter must also be `NULL`.
366 : : *
367 : : * If the @parameter [type@GLib.Variant] is floating, it is consumed.
368 : : *
369 : : * Since: 2.28
370 : : **/
371 : : void
372 : 38 : g_action_activate (GAction *action,
373 : : GVariant *parameter)
374 : : {
375 : 38 : g_return_if_fail (G_IS_ACTION (action));
376 : :
377 : 38 : if (parameter != NULL)
378 : 14 : g_variant_ref_sink (parameter);
379 : :
380 : 38 : G_ACTION_GET_IFACE (action)
381 : 38 : ->activate (action, parameter);
382 : :
383 : 38 : if (parameter != NULL)
384 : 14 : g_variant_unref (parameter);
385 : : }
386 : :
387 : : /**
388 : : * g_action_name_is_valid:
389 : : * @action_name: a potential action name
390 : : *
391 : : * Checks if @action_name is valid.
392 : : *
393 : : * @action_name is valid if it consists only of alphanumeric characters,
394 : : * plus `-` and `.`. The empty string is not a valid action name.
395 : : *
396 : : * It is an error to call this function with a non-UTF-8 @action_name.
397 : : * @action_name must not be `NULL`.
398 : : *
399 : : * Returns: `TRUE` if @action_name is valid
400 : : *
401 : : * Since: 2.38
402 : : **/
403 : : gboolean
404 : 18 : g_action_name_is_valid (const gchar *action_name)
405 : : {
406 : : gchar c;
407 : : gint i;
408 : :
409 : 18 : g_return_val_if_fail (action_name != NULL, FALSE);
410 : :
411 : 99 : for (i = 0; (c = action_name[i]); i++)
412 : 84 : if (!g_ascii_isalnum (c) && c != '.' && c != '-')
413 : 3 : return FALSE;
414 : :
415 : 15 : return i > 0;
416 : : }
417 : :
418 : : /**
419 : : * g_action_parse_detailed_name:
420 : : * @detailed_name: a detailed action name
421 : : * @action_name: (out) (optional) (not nullable) (transfer full): the action name
422 : : * @target_value: (out) (optional) (nullable) (transfer full): the target value,
423 : : * or `NULL` for no target
424 : : * @error: a pointer to a `NULL` [type@GLib.Error], or `NULL`
425 : : *
426 : : * Parses a detailed action name into its separate name and target
427 : : * components.
428 : : *
429 : : * Detailed action names can have three formats.
430 : : *
431 : : * The first format is used to represent an action name with no target
432 : : * value and consists of just an action name containing no whitespace
433 : : * nor the characters `:`, `(` or `)`. For example: `app.action`.
434 : : *
435 : : * The second format is used to represent an action with a target value
436 : : * that is a non-empty string consisting only of alphanumerics, plus `-`
437 : : * and `.`. In that case, the action name and target value are
438 : : * separated by a double colon (`::`). For example:
439 : : * `app.action::target`.
440 : : *
441 : : * The third format is used to represent an action with any type of
442 : : * target value, including strings. The target value follows the action
443 : : * name, surrounded in parens. For example: `app.action(42)`. The
444 : : * target value is parsed using [func@GLib.Variant.parse]. If a tuple-typed
445 : : * value is desired, it must be specified in the same way, resulting in
446 : : * two sets of parens, for example: `app.action((1,2,3))`. A string
447 : : * target can be specified this way as well: `app.action('target')`.
448 : : * For strings, this third format must be used if target value is
449 : : * empty or contains characters other than alphanumerics, `-` and `.`.
450 : : *
451 : : * If this function returns `TRUE`, a non-`NULL` value is guaranteed to be returned
452 : : * in @action_name (if a pointer is passed in). A `NULL` value may still be
453 : : * returned in @target_value, as the @detailed_name may not contain a target.
454 : : *
455 : : * If returned, the [type@GLib.Variant] in @target_value is guaranteed to not be floating.
456 : : *
457 : : * Returns: `TRUE` if successful, else `FALSE` with @error set
458 : : *
459 : : * Since: 2.38
460 : : **/
461 : : gboolean
462 : 35 : g_action_parse_detailed_name (const gchar *detailed_name,
463 : : gchar **action_name,
464 : : GVariant **target_value,
465 : : GError **error)
466 : : {
467 : : const gchar *target;
468 : : gsize target_len;
469 : : gsize base_len;
470 : :
471 : : /* For historical (compatibility) reasons, this function accepts some
472 : : * cases of invalid action names as long as they don't interfere with
473 : : * the separation of the action from the target value.
474 : : *
475 : : * We decide which format we have based on which we see first between
476 : : * '::' '(' and '\0'.
477 : : */
478 : :
479 : 35 : if (*detailed_name == '\0' || *detailed_name == ' ')
480 : 2 : goto bad_fmt;
481 : :
482 : 33 : base_len = strcspn (detailed_name, ": ()");
483 : 33 : target = detailed_name + base_len;
484 : 33 : target_len = strlen (target);
485 : :
486 : 33 : switch (target[0])
487 : : {
488 : 3 : case ' ':
489 : : case ')':
490 : 3 : goto bad_fmt;
491 : :
492 : 11 : case ':':
493 : 11 : if (target[1] != ':')
494 : 2 : goto bad_fmt;
495 : :
496 : 9 : *target_value = g_variant_ref_sink (g_variant_new_string (target + 2));
497 : 9 : break;
498 : :
499 : 11 : case '(':
500 : : {
501 : 11 : if (target[target_len - 1] != ')')
502 : 3 : goto bad_fmt;
503 : :
504 : 8 : *target_value = g_variant_parse (NULL, target + 1, target + target_len - 1, NULL, error);
505 : 8 : if (*target_value == NULL)
506 : 3 : goto bad_fmt;
507 : : }
508 : 5 : break;
509 : :
510 : 8 : case '\0':
511 : 8 : *target_value = NULL;
512 : 8 : break;
513 : : }
514 : :
515 : 22 : *action_name = g_strndup (detailed_name, base_len);
516 : :
517 : 22 : return TRUE;
518 : :
519 : 13 : bad_fmt:
520 : 13 : if (error)
521 : : {
522 : 12 : if (*error == NULL)
523 : 9 : g_set_error (error, G_VARIANT_PARSE_ERROR, G_VARIANT_PARSE_ERROR_FAILED,
524 : : "Detailed action name '%s' has invalid format", detailed_name);
525 : : else
526 : 3 : g_prefix_error (error, "Detailed action name '%s' has invalid format: ", detailed_name);
527 : : }
528 : :
529 : 13 : return FALSE;
530 : : }
531 : :
532 : : /**
533 : : * g_action_print_detailed_name:
534 : : * @action_name: a valid action name
535 : : * @target_value: (nullable): a [type@GLib.Variant] target value, or `NULL`
536 : : *
537 : : * Formats a detailed action name from @action_name and @target_value.
538 : : *
539 : : * It is an error to call this function with an invalid action name.
540 : : *
541 : : * This function is the opposite of [func@Gio.Action.parse_detailed_name].
542 : : * It will produce a string that can be parsed back to the @action_name
543 : : * and @target_value by that function.
544 : : *
545 : : * See that function for the types of strings that will be printed by
546 : : * this function.
547 : : *
548 : : * Returns: a detailed format string
549 : : *
550 : : * Since: 2.38
551 : : **/
552 : : gchar *
553 : 6 : g_action_print_detailed_name (const gchar *action_name,
554 : : GVariant *target_value)
555 : : {
556 : 6 : g_return_val_if_fail (g_action_name_is_valid (action_name), NULL);
557 : :
558 : 6 : if (target_value == NULL)
559 : 1 : return g_strdup (action_name);
560 : :
561 : 5 : if (g_variant_is_of_type (target_value, G_VARIANT_TYPE_STRING))
562 : : {
563 : 2 : const gchar *str = g_variant_get_string (target_value, NULL);
564 : :
565 : 2 : if (g_action_name_is_valid (str))
566 : 2 : return g_strconcat (action_name, "::", str, NULL);
567 : : }
568 : :
569 : : {
570 : 3 : GString *result = g_string_new (action_name);
571 : : g_string_append_c (result, '(');
572 : 3 : g_variant_print_string (target_value, result, TRUE);
573 : : g_string_append_c (result, ')');
574 : :
575 : 3 : return g_string_free (result, FALSE);
576 : : }
577 : : }
|