nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /* GIO - GLib Input, Output and Streaming Library |
2 | * |
||
3 | * Copyright (C) 2006-2007 Red Hat, Inc. |
||
4 | * |
||
5 | * This library is free software; you can redistribute it and/or |
||
6 | * modify it under the terms of the GNU Lesser General Public |
||
7 | * License as published by the Free Software Foundation; either |
||
8 | * version 2 of the License, or (at your option) any later version. |
||
9 | * |
||
10 | * This library is distributed in the hope that it will be useful, |
||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||
13 | * Lesser General Public License for more details. |
||
14 | * |
||
15 | * You should have received a copy of the GNU Lesser General |
||
16 | * Public License along with this library; if not, see <http://www.gnu.org/licenses/>. |
||
17 | * |
||
18 | * Author: Alexander Larsson <alexl@redhat.com> |
||
19 | */ |
||
20 | |||
21 | #include "config.h" |
||
22 | #include <stdlib.h> |
||
23 | #include <string.h> |
||
24 | |||
25 | #include "gicon.h" |
||
26 | #include "gthemedicon.h" |
||
27 | #include "gfileicon.h" |
||
28 | #include "gemblemedicon.h" |
||
29 | #include "gbytesicon.h" |
||
30 | #include "gfile.h" |
||
31 | #include "gioerror.h" |
||
32 | #include "gioenumtypes.h" |
||
33 | #include "gvfs.h" |
||
34 | |||
35 | #include "glibintl.h" |
||
36 | |||
37 | |||
38 | /* There versioning of this is implicit, version 1 would be ".1 " */ |
||
39 | #define G_ICON_SERIALIZATION_MAGIC0 ". " |
||
40 | |||
41 | /** |
||
42 | * SECTION:gicon |
||
43 | * @short_description: Interface for icons |
||
44 | * @include: gio/gio.h |
||
45 | * |
||
46 | * #GIcon is a very minimal interface for icons. It provides functions |
||
47 | * for checking the equality of two icons, hashing of icons and |
||
48 | * serializing an icon to and from strings. |
||
49 | * |
||
50 | * #GIcon does not provide the actual pixmap for the icon as this is out |
||
51 | * of GIO's scope, however implementations of #GIcon may contain the name |
||
52 | * of an icon (see #GThemedIcon), or the path to an icon (see #GLoadableIcon). |
||
53 | * |
||
54 | * To obtain a hash of a #GIcon, see g_icon_hash(). |
||
55 | * |
||
56 | * To check if two #GIcons are equal, see g_icon_equal(). |
||
57 | * |
||
58 | * For serializing a #GIcon, use g_icon_serialize() and |
||
59 | * g_icon_deserialize(). |
||
60 | * |
||
61 | * If you want to consume #GIcon (for example, in a toolkit) you must |
||
62 | * be prepared to handle at least the three following cases: |
||
63 | * #GLoadableIcon, #GThemedIcon and #GEmblemedIcon. It may also make |
||
64 | * sense to have fast-paths for other cases (like handling #GdkPixbuf |
||
65 | * directly, for example) but all compliant #GIcon implementations |
||
66 | * outside of GIO must implement #GLoadableIcon. |
||
67 | * |
||
68 | * If your application or library provides one or more #GIcon |
||
69 | * implementations you need to ensure that your new implementation also |
||
70 | * implements #GLoadableIcon. Additionally, you must provide an |
||
71 | * implementation of g_icon_serialize() that gives a result that is |
||
72 | * understood by g_icon_deserialize(), yielding one of the built-in icon |
||
73 | * types. |
||
74 | **/ |
||
75 | |||
76 | typedef GIconIface GIconInterface; |
||
77 | G_DEFINE_INTERFACE(GIcon, g_icon, G_TYPE_OBJECT) |
||
78 | |||
79 | static void |
||
80 | g_icon_default_init (GIconInterface *iface) |
||
81 | { |
||
82 | } |
||
83 | |||
84 | /** |
||
85 | * g_icon_hash: |
||
86 | * @icon: (not nullable): #gconstpointer to an icon object. |
||
87 | * |
||
88 | * Gets a hash for an icon. |
||
89 | * |
||
90 | * Virtual: hash |
||
91 | * Returns: a #guint containing a hash for the @icon, suitable for |
||
92 | * use in a #GHashTable or similar data structure. |
||
93 | **/ |
||
94 | guint |
||
95 | g_icon_hash (gconstpointer icon) |
||
96 | { |
||
97 | GIconIface *iface; |
||
98 | |||
99 | g_return_val_if_fail (G_IS_ICON (icon), 0); |
||
100 | |||
101 | iface = G_ICON_GET_IFACE (icon); |
||
102 | |||
103 | return (* iface->hash) ((GIcon *)icon); |
||
104 | } |
||
105 | |||
106 | /** |
||
107 | * g_icon_equal: |
||
108 | * @icon1: (allow-none): pointer to the first #GIcon. |
||
109 | * @icon2: (allow-none): pointer to the second #GIcon. |
||
110 | * |
||
111 | * Checks if two icons are equal. |
||
112 | * |
||
113 | * Returns: %TRUE if @icon1 is equal to @icon2. %FALSE otherwise. |
||
114 | **/ |
||
115 | gboolean |
||
116 | g_icon_equal (GIcon *icon1, |
||
117 | GIcon *icon2) |
||
118 | { |
||
119 | GIconIface *iface; |
||
120 | |||
121 | if (icon1 == NULL && icon2 == NULL) |
||
122 | return TRUE; |
||
123 | |||
124 | if (icon1 == NULL || icon2 == NULL) |
||
125 | return FALSE; |
||
126 | |||
127 | if (G_TYPE_FROM_INSTANCE (icon1) != G_TYPE_FROM_INSTANCE (icon2)) |
||
128 | return FALSE; |
||
129 | |||
130 | iface = G_ICON_GET_IFACE (icon1); |
||
131 | |||
132 | return (* iface->equal) (icon1, icon2); |
||
133 | } |
||
134 | |||
135 | static gboolean |
||
136 | g_icon_to_string_tokenized (GIcon *icon, GString *s) |
||
137 | { |
||
138 | GPtrArray *tokens; |
||
139 | gint version; |
||
140 | GIconIface *icon_iface; |
||
141 | int i; |
||
142 | |||
143 | g_return_val_if_fail (icon != NULL, FALSE); |
||
144 | g_return_val_if_fail (G_IS_ICON (icon), FALSE); |
||
145 | |||
146 | icon_iface = G_ICON_GET_IFACE (icon); |
||
147 | if (icon_iface->to_tokens == NULL) |
||
148 | return FALSE; |
||
149 | |||
150 | tokens = g_ptr_array_new (); |
||
151 | if (!icon_iface->to_tokens (icon, tokens, &version)) |
||
152 | { |
||
153 | g_ptr_array_free (tokens, TRUE); |
||
154 | return FALSE; |
||
155 | } |
||
156 | |||
157 | /* format: TypeName[.Version] <token_0> .. <token_N-1> |
||
158 | version 0 is implicit and can be omitted |
||
159 | all the tokens are url escaped to ensure they have no spaces in them */ |
||
160 | |||
161 | g_string_append (s, g_type_name_from_instance ((GTypeInstance *)icon)); |
||
162 | if (version != 0) |
||
163 | g_string_append_printf (s, ".%d", version); |
||
164 | |||
165 | for (i = 0; i < tokens->len; i++) |
||
166 | { |
||
167 | char *token; |
||
168 | |||
169 | token = g_ptr_array_index (tokens, i); |
||
170 | |||
171 | g_string_append_c (s, ' '); |
||
172 | /* We really only need to escape spaces here, so allow lots of otherwise reserved chars */ |
||
173 | g_string_append_uri_escaped (s, token, |
||
174 | G_URI_RESERVED_CHARS_ALLOWED_IN_PATH, TRUE); |
||
175 | |||
176 | g_free (token); |
||
177 | } |
||
178 | |||
179 | g_ptr_array_free (tokens, TRUE); |
||
180 | |||
181 | return TRUE; |
||
182 | } |
||
183 | |||
184 | /** |
||
185 | * g_icon_to_string: |
||
186 | * @icon: a #GIcon. |
||
187 | * |
||
188 | * Generates a textual representation of @icon that can be used for |
||
189 | * serialization such as when passing @icon to a different process or |
||
190 | * saving it to persistent storage. Use g_icon_new_for_string() to |
||
191 | * get @icon back from the returned string. |
||
192 | * |
||
193 | * The encoding of the returned string is proprietary to #GIcon except |
||
194 | * in the following two cases |
||
195 | * |
||
196 | * - If @icon is a #GFileIcon, the returned string is a native path |
||
197 | * (such as `/path/to/my icon.png`) without escaping |
||
198 | * if the #GFile for @icon is a native file. If the file is not |
||
199 | * native, the returned string is the result of g_file_get_uri() |
||
200 | * (such as `sftp://path/to/my%20icon.png`). |
||
201 | * |
||
202 | * - If @icon is a #GThemedIcon with exactly one name, the encoding is |
||
203 | * simply the name (such as `network-server`). |
||
204 | * |
||
205 | * Virtual: to_tokens |
||
206 | * Returns: (nullable): An allocated NUL-terminated UTF8 string or |
||
207 | * %NULL if @icon can't be serialized. Use g_free() to free. |
||
208 | * |
||
209 | * Since: 2.20 |
||
210 | */ |
||
211 | gchar * |
||
212 | g_icon_to_string (GIcon *icon) |
||
213 | { |
||
214 | gchar *ret; |
||
215 | |||
216 | g_return_val_if_fail (icon != NULL, NULL); |
||
217 | g_return_val_if_fail (G_IS_ICON (icon), NULL); |
||
218 | |||
219 | ret = NULL; |
||
220 | |||
221 | if (G_IS_FILE_ICON (icon)) |
||
222 | { |
||
223 | GFile *file; |
||
224 | |||
225 | file = g_file_icon_get_file (G_FILE_ICON (icon)); |
||
226 | if (g_file_is_native (file)) |
||
227 | { |
||
228 | ret = g_file_get_path (file); |
||
229 | if (!g_utf8_validate (ret, -1, NULL)) |
||
230 | { |
||
231 | g_free (ret); |
||
232 | ret = NULL; |
||
233 | } |
||
234 | } |
||
235 | else |
||
236 | ret = g_file_get_uri (file); |
||
237 | } |
||
238 | else if (G_IS_THEMED_ICON (icon)) |
||
239 | { |
||
240 | const char * const *names; |
||
241 | |||
242 | names = g_themed_icon_get_names (G_THEMED_ICON (icon)); |
||
243 | if (names != NULL && |
||
244 | names[0] != NULL && |
||
245 | names[0][0] != '.' && /* Allowing icons starting with dot would break G_ICON_SERIALIZATION_MAGIC0 */ |
||
246 | g_utf8_validate (names[0], -1, NULL) && /* Only return utf8 strings */ |
||
247 | names[1] == NULL) |
||
248 | ret = g_strdup (names[0]); |
||
249 | } |
||
250 | |||
251 | if (ret == NULL) |
||
252 | { |
||
253 | GString *s; |
||
254 | |||
255 | s = g_string_new (G_ICON_SERIALIZATION_MAGIC0); |
||
256 | |||
257 | if (g_icon_to_string_tokenized (icon, s)) |
||
258 | ret = g_string_free (s, FALSE); |
||
259 | else |
||
260 | g_string_free (s, TRUE); |
||
261 | } |
||
262 | |||
263 | return ret; |
||
264 | } |
||
265 | |||
266 | static GIcon * |
||
267 | g_icon_new_from_tokens (char **tokens, |
||
268 | GError **error) |
||
269 | { |
||
270 | GIcon *icon; |
||
271 | char *typename, *version_str; |
||
272 | GType type; |
||
273 | gpointer klass; |
||
274 | GIconIface *icon_iface; |
||
275 | gint version; |
||
276 | char *endp; |
||
277 | int num_tokens; |
||
278 | int i; |
||
279 | |||
280 | icon = NULL; |
||
281 | klass = NULL; |
||
282 | |||
283 | num_tokens = g_strv_length (tokens); |
||
284 | |||
285 | if (num_tokens < 1) |
||
286 | { |
||
287 | g_set_error (error, |
||
288 | G_IO_ERROR, |
||
289 | G_IO_ERROR_INVALID_ARGUMENT, |
||
290 | _("Wrong number of tokens (%d)"), |
||
291 | num_tokens); |
||
292 | goto out; |
||
293 | } |
||
294 | |||
295 | typename = tokens[0]; |
||
296 | version_str = strchr (typename, '.'); |
||
297 | if (version_str) |
||
298 | { |
||
299 | *version_str = 0; |
||
300 | version_str += 1; |
||
301 | } |
||
302 | |||
303 | |||
304 | type = g_type_from_name (tokens[0]); |
||
305 | if (type == 0) |
||
306 | { |
||
307 | g_set_error (error, |
||
308 | G_IO_ERROR, |
||
309 | G_IO_ERROR_INVALID_ARGUMENT, |
||
310 | _("No type for class name %s"), |
||
311 | tokens[0]); |
||
312 | goto out; |
||
313 | } |
||
314 | |||
315 | if (!g_type_is_a (type, G_TYPE_ICON)) |
||
316 | { |
||
317 | g_set_error (error, |
||
318 | G_IO_ERROR, |
||
319 | G_IO_ERROR_INVALID_ARGUMENT, |
||
320 | _("Type %s does not implement the GIcon interface"), |
||
321 | tokens[0]); |
||
322 | goto out; |
||
323 | } |
||
324 | |||
325 | klass = g_type_class_ref (type); |
||
326 | if (klass == NULL) |
||
327 | { |
||
328 | g_set_error (error, |
||
329 | G_IO_ERROR, |
||
330 | G_IO_ERROR_INVALID_ARGUMENT, |
||
331 | _("Type %s is not classed"), |
||
332 | tokens[0]); |
||
333 | goto out; |
||
334 | } |
||
335 | |||
336 | version = 0; |
||
337 | if (version_str) |
||
338 | { |
||
339 | version = strtol (version_str, &endp, 10); |
||
340 | if (endp == NULL || *endp != '\0') |
||
341 | { |
||
342 | g_set_error (error, |
||
343 | G_IO_ERROR, |
||
344 | G_IO_ERROR_INVALID_ARGUMENT, |
||
345 | _("Malformed version number: %s"), |
||
346 | version_str); |
||
347 | goto out; |
||
348 | } |
||
349 | } |
||
350 | |||
351 | icon_iface = g_type_interface_peek (klass, G_TYPE_ICON); |
||
352 | g_assert (icon_iface != NULL); |
||
353 | |||
354 | if (icon_iface->from_tokens == NULL) |
||
355 | { |
||
356 | g_set_error (error, |
||
357 | G_IO_ERROR, |
||
358 | G_IO_ERROR_INVALID_ARGUMENT, |
||
359 | _("Type %s does not implement from_tokens() on the GIcon interface"), |
||
360 | tokens[0]); |
||
361 | goto out; |
||
362 | } |
||
363 | |||
364 | for (i = 1; i < num_tokens; i++) |
||
365 | { |
||
366 | char *escaped; |
||
367 | |||
368 | escaped = tokens[i]; |
||
369 | tokens[i] = g_uri_unescape_string (escaped, NULL); |
||
370 | g_free (escaped); |
||
371 | } |
||
372 | |||
373 | icon = icon_iface->from_tokens (tokens + 1, num_tokens - 1, version, error); |
||
374 | |||
375 | out: |
||
376 | if (klass != NULL) |
||
377 | g_type_class_unref (klass); |
||
378 | return icon; |
||
379 | } |
||
380 | |||
381 | static void |
||
382 | ensure_builtin_icon_types (void) |
||
383 | { |
||
384 | g_type_ensure (G_TYPE_THEMED_ICON); |
||
385 | g_type_ensure (G_TYPE_FILE_ICON); |
||
386 | g_type_ensure (G_TYPE_EMBLEMED_ICON); |
||
387 | g_type_ensure (G_TYPE_EMBLEM); |
||
388 | } |
||
389 | |||
390 | /* handles the 'simple' cases: GFileIcon and GThemedIcon */ |
||
391 | static GIcon * |
||
392 | g_icon_new_for_string_simple (const gchar *str) |
||
393 | { |
||
394 | gchar *scheme; |
||
395 | GIcon *icon; |
||
396 | |||
397 | if (str[0] == '.') |
||
398 | return NULL; |
||
399 | |||
400 | /* handle special GFileIcon and GThemedIcon cases */ |
||
401 | scheme = g_uri_parse_scheme (str); |
||
402 | if (scheme != NULL || str[0] == '/' || str[0] == G_DIR_SEPARATOR) |
||
403 | { |
||
404 | GFile *location; |
||
405 | location = g_file_new_for_commandline_arg (str); |
||
406 | icon = g_file_icon_new (location); |
||
407 | g_object_unref (location); |
||
408 | } |
||
409 | else |
||
410 | icon = g_themed_icon_new (str); |
||
411 | |||
412 | g_free (scheme); |
||
413 | |||
414 | return icon; |
||
415 | } |
||
416 | |||
417 | /** |
||
418 | * g_icon_new_for_string: |
||
419 | * @str: A string obtained via g_icon_to_string(). |
||
420 | * @error: Return location for error. |
||
421 | * |
||
422 | * Generate a #GIcon instance from @str. This function can fail if |
||
423 | * @str is not valid - see g_icon_to_string() for discussion. |
||
424 | * |
||
425 | * If your application or library provides one or more #GIcon |
||
426 | * implementations you need to ensure that each #GType is registered |
||
427 | * with the type system prior to calling g_icon_new_for_string(). |
||
428 | * |
||
429 | * Returns: (transfer full): An object implementing the #GIcon |
||
430 | * interface or %NULL if @error is set. |
||
431 | * |
||
432 | * Since: 2.20 |
||
433 | **/ |
||
434 | GIcon * |
||
435 | g_icon_new_for_string (const gchar *str, |
||
436 | GError **error) |
||
437 | { |
||
438 | GIcon *icon = NULL; |
||
439 | |||
440 | g_return_val_if_fail (str != NULL, NULL); |
||
441 | |||
442 | icon = g_icon_new_for_string_simple (str); |
||
443 | if (icon) |
||
444 | return icon; |
||
445 | |||
446 | ensure_builtin_icon_types (); |
||
447 | |||
448 | if (g_str_has_prefix (str, G_ICON_SERIALIZATION_MAGIC0)) |
||
449 | { |
||
450 | gchar **tokens; |
||
451 | |||
452 | /* handle tokenized encoding */ |
||
453 | tokens = g_strsplit (str + sizeof (G_ICON_SERIALIZATION_MAGIC0) - 1, " ", 0); |
||
454 | icon = g_icon_new_from_tokens (tokens, error); |
||
455 | g_strfreev (tokens); |
||
456 | } |
||
457 | else |
||
458 | g_set_error_literal (error, |
||
459 | G_IO_ERROR, |
||
460 | G_IO_ERROR_INVALID_ARGUMENT, |
||
461 | _("Can't handle the supplied version of the icon encoding")); |
||
462 | |||
463 | return icon; |
||
464 | } |
||
465 | |||
466 | static GEmblem * |
||
467 | g_icon_deserialize_emblem (GVariant *value) |
||
468 | { |
||
469 | GVariant *emblem_metadata; |
||
470 | GVariant *emblem_data; |
||
471 | const gchar *origin_nick; |
||
472 | GIcon *emblem_icon; |
||
473 | GEmblem *emblem; |
||
474 | |||
475 | g_variant_get (value, "(v@a{sv})", &emblem_data, &emblem_metadata); |
||
476 | |||
477 | emblem = NULL; |
||
478 | |||
479 | emblem_icon = g_icon_deserialize (emblem_data); |
||
480 | if (emblem_icon != NULL) |
||
481 | { |
||
482 | /* Check if we should create it with an origin. */ |
||
483 | if (g_variant_lookup (emblem_metadata, "origin", "&s", &origin_nick)) |
||
484 | { |
||
485 | GEnumClass *origin_class; |
||
486 | GEnumValue *origin_value; |
||
487 | |||
488 | origin_class = g_type_class_ref (G_TYPE_EMBLEM_ORIGIN); |
||
489 | origin_value = g_enum_get_value_by_nick (origin_class, origin_nick); |
||
490 | if (origin_value) |
||
491 | emblem = g_emblem_new_with_origin (emblem_icon, origin_value->value); |
||
492 | g_type_class_unref (origin_class); |
||
493 | } |
||
494 | |||
495 | /* We didn't create it with an origin, so do it without. */ |
||
496 | if (emblem == NULL) |
||
497 | emblem = g_emblem_new (emblem_icon); |
||
498 | |||
499 | g_object_unref (emblem_icon); |
||
500 | } |
||
501 | |||
502 | g_variant_unref (emblem_metadata); |
||
503 | g_variant_unref (emblem_data); |
||
504 | |||
505 | return emblem; |
||
506 | } |
||
507 | |||
508 | static GIcon * |
||
509 | g_icon_deserialize_emblemed (GVariant *value) |
||
510 | { |
||
511 | GVariantIter *emblems; |
||
512 | GVariant *icon_data; |
||
513 | GIcon *main_icon; |
||
514 | GIcon *icon; |
||
515 | |||
516 | g_variant_get (value, "(va(va{sv}))", &icon_data, &emblems); |
||
517 | main_icon = g_icon_deserialize (icon_data); |
||
518 | |||
519 | if (main_icon) |
||
520 | { |
||
521 | GVariant *emblem_data; |
||
522 | |||
523 | icon = g_emblemed_icon_new (main_icon, NULL); |
||
524 | |||
525 | while ((emblem_data = g_variant_iter_next_value (emblems))) |
||
526 | { |
||
527 | GEmblem *emblem; |
||
528 | |||
529 | emblem = g_icon_deserialize_emblem (emblem_data); |
||
530 | |||
531 | if (emblem) |
||
532 | { |
||
533 | g_emblemed_icon_add_emblem (G_EMBLEMED_ICON (icon), emblem); |
||
534 | g_object_unref (emblem); |
||
535 | } |
||
536 | |||
537 | g_variant_unref (emblem_data); |
||
538 | } |
||
539 | |||
540 | g_object_unref (main_icon); |
||
541 | } |
||
542 | else |
||
543 | icon = NULL; |
||
544 | |||
545 | g_variant_iter_free (emblems); |
||
546 | g_variant_unref (icon_data); |
||
547 | |||
548 | return icon; |
||
549 | } |
||
550 | |||
551 | /** |
||
552 | * g_icon_deserialize: |
||
553 | * @value: a #GVariant created with g_icon_serialize() |
||
554 | * |
||
555 | * Deserializes a #GIcon previously serialized using g_icon_serialize(). |
||
556 | * |
||
557 | * Returns: (transfer full): a #GIcon, or %NULL when deserialization fails. |
||
558 | * |
||
559 | * Since: 2.38 |
||
560 | */ |
||
561 | GIcon * |
||
562 | g_icon_deserialize (GVariant *value) |
||
563 | { |
||
564 | const gchar *tag; |
||
565 | GVariant *val; |
||
566 | GIcon *icon; |
||
567 | |||
568 | g_return_val_if_fail (value != NULL, NULL); |
||
569 | g_return_val_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE_STRING) || |
||
570 | g_variant_is_of_type (value, G_VARIANT_TYPE ("(sv)")), NULL); |
||
571 | |||
572 | /* Handle some special cases directly so that people can hard-code |
||
573 | * stuff into GMenuModel xml files without resorting to using GVariant |
||
574 | * text format to describe one of the explicitly-tagged possibilities |
||
575 | * below. |
||
576 | */ |
||
577 | if (g_variant_is_of_type (value, G_VARIANT_TYPE_STRING)) |
||
578 | return g_icon_new_for_string_simple (g_variant_get_string (value, NULL)); |
||
579 | |||
580 | /* Otherwise, use the tagged union format */ |
||
581 | g_variant_get (value, "(&sv)", &tag, &val); |
||
582 | |||
583 | icon = NULL; |
||
584 | |||
585 | if (g_str_equal (tag, "file") && g_variant_is_of_type (val, G_VARIANT_TYPE_STRING)) |
||
586 | { |
||
587 | GFile *file; |
||
588 | |||
589 | file = g_file_new_for_commandline_arg (g_variant_get_string (val, NULL)); |
||
590 | icon = g_file_icon_new (file); |
||
591 | g_object_unref (file); |
||
592 | } |
||
593 | else if (g_str_equal (tag, "themed") && g_variant_is_of_type (val, G_VARIANT_TYPE_STRING_ARRAY)) |
||
594 | { |
||
595 | const gchar **names; |
||
596 | gsize size; |
||
597 | |||
598 | names = g_variant_get_strv (val, &size); |
||
599 | icon = g_themed_icon_new_from_names ((gchar **) names, size); |
||
600 | g_free (names); |
||
601 | } |
||
602 | else if (g_str_equal (tag, "bytes") && g_variant_is_of_type (val, G_VARIANT_TYPE_BYTESTRING)) |
||
603 | { |
||
604 | GBytes *bytes; |
||
605 | |||
606 | bytes = g_variant_get_data_as_bytes (val); |
||
607 | icon = g_bytes_icon_new (bytes); |
||
608 | g_bytes_unref (bytes); |
||
609 | } |
||
610 | else if (g_str_equal (tag, "emblem") && g_variant_is_of_type (val, G_VARIANT_TYPE ("(va{sv})"))) |
||
611 | { |
||
612 | GEmblem *emblem; |
||
613 | |||
614 | emblem = g_icon_deserialize_emblem (val); |
||
615 | if (emblem) |
||
616 | icon = G_ICON (emblem); |
||
617 | } |
||
618 | else if (g_str_equal (tag, "emblemed") && g_variant_is_of_type (val, G_VARIANT_TYPE ("(va(va{sv}))"))) |
||
619 | { |
||
620 | icon = g_icon_deserialize_emblemed (val); |
||
621 | } |
||
622 | else if (g_str_equal (tag, "gvfs")) |
||
623 | { |
||
624 | GVfsClass *class; |
||
625 | GVfs *vfs; |
||
626 | |||
627 | vfs = g_vfs_get_default (); |
||
628 | class = G_VFS_GET_CLASS (vfs); |
||
629 | if (class->deserialize_icon) |
||
630 | icon = (* class->deserialize_icon) (vfs, val); |
||
631 | } |
||
632 | |||
633 | g_variant_unref (val); |
||
634 | |||
635 | return icon; |
||
636 | } |
||
637 | |||
638 | /** |
||
639 | * g_icon_serialize: |
||
640 | * @icon: a #GIcon |
||
641 | * |
||
642 | * Serializes a #GIcon into a #GVariant. An equivalent #GIcon can be retrieved |
||
643 | * back by calling g_icon_deserialize() on the returned value. |
||
644 | * As serialization will avoid using raw icon data when possible, it only |
||
645 | * makes sense to transfer the #GVariant between processes on the same machine, |
||
646 | * (as opposed to over the network), and within the same file system namespace. |
||
647 | * |
||
648 | * Returns: (transfer full): a #GVariant, or %NULL when serialization fails. |
||
649 | * |
||
650 | * Since: 2.38 |
||
651 | */ |
||
652 | GVariant * |
||
653 | g_icon_serialize (GIcon *icon) |
||
654 | { |
||
655 | GIconInterface *iface; |
||
656 | GVariant *result; |
||
657 | |||
658 | iface = G_ICON_GET_IFACE (icon); |
||
659 | |||
660 | if (!iface->serialize) |
||
661 | { |
||
662 | g_critical ("g_icon_serialize() on icon type '%s' is not implemented", G_OBJECT_TYPE_NAME (icon)); |
||
663 | return NULL; |
||
664 | } |
||
665 | |||
666 | result = (* iface->serialize) (icon); |
||
667 | |||
668 | if (result) |
||
669 | { |
||
670 | g_variant_take_ref (result); |
||
671 | |||
672 | if (!g_variant_is_of_type (result, G_VARIANT_TYPE ("(sv)"))) |
||
673 | { |
||
674 | g_critical ("g_icon_serialize() on icon type '%s' returned GVariant of type '%s' but it must return " |
||
675 | "one with type '(sv)'", G_OBJECT_TYPE_NAME (icon), g_variant_get_type_string (result)); |
||
676 | g_variant_unref (result); |
||
677 | result = NULL; |
||
678 | } |
||
679 | } |
||
680 | |||
681 | return result; |
||
682 | } |