Branch data Line data Source code
1 : : /* GIO - GLib Input, Output and Streaming Library
2 : : *
3 : : * Copyright (C) 2008 Clemens N. Buss <cebuzz@gmail.com>
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 : :
21 : : #include <config.h>
22 : :
23 : : #include "gicon.h"
24 : : #include "gemblem.h"
25 : : #include "glibintl.h"
26 : : #include "gioenums.h"
27 : : #include "gioenumtypes.h"
28 : : #include "gioerror.h"
29 : : #include <stdint.h>
30 : : #include <stdlib.h>
31 : : #include <string.h>
32 : :
33 : :
34 : : /**
35 : : * GEmblem:
36 : : *
37 : : * `GEmblem` is an implementation of [iface@Gio.Icon] that supports
38 : : * having an emblem, which is an icon with additional properties.
39 : : * It can than be added to a [class@Gio.EmblemedIcon].
40 : : *
41 : : * Currently, only metainformation about the emblem's origin is
42 : : * supported. More may be added in the future.
43 : : */
44 : :
45 : : static void g_emblem_iface_init (GIconIface *iface);
46 : :
47 : : struct _GEmblem
48 : : {
49 : : GObject parent_instance;
50 : :
51 : : GIcon *icon;
52 : : GEmblemOrigin origin;
53 : : };
54 : :
55 : : struct _GEmblemClass
56 : : {
57 : : GObjectClass parent_class;
58 : : };
59 : :
60 : : enum
61 : : {
62 : : PROP_0_GEMBLEM,
63 : : PROP_ICON,
64 : : PROP_ORIGIN
65 : : };
66 : :
67 : 196 : G_DEFINE_TYPE_WITH_CODE (GEmblem, g_emblem, G_TYPE_OBJECT,
68 : : G_IMPLEMENT_INTERFACE (G_TYPE_ICON, g_emblem_iface_init))
69 : :
70 : : static void
71 : 6 : g_emblem_get_property (GObject *object,
72 : : guint prop_id,
73 : : GValue *value,
74 : : GParamSpec *pspec)
75 : : {
76 : 6 : GEmblem *emblem = G_EMBLEM (object);
77 : :
78 : 6 : switch (prop_id)
79 : : {
80 : 3 : case PROP_ICON:
81 : 3 : g_value_set_object (value, emblem->icon);
82 : 3 : break;
83 : :
84 : 3 : case PROP_ORIGIN:
85 : 3 : g_value_set_enum (value, (int) emblem->origin);
86 : 3 : break;
87 : :
88 : 0 : default:
89 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
90 : 0 : break;
91 : : }
92 : 6 : }
93 : :
94 : : static void
95 : 34 : g_emblem_set_property (GObject *object,
96 : : guint prop_id,
97 : : const GValue *value,
98 : : GParamSpec *pspec)
99 : : {
100 : 34 : GEmblem *emblem = G_EMBLEM (object);
101 : :
102 : 34 : switch (prop_id)
103 : : {
104 : 17 : case PROP_ICON:
105 : 17 : emblem->icon = g_value_dup_object (value);
106 : 17 : break;
107 : :
108 : 17 : case PROP_ORIGIN:
109 : 17 : emblem->origin = (GEmblemOrigin) g_value_get_enum (value);
110 : 17 : break;
111 : :
112 : 0 : default:
113 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
114 : 0 : break;
115 : : }
116 : 34 : }
117 : :
118 : : static void
119 : 17 : g_emblem_finalize (GObject *object)
120 : : {
121 : 17 : GEmblem *emblem = G_EMBLEM (object);
122 : :
123 : 17 : if (emblem->icon)
124 : 16 : g_object_unref (emblem->icon);
125 : :
126 : 17 : (*G_OBJECT_CLASS (g_emblem_parent_class)->finalize) (object);
127 : 17 : }
128 : :
129 : : static void
130 : 3 : g_emblem_class_init (GEmblemClass *klass)
131 : : {
132 : 3 : GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
133 : :
134 : 3 : gobject_class->finalize = g_emblem_finalize;
135 : 3 : gobject_class->set_property = g_emblem_set_property;
136 : 3 : gobject_class->get_property = g_emblem_get_property;
137 : :
138 : : /**
139 : : * GEmblem:origin:
140 : : *
141 : : * The origin the emblem is derived from.
142 : : *
143 : : * Since: 2.18
144 : : */
145 : 3 : g_object_class_install_property (gobject_class,
146 : : PROP_ORIGIN,
147 : : g_param_spec_enum ("origin", NULL, NULL,
148 : : G_TYPE_EMBLEM_ORIGIN,
149 : : G_EMBLEM_ORIGIN_UNKNOWN,
150 : : G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
151 : :
152 : : /**
153 : : * GEmblem:icon:
154 : : *
155 : : * The actual icon of the emblem.
156 : : *
157 : : * Since: 2.18
158 : : */
159 : 3 : g_object_class_install_property (gobject_class,
160 : : PROP_ICON,
161 : : g_param_spec_object ("icon", NULL, NULL,
162 : : G_TYPE_OBJECT,
163 : : G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
164 : :
165 : 3 : }
166 : :
167 : : static void
168 : 17 : g_emblem_init (GEmblem *emblem)
169 : : {
170 : 17 : }
171 : :
172 : : /**
173 : : * g_emblem_new:
174 : : * @icon: a GIcon containing the icon.
175 : : *
176 : : * Creates a new emblem for @icon.
177 : : *
178 : : * Returns: a new #GEmblem.
179 : : *
180 : : * Since: 2.18
181 : : */
182 : : GEmblem *
183 : 1 : g_emblem_new (GIcon *icon)
184 : : {
185 : : GEmblem* emblem;
186 : :
187 : 1 : g_return_val_if_fail (icon != NULL, NULL);
188 : 1 : g_return_val_if_fail (G_IS_ICON (icon), NULL);
189 : 1 : g_return_val_if_fail (!G_IS_EMBLEM (icon), NULL);
190 : :
191 : 1 : emblem = g_object_new (G_TYPE_EMBLEM, NULL);
192 : 1 : emblem->icon = g_object_ref (icon);
193 : 1 : emblem->origin = G_EMBLEM_ORIGIN_UNKNOWN;
194 : :
195 : 1 : return emblem;
196 : : }
197 : :
198 : : /**
199 : : * g_emblem_new_with_origin:
200 : : * @icon: a GIcon containing the icon.
201 : : * @origin: a GEmblemOrigin enum defining the emblem's origin
202 : : *
203 : : * Creates a new emblem for @icon.
204 : : *
205 : : * Returns: a new #GEmblem.
206 : : *
207 : : * Since: 2.18
208 : : */
209 : : GEmblem *
210 : 15 : g_emblem_new_with_origin (GIcon *icon,
211 : : GEmblemOrigin origin)
212 : : {
213 : : GEmblem* emblem;
214 : :
215 : 15 : g_return_val_if_fail (icon != NULL, NULL);
216 : 15 : g_return_val_if_fail (G_IS_ICON (icon), NULL);
217 : 15 : g_return_val_if_fail (!G_IS_EMBLEM (icon), NULL);
218 : :
219 : 15 : emblem = g_object_new (G_TYPE_EMBLEM, NULL);
220 : 15 : emblem->icon = g_object_ref (icon);
221 : 15 : emblem->origin = origin;
222 : :
223 : 15 : return emblem;
224 : : }
225 : :
226 : : /**
227 : : * g_emblem_get_icon:
228 : : * @emblem: a #GEmblem from which the icon should be extracted.
229 : : *
230 : : * Gives back the icon from @emblem.
231 : : *
232 : : * Returns: (transfer none): a #GIcon. The returned object belongs to
233 : : * the emblem and should not be modified or freed.
234 : : *
235 : : * Since: 2.18
236 : : */
237 : : GIcon *
238 : 16 : g_emblem_get_icon (GEmblem *emblem)
239 : : {
240 : 16 : g_return_val_if_fail (G_IS_EMBLEM (emblem), NULL);
241 : :
242 : 16 : return emblem->icon;
243 : : }
244 : :
245 : :
246 : : /**
247 : : * g_emblem_get_origin:
248 : : * @emblem: a #GEmblem
249 : : *
250 : : * Gets the origin of the emblem.
251 : : *
252 : : * Returns: (transfer none): the origin of the emblem
253 : : *
254 : : * Since: 2.18
255 : : */
256 : : GEmblemOrigin
257 : 6 : g_emblem_get_origin (GEmblem *emblem)
258 : : {
259 : 6 : g_return_val_if_fail (G_IS_EMBLEM (emblem), G_EMBLEM_ORIGIN_UNKNOWN);
260 : :
261 : 6 : return emblem->origin;
262 : : }
263 : :
264 : : static guint
265 : 14 : g_emblem_hash (GIcon *icon)
266 : : {
267 : 14 : GEmblem *emblem = G_EMBLEM (icon);
268 : : guint hash;
269 : :
270 : 14 : hash = g_icon_hash (g_emblem_get_icon (emblem));
271 : 14 : hash ^= emblem->origin;
272 : :
273 : 14 : return hash;
274 : : }
275 : :
276 : : static gboolean
277 : 7 : g_emblem_equal (GIcon *icon1,
278 : : GIcon *icon2)
279 : : {
280 : 7 : GEmblem *emblem1 = G_EMBLEM (icon1);
281 : 7 : GEmblem *emblem2 = G_EMBLEM (icon2);
282 : :
283 : 14 : return emblem1->origin == emblem2->origin &&
284 : 7 : g_icon_equal (emblem1->icon, emblem2->icon);
285 : : }
286 : :
287 : : static gboolean
288 : 2 : g_emblem_to_tokens (GIcon *icon,
289 : : GPtrArray *tokens,
290 : : gint *out_version)
291 : : {
292 : 2 : GEmblem *emblem = G_EMBLEM (icon);
293 : : char *s;
294 : :
295 : : /* GEmblem are encoded as
296 : : *
297 : : * <origin> <icon>
298 : : */
299 : :
300 : 2 : g_return_val_if_fail (out_version != NULL, FALSE);
301 : :
302 : 2 : *out_version = 0;
303 : :
304 : 2 : s = g_icon_to_string (emblem->icon);
305 : 2 : if (s == NULL)
306 : 0 : return FALSE;
307 : :
308 : 2 : g_ptr_array_add (tokens, s);
309 : :
310 : 2 : s = g_strdup_printf ("%d", emblem->origin);
311 : 2 : g_ptr_array_add (tokens, s);
312 : :
313 : 2 : return TRUE;
314 : : }
315 : :
316 : : static GIcon *
317 : 8 : g_emblem_from_tokens (gchar **tokens,
318 : : gint num_tokens,
319 : : gint version,
320 : : GError **error)
321 : : {
322 : : GEmblem *emblem;
323 : : GIcon *icon;
324 : : GEmblemOrigin origin;
325 : : uint64_t origin_parsed;
326 : :
327 : : /* This is guaranteed by the GIcon interface */
328 : 8 : g_assert (num_tokens >= 0);
329 : :
330 : 8 : emblem = NULL;
331 : :
332 : 8 : if (version != 0)
333 : : {
334 : 0 : g_set_error (error,
335 : : G_IO_ERROR,
336 : : G_IO_ERROR_INVALID_ARGUMENT,
337 : : _("Can’t handle version %d of GEmblem encoding"),
338 : : version);
339 : 0 : return NULL;
340 : : }
341 : :
342 : 8 : if (num_tokens != 2)
343 : : {
344 : 0 : g_set_error (error,
345 : : G_IO_ERROR,
346 : : G_IO_ERROR_INVALID_ARGUMENT,
347 : : _("Malformed number of tokens (%d) in GEmblem encoding"),
348 : : num_tokens);
349 : 0 : return NULL;
350 : : }
351 : :
352 : 8 : icon = g_icon_new_for_string (tokens[0], error);
353 : :
354 : 8 : if (icon == NULL)
355 : 0 : return NULL;
356 : :
357 : 8 : if (!g_ascii_string_to_unsigned (tokens[1], 10, G_EMBLEM_ORIGIN_UNKNOWN, G_EMBLEM_ORIGIN_TAG,
358 : 6 : &origin_parsed, NULL) ||
359 : 6 : (origin_parsed != G_EMBLEM_ORIGIN_UNKNOWN &&
360 : 5 : origin_parsed != G_EMBLEM_ORIGIN_DEVICE &&
361 : 3 : origin_parsed != G_EMBLEM_ORIGIN_LIVEMETADATA &&
362 : 1 : origin_parsed != G_EMBLEM_ORIGIN_TAG))
363 : : {
364 : 2 : g_object_unref (icon);
365 : 2 : g_set_error (error,
366 : : G_IO_ERROR,
367 : : G_IO_ERROR_INVALID_ARGUMENT,
368 : : _("Malformed origin (%s) in GEmblem encoding"),
369 : 2 : tokens[1]);
370 : 2 : return NULL;
371 : : }
372 : :
373 : 6 : origin = (GEmblemOrigin) origin_parsed;
374 : :
375 : 6 : emblem = g_emblem_new_with_origin (icon, origin);
376 : 6 : g_object_unref (icon);
377 : :
378 : 6 : return G_ICON (emblem);
379 : : }
380 : :
381 : : static GVariant *
382 : 4 : g_emblem_serialize (GIcon *icon)
383 : : {
384 : 4 : GEmblem *emblem = G_EMBLEM (icon);
385 : : GVariant *icon_data;
386 : : GEnumValue *origin;
387 : : GVariant *result;
388 : :
389 : 4 : icon_data = g_icon_serialize (emblem->icon);
390 : 4 : if (!icon_data)
391 : 0 : return NULL;
392 : :
393 : 4 : origin = g_enum_get_value (g_type_class_peek (G_TYPE_EMBLEM_ORIGIN), (int) emblem->origin);
394 : 4 : result = g_variant_new_parsed ("('emblem', <(%v, {'origin': <%s>})>)",
395 : : icon_data, origin ? origin->value_nick : "unknown");
396 : 4 : g_variant_unref (icon_data);
397 : :
398 : 4 : return result;
399 : : }
400 : :
401 : : static void
402 : 3 : g_emblem_iface_init (GIconIface *iface)
403 : : {
404 : 3 : iface->hash = g_emblem_hash;
405 : 3 : iface->equal = g_emblem_equal;
406 : 3 : iface->to_tokens = g_emblem_to_tokens;
407 : 3 : iface->from_tokens = g_emblem_from_tokens;
408 : 3 : iface->serialize = g_emblem_serialize;
409 : 3 : }
|