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 : :
24 : : #include "gsimpleaction.h"
25 : :
26 : : #include "gaction.h"
27 : : #include "glibintl.h"
28 : :
29 : : /**
30 : : * GSimpleAction:
31 : : *
32 : : * A `GSimpleAction` is the obvious simple implementation of the
33 : : * [iface@Gio.Action] interface. This is the easiest way to create an action for
34 : : * purposes of adding it to a [class@Gio.SimpleActionGroup].
35 : : */
36 : :
37 : : struct _GSimpleAction
38 : : {
39 : : GObject parent_instance;
40 : :
41 : : gchar *name;
42 : : GVariantType *parameter_type;
43 : : gboolean enabled;
44 : : GVariant *state;
45 : : GVariant *state_hint;
46 : : gboolean state_set_already;
47 : : };
48 : :
49 : : typedef GObjectClass GSimpleActionClass;
50 : :
51 : : static void g_simple_action_iface_init (GActionInterface *iface);
52 : 501677 : G_DEFINE_TYPE_WITH_CODE (GSimpleAction, g_simple_action, G_TYPE_OBJECT,
53 : : G_IMPLEMENT_INTERFACE (G_TYPE_ACTION, g_simple_action_iface_init))
54 : :
55 : : enum
56 : : {
57 : : PROP_NONE,
58 : : PROP_NAME,
59 : : PROP_PARAMETER_TYPE,
60 : : PROP_ENABLED,
61 : : PROP_STATE_TYPE,
62 : : PROP_STATE
63 : : };
64 : :
65 : : enum
66 : : {
67 : : SIGNAL_CHANGE_STATE,
68 : : SIGNAL_ACTIVATE,
69 : : NR_SIGNALS
70 : : };
71 : :
72 : : static guint g_simple_action_signals[NR_SIGNALS];
73 : :
74 : : static const gchar *
75 : 100227 : g_simple_action_get_name (GAction *action)
76 : : {
77 : 100227 : GSimpleAction *simple = G_SIMPLE_ACTION (action);
78 : :
79 : 100227 : return simple->name;
80 : : }
81 : :
82 : : static const GVariantType *
83 : 110 : g_simple_action_get_parameter_type (GAction *action)
84 : : {
85 : 110 : GSimpleAction *simple = G_SIMPLE_ACTION (action);
86 : :
87 : 110 : return simple->parameter_type;
88 : : }
89 : :
90 : : static const GVariantType *
91 : 175 : g_simple_action_get_state_type (GAction *action)
92 : : {
93 : 175 : GSimpleAction *simple = G_SIMPLE_ACTION (action);
94 : :
95 : 175 : if (simple->state != NULL)
96 : 52 : return g_variant_get_type (simple->state);
97 : : else
98 : 123 : return NULL;
99 : : }
100 : :
101 : : static GVariant *
102 : 64 : g_simple_action_get_state_hint (GAction *action)
103 : : {
104 : 64 : GSimpleAction *simple = G_SIMPLE_ACTION (action);
105 : :
106 : 64 : if (simple->state_hint != NULL)
107 : 0 : return g_variant_ref (simple->state_hint);
108 : : else
109 : 64 : return NULL;
110 : : }
111 : :
112 : : static gboolean
113 : 200089 : g_simple_action_get_enabled (GAction *action)
114 : : {
115 : 200089 : GSimpleAction *simple = G_SIMPLE_ACTION (action);
116 : :
117 : 200089 : return simple->enabled;
118 : : }
119 : :
120 : : static void
121 : 9 : g_simple_action_change_state (GAction *action,
122 : : GVariant *value)
123 : : {
124 : 9 : GSimpleAction *simple = G_SIMPLE_ACTION (action);
125 : :
126 : : /* If the user connected a signal handler then they are responsible
127 : : * for handling state changes.
128 : : */
129 : 9 : if (g_signal_has_handler_pending (action, g_simple_action_signals[SIGNAL_CHANGE_STATE], 0, TRUE))
130 : 2 : g_signal_emit (action, g_simple_action_signals[SIGNAL_CHANGE_STATE], 0, value);
131 : :
132 : : /* If not, then the default behaviour is to just set the state. */
133 : : else
134 : 7 : g_simple_action_set_state (simple, value);
135 : 9 : }
136 : :
137 : : /**
138 : : * g_simple_action_set_state:
139 : : * @simple: a #GSimpleAction
140 : : * @value: the new #GVariant for the state
141 : : *
142 : : * Sets the state of the action.
143 : : *
144 : : * This directly updates the 'state' property to the given value.
145 : : *
146 : : * This should only be called by the implementor of the action. Users
147 : : * of the action should not attempt to directly modify the 'state'
148 : : * property. Instead, they should call g_action_change_state() to
149 : : * request the change.
150 : : *
151 : : * If the @value GVariant is floating, it is consumed.
152 : : *
153 : : * Since: 2.30
154 : : **/
155 : : void
156 : 14 : g_simple_action_set_state (GSimpleAction *simple,
157 : : GVariant *value)
158 : : {
159 : 14 : g_return_if_fail (G_IS_SIMPLE_ACTION (simple));
160 : 14 : g_return_if_fail (value != NULL);
161 : :
162 : : {
163 : : const GVariantType *state_type;
164 : :
165 : 28 : state_type = simple->state ?
166 : 14 : g_variant_get_type (simple->state) : NULL;
167 : 14 : g_return_if_fail (state_type != NULL);
168 : 13 : g_return_if_fail (g_variant_is_of_type (value, state_type));
169 : : }
170 : :
171 : 12 : g_variant_ref_sink (value);
172 : :
173 : 12 : if (!simple->state || !g_variant_equal (simple->state, value))
174 : : {
175 : 12 : if (simple->state)
176 : 12 : g_variant_unref (simple->state);
177 : :
178 : 12 : simple->state = g_variant_ref (value);
179 : :
180 : 12 : g_object_notify (G_OBJECT (simple), "state");
181 : : }
182 : :
183 : 12 : g_variant_unref (value);
184 : : }
185 : :
186 : : static GVariant *
187 : 110 : g_simple_action_get_state (GAction *action)
188 : : {
189 : 110 : GSimpleAction *simple = G_SIMPLE_ACTION (action);
190 : :
191 : 110 : return simple->state ? g_variant_ref (simple->state) : NULL;
192 : : }
193 : :
194 : : static void
195 : 29 : g_simple_action_activate (GAction *action,
196 : : GVariant *parameter)
197 : : {
198 : 29 : GSimpleAction *simple = G_SIMPLE_ACTION (action);
199 : :
200 : 29 : g_return_if_fail (simple->parameter_type == NULL ?
201 : : parameter == NULL :
202 : : (parameter != NULL &&
203 : : g_variant_is_of_type (parameter,
204 : : simple->parameter_type)));
205 : :
206 : 27 : if (parameter != NULL)
207 : 9 : g_variant_ref_sink (parameter);
208 : :
209 : 27 : if (simple->enabled)
210 : : {
211 : : /* If the user connected a signal handler then they are responsible
212 : : * for handling activation.
213 : : */
214 : 26 : if (g_signal_has_handler_pending (action, g_simple_action_signals[SIGNAL_ACTIVATE], 0, TRUE))
215 : 23 : g_signal_emit (action, g_simple_action_signals[SIGNAL_ACTIVATE], 0, parameter);
216 : :
217 : : /* If not, do some reasonable defaults for stateful actions. */
218 : 3 : else if (simple->state)
219 : : {
220 : : /* If we have no parameter and this is a boolean action, toggle. */
221 : 3 : if (parameter == NULL && g_variant_is_of_type (simple->state, G_VARIANT_TYPE_BOOLEAN))
222 : 2 : {
223 : 2 : gboolean was_enabled = g_variant_get_boolean (simple->state);
224 : 2 : g_simple_action_change_state (action, g_variant_new_boolean (!was_enabled));
225 : : }
226 : :
227 : : /* else, if the parameter and state type are the same, do a change-state */
228 : 1 : else if (g_variant_is_of_type (simple->state, g_variant_get_type (parameter)))
229 : 1 : g_simple_action_change_state (action, parameter);
230 : : }
231 : : }
232 : :
233 : 27 : if (parameter != NULL)
234 : 9 : g_variant_unref (parameter);
235 : : }
236 : :
237 : : static void
238 : 480 : g_simple_action_set_property (GObject *object,
239 : : guint prop_id,
240 : : const GValue *value,
241 : : GParamSpec *pspec)
242 : : {
243 : 480 : GSimpleAction *action = G_SIMPLE_ACTION (object);
244 : :
245 : 480 : switch (prop_id)
246 : : {
247 : 160 : case PROP_NAME:
248 : 160 : action->name = g_strdup (g_value_get_string (value));
249 : 160 : break;
250 : :
251 : 160 : case PROP_PARAMETER_TYPE:
252 : 160 : action->parameter_type = g_value_dup_boxed (value);
253 : 160 : break;
254 : :
255 : 0 : case PROP_ENABLED:
256 : 0 : action->enabled = g_value_get_boolean (value);
257 : 0 : break;
258 : :
259 : 160 : case PROP_STATE:
260 : : /* The first time we see this (during construct) we should just
261 : : * take the state as it was handed to us.
262 : : *
263 : : * After that, we should make sure we go through the same checks
264 : : * as the C API.
265 : : */
266 : 160 : if (!action->state_set_already)
267 : : {
268 : 160 : action->state = g_value_dup_variant (value);
269 : 160 : action->state_set_already = TRUE;
270 : : }
271 : : else
272 : 0 : g_simple_action_set_state (action, g_value_get_variant (value));
273 : :
274 : 160 : break;
275 : :
276 : 0 : default:
277 : : g_assert_not_reached ();
278 : : }
279 : 480 : }
280 : :
281 : : static void
282 : 14 : g_simple_action_get_property (GObject *object,
283 : : guint prop_id,
284 : : GValue *value,
285 : : GParamSpec *pspec)
286 : : {
287 : 14 : GAction *action = G_ACTION (object);
288 : :
289 : 14 : switch (prop_id)
290 : : {
291 : 2 : case PROP_NAME:
292 : 2 : g_value_set_string (value, g_simple_action_get_name (action));
293 : 2 : break;
294 : :
295 : 2 : case PROP_PARAMETER_TYPE:
296 : 2 : g_value_set_boxed (value, g_simple_action_get_parameter_type (action));
297 : 2 : break;
298 : :
299 : 6 : case PROP_ENABLED:
300 : 6 : g_value_set_boolean (value, g_simple_action_get_enabled (action));
301 : 6 : break;
302 : :
303 : 2 : case PROP_STATE_TYPE:
304 : 2 : g_value_set_boxed (value, g_simple_action_get_state_type (action));
305 : 2 : break;
306 : :
307 : 2 : case PROP_STATE:
308 : 2 : g_value_take_variant (value, g_simple_action_get_state (action));
309 : 2 : break;
310 : :
311 : 0 : default:
312 : : g_assert_not_reached ();
313 : : }
314 : 14 : }
315 : :
316 : : static void
317 : 159 : g_simple_action_finalize (GObject *object)
318 : : {
319 : 159 : GSimpleAction *simple = G_SIMPLE_ACTION (object);
320 : :
321 : 159 : g_free (simple->name);
322 : 159 : if (simple->parameter_type)
323 : 44 : g_variant_type_free (simple->parameter_type);
324 : 159 : if (simple->state)
325 : 24 : g_variant_unref (simple->state);
326 : 159 : if (simple->state_hint)
327 : 0 : g_variant_unref (simple->state_hint);
328 : :
329 : 159 : G_OBJECT_CLASS (g_simple_action_parent_class)
330 : 159 : ->finalize (object);
331 : 159 : }
332 : :
333 : : void
334 : 160 : g_simple_action_init (GSimpleAction *simple)
335 : : {
336 : 160 : simple->enabled = TRUE;
337 : 160 : }
338 : :
339 : : void
340 : 7 : g_simple_action_iface_init (GActionInterface *iface)
341 : : {
342 : 7 : iface->get_name = g_simple_action_get_name;
343 : 7 : iface->get_parameter_type = g_simple_action_get_parameter_type;
344 : 7 : iface->get_state_type = g_simple_action_get_state_type;
345 : 7 : iface->get_state_hint = g_simple_action_get_state_hint;
346 : 7 : iface->get_enabled = g_simple_action_get_enabled;
347 : 7 : iface->get_state = g_simple_action_get_state;
348 : 7 : iface->change_state = g_simple_action_change_state;
349 : 7 : iface->activate = g_simple_action_activate;
350 : 7 : }
351 : :
352 : : void
353 : 7 : g_simple_action_class_init (GSimpleActionClass *class)
354 : : {
355 : 7 : GObjectClass *object_class = G_OBJECT_CLASS (class);
356 : :
357 : 7 : object_class->set_property = g_simple_action_set_property;
358 : 7 : object_class->get_property = g_simple_action_get_property;
359 : 7 : object_class->finalize = g_simple_action_finalize;
360 : :
361 : : /**
362 : : * GSimpleAction::activate:
363 : : * @simple: the #GSimpleAction
364 : : * @parameter: (nullable): the parameter to the activation, or %NULL if it has
365 : : * no parameter
366 : : *
367 : : * Indicates that the action was just activated.
368 : : *
369 : : * @parameter will always be of the expected type, i.e. the parameter type
370 : : * specified when the action was created. If an incorrect type is given when
371 : : * activating the action, this signal is not emitted.
372 : : *
373 : : * Since GLib 2.40, if no handler is connected to this signal then the
374 : : * default behaviour for boolean-stated actions with a %NULL parameter
375 : : * type is to toggle them via the #GSimpleAction::change-state signal.
376 : : * For stateful actions where the state type is equal to the parameter
377 : : * type, the default is to forward them directly to
378 : : * #GSimpleAction::change-state. This should allow almost all users
379 : : * of #GSimpleAction to connect only one handler or the other.
380 : : *
381 : : * Since: 2.28
382 : : */
383 : 7 : g_simple_action_signals[SIGNAL_ACTIVATE] =
384 : 7 : g_signal_new (I_("activate"),
385 : : G_TYPE_SIMPLE_ACTION,
386 : : G_SIGNAL_RUN_LAST | G_SIGNAL_MUST_COLLECT,
387 : : 0, NULL, NULL,
388 : : NULL,
389 : : G_TYPE_NONE, 1,
390 : : G_TYPE_VARIANT);
391 : :
392 : : /**
393 : : * GSimpleAction::change-state:
394 : : * @simple: the #GSimpleAction
395 : : * @value: (nullable): the requested value for the state
396 : : *
397 : : * Indicates that the action just received a request to change its
398 : : * state.
399 : : *
400 : : * @value will always be of the correct state type, i.e. the type of the
401 : : * initial state passed to g_simple_action_new_stateful(). If an incorrect
402 : : * type is given when requesting to change the state, this signal is not
403 : : * emitted.
404 : : *
405 : : * If no handler is connected to this signal then the default
406 : : * behaviour is to call g_simple_action_set_state() to set the state
407 : : * to the requested value. If you connect a signal handler then no
408 : : * default action is taken. If the state should change then you must
409 : : * call g_simple_action_set_state() from the handler.
410 : : *
411 : : * An example of a 'change-state' handler:
412 : : * |[<!-- language="C" -->
413 : : * static void
414 : : * change_volume_state (GSimpleAction *action,
415 : : * GVariant *value,
416 : : * gpointer user_data)
417 : : * {
418 : : * gint requested;
419 : : *
420 : : * requested = g_variant_get_int32 (value);
421 : : *
422 : : * // Volume only goes from 0 to 10
423 : : * if (0 <= requested && requested <= 10)
424 : : * g_simple_action_set_state (action, value);
425 : : * }
426 : : * ]|
427 : : *
428 : : * The handler need not set the state to the requested value.
429 : : * It could set it to any value at all, or take some other action.
430 : : *
431 : : * Since: 2.30
432 : : */
433 : 7 : g_simple_action_signals[SIGNAL_CHANGE_STATE] =
434 : 7 : g_signal_new (I_("change-state"),
435 : : G_TYPE_SIMPLE_ACTION,
436 : : G_SIGNAL_RUN_LAST | G_SIGNAL_MUST_COLLECT,
437 : : 0, NULL, NULL,
438 : : NULL,
439 : : G_TYPE_NONE, 1,
440 : : G_TYPE_VARIANT);
441 : :
442 : : /**
443 : : * GSimpleAction:name:
444 : : *
445 : : * The name of the action. This is mostly meaningful for identifying
446 : : * the action once it has been added to a #GSimpleActionGroup.
447 : : *
448 : : * Since: 2.28
449 : : **/
450 : 7 : g_object_class_install_property (object_class, PROP_NAME,
451 : : g_param_spec_string ("name", NULL, NULL,
452 : : NULL,
453 : : G_PARAM_READWRITE |
454 : : G_PARAM_CONSTRUCT_ONLY |
455 : : G_PARAM_STATIC_STRINGS));
456 : :
457 : : /**
458 : : * GSimpleAction:parameter-type:
459 : : *
460 : : * The type of the parameter that must be given when activating the
461 : : * action.
462 : : *
463 : : * Since: 2.28
464 : : **/
465 : 7 : g_object_class_install_property (object_class, PROP_PARAMETER_TYPE,
466 : : g_param_spec_boxed ("parameter-type", NULL, NULL,
467 : : G_TYPE_VARIANT_TYPE,
468 : : G_PARAM_READWRITE |
469 : : G_PARAM_CONSTRUCT_ONLY |
470 : : G_PARAM_STATIC_STRINGS));
471 : :
472 : : /**
473 : : * GSimpleAction:enabled:
474 : : *
475 : : * If @action is currently enabled.
476 : : *
477 : : * If the action is disabled then calls to g_action_activate() and
478 : : * g_action_change_state() have no effect.
479 : : *
480 : : * Since: 2.28
481 : : **/
482 : 7 : g_object_class_install_property (object_class, PROP_ENABLED,
483 : : g_param_spec_boolean ("enabled", NULL, NULL,
484 : : TRUE,
485 : : G_PARAM_READWRITE |
486 : : G_PARAM_STATIC_STRINGS));
487 : :
488 : : /**
489 : : * GSimpleAction:state-type:
490 : : *
491 : : * The #GVariantType of the state that the action has, or %NULL if the
492 : : * action is stateless.
493 : : *
494 : : * Since: 2.28
495 : : **/
496 : 7 : g_object_class_install_property (object_class, PROP_STATE_TYPE,
497 : : g_param_spec_boxed ("state-type", NULL, NULL,
498 : : G_TYPE_VARIANT_TYPE,
499 : : G_PARAM_READABLE |
500 : : G_PARAM_STATIC_STRINGS));
501 : :
502 : : /**
503 : : * GSimpleAction:state:
504 : : *
505 : : * The state of the action, or %NULL if the action is stateless.
506 : : *
507 : : * Since: 2.28
508 : : **/
509 : 7 : g_object_class_install_property (object_class, PROP_STATE,
510 : : g_param_spec_variant ("state", NULL, NULL,
511 : : G_VARIANT_TYPE_ANY,
512 : : NULL,
513 : : G_PARAM_READWRITE | G_PARAM_CONSTRUCT |
514 : : G_PARAM_STATIC_STRINGS));
515 : 7 : }
516 : :
517 : : /**
518 : : * g_simple_action_set_enabled:
519 : : * @simple: a #GSimpleAction
520 : : * @enabled: whether the action is enabled
521 : : *
522 : : * Sets the action as enabled or not.
523 : : *
524 : : * An action must be enabled in order to be activated or in order to
525 : : * have its state changed from outside callers.
526 : : *
527 : : * This should only be called by the implementor of the action. Users
528 : : * of the action should not attempt to modify its enabled flag.
529 : : *
530 : : * Since: 2.28
531 : : **/
532 : : void
533 : 100005 : g_simple_action_set_enabled (GSimpleAction *simple,
534 : : gboolean enabled)
535 : : {
536 : 100005 : g_return_if_fail (G_IS_SIMPLE_ACTION (simple));
537 : :
538 : 100005 : enabled = !!enabled;
539 : :
540 : 100005 : if (simple->enabled != enabled)
541 : : {
542 : 100005 : simple->enabled = enabled;
543 : 100005 : g_object_notify (G_OBJECT (simple), "enabled");
544 : : }
545 : : }
546 : :
547 : : /**
548 : : * g_simple_action_set_state_hint:
549 : : * @simple: a #GSimpleAction
550 : : * @state_hint: (nullable): a #GVariant representing the state hint
551 : : *
552 : : * Sets the state hint for the action.
553 : : *
554 : : * See g_action_get_state_hint() for more information about
555 : : * action state hints.
556 : : *
557 : : * Since: 2.44
558 : : **/
559 : : void
560 : 0 : g_simple_action_set_state_hint (GSimpleAction *simple,
561 : : GVariant *state_hint)
562 : : {
563 : 0 : g_return_if_fail (G_IS_SIMPLE_ACTION (simple));
564 : :
565 : 0 : if (simple->state_hint != NULL)
566 : : {
567 : 0 : g_variant_unref (simple->state_hint);
568 : 0 : simple->state_hint = NULL;
569 : : }
570 : :
571 : 0 : if (state_hint != NULL)
572 : 0 : simple->state_hint = g_variant_ref (state_hint);
573 : : }
574 : :
575 : : /**
576 : : * g_simple_action_new:
577 : : * @name: the name of the action
578 : : * @parameter_type: (nullable): the type of parameter that will be passed to
579 : : * handlers for the #GSimpleAction::activate signal, or %NULL for no parameter
580 : : *
581 : : * Creates a new action.
582 : : *
583 : : * The created action is stateless. See g_simple_action_new_stateful() to create
584 : : * an action that has state.
585 : : *
586 : : * Returns: a new #GSimpleAction
587 : : *
588 : : * Since: 2.28
589 : : **/
590 : : GSimpleAction *
591 : 134 : g_simple_action_new (const gchar *name,
592 : : const GVariantType *parameter_type)
593 : : {
594 : 134 : g_return_val_if_fail (name != NULL, NULL);
595 : :
596 : 133 : return g_object_new (G_TYPE_SIMPLE_ACTION,
597 : : "name", name,
598 : : "parameter-type", parameter_type,
599 : : NULL);
600 : : }
601 : :
602 : : /**
603 : : * g_simple_action_new_stateful:
604 : : * @name: the name of the action
605 : : * @parameter_type: (nullable): the type of the parameter that will be passed to
606 : : * handlers for the #GSimpleAction::activate signal, or %NULL for no parameter
607 : : * @state: the initial state of the action
608 : : *
609 : : * Creates a new stateful action.
610 : : *
611 : : * All future state values must have the same #GVariantType as the initial
612 : : * @state.
613 : : *
614 : : * If the @state #GVariant is floating, it is consumed.
615 : : *
616 : : * Returns: a new #GSimpleAction
617 : : *
618 : : * Since: 2.28
619 : : **/
620 : : GSimpleAction *
621 : 25 : g_simple_action_new_stateful (const gchar *name,
622 : : const GVariantType *parameter_type,
623 : : GVariant *state)
624 : : {
625 : 25 : return g_object_new (G_TYPE_SIMPLE_ACTION,
626 : : "name", name,
627 : : "parameter-type", parameter_type,
628 : : "state", state,
629 : : NULL);
630 : : }
|