/src/pango/subprojects/glib/gio/gthemedicon.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* GIO - GLib Input, Output and Streaming Library |
2 | | * |
3 | | * Copyright (C) 2006-2007 Red Hat, Inc. |
4 | | * |
5 | | * SPDX-License-Identifier: LGPL-2.1-or-later |
6 | | * |
7 | | * This library is free software; you can redistribute it and/or |
8 | | * modify it under the terms of the GNU Lesser General Public |
9 | | * License as published by the Free Software Foundation; either |
10 | | * version 2.1 of the License, or (at your option) any later version. |
11 | | * |
12 | | * This library is distributed in the hope that it will be useful, |
13 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | | * Lesser General Public License for more details. |
16 | | * |
17 | | * You should have received a copy of the GNU Lesser General |
18 | | * Public License along with this library; if not, see <http://www.gnu.org/licenses/>. |
19 | | * |
20 | | * Author: Alexander Larsson <alexl@redhat.com> |
21 | | */ |
22 | | |
23 | | #include "config.h" |
24 | | |
25 | | #include <string.h> |
26 | | |
27 | | #include "gthemedicon.h" |
28 | | #include "gicon.h" |
29 | | #include "gioerror.h" |
30 | | #include "glibintl.h" |
31 | | |
32 | | |
33 | | /** |
34 | | * GThemedIcon: |
35 | | * |
36 | | * `GThemedIcon` is an implementation of [iface@Gio.Icon] that supports icon |
37 | | * themes. |
38 | | * |
39 | | * `GThemedIcon` contains a list of all of the icons present in an icon |
40 | | * theme, so that icons can be looked up quickly. `GThemedIcon` does |
41 | | * not provide actual pixmaps for icons, just the icon names. |
42 | | * Ideally something like [method@Gtk.IconTheme.choose_icon] should be used to |
43 | | * resolve the list of names so that fallback icons work nicely with |
44 | | * themes that inherit other themes. |
45 | | **/ |
46 | | |
47 | | static void g_themed_icon_icon_iface_init (GIconIface *iface); |
48 | | |
49 | | struct _GThemedIcon |
50 | | { |
51 | | GObject parent_instance; |
52 | | |
53 | | char **init_names; |
54 | | char **names; |
55 | | gboolean use_default_fallbacks; |
56 | | }; |
57 | | |
58 | | struct _GThemedIconClass |
59 | | { |
60 | | GObjectClass parent_class; |
61 | | }; |
62 | | |
63 | | enum |
64 | | { |
65 | | PROP_0, |
66 | | PROP_NAME, |
67 | | PROP_NAMES, |
68 | | PROP_USE_DEFAULT_FALLBACKS |
69 | | }; |
70 | | |
71 | | static void g_themed_icon_update_names (GThemedIcon *themed); |
72 | | |
73 | | G_DEFINE_TYPE_WITH_CODE (GThemedIcon, g_themed_icon, G_TYPE_OBJECT, |
74 | | G_IMPLEMENT_INTERFACE (G_TYPE_ICON, |
75 | | g_themed_icon_icon_iface_init)) |
76 | | |
77 | | static void |
78 | | g_themed_icon_get_property (GObject *object, |
79 | | guint prop_id, |
80 | | GValue *value, |
81 | | GParamSpec *pspec) |
82 | 0 | { |
83 | 0 | GThemedIcon *icon = G_THEMED_ICON (object); |
84 | |
|
85 | 0 | switch (prop_id) |
86 | 0 | { |
87 | 0 | case PROP_NAMES: |
88 | 0 | g_value_set_boxed (value, icon->init_names); |
89 | 0 | break; |
90 | | |
91 | 0 | case PROP_USE_DEFAULT_FALLBACKS: |
92 | 0 | g_value_set_boolean (value, icon->use_default_fallbacks); |
93 | 0 | break; |
94 | | |
95 | 0 | default: |
96 | 0 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
97 | 0 | } |
98 | 0 | } |
99 | | |
100 | | static void |
101 | | g_themed_icon_set_property (GObject *object, |
102 | | guint prop_id, |
103 | | const GValue *value, |
104 | | GParamSpec *pspec) |
105 | 0 | { |
106 | 0 | GThemedIcon *icon = G_THEMED_ICON (object); |
107 | 0 | gchar **names; |
108 | 0 | const gchar *name; |
109 | |
|
110 | 0 | switch (prop_id) |
111 | 0 | { |
112 | 0 | case PROP_NAME: |
113 | 0 | name = g_value_get_string (value); |
114 | |
|
115 | 0 | if (!name) |
116 | 0 | break; |
117 | | |
118 | 0 | if (icon->init_names) |
119 | 0 | g_strfreev (icon->init_names); |
120 | |
|
121 | 0 | icon->init_names = g_new (char *, 2); |
122 | 0 | icon->init_names[0] = g_strdup (name); |
123 | 0 | icon->init_names[1] = NULL; |
124 | 0 | break; |
125 | | |
126 | 0 | case PROP_NAMES: |
127 | 0 | names = g_value_dup_boxed (value); |
128 | |
|
129 | 0 | if (!names) |
130 | 0 | break; |
131 | | |
132 | 0 | if (icon->init_names) |
133 | 0 | g_strfreev (icon->init_names); |
134 | |
|
135 | 0 | icon->init_names = names; |
136 | 0 | break; |
137 | | |
138 | 0 | case PROP_USE_DEFAULT_FALLBACKS: |
139 | 0 | icon->use_default_fallbacks = g_value_get_boolean (value); |
140 | 0 | break; |
141 | | |
142 | 0 | default: |
143 | 0 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
144 | 0 | } |
145 | 0 | } |
146 | | |
147 | | static void |
148 | | g_themed_icon_constructed (GObject *object) |
149 | 0 | { |
150 | 0 | g_themed_icon_update_names (G_THEMED_ICON (object)); |
151 | 0 | } |
152 | | |
153 | | static void |
154 | | g_themed_icon_finalize (GObject *object) |
155 | 0 | { |
156 | 0 | GThemedIcon *themed; |
157 | |
|
158 | 0 | themed = G_THEMED_ICON (object); |
159 | |
|
160 | 0 | g_strfreev (themed->init_names); |
161 | 0 | g_strfreev (themed->names); |
162 | |
|
163 | 0 | G_OBJECT_CLASS (g_themed_icon_parent_class)->finalize (object); |
164 | 0 | } |
165 | | |
166 | | static void |
167 | | g_themed_icon_class_init (GThemedIconClass *klass) |
168 | 0 | { |
169 | 0 | GObjectClass *gobject_class = G_OBJECT_CLASS (klass); |
170 | | |
171 | 0 | gobject_class->finalize = g_themed_icon_finalize; |
172 | 0 | gobject_class->constructed = g_themed_icon_constructed; |
173 | 0 | gobject_class->set_property = g_themed_icon_set_property; |
174 | 0 | gobject_class->get_property = g_themed_icon_get_property; |
175 | | |
176 | | /** |
177 | | * GThemedIcon:name: |
178 | | * |
179 | | * The icon name. |
180 | | */ |
181 | 0 | g_object_class_install_property (gobject_class, PROP_NAME, |
182 | 0 | g_param_spec_string ("name", NULL, NULL, |
183 | 0 | NULL, |
184 | 0 | G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK)); |
185 | | |
186 | | /** |
187 | | * GThemedIcon:names: |
188 | | * |
189 | | * A %NULL-terminated array of icon names. |
190 | | */ |
191 | 0 | g_object_class_install_property (gobject_class, PROP_NAMES, |
192 | 0 | g_param_spec_boxed ("names", NULL, NULL, |
193 | 0 | G_TYPE_STRV, |
194 | 0 | G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK)); |
195 | | |
196 | | /** |
197 | | * GThemedIcon:use-default-fallbacks: |
198 | | * |
199 | | * Whether to use the default fallbacks found by shortening the icon name |
200 | | * at '-' characters. If the "names" array has more than one element, |
201 | | * ignores any past the first. |
202 | | * |
203 | | * For example, if the icon name was "gnome-dev-cdrom-audio", the array |
204 | | * would become |
205 | | * |[<!-- language="C" --> |
206 | | * { |
207 | | * "gnome-dev-cdrom-audio", |
208 | | * "gnome-dev-cdrom", |
209 | | * "gnome-dev", |
210 | | * "gnome", |
211 | | * NULL |
212 | | * }; |
213 | | * ]| |
214 | | */ |
215 | 0 | g_object_class_install_property (gobject_class, PROP_USE_DEFAULT_FALLBACKS, |
216 | 0 | g_param_spec_boolean ("use-default-fallbacks", NULL, NULL, |
217 | 0 | FALSE, |
218 | 0 | G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK)); |
219 | 0 | } |
220 | | |
221 | | static void |
222 | | g_themed_icon_init (GThemedIcon *themed) |
223 | 0 | { |
224 | 0 | themed->init_names = NULL; |
225 | 0 | themed->names = NULL; |
226 | 0 | } |
227 | | |
228 | | /** |
229 | | * g_themed_icon_update_names: |
230 | | * @themed: a #GThemedIcon. |
231 | | * |
232 | | * Update the actual icon name list, based on the requested names (from |
233 | | * construction, or later added with g_themed_icon_prepend_name() and |
234 | | * g_themed_icon_append_name()). |
235 | | * The order of the list matters, indicating priority: |
236 | | * - The first requested icon is first in priority. |
237 | | * - If "use-default-fallbacks" is #TRUE, then it is followed by all its |
238 | | * fallbacks (starting from top to lower context levels). |
239 | | * - Then next requested icons, and optionally their fallbacks, follow. |
240 | | * - Finally all the style variants (symbolic or regular, opposite to whatever |
241 | | * is the requested style) follow in the same order. |
242 | | * |
243 | | * An icon is not added twice in the list if it was previously added. |
244 | | * |
245 | | * For instance, if requested names are: |
246 | | * [ "some-icon-symbolic", "some-other-icon" ] |
247 | | * and use-default-fallbacks is TRUE, the final name list shall be: |
248 | | * [ "some-icon-symbolic", "some-symbolic", "some-other-icon", |
249 | | * "some-other", "some", "some-icon", "some-other-icon-symbolic", |
250 | | * "some-other-symbolic" ] |
251 | | * |
252 | | * Returns: (transfer full) (type GThemedIcon): a new #GThemedIcon |
253 | | **/ |
254 | | static void |
255 | | g_themed_icon_update_names (GThemedIcon *themed) |
256 | 0 | { |
257 | 0 | GList *names = NULL; |
258 | 0 | GList *variants = NULL; |
259 | 0 | GList *iter; |
260 | 0 | guint i; |
261 | |
|
262 | 0 | g_return_if_fail (themed->init_names != NULL && themed->init_names[0] != NULL); |
263 | | |
264 | 0 | for (i = 0; themed->init_names[i]; i++) |
265 | 0 | { |
266 | 0 | gchar *name; |
267 | 0 | gboolean is_symbolic; |
268 | |
|
269 | 0 | is_symbolic = g_str_has_suffix (themed->init_names[i], "-symbolic"); |
270 | 0 | if (is_symbolic) |
271 | 0 | name = g_strndup (themed->init_names[i], strlen (themed->init_names[i]) - 9); |
272 | 0 | else |
273 | 0 | name = g_strdup (themed->init_names[i]); |
274 | |
|
275 | 0 | if (g_list_find_custom (names, name, (GCompareFunc) g_strcmp0)) |
276 | 0 | { |
277 | 0 | g_free (name); |
278 | 0 | continue; |
279 | 0 | } |
280 | | |
281 | 0 | if (is_symbolic) |
282 | 0 | names = g_list_prepend (names, g_strdup (themed->init_names[i])); |
283 | 0 | else |
284 | 0 | names = g_list_prepend (names, name); |
285 | |
|
286 | 0 | if (themed->use_default_fallbacks) |
287 | 0 | { |
288 | 0 | char *dashp; |
289 | 0 | char *last; |
290 | |
|
291 | 0 | last = name; |
292 | |
|
293 | 0 | while ((dashp = strrchr (last, '-')) != NULL) |
294 | 0 | { |
295 | 0 | gchar *tmp = last; |
296 | 0 | gchar *fallback; |
297 | |
|
298 | 0 | last = g_strndup (last, dashp - last); |
299 | 0 | if (is_symbolic) |
300 | 0 | { |
301 | 0 | g_free (tmp); |
302 | 0 | fallback = g_strdup_printf ("%s-symbolic", last); |
303 | 0 | } |
304 | 0 | else |
305 | 0 | fallback = last; |
306 | 0 | if (g_list_find_custom (names, fallback, (GCompareFunc) g_strcmp0)) |
307 | 0 | { |
308 | 0 | g_free (fallback); |
309 | 0 | break; |
310 | 0 | } |
311 | 0 | names = g_list_prepend (names, fallback); |
312 | 0 | } |
313 | 0 | if (is_symbolic) |
314 | 0 | g_free (last); |
315 | 0 | } |
316 | 0 | else if (is_symbolic) |
317 | 0 | g_free (name); |
318 | 0 | } |
319 | 0 | for (iter = names; iter; iter = iter->next) |
320 | 0 | { |
321 | 0 | gchar *name = (gchar *) iter->data; |
322 | 0 | gchar *variant; |
323 | 0 | gboolean is_symbolic; |
324 | |
|
325 | 0 | is_symbolic = g_str_has_suffix (name, "-symbolic"); |
326 | 0 | if (is_symbolic) |
327 | 0 | variant = g_strndup (name, strlen (name) - 9); |
328 | 0 | else |
329 | 0 | variant = g_strdup_printf ("%s-symbolic", name); |
330 | 0 | if (g_list_find_custom (names, variant, (GCompareFunc) g_strcmp0) || |
331 | 0 | g_list_find_custom (variants, variant, (GCompareFunc) g_strcmp0)) |
332 | 0 | { |
333 | 0 | g_free (variant); |
334 | 0 | continue; |
335 | 0 | } |
336 | | |
337 | 0 | variants = g_list_prepend (variants, variant); |
338 | 0 | } |
339 | 0 | names = g_list_reverse (names); |
340 | |
|
341 | 0 | g_strfreev (themed->names); |
342 | 0 | themed->names = g_new (char *, g_list_length (names) + g_list_length (variants) + 1); |
343 | |
|
344 | 0 | for (iter = names, i = 0; iter; iter = iter->next, i++) |
345 | 0 | themed->names[i] = iter->data; |
346 | 0 | for (iter = variants; iter; iter = iter->next, i++) |
347 | 0 | themed->names[i] = iter->data; |
348 | 0 | themed->names[i] = NULL; |
349 | |
|
350 | 0 | g_list_free (names); |
351 | 0 | g_list_free (variants); |
352 | |
|
353 | 0 | g_object_notify (G_OBJECT (themed), "names"); |
354 | 0 | } |
355 | | |
356 | | /** |
357 | | * g_themed_icon_new: |
358 | | * @iconname: a string containing an icon name. |
359 | | * |
360 | | * Creates a new themed icon for @iconname. |
361 | | * |
362 | | * Returns: (transfer full) (type GThemedIcon): a new #GThemedIcon. |
363 | | **/ |
364 | | GIcon * |
365 | | g_themed_icon_new (const char *iconname) |
366 | 0 | { |
367 | 0 | g_return_val_if_fail (iconname != NULL, NULL); |
368 | | |
369 | 0 | return G_ICON (g_object_new (G_TYPE_THEMED_ICON, "name", iconname, NULL)); |
370 | 0 | } |
371 | | |
372 | | /** |
373 | | * g_themed_icon_new_from_names: |
374 | | * @iconnames: (array length=len): an array of strings containing icon names. |
375 | | * @len: the length of the @iconnames array, or -1 if @iconnames is |
376 | | * %NULL-terminated |
377 | | * |
378 | | * Creates a new themed icon for @iconnames. |
379 | | * |
380 | | * Returns: (transfer full) (type GThemedIcon): a new #GThemedIcon |
381 | | **/ |
382 | | GIcon * |
383 | | g_themed_icon_new_from_names (char **iconnames, |
384 | | int len) |
385 | 0 | { |
386 | 0 | GIcon *icon; |
387 | |
|
388 | 0 | g_return_val_if_fail (iconnames != NULL, NULL); |
389 | | |
390 | 0 | if (len >= 0) |
391 | 0 | { |
392 | 0 | char **names; |
393 | 0 | int i; |
394 | |
|
395 | 0 | names = g_new (char *, len + 1); |
396 | |
|
397 | 0 | for (i = 0; i < len; i++) |
398 | 0 | names[i] = iconnames[i]; |
399 | |
|
400 | 0 | names[i] = NULL; |
401 | |
|
402 | 0 | icon = G_ICON (g_object_new (G_TYPE_THEMED_ICON, "names", names, NULL)); |
403 | |
|
404 | 0 | g_free (names); |
405 | 0 | } |
406 | 0 | else |
407 | 0 | icon = G_ICON (g_object_new (G_TYPE_THEMED_ICON, "names", iconnames, NULL)); |
408 | |
|
409 | 0 | return icon; |
410 | 0 | } |
411 | | |
412 | | /** |
413 | | * g_themed_icon_new_with_default_fallbacks: |
414 | | * @iconname: a string containing an icon name |
415 | | * |
416 | | * Creates a new themed icon for @iconname, and all the names |
417 | | * that can be created by shortening @iconname at '-' characters. |
418 | | * |
419 | | * In the following example, @icon1 and @icon2 are equivalent: |
420 | | * |[<!-- language="C" --> |
421 | | * const char *names[] = { |
422 | | * "gnome-dev-cdrom-audio", |
423 | | * "gnome-dev-cdrom", |
424 | | * "gnome-dev", |
425 | | * "gnome" |
426 | | * }; |
427 | | * |
428 | | * icon1 = g_themed_icon_new_from_names (names, 4); |
429 | | * icon2 = g_themed_icon_new_with_default_fallbacks ("gnome-dev-cdrom-audio"); |
430 | | * ]| |
431 | | * |
432 | | * Returns: (transfer full) (type GThemedIcon): a new #GThemedIcon. |
433 | | */ |
434 | | GIcon * |
435 | | g_themed_icon_new_with_default_fallbacks (const char *iconname) |
436 | 0 | { |
437 | 0 | g_return_val_if_fail (iconname != NULL, NULL); |
438 | | |
439 | 0 | return G_ICON (g_object_new (G_TYPE_THEMED_ICON, "name", iconname, "use-default-fallbacks", TRUE, NULL)); |
440 | 0 | } |
441 | | |
442 | | |
443 | | /** |
444 | | * g_themed_icon_get_names: |
445 | | * @icon: a #GThemedIcon. |
446 | | * |
447 | | * Gets the names of icons from within @icon. |
448 | | * |
449 | | * Returns: (transfer none): a list of icon names. |
450 | | */ |
451 | | const char * const * |
452 | | g_themed_icon_get_names (GThemedIcon *icon) |
453 | 0 | { |
454 | 0 | g_return_val_if_fail (G_IS_THEMED_ICON (icon), NULL); |
455 | 0 | return (const char * const *)icon->names; |
456 | 0 | } |
457 | | |
458 | | /** |
459 | | * g_themed_icon_append_name: |
460 | | * @icon: a #GThemedIcon |
461 | | * @iconname: name of icon to append to list of icons from within @icon. |
462 | | * |
463 | | * Append a name to the list of icons from within @icon. |
464 | | * |
465 | | * Note that doing so invalidates the hash computed by prior calls |
466 | | * to g_icon_hash(). |
467 | | */ |
468 | | void |
469 | | g_themed_icon_append_name (GThemedIcon *icon, |
470 | | const char *iconname) |
471 | 0 | { |
472 | 0 | guint num_names; |
473 | |
|
474 | 0 | g_return_if_fail (G_IS_THEMED_ICON (icon)); |
475 | 0 | g_return_if_fail (iconname != NULL); |
476 | | |
477 | 0 | num_names = g_strv_length (icon->init_names); |
478 | 0 | icon->init_names = g_realloc (icon->init_names, sizeof (char*) * (num_names + 2)); |
479 | 0 | icon->init_names[num_names] = g_strdup (iconname); |
480 | 0 | icon->init_names[num_names + 1] = NULL; |
481 | |
|
482 | 0 | g_themed_icon_update_names (icon); |
483 | 0 | } |
484 | | |
485 | | /** |
486 | | * g_themed_icon_prepend_name: |
487 | | * @icon: a #GThemedIcon |
488 | | * @iconname: name of icon to prepend to list of icons from within @icon. |
489 | | * |
490 | | * Prepend a name to the list of icons from within @icon. |
491 | | * |
492 | | * Note that doing so invalidates the hash computed by prior calls |
493 | | * to g_icon_hash(). |
494 | | * |
495 | | * Since: 2.18 |
496 | | */ |
497 | | void |
498 | | g_themed_icon_prepend_name (GThemedIcon *icon, |
499 | | const char *iconname) |
500 | 0 | { |
501 | 0 | guint num_names; |
502 | 0 | gchar **names; |
503 | 0 | gint i; |
504 | |
|
505 | 0 | g_return_if_fail (G_IS_THEMED_ICON (icon)); |
506 | 0 | g_return_if_fail (iconname != NULL); |
507 | | |
508 | 0 | num_names = g_strv_length (icon->init_names); |
509 | 0 | names = g_new (char*, num_names + 2); |
510 | 0 | for (i = 0; icon->init_names[i]; i++) |
511 | 0 | names[i + 1] = icon->init_names[i]; |
512 | 0 | names[0] = g_strdup (iconname); |
513 | 0 | names[num_names + 1] = NULL; |
514 | |
|
515 | 0 | g_free (icon->init_names); |
516 | 0 | icon->init_names = names; |
517 | |
|
518 | 0 | g_themed_icon_update_names (icon); |
519 | 0 | } |
520 | | |
521 | | static guint |
522 | | g_themed_icon_hash (GIcon *icon) |
523 | 0 | { |
524 | 0 | GThemedIcon *themed = G_THEMED_ICON (icon); |
525 | 0 | guint hash; |
526 | 0 | int i; |
527 | |
|
528 | 0 | hash = 0; |
529 | |
|
530 | 0 | for (i = 0; themed->names[i] != NULL; i++) |
531 | 0 | hash ^= g_str_hash (themed->names[i]); |
532 | | |
533 | 0 | return hash; |
534 | 0 | } |
535 | | |
536 | | static gboolean |
537 | | g_themed_icon_equal (GIcon *icon1, |
538 | | GIcon *icon2) |
539 | 0 | { |
540 | 0 | GThemedIcon *themed1 = G_THEMED_ICON (icon1); |
541 | 0 | GThemedIcon *themed2 = G_THEMED_ICON (icon2); |
542 | 0 | int i; |
543 | |
|
544 | 0 | for (i = 0; themed1->names[i] != NULL && themed2->names[i] != NULL; i++) |
545 | 0 | { |
546 | 0 | if (!g_str_equal (themed1->names[i], themed2->names[i])) |
547 | 0 | return FALSE; |
548 | 0 | } |
549 | | |
550 | 0 | return themed1->names[i] == NULL && themed2->names[i] == NULL; |
551 | 0 | } |
552 | | |
553 | | |
554 | | static gboolean |
555 | | g_themed_icon_to_tokens (GIcon *icon, |
556 | | GPtrArray *tokens, |
557 | | gint *out_version) |
558 | 0 | { |
559 | 0 | GThemedIcon *themed_icon = G_THEMED_ICON (icon); |
560 | 0 | int n; |
561 | |
|
562 | 0 | g_return_val_if_fail (out_version != NULL, FALSE); |
563 | | |
564 | 0 | *out_version = 0; |
565 | |
|
566 | 0 | for (n = 0; themed_icon->names[n] != NULL; n++) |
567 | 0 | g_ptr_array_add (tokens, |
568 | 0 | g_strdup (themed_icon->names[n])); |
569 | | |
570 | 0 | return TRUE; |
571 | 0 | } |
572 | | |
573 | | static GIcon * |
574 | | g_themed_icon_from_tokens (gchar **tokens, |
575 | | gint num_tokens, |
576 | | gint version, |
577 | | GError **error) |
578 | 0 | { |
579 | 0 | GIcon *icon; |
580 | 0 | gchar **names; |
581 | 0 | int n; |
582 | |
|
583 | 0 | icon = NULL; |
584 | |
|
585 | 0 | if (version != 0) |
586 | 0 | { |
587 | 0 | g_set_error (error, |
588 | 0 | G_IO_ERROR, |
589 | 0 | G_IO_ERROR_INVALID_ARGUMENT, |
590 | 0 | _("Can’t handle version %d of GThemedIcon encoding"), |
591 | 0 | version); |
592 | 0 | goto out; |
593 | 0 | } |
594 | | |
595 | 0 | names = g_new0 (gchar *, num_tokens + 1); |
596 | 0 | for (n = 0; n < num_tokens; n++) |
597 | 0 | names[n] = tokens[n]; |
598 | 0 | names[n] = NULL; |
599 | |
|
600 | 0 | icon = g_themed_icon_new_from_names (names, num_tokens); |
601 | 0 | g_free (names); |
602 | |
|
603 | 0 | out: |
604 | 0 | return icon; |
605 | 0 | } |
606 | | |
607 | | static GVariant * |
608 | | g_themed_icon_serialize (GIcon *icon) |
609 | 0 | { |
610 | 0 | GThemedIcon *themed_icon = G_THEMED_ICON (icon); |
611 | |
|
612 | 0 | return g_variant_new ("(sv)", "themed", g_variant_new ("^as", themed_icon->names)); |
613 | 0 | } |
614 | | |
615 | | static void |
616 | | g_themed_icon_icon_iface_init (GIconIface *iface) |
617 | 0 | { |
618 | 0 | iface->hash = g_themed_icon_hash; |
619 | 0 | iface->equal = g_themed_icon_equal; |
620 | 0 | iface->to_tokens = g_themed_icon_to_tokens; |
621 | 0 | iface->from_tokens = g_themed_icon_from_tokens; |
622 | 0 | iface->serialize = g_themed_icon_serialize; |
623 | 0 | } |