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