1 /*
2 * This file is part of Amtk - Actions, Menus and Toolbars Kit
3 *
4 * Copyright 2017, 2018, 2020 - Sébastien Wilmet <swilmet@gnome.org>
5 *
6 * Amtk is free software; you can redistribute it and/or modify it under
7 * the terms of the GNU Lesser General Public License as published by the
8 * Free Software Foundation; either version 2.1 of the License, or (at your
9 * option) any later version.
10 *
11 * Amtk is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14 * License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this library; if not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "config.h"
21 #include "amtk-action-info.h"
22 #include <glib/gi18n-lib.h>
23 #include "amtk-utils.h"
24
25 /**
26 * SECTION:amtk-action-info
27 * @Short_description: #GAction information
28 * @Title: AmtkActionInfo
29 * @See_also: #AmtkActionInfoStore
30 *
31 * An #AmtkActionInfo instance contains a set of information about a #GAction.
32 * Those pieces of information are useful to create UI elements that trigger the
33 * #GAction, for example a menu item or a toolbar item.
34 *
35 * The recommended way to create a set of #AmtkActionInfo's is to use the
36 * amtk_action_info_store_add_entries() function.
37 */
38
39 struct _AmtkActionInfo
40 {
41 gchar *action_name;
42 gchar *icon_name;
43 gchar *label;
44 gchar *tooltip;
45
46 /* Must never be NULL, must be a NULL-terminated array. This way, it
47 * can be used directly as an argument to
48 * gtk_application_set_accels_for_action().
49 */
50 gchar **accels;
51
52 gint ref_count;
53
54 guint used : 1;
55 };
56
57 static void _amtk_action_info_free (AmtkActionInfo *info);
58
G_DEFINE_BOXED_TYPE(AmtkActionInfo,amtk_action_info,amtk_action_info_copy,_amtk_action_info_free)59 G_DEFINE_BOXED_TYPE (AmtkActionInfo, amtk_action_info,
60 amtk_action_info_copy,
61 _amtk_action_info_free)
62
63 static void
64 _amtk_action_info_free (AmtkActionInfo *info)
65 {
66 if (info != NULL)
67 {
68 g_free (info->action_name);
69 g_free (info->icon_name);
70 g_free (info->label);
71 g_free (info->tooltip);
72 g_strfreev (info->accels);
73
74 g_free (info);
75 }
76 }
77
78 /**
79 * amtk_action_info_new:
80 *
81 * Returns: a new #AmtkActionInfo.
82 * Since: 2.0
83 */
84 AmtkActionInfo *
amtk_action_info_new(void)85 amtk_action_info_new (void)
86 {
87 AmtkActionInfo *info;
88
89 info = g_new0 (AmtkActionInfo, 1);
90 info->accels = g_malloc0 (sizeof (gchar *));
91 info->ref_count = 1;
92
93 return info;
94 }
95
96 /**
97 * amtk_action_info_new_from_entry:
98 * @info_entry: an #AmtkActionInfoEntry.
99 * @translation_domain: (nullable): a gettext domain, or %NULL.
100 *
101 * Creates a new #AmtkActionInfo from an #AmtkActionInfoEntry.
102 *
103 * If @translation_domain is not %NULL, g_dgettext() is used to translate the
104 * @label and @tooltip before setting them to the #AmtkActionInfo.
105 *
106 * Returns: a new #AmtkActionInfo.
107 * Since: 2.0
108 */
109 AmtkActionInfo *
amtk_action_info_new_from_entry(const AmtkActionInfoEntry * info_entry,const gchar * translation_domain)110 amtk_action_info_new_from_entry (const AmtkActionInfoEntry *info_entry,
111 const gchar *translation_domain)
112 {
113 AmtkActionInfo *info;
114
115 info = amtk_action_info_new ();
116 info->action_name = g_strdup (info_entry->action_name);
117 info->icon_name = g_strdup (info_entry->icon_name);
118
119 if (translation_domain != NULL)
120 {
121 info->label = g_strdup (g_dgettext (translation_domain, info_entry->label));
122 info->tooltip = g_strdup (g_dgettext (translation_domain, info_entry->tooltip));
123 }
124 else
125 {
126 info->label = g_strdup (info_entry->label);
127 info->tooltip = g_strdup (info_entry->tooltip);
128 }
129
130 if (info_entry->accel != NULL)
131 {
132 g_strfreev (info->accels);
133
134 info->accels = g_malloc (2 * sizeof (gchar *));
135 info->accels[0] = g_strdup (info_entry->accel);
136 info->accels[1] = NULL;
137 }
138
139 return info;
140 }
141
142 /**
143 * amtk_action_info_ref:
144 * @info: an #AmtkActionInfo.
145 *
146 * Increments the reference count of @info by one.
147 *
148 * Returns: the passed in @info.
149 * Since: 2.0
150 */
151 AmtkActionInfo *
amtk_action_info_ref(AmtkActionInfo * info)152 amtk_action_info_ref (AmtkActionInfo *info)
153 {
154 g_return_val_if_fail (info != NULL, NULL);
155
156 info->ref_count++;
157
158 return info;
159 }
160
161 /**
162 * amtk_action_info_unref:
163 * @info: an #AmtkActionInfo.
164 *
165 * Decrements the reference count of @info by one. If the reference count drops
166 * to 0, @info is freed.
167 *
168 * Since: 2.0
169 */
170 void
amtk_action_info_unref(AmtkActionInfo * info)171 amtk_action_info_unref (AmtkActionInfo *info)
172 {
173 g_return_if_fail (info != NULL);
174
175 info->ref_count--;
176
177 if (info->ref_count == 0)
178 {
179 _amtk_action_info_free (info);
180 }
181 }
182
183 /**
184 * amtk_action_info_copy:
185 * @info: an #AmtkActionInfo.
186 *
187 * Returns: (transfer full): a copy of @info. The copy will have a reference
188 * count of one.
189 * Since: 2.0
190 */
191 AmtkActionInfo *
amtk_action_info_copy(const AmtkActionInfo * info)192 amtk_action_info_copy (const AmtkActionInfo *info)
193 {
194 AmtkActionInfo *new_info;
195
196 g_return_val_if_fail (info != NULL, NULL);
197
198 new_info = amtk_action_info_new ();
199
200 new_info->action_name = g_strdup (info->action_name);
201 new_info->icon_name = g_strdup (info->icon_name);
202 new_info->label = g_strdup (info->label);
203 new_info->tooltip = g_strdup (info->tooltip);
204
205 amtk_action_info_set_accels (new_info, (const gchar * const *)info->accels);
206
207 return new_info;
208 }
209
210 /**
211 * amtk_action_info_get_action_name:
212 * @info: an #AmtkActionInfo.
213 *
214 * Returns: (nullable): the action name, or %NULL. Example: `"win.save"`. Can be
215 * a detailed action name, see g_action_parse_detailed_name().
216 * Since: 2.0
217 */
218 const gchar *
amtk_action_info_get_action_name(const AmtkActionInfo * info)219 amtk_action_info_get_action_name (const AmtkActionInfo *info)
220 {
221 g_return_val_if_fail (info != NULL, NULL);
222
223 return info->action_name;
224 }
225
226 /**
227 * amtk_action_info_set_action_name:
228 * @info: an #AmtkActionInfo.
229 * @action_name: the action name.
230 *
231 * Sets the action name, for example `"win.save"`. Can be a detailed action
232 * name, see g_action_parse_detailed_name().
233 *
234 * Since: 2.0
235 */
236 void
amtk_action_info_set_action_name(AmtkActionInfo * info,const gchar * action_name)237 amtk_action_info_set_action_name (AmtkActionInfo *info,
238 const gchar *action_name)
239 {
240 g_return_if_fail (info != NULL);
241 g_return_if_fail (action_name != NULL);
242
243 g_free (info->action_name);
244 info->action_name = g_strdup (action_name);
245 }
246
247 /**
248 * amtk_action_info_get_icon_name:
249 * @info: an #AmtkActionInfo.
250 *
251 * Returns: (nullable): the icon name, or %NULL.
252 * Since: 2.0
253 */
254 const gchar *
amtk_action_info_get_icon_name(const AmtkActionInfo * info)255 amtk_action_info_get_icon_name (const AmtkActionInfo *info)
256 {
257 g_return_val_if_fail (info != NULL, NULL);
258
259 return info->icon_name;
260 }
261
262 /**
263 * amtk_action_info_set_icon_name:
264 * @info: an #AmtkActionInfo.
265 * @icon_name: (nullable): the icon name, or %NULL.
266 *
267 * Since: 2.0
268 */
269 void
amtk_action_info_set_icon_name(AmtkActionInfo * info,const gchar * icon_name)270 amtk_action_info_set_icon_name (AmtkActionInfo *info,
271 const gchar *icon_name)
272 {
273 g_return_if_fail (info != NULL);
274
275 g_free (info->icon_name);
276 info->icon_name = g_strdup (icon_name);
277 }
278
279 /**
280 * amtk_action_info_get_label:
281 * @info: an #AmtkActionInfo.
282 *
283 * Gets the label. The label has normally a mnemonic. To remove the mnemonic,
284 * there is the amtk_utils_remove_mnemonic() function.
285 *
286 * Returns: (nullable): the label (i.e. a short description), or %NULL.
287 * Since: 2.0
288 */
289 const gchar *
amtk_action_info_get_label(const AmtkActionInfo * info)290 amtk_action_info_get_label (const AmtkActionInfo *info)
291 {
292 g_return_val_if_fail (info != NULL, NULL);
293
294 return info->label;
295 }
296
297 /**
298 * amtk_action_info_set_label:
299 * @info: an #AmtkActionInfo.
300 * @label: (nullable): the label (i.e. a short description), or %NULL.
301 *
302 * Sets the label with a mnemonic. To know how to encode the mnemonic, see the
303 * documentation of gtk_label_new_with_mnemonic().
304 *
305 * Since: 2.0
306 */
307 void
amtk_action_info_set_label(AmtkActionInfo * info,const gchar * label)308 amtk_action_info_set_label (AmtkActionInfo *info,
309 const gchar *label)
310 {
311 g_return_if_fail (info != NULL);
312
313 g_free (info->label);
314 info->label = g_strdup (label);
315 }
316
317 /**
318 * amtk_action_info_get_tooltip:
319 * @info: an #AmtkActionInfo.
320 *
321 * Returns: (nullable): the tooltip (i.e. a long description), or %NULL.
322 * Since: 2.0
323 */
324 const gchar *
amtk_action_info_get_tooltip(const AmtkActionInfo * info)325 amtk_action_info_get_tooltip (const AmtkActionInfo *info)
326 {
327 g_return_val_if_fail (info != NULL, NULL);
328
329 return info->tooltip;
330 }
331
332 /**
333 * amtk_action_info_set_tooltip:
334 * @info: an #AmtkActionInfo.
335 * @tooltip: (nullable): the tooltip (i.e. a long description), or %NULL.
336 *
337 * Since: 2.0
338 */
339 void
amtk_action_info_set_tooltip(AmtkActionInfo * info,const gchar * tooltip)340 amtk_action_info_set_tooltip (AmtkActionInfo *info,
341 const gchar *tooltip)
342 {
343 g_return_if_fail (info != NULL);
344
345 g_free (info->tooltip);
346 info->tooltip = g_strdup (tooltip);
347 }
348
349 /**
350 * amtk_action_info_get_accels:
351 * @info: an #AmtkActionInfo.
352 *
353 * Returns the accelerators. This function never returns %NULL, it always
354 * returns a %NULL-terminated array, to be suitable for
355 * gtk_application_set_accels_for_action().
356 *
357 * Returns: (transfer none) (array zero-terminated=1): a %NULL-terminated array
358 * of accelerators in the format understood by gtk_accelerator_parse().
359 * Since: 2.0
360 */
361 const gchar * const *
amtk_action_info_get_accels(const AmtkActionInfo * info)362 amtk_action_info_get_accels (const AmtkActionInfo *info)
363 {
364 g_return_val_if_fail (info != NULL, NULL);
365
366 g_assert (info->accels != NULL);
367
368 return (const gchar * const *)info->accels;
369 }
370
371 /**
372 * amtk_action_info_set_accels:
373 * @info: an #AmtkActionInfo.
374 * @accels: (array zero-terminated=1): a %NULL-terminated array of accelerators
375 * in the format understood by gtk_accelerator_parse().
376 *
377 * A function similar to gtk_application_set_accels_for_action().
378 *
379 * @accels must not be %NULL, it must be a %NULL-terminated array, to be
380 * consistent with gtk_application_set_accels_for_action().
381 *
382 * Since: 2.0
383 */
384 void
amtk_action_info_set_accels(AmtkActionInfo * info,const gchar * const * accels)385 amtk_action_info_set_accels (AmtkActionInfo *info,
386 const gchar * const *accels)
387 {
388 g_return_if_fail (info != NULL);
389 g_return_if_fail (accels != NULL);
390
391 g_strfreev (info->accels);
392 info->accels = g_strdupv ((gchar **) accels);
393 }
394
395 /**
396 * amtk_action_info_mark_as_used:
397 * @info: an #AmtkActionInfo.
398 *
399 * Mark @info as used. An #AmtkFactory function that uses an #AmtkActionInfo
400 * should call this function. See amtk_action_info_store_check_all_used().
401 *
402 * Since: 3.0
403 */
404 void
amtk_action_info_mark_as_used(AmtkActionInfo * info)405 amtk_action_info_mark_as_used (AmtkActionInfo *info)
406 {
407 g_return_if_fail (info != NULL);
408
409 info->used = TRUE;
410 }
411
412 /**
413 * amtk_action_info_has_been_used:
414 * @info: an #AmtkActionInfo.
415 *
416 * Returns whether @info has been used (for example by an #AmtkFactory
417 * function). See also amtk_action_info_store_check_all_used().
418 *
419 * Returns: whether @info has been used.
420 * Since: 3.0
421 */
422 gboolean
amtk_action_info_has_been_used(const AmtkActionInfo * info)423 amtk_action_info_has_been_used (const AmtkActionInfo *info)
424 {
425 g_return_val_if_fail (info != NULL, FALSE);
426
427 return info->used;
428 }
429