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 <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 : 157 : 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 : 6 : g_emblem_get_property (GObject *object,
71 : : guint prop_id,
72 : : GValue *value,
73 : : GParamSpec *pspec)
74 : : {
75 : 6 : GEmblem *emblem = G_EMBLEM (object);
76 : :
77 : 6 : switch (prop_id)
78 : : {
79 : 3 : case PROP_ICON:
80 : 3 : g_value_set_object (value, emblem->icon);
81 : 3 : break;
82 : :
83 : 3 : case PROP_ORIGIN:
84 : 3 : g_value_set_enum (value, emblem->origin);
85 : 3 : break;
86 : :
87 : 0 : default:
88 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
89 : 0 : break;
90 : : }
91 : 6 : }
92 : :
93 : : static void
94 : 26 : g_emblem_set_property (GObject *object,
95 : : guint prop_id,
96 : : const GValue *value,
97 : : GParamSpec *pspec)
98 : : {
99 : 26 : GEmblem *emblem = G_EMBLEM (object);
100 : :
101 : 26 : switch (prop_id)
102 : : {
103 : 13 : case PROP_ICON:
104 : 13 : emblem->icon = g_value_dup_object (value);
105 : 13 : break;
106 : :
107 : 13 : case PROP_ORIGIN:
108 : 13 : emblem->origin = g_value_get_enum (value);
109 : 13 : break;
110 : :
111 : 0 : default:
112 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
113 : 0 : break;
114 : : }
115 : 26 : }
116 : :
117 : : static void
118 : 13 : g_emblem_finalize (GObject *object)
119 : : {
120 : 13 : GEmblem *emblem = G_EMBLEM (object);
121 : :
122 : 13 : if (emblem->icon)
123 : 12 : g_object_unref (emblem->icon);
124 : :
125 : 13 : (*G_OBJECT_CLASS (g_emblem_parent_class)->finalize) (object);
126 : 13 : }
127 : :
128 : : static void
129 : 3 : g_emblem_class_init (GEmblemClass *klass)
130 : : {
131 : 3 : GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
132 : :
133 : 3 : gobject_class->finalize = g_emblem_finalize;
134 : 3 : gobject_class->set_property = g_emblem_set_property;
135 : 3 : 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 : 3 : 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 : 3 : 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 : 3 : }
165 : :
166 : : static void
167 : 13 : g_emblem_init (GEmblem *emblem)
168 : : {
169 : 13 : }
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 : 1 : g_emblem_new (GIcon *icon)
183 : : {
184 : : GEmblem* emblem;
185 : :
186 : 1 : g_return_val_if_fail (icon != NULL, NULL);
187 : 1 : g_return_val_if_fail (G_IS_ICON (icon), NULL);
188 : 1 : g_return_val_if_fail (!G_IS_EMBLEM (icon), NULL);
189 : :
190 : 1 : emblem = g_object_new (G_TYPE_EMBLEM, NULL);
191 : 1 : emblem->icon = g_object_ref (icon);
192 : 1 : emblem->origin = G_EMBLEM_ORIGIN_UNKNOWN;
193 : :
194 : 1 : 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 : 11 : g_emblem_new_with_origin (GIcon *icon,
210 : : GEmblemOrigin origin)
211 : : {
212 : : GEmblem* emblem;
213 : :
214 : 11 : g_return_val_if_fail (icon != NULL, NULL);
215 : 11 : g_return_val_if_fail (G_IS_ICON (icon), NULL);
216 : 11 : g_return_val_if_fail (!G_IS_EMBLEM (icon), NULL);
217 : :
218 : 11 : emblem = g_object_new (G_TYPE_EMBLEM, NULL);
219 : 11 : emblem->icon = g_object_ref (icon);
220 : 11 : emblem->origin = origin;
221 : :
222 : 11 : 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 : 16 : g_emblem_get_icon (GEmblem *emblem)
238 : : {
239 : 16 : g_return_val_if_fail (G_IS_EMBLEM (emblem), NULL);
240 : :
241 : 16 : 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 : 2 : g_emblem_get_origin (GEmblem *emblem)
257 : : {
258 : 2 : g_return_val_if_fail (G_IS_EMBLEM (emblem), G_EMBLEM_ORIGIN_UNKNOWN);
259 : :
260 : 2 : return emblem->origin;
261 : : }
262 : :
263 : : static guint
264 : 14 : g_emblem_hash (GIcon *icon)
265 : : {
266 : 14 : GEmblem *emblem = G_EMBLEM (icon);
267 : : guint hash;
268 : :
269 : 14 : hash = g_icon_hash (g_emblem_get_icon (emblem));
270 : 14 : hash ^= emblem->origin;
271 : :
272 : 14 : return hash;
273 : : }
274 : :
275 : : static gboolean
276 : 7 : g_emblem_equal (GIcon *icon1,
277 : : GIcon *icon2)
278 : : {
279 : 7 : GEmblem *emblem1 = G_EMBLEM (icon1);
280 : 7 : GEmblem *emblem2 = G_EMBLEM (icon2);
281 : :
282 : 14 : return emblem1->origin == emblem2->origin &&
283 : 7 : g_icon_equal (emblem1->icon, emblem2->icon);
284 : : }
285 : :
286 : : static gboolean
287 : 2 : g_emblem_to_tokens (GIcon *icon,
288 : : GPtrArray *tokens,
289 : : gint *out_version)
290 : : {
291 : 2 : GEmblem *emblem = G_EMBLEM (icon);
292 : : char *s;
293 : :
294 : : /* GEmblem are encoded as
295 : : *
296 : : * <origin> <icon>
297 : : */
298 : :
299 : 2 : g_return_val_if_fail (out_version != NULL, FALSE);
300 : :
301 : 2 : *out_version = 0;
302 : :
303 : 2 : s = g_icon_to_string (emblem->icon);
304 : 2 : if (s == NULL)
305 : 0 : return FALSE;
306 : :
307 : 2 : g_ptr_array_add (tokens, s);
308 : :
309 : 2 : s = g_strdup_printf ("%d", emblem->origin);
310 : 2 : g_ptr_array_add (tokens, s);
311 : :
312 : 2 : return TRUE;
313 : : }
314 : :
315 : : static GIcon *
316 : 2 : 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 : 2 : emblem = NULL;
326 : :
327 : 2 : if (version != 0)
328 : : {
329 : 0 : 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 : 0 : return NULL;
335 : : }
336 : :
337 : 2 : if (num_tokens != 2)
338 : : {
339 : 0 : 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 : 0 : return NULL;
345 : : }
346 : :
347 : 2 : icon = g_icon_new_for_string (tokens[0], error);
348 : :
349 : 2 : if (icon == NULL)
350 : 0 : return NULL;
351 : :
352 : 2 : origin = atoi (tokens[1]);
353 : :
354 : 2 : emblem = g_emblem_new_with_origin (icon, origin);
355 : 2 : g_object_unref (icon);
356 : :
357 : 2 : return G_ICON (emblem);
358 : : }
359 : :
360 : : static GVariant *
361 : 4 : g_emblem_serialize (GIcon *icon)
362 : : {
363 : 4 : GEmblem *emblem = G_EMBLEM (icon);
364 : : GVariant *icon_data;
365 : : GEnumValue *origin;
366 : : GVariant *result;
367 : :
368 : 4 : icon_data = g_icon_serialize (emblem->icon);
369 : 4 : if (!icon_data)
370 : 0 : return NULL;
371 : :
372 : 4 : origin = g_enum_get_value (g_type_class_peek (G_TYPE_EMBLEM_ORIGIN), emblem->origin);
373 : 4 : result = g_variant_new_parsed ("('emblem', <(%v, {'origin': <%s>})>)",
374 : : icon_data, origin ? origin->value_nick : "unknown");
375 : 4 : g_variant_unref (icon_data);
376 : :
377 : 4 : return result;
378 : : }
379 : :
380 : : static void
381 : 3 : g_emblem_iface_init (GIconIface *iface)
382 : : {
383 : 3 : iface->hash = g_emblem_hash;
384 : 3 : iface->equal = g_emblem_equal;
385 : 3 : iface->to_tokens = g_emblem_to_tokens;
386 : 3 : iface->from_tokens = g_emblem_from_tokens;
387 : 3 : iface->serialize = g_emblem_serialize;
388 : 3 : }
|