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