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