add GActionGroup base class
[platform/upstream/glib.git] / gio / gactiongroup.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 "gactiongroup.h"
23 #include "gio-marshal.h"
24
25 /**
26  * SECTION:gactiongroup
27  * @title: GActionGroup
28  * @short_description: a group of actions
29  *
30  * #GActionGroup represents a group of actions.
31  *
32  * Each action in the group has a unique name (which is a string).  All
33  * method calls, except g_action_group_list_actions() take the name of
34  * an action as an argument.
35  *
36  * The #GActionGroup API is meant to be the 'public' API to the action
37  * group.  The calls here are exactly the interaction that 'external
38  * forces' (eg: UI, incoming D-Bus messages, etc.) are supposed to have
39  * with actions.  'Internal' APIs (ie: ones meant only to be accessed by
40  * the action group implementation) are found on subclasses.  This is
41  * why you will find -- for example -- g_action_group_get_enabled() but
42  * not an equivalent <function>set()</function> call.
43  *
44  * Signals are emitted on the action group in response to state changes
45  * on individual actions.
46  **/
47
48 G_DEFINE_ABSTRACT_TYPE (GActionGroup, g_action_group, G_TYPE_OBJECT)
49
50 enum
51 {
52   SIGNAL_ACTION_ADDED,
53   SIGNAL_ACTION_REMOVED,
54   SIGNAL_ACTION_ENABLED_CHANGED,
55   SIGNAL_ACTION_STATE_CHANGED,
56   NR_SIGNALS
57 };
58
59 static guint g_action_group_signals[NR_SIGNALS];
60
61 static void
62 g_action_group_init (GActionGroup *action_group)
63 {
64 }
65
66 static void
67 g_action_group_class_init (GActionGroupClass *class)
68 {
69   /**
70    * GActionGroup::action-added:
71    * @action_group: the #GActionGroup that changed
72    * @action_name: the name of the action in @action_group
73    *
74    * Signals that a new action was just added to the group.  This signal
75    * is emitted after the action has been added and is now visible.
76    **/
77   g_action_group_signals[SIGNAL_ACTION_ADDED] =
78     g_signal_new ("action-added",
79                   G_TYPE_ACTION_GROUP, G_SIGNAL_RUN_LAST,
80                   G_STRUCT_OFFSET (GActionGroupClass, action_added),
81                   NULL, NULL, g_cclosure_marshal_VOID__STRING,
82                   G_TYPE_NONE, 1, G_TYPE_STRING);
83
84   /**
85    * GActionGroup::action-removed:
86    * @action_group: the #GActionGroup that changed
87    * @action_name: the name of the action in @action_group
88    *
89    * Signals that an action is just about to be removed from the group.
90    * This signal is emitted before the action is removed, so the action
91    * is still visible and can be queried from the signal handler.
92    **/
93   g_action_group_signals[SIGNAL_ACTION_REMOVED] =
94     g_signal_new ("action-removed",
95                   G_TYPE_ACTION_GROUP, G_SIGNAL_RUN_LAST,
96                   G_STRUCT_OFFSET (GActionGroupClass, action_removed),
97                   NULL, NULL, g_cclosure_marshal_VOID__STRING,
98                   G_TYPE_NONE, 1, G_TYPE_STRING);
99
100
101   /**
102    * GActionGroup::action-enabled-changed:
103    * @action_group: the #GActionGroup that changed
104    * @action_name: the name of the action in @action_group
105    * @enabled: whether the action is enabled or not
106    *
107    * Signals that the enabled status of the named action has changed.
108    **/
109   g_action_group_signals[SIGNAL_ACTION_ENABLED_CHANGED] =
110     g_signal_new ("action-enabled-changed",
111                   G_TYPE_ACTION_GROUP, G_SIGNAL_RUN_LAST,
112                   G_STRUCT_OFFSET (GActionGroupClass, action_enabled_changed),
113                   NULL, NULL, _gio_marshal_VOID__STRING_BOOLEAN,
114                   G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_BOOLEAN);
115
116   /**
117    * GActionGroup::action-state-changed:
118    * @action_group: the #GActionGroup that changed
119    * @action_name: the name of the action in @action_group
120    * @value: the new value of the state
121    *
122    * Signals that the state of the named action has changed.
123    **/
124   g_action_group_signals[SIGNAL_ACTION_STATE_CHANGED] =
125     g_signal_new ("action-state-changed",
126                   G_TYPE_ACTION_GROUP, G_SIGNAL_RUN_LAST,
127                   G_STRUCT_OFFSET (GActionGroupClass, action_state_changed),
128                   NULL, NULL, _gio_marshal_VOID__STRING_VARIANT,
129                   G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_VARIANT);
130
131 }
132
133 /**
134  * g_action_group_has_action:
135  * @action_group: a #GActionGroup
136  *
137  * Lists the actions contained within @action_group.
138  *
139  * The caller is responsible for freeing the list with g_strfreev() when
140  * it is no longer required.
141  *
142  * Returns: a list of the actions in the group
143  *
144  * Since: 2.26
145  **/
146 gchar **
147 g_action_group_list_actions (GActionGroup *action_group)
148 {
149   return G_ACTION_GROUP_GET_CLASS (action_group)
150     ->list_actions (action_group);
151 }
152
153 /**
154  * g_action_group_has_action:
155  * @action_group: a #GActionGroup
156  * @action_name: the name of the action to check for
157  *
158  * Checks if the named action exists within @action_group.
159  *
160  * Returns: whether the named action exists
161  *
162  * Since: 2.26
163  **/
164 gboolean
165 g_action_group_has_action (GActionGroup *action_group,
166                            const gchar  *action_name)
167 {
168   return G_ACTION_GROUP_GET_CLASS (action_group)
169     ->has_action (action_group, action_name);
170 }
171
172 /**
173  * g_action_group_get_parameter_type:
174  * @action_group: a #GActionGroup
175  * @action_name: the name of the action to query
176  *
177  * Queries the type of the parameter that must be given when activating
178  * the named action within @action_group.
179  *
180  * When activating the action using g_action_group_activate(), the
181  * #GVariant given to that function must be of the type returned by this
182  * function.
183  *
184  * In the case that this function returns %NULL, you must not give any
185  * #GVariant, but %NULL instead.
186  *
187  * The parameter type of a particular action will never change but it is
188  * possible for an action to be removed and for a new action to be added
189  * with the same name but a different parameter type.
190  *
191  * Returns: (allow-none): the parameter type
192  *
193  * Since: 2.26
194  **/
195 const GVariantType *
196 g_action_group_get_parameter_type (GActionGroup *action_group,
197                                    const gchar  *action_name)
198 {
199   return G_ACTION_GROUP_GET_CLASS (action_group)
200     ->get_parameter_type (action_group, action_name);
201 }
202
203 /**
204  * g_action_group_get_state_type:
205  * @action_group: a #GActionGroup
206  * @action_name: the name of the action to query
207  *
208  * Queries the type of the state of the named action within
209  * @action_group.
210  *
211  * If the action is stateful then this function returns the
212  * #GVariantType of the state.  All calls to g_action_group_set_state()
213  * must give a #GVariant of this type and g_action_group_get_state()
214  * will return a #GVariant of the same type.
215  *
216  * If the action is not stateful then this function will return %NULL.
217  * In that case, g_action_group_get_state() will return %NULL and you
218  * must not call g_action_group_set_state().
219  *
220  * The state type of a particular action will never change but it is
221  * possible for an action to be removed and for a new action to be added
222  * with the same name but a different state type.
223  *
224  * Returns: (allow-none): the state type, if the action is stateful
225  *
226  * Since: 2.26
227  **/
228  const GVariantType *
229 g_action_group_get_state_type (GActionGroup *action_group,
230                                const gchar  *action_name)
231 {
232   return G_ACTION_GROUP_GET_CLASS (action_group)
233     ->get_state_type (action_group, action_name);
234 }
235
236 /**
237  * g_action_group_get_state_hint:
238  * @action_group: a #GActionGroup
239  * @action_name: the name of the action to query
240  *
241  * Requests a hint about the valid range of values for the state of the
242  * named action within @action_group.
243  *
244  * If %NULL is returned it either means that the action is not stateful
245  * or that there is no hint about the valid range of values for the
246  * state of the action.
247  *
248  * If a #GVariant array is returned then each item in the array is a
249  * possible value for the state.  If a #GVariant pair (ie: two-tuple) is
250  * returned then the tuple specifies the inclusive lower and upper bound
251  * of valid values for the state.
252  *
253  * In any case, the information is merely a hint.  It may be possible to
254  * have a state value outside of the hinted range and setting a value
255  * within the range may fail.
256  *
257  * The return value (if non-%NULL) should be freed with
258  * g_variant_unref() when it is no longer required.
259  *
260  * Returns: (allow-none): the state range hint
261  *
262  * Since: 2.26
263  **/
264 GVariant *
265 g_action_group_get_state_hint (GActionGroup *action_group,
266                                 const gchar  *action_name)
267 {
268   return G_ACTION_GROUP_GET_CLASS (action_group)
269     ->get_state_hint (action_group, action_name);
270 }
271
272 /**
273  * g_action_group_get_enabled:
274  * @action_group: a #GActionGroup
275  * @action_name: the name of the action to query
276  *
277  * Checks if the named action within @action_group is currently enabled.
278  *
279  * An action must be enabled in order to be activated or in order to
280  * have its state changed from outside callers.
281  *
282  * Returns: whether or not the action is currently enabled
283  *
284  * Since: 2.26
285  **/
286 gboolean
287 g_action_group_get_enabled (GActionGroup *action_group,
288                             const gchar  *action_name)
289 {
290   return G_ACTION_GROUP_GET_CLASS (action_group)
291     ->get_enabled (action_group, action_name);
292 }
293
294 /**
295  * g_action_group_get_state:
296  * @action_group: a #GActionGroup
297  * @action_name: the name of the action to query
298  *
299  * Queries the current state of the named action within @action_group.
300  *
301  * If the action is not stateful then %NULL will be returned.  If the
302  * action is stateful then the type of the return value is the type
303  * given by g_action_group_get_state_type().
304  *
305  * The return value (if non-%NULL) should be freed with
306  * g_variant_unref() when it is no longer required.
307  *
308  * Returns: (allow-none): the current state of the action
309  *
310  * Since: 2.26
311  **/
312 GVariant *
313 g_action_group_get_state (GActionGroup *action_group,
314                           const gchar  *action_name)
315 {
316   return G_ACTION_GROUP_GET_CLASS (action_group)
317     ->get_state (action_group, action_name);
318 }
319
320 /**
321  * g_action_group_set_state:
322  * @action_group: a #GActionGroup
323  * @action_name: the name of the action to request the change on
324  * @value: the new state
325  *
326  * Request for the state of the named action within @action_group to be
327  * changed to @value.
328  *
329  * The action must be stateful and @value must be of the correct type.
330  * See g_action_group_get_state_type().
331  *
332  * This call merely requests a change.  The action may refuse to change
333  * its state or may change its state to something other than @value.
334  * See g_action_group_get_state_hint().
335  *
336  * Since: 2.26
337  **/
338 void
339 g_action_group_set_state (GActionGroup *action_group,
340                           const gchar  *action_name,
341                           GVariant     *value)
342 {
343   G_ACTION_GROUP_GET_CLASS (action_group)
344     ->set_state (action_group, action_name, value);
345 }
346
347 /**
348  * g_action_group_activate:
349  * @action_group: a #GActionGroup
350  * @action_name: the name of the action to activate
351  * @parameter: (allow-none): parameters to the activation
352  *
353  * Activate the named action within @action_group.
354  *
355  * If the action is expecting a parameter, then the correct type of
356  * parameter must be given as @parameter.  If the action is expecting no
357  * parameters then @parameter must be %NULL.  See
358  * g_action_group_get_parameter_type().
359  *
360  * Since: 2.26
361  **/
362 void
363 g_action_group_activate (GActionGroup *action_group,
364                          const gchar  *action_name,
365                          GVariant     *parameter)
366 {
367   G_ACTION_GROUP_GET_CLASS (action_group)
368     ->activate (action_group, action_name, parameter);
369 }
370
371 /**
372  * g_action_group_action_added:
373  * @action_group: a #GActionGroup
374  * @action_name: the name of an action in the group
375  *
376  * Emits the "action-added" signal on @action_group.
377  *
378  * This function should only be called by #GActionGroup implementations.
379  *
380  * Since: 2.26
381  **/
382 void
383 g_action_group_action_added (GActionGroup *action_group,
384                              const gchar  *action_name)
385 {
386   g_signal_emit (action_group,
387                  g_action_group_signals[SIGNAL_ACTION_ADDED],
388                  g_quark_try_string (action_name), action_name);
389 }
390
391 /**
392  * g_action_group_action_removed:
393  * @action_group: a #GActionGroup
394  * @action_name: the name of an action in the group
395  *
396  * Emits the "action-removed" signal on @action_group.
397  *
398  * This function should only be called by #GActionGroup implementations.
399  *
400  * Since: 2.26
401  **/
402 void
403 g_action_group_action_removed (GActionGroup *action_group,
404                                const gchar  *action_name)
405 {
406   g_signal_emit (action_group,
407                  g_action_group_signals[SIGNAL_ACTION_REMOVED],
408                  g_quark_try_string (action_name), action_name);
409 }
410
411 /**
412  * g_action_group_action_enabled_changed:
413  * @action_group: a #GActionGroup
414  * @action_name: the name of an action in the group
415  * @enabled: whether or not the action is now enabled
416  *
417  * Emits the "action-enabled-changed" signal on @action_group.
418  *
419  * This function should only be called by #GActionGroup implementations.
420  *
421  * Since: 2.26
422  **/
423 void
424 g_action_group_action_enabled_changed (GActionGroup *action_group,
425                                        const gchar  *action_name,
426                                        gboolean      enabled)
427 {
428   g_signal_emit (action_group,
429                  g_action_group_signals[SIGNAL_ACTION_ENABLED_CHANGED],
430                  g_quark_try_string (action_name), action_name);
431 }
432
433 /**
434  * g_action_group_action_state_changed:
435  * @action_group: a #GActionGroup
436  * @action_name: the name of an action in the group
437  * @state: the new state of the named action
438  *
439  * Emits the "action-state-changed" signal on @action_group.
440  *
441  * This function should only be called by #GActionGroup implementations.
442  *
443  * Since: 2.26
444  **/
445 void
446 g_action_group_action_state_changed (GActionGroup *action_group,
447                                      const gchar  *action_name,
448                                      GVariant     *state)
449 {
450   g_signal_emit (action_group,
451                  g_action_group_signals[SIGNAL_ACTION_STATE_CHANGED],
452                  g_quark_try_string (action_name), action_name);
453 }