Coverage Report

Created: 2025-07-23 08:13

/src/pango/subprojects/glib/gio/gemblem.c
Line
Count
Source (jump to first uncovered line)
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
0
{
75
0
  GEmblem *emblem = G_EMBLEM (object);
76
77
0
  switch (prop_id)
78
0
    {
79
0
      case PROP_ICON:
80
0
        g_value_set_object (value, emblem->icon);
81
0
  break;
82
83
0
      case PROP_ORIGIN:
84
0
        g_value_set_enum (value, emblem->origin);
85
0
        break;
86
87
0
      default:
88
0
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
89
0
        break;
90
0
  }
91
0
}
92
93
static void
94
g_emblem_set_property (GObject      *object,
95
                       guint         prop_id,
96
                       const GValue *value,
97
                       GParamSpec   *pspec)
98
0
{
99
0
  GEmblem *emblem = G_EMBLEM (object);
100
101
0
  switch (prop_id)
102
0
    {
103
0
      case PROP_ICON:
104
0
        emblem->icon = g_value_dup_object (value);
105
0
        break;
106
107
0
      case PROP_ORIGIN:
108
0
        emblem->origin = g_value_get_enum (value);
109
0
        break;
110
111
0
      default:
112
0
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
113
0
        break;
114
0
    }
115
0
}
116
117
static void
118
g_emblem_finalize (GObject *object)
119
0
{
120
0
  GEmblem *emblem = G_EMBLEM (object);
121
122
0
  if (emblem->icon)
123
0
    g_object_unref (emblem->icon);
124
125
0
  (*G_OBJECT_CLASS (g_emblem_parent_class)->finalize) (object);
126
0
}
127
128
static void
129
g_emblem_class_init (GEmblemClass *klass)
130
0
{
131
0
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
132
133
0
  gobject_class->finalize = g_emblem_finalize;
134
0
  gobject_class->set_property = g_emblem_set_property;
135
0
  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
0
  g_object_class_install_property (gobject_class,
145
0
                                   PROP_ORIGIN,
146
0
                                   g_param_spec_enum ("origin", NULL, NULL,
147
0
                                                      G_TYPE_EMBLEM_ORIGIN,
148
0
                                                      G_EMBLEM_ORIGIN_UNKNOWN,
149
0
                                                      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
0
  g_object_class_install_property (gobject_class,
159
0
                                   PROP_ICON,
160
0
                                   g_param_spec_object ("icon", NULL, NULL,
161
0
                                                      G_TYPE_OBJECT,
162
0
                                                      G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
163
164
0
}
165
166
static void
167
g_emblem_init (GEmblem *emblem)
168
0
{
169
0
}
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
0
{
184
0
  GEmblem* emblem;
185
186
0
  g_return_val_if_fail (icon != NULL, NULL);
187
0
  g_return_val_if_fail (G_IS_ICON (icon), NULL);
188
0
  g_return_val_if_fail (!G_IS_EMBLEM (icon), NULL);
189
190
0
  emblem = g_object_new (G_TYPE_EMBLEM, NULL);
191
0
  emblem->icon = g_object_ref (icon);
192
0
  emblem->origin = G_EMBLEM_ORIGIN_UNKNOWN;
193
194
0
  return emblem;
195
0
}
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
0
{
212
0
  GEmblem* emblem;
213
214
0
  g_return_val_if_fail (icon != NULL, NULL);
215
0
  g_return_val_if_fail (G_IS_ICON (icon), NULL);
216
0
  g_return_val_if_fail (!G_IS_EMBLEM (icon), NULL);
217
218
0
  emblem = g_object_new (G_TYPE_EMBLEM, NULL);
219
0
  emblem->icon = g_object_ref (icon);
220
0
  emblem->origin = origin;
221
222
0
  return emblem;
223
0
}
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
0
{
239
0
  g_return_val_if_fail (G_IS_EMBLEM (emblem), NULL);
240
241
0
  return emblem->icon;
242
0
}
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
0
{
258
0
  g_return_val_if_fail (G_IS_EMBLEM (emblem), G_EMBLEM_ORIGIN_UNKNOWN);
259
260
0
  return emblem->origin;
261
0
}
262
263
static guint
264
g_emblem_hash (GIcon *icon)
265
0
{
266
0
  GEmblem *emblem = G_EMBLEM (icon);
267
0
  guint hash;
268
269
0
  hash  = g_icon_hash (g_emblem_get_icon (emblem));
270
0
  hash ^= emblem->origin;
271
272
0
  return hash;
273
0
}
274
275
static gboolean
276
g_emblem_equal (GIcon *icon1,
277
                GIcon *icon2)
278
0
{
279
0
  GEmblem *emblem1 = G_EMBLEM (icon1);
280
0
  GEmblem *emblem2 = G_EMBLEM (icon2);
281
282
0
  return emblem1->origin == emblem2->origin &&
283
0
         g_icon_equal (emblem1->icon, emblem2->icon);
284
0
}
285
286
static gboolean
287
g_emblem_to_tokens (GIcon *icon,
288
        GPtrArray *tokens,
289
        gint  *out_version)
290
0
{
291
0
  GEmblem *emblem = G_EMBLEM (icon);
292
0
  char *s;
293
294
  /* GEmblem are encoded as
295
   *
296
   * <origin> <icon>
297
   */
298
299
0
  g_return_val_if_fail (out_version != NULL, FALSE);
300
301
0
  *out_version = 0;
302
303
0
  s = g_icon_to_string (emblem->icon);
304
0
  if (s == NULL)
305
0
    return FALSE;
306
307
0
  g_ptr_array_add (tokens, s);
308
309
0
  s = g_strdup_printf ("%d", emblem->origin);
310
0
  g_ptr_array_add (tokens, s);
311
312
0
  return TRUE;
313
0
}
314
315
static GIcon *
316
g_emblem_from_tokens (gchar  **tokens,
317
          gint     num_tokens,
318
          gint     version,
319
          GError **error)
320
0
{
321
0
  GEmblem *emblem;
322
0
  GIcon *icon;
323
0
  GEmblemOrigin origin;
324
325
0
  emblem = NULL;
326
327
0
  if (version != 0)
328
0
    {
329
0
      g_set_error (error,
330
0
                   G_IO_ERROR,
331
0
                   G_IO_ERROR_INVALID_ARGUMENT,
332
0
                   _("Can’t handle version %d of GEmblem encoding"),
333
0
                   version);
334
0
      return NULL;
335
0
    }
336
337
0
  if (num_tokens != 2)
338
0
    {
339
0
      g_set_error (error,
340
0
                   G_IO_ERROR,
341
0
                   G_IO_ERROR_INVALID_ARGUMENT,
342
0
                   _("Malformed number of tokens (%d) in GEmblem encoding"),
343
0
                   num_tokens);
344
0
      return NULL;
345
0
    }
346
347
0
  icon = g_icon_new_for_string (tokens[0], error);
348
349
0
  if (icon == NULL)
350
0
    return NULL;
351
352
0
  origin = atoi (tokens[1]);
353
354
0
  emblem = g_emblem_new_with_origin (icon, origin);
355
0
  g_object_unref (icon);
356
357
0
  return G_ICON (emblem);
358
0
}
359
360
static GVariant *
361
g_emblem_serialize (GIcon *icon)
362
0
{
363
0
  GEmblem *emblem = G_EMBLEM (icon);
364
0
  GVariant *icon_data;
365
0
  GEnumValue *origin;
366
0
  GVariant *result;
367
368
0
  icon_data = g_icon_serialize (emblem->icon);
369
0
  if (!icon_data)
370
0
    return NULL;
371
372
0
  origin = g_enum_get_value (g_type_class_peek (G_TYPE_EMBLEM_ORIGIN), emblem->origin);
373
0
  result = g_variant_new_parsed ("('emblem', <(%v, {'origin': <%s>})>)",
374
0
                                 icon_data, origin ? origin->value_nick : "unknown");
375
0
  g_variant_unref (icon_data);
376
377
0
  return result;
378
0
}
379
380
static void
381
g_emblem_iface_init (GIconIface *iface)
382
0
{
383
0
  iface->hash  = g_emblem_hash;
384
0
  iface->equal = g_emblem_equal;
385
0
  iface->to_tokens = g_emblem_to_tokens;
386
0
  iface->from_tokens = g_emblem_from_tokens;
387
0
  iface->serialize = g_emblem_serialize;
388
0
}