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 : : #include "gactionmap.h"
26 : : #include "gaction.h"
27 : :
28 : : /**
29 : : * GActionMap:
30 : : *
31 : : * `GActionMap` is an interface for action containers.
32 : : *
33 : : * The `GActionMap` interface is implemented by [iface@Gio.ActionGroup]
34 : : * implementations that operate by containing a number of named
35 : : * [iface@Gio.Action] instances, such as [class@Gio.SimpleActionGroup].
36 : : *
37 : : * One useful application of this interface is to map the
38 : : * names of actions from various action groups to unique,
39 : : * prefixed names (e.g. by prepending "app." or "win.").
40 : : * This is the motivation for the 'Map' part of the interface
41 : : * name.
42 : : *
43 : : * Since: 2.32
44 : : */
45 : :
46 : : /**
47 : : * GActionMapInterface:
48 : : * @lookup_action: the virtual function pointer for g_action_map_lookup_action()
49 : : * @add_action: the virtual function pointer for g_action_map_add_action()
50 : : * @remove_action: the virtual function pointer for g_action_map_remove_action()
51 : : *
52 : : * The virtual function table for #GActionMap.
53 : : *
54 : : * Since: 2.32
55 : : **/
56 : :
57 [ + + + - : 200231 : G_DEFINE_INTERFACE (GActionMap, g_action_map, G_TYPE_OBJECT)
+ + ]
58 : :
59 : : static void
60 : 13 : g_action_map_default_init (GActionMapInterface *iface)
61 : : {
62 : 13 : }
63 : :
64 : : /**
65 : : * g_action_map_lookup_action:
66 : : * @action_map: a #GActionMap
67 : : * @action_name: the name of an action
68 : : *
69 : : * Looks up the action with the name @action_name in @action_map.
70 : : *
71 : : * If no such action exists, returns %NULL.
72 : : *
73 : : * Returns: (nullable) (transfer none): a #GAction, or %NULL
74 : : *
75 : : * Since: 2.32
76 : : */
77 : : GAction *
78 : 100005 : g_action_map_lookup_action (GActionMap *action_map,
79 : : const gchar *action_name)
80 : : {
81 : 100005 : return G_ACTION_MAP_GET_IFACE (action_map)
82 : 100006 : ->lookup_action (action_map, action_name);
83 : : }
84 : :
85 : : /**
86 : : * g_action_map_add_action:
87 : : * @action_map: a #GActionMap
88 : : * @action: a #GAction
89 : : *
90 : : * Adds an action to the @action_map.
91 : : *
92 : : * If the action map already contains an action with the same name
93 : : * as @action then the old action is dropped from the action map.
94 : : *
95 : : * The action map takes its own reference on @action.
96 : : *
97 : : * Since: 2.32
98 : : */
99 : : void
100 : 82 : g_action_map_add_action (GActionMap *action_map,
101 : : GAction *action)
102 : : {
103 : 82 : G_ACTION_MAP_GET_IFACE (action_map)->add_action (action_map, action);
104 : 82 : }
105 : :
106 : : /**
107 : : * g_action_map_remove_action:
108 : : * @action_map: a #GActionMap
109 : : * @action_name: the name of the action
110 : : *
111 : : * Removes the named action from the action map.
112 : : *
113 : : * If no action of this name is in the map then nothing happens.
114 : : *
115 : : * Since: 2.32
116 : : */
117 : : void
118 : 10 : g_action_map_remove_action (GActionMap *action_map,
119 : : const gchar *action_name)
120 : : {
121 : 10 : G_ACTION_MAP_GET_IFACE (action_map)->remove_action (action_map, action_name);
122 : 10 : }
123 : :
124 : : /**
125 : : * GActionEntry:
126 : : * @name: the name of the action
127 : : * @activate: the callback to connect to the "activate" signal of the
128 : : * action. Since GLib 2.40, this can be %NULL for stateful
129 : : * actions, in which case the default handler is used. For
130 : : * boolean-stated actions with no parameter, this is a
131 : : * toggle. For other state types (and parameter type equal
132 : : * to the state type) this will be a function that
133 : : * just calls @change_state (which you should provide).
134 : : * @parameter_type: the type of the parameter that must be passed to the
135 : : * activate function for this action, given as a single
136 : : * GVariant type string (or %NULL for no parameter)
137 : : * @state: the initial state for this action, given in
138 : : * [GVariant text format](gvariant-text-format.html). The state is parsed
139 : : * with no extra type information, so type tags must be added to
140 : : * the string if they are necessary. Stateless actions should
141 : : * give %NULL here.
142 : : * @change_state: the callback to connect to the "change-state" signal
143 : : * of the action. All stateful actions should provide a
144 : : * handler here; stateless actions should not.
145 : : *
146 : : * This struct defines a single action. It is for use with
147 : : * g_action_map_add_action_entries().
148 : : *
149 : : * The order of the items in the structure are intended to reflect
150 : : * frequency of use. It is permissible to use an incomplete initialiser
151 : : * in order to leave some of the later values as %NULL. All values
152 : : * after @name are optional. Additional optional fields may be added in
153 : : * the future.
154 : : *
155 : : * See g_action_map_add_action_entries() for an example.
156 : : **/
157 : :
158 : : /**
159 : : * g_action_map_add_action_entries:
160 : : * @action_map: a #GActionMap
161 : : * @entries: (array length=n_entries) (element-type GActionEntry): a pointer to
162 : : * the first item in an array of #GActionEntry structs
163 : : * @n_entries: the length of @entries, or -1 if @entries is %NULL-terminated
164 : : * @user_data: the user data for signal connections
165 : : *
166 : : * A convenience function for creating multiple #GSimpleAction instances
167 : : * and adding them to a #GActionMap.
168 : : *
169 : : * Each action is constructed as per one #GActionEntry.
170 : : *
171 : : * |[<!-- language="C" -->
172 : : * static void
173 : : * activate_quit (GSimpleAction *simple,
174 : : * GVariant *parameter,
175 : : * gpointer user_data)
176 : : * {
177 : : * exit (0);
178 : : * }
179 : : *
180 : : * static void
181 : : * activate_print_string (GSimpleAction *simple,
182 : : * GVariant *parameter,
183 : : * gpointer user_data)
184 : : * {
185 : : * g_print ("%s\n", g_variant_get_string (parameter, NULL));
186 : : * }
187 : : *
188 : : * static GActionGroup *
189 : : * create_action_group (void)
190 : : * {
191 : : * const GActionEntry entries[] = {
192 : : * { "quit", activate_quit },
193 : : * { "print-string", activate_print_string, "s" }
194 : : * };
195 : : * GSimpleActionGroup *group;
196 : : *
197 : : * group = g_simple_action_group_new ();
198 : : * g_action_map_add_action_entries (G_ACTION_MAP (group), entries, G_N_ELEMENTS (entries), NULL);
199 : : *
200 : : * return G_ACTION_GROUP (group);
201 : : * }
202 : : * ]|
203 : : *
204 : : * Since: 2.32
205 : : */
206 : : void
207 : 23 : g_action_map_add_action_entries (GActionMap *action_map,
208 : : const GActionEntry *entries,
209 : : gint n_entries,
210 : : gpointer user_data)
211 : : {
212 : 23 : g_return_if_fail (G_IS_ACTION_MAP (action_map));
213 : 23 : g_return_if_fail (entries != NULL || n_entries == 0);
214 : :
215 [ + + + + ]: 75 : for (int i = 0; n_entries < 0 ? entries[i].name != NULL : i < n_entries; i++)
216 : : {
217 : 53 : const GActionEntry *entry = &entries[i];
218 : : const GVariantType *parameter_type;
219 : : GSimpleAction *action;
220 : :
221 [ + + ]: 53 : if (entry->parameter_type)
222 : : {
223 [ + + ]: 11 : if (!g_variant_type_string_is_valid (entry->parameter_type))
224 : : {
225 : 1 : g_critical ("g_action_map_add_entries: the type "
226 : : "string '%s' given as the parameter type for "
227 : : "action '%s' is not a valid GVariant type "
228 : : "string. This action will not be added.",
229 : : entry->parameter_type, entry->name);
230 : 1 : return;
231 : : }
232 : :
233 : 10 : parameter_type = G_VARIANT_TYPE (entry->parameter_type);
234 : : }
235 : : else
236 : 42 : parameter_type = NULL;
237 : :
238 [ + + ]: 52 : if (entry->state)
239 : : {
240 : 12 : GError *error = NULL;
241 : : GVariant *state;
242 : :
243 : 12 : state = g_variant_parse (NULL, entry->state, NULL, NULL, &error);
244 [ + + ]: 12 : if (state == NULL)
245 : : {
246 : 1 : g_critical ("g_action_map_add_entries: GVariant could "
247 : : "not parse the state value given for action '%s' "
248 : : "('%s'): %s. This action will not be added.",
249 : : entry->name, entry->state, error->message);
250 : 1 : g_error_free (error);
251 : 1 : continue;
252 : : }
253 : :
254 : 11 : action = g_simple_action_new_stateful (entry->name,
255 : : parameter_type,
256 : : state);
257 : :
258 : 11 : g_variant_unref (state);
259 : : }
260 : : else
261 : : {
262 : 40 : action = g_simple_action_new (entry->name,
263 : : parameter_type);
264 : : }
265 : :
266 [ + + ]: 51 : if (entry->activate != NULL)
267 : 49 : g_signal_connect (action, "activate",
268 : : G_CALLBACK (entry->activate), user_data);
269 : :
270 [ + + ]: 51 : if (entry->change_state != NULL)
271 : 1 : g_signal_connect (action, "change-state",
272 : : G_CALLBACK (entry->change_state), user_data);
273 : :
274 : 51 : g_action_map_add_action (action_map, G_ACTION (action));
275 : 51 : g_object_unref (action);
276 : : }
277 : : }
278 : :
279 : : /**
280 : : * g_action_map_remove_action_entries:
281 : : * @action_map: The #GActionMap
282 : : * @entries: (array length=n_entries) (element-type GActionEntry): a pointer to
283 : : * the first item in an array of #GActionEntry structs
284 : : * @n_entries: the length of @entries, or -1 if @entries is %NULL-terminated
285 : : *
286 : : * Remove actions from a #GActionMap. This is meant as the reverse of
287 : : * g_action_map_add_action_entries().
288 : : *
289 : : *
290 : : * |[<!-- language="C" -->
291 : : * static const GActionEntry entries[] = {
292 : : * { "quit", activate_quit },
293 : : * { "print-string", activate_print_string, "s" }
294 : : * };
295 : : *
296 : : * void
297 : : * add_actions (GActionMap *map)
298 : : * {
299 : : * g_action_map_add_action_entries (map, entries, G_N_ELEMENTS (entries), NULL);
300 : : * }
301 : : *
302 : : * void
303 : : * remove_actions (GActionMap *map)
304 : : * {
305 : : * g_action_map_remove_action_entries (map, entries, G_N_ELEMENTS (entries));
306 : : * }
307 : : * ]|
308 : : *
309 : : * Since: 2.78
310 : : */
311 : : void
312 : 2 : g_action_map_remove_action_entries (GActionMap *action_map,
313 : : const GActionEntry entries[],
314 : : gint n_entries)
315 : : {
316 : 2 : g_return_if_fail (G_IS_ACTION_MAP (action_map));
317 : 2 : g_return_if_fail (entries != NULL || n_entries == 0);
318 : :
319 [ + + + + ]: 8 : for (int i = 0; n_entries < 0 ? entries[i].name != NULL : i < n_entries; i++)
320 : 6 : g_action_map_remove_action (action_map, entries[i].name);
321 : : }
|