1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 2 3 /* GIO - GLib Input, Output and Streaming Library 4 * 5 * Copyright (C) 2006-2007 Red Hat, Inc. 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 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, write to the 19 * Free Software Foundation, Inc., 59 Temple Place, Suite 330, 20 * Boston, MA 02111-1307, USA. 21 * 22 * Author: Matthias Clasen <mclasen (at) redhat.com> 23 * Clemens N. Buss <cebuzz (at) gmail.com> 24 */ 25 26 #include <config.h> 27 28 #include <string.h> 29 30 #include "gemblemedicon.h" 31 #include "glibintl.h" 32 #include "gioerror.h" 33 34 #include "gioalias.h" 35 36 /** 37 * SECTION:gemblemedicon 38 * @short_description: Icon with emblems 39 * @include: gio/gio.h 40 * @see_also: #GIcon, #GLoadableIcon, #GThemedIcon, #GEmblem 41 * 42 * #GEmblemedIcon is an implementation of #GIcon that supports 43 * adding an emblem to an icon. Adding multiple emblems to an 44 * icon is ensured via g_emblemed_icon_add_emblem(). 45 * 46 * Note that #GEmblemedIcon allows no control over the position 47 * of the emblems. See also #GEmblem for more information. 48 **/ 49 50 static void g_emblemed_icon_icon_iface_init (GIconIface *iface); 51 52 struct _GEmblemedIcon 53 { 54 GObject parent_instance; 55 56 GIcon *icon; 57 GList *emblems; 58 }; 59 60 struct _GEmblemedIconClass 61 { 62 GObjectClass parent_class; 63 }; 64 65 G_DEFINE_TYPE_WITH_CODE (GEmblemedIcon, g_emblemed_icon, G_TYPE_OBJECT, 66 G_IMPLEMENT_INTERFACE (G_TYPE_ICON, 67 g_emblemed_icon_icon_iface_init)) 68 69 70 static void 71 g_emblemed_icon_finalize (GObject *object) 72 { 73 GEmblemedIcon *emblemed; 74 75 emblemed = G_EMBLEMED_ICON (object); 76 77 g_object_unref (emblemed->icon); 78 g_list_foreach (emblemed->emblems, (GFunc) g_object_unref, NULL); 79 g_list_free (emblemed->emblems); 80 81 (*G_OBJECT_CLASS (g_emblemed_icon_parent_class)->finalize) (object); 82 } 83 84 static void 85 g_emblemed_icon_class_init (GEmblemedIconClass *klass) 86 { 87 GObjectClass *gobject_class = G_OBJECT_CLASS (klass); 88 gobject_class->finalize = g_emblemed_icon_finalize; 89 } 90 91 static void 92 g_emblemed_icon_init (GEmblemedIcon *emblemed) 93 { 94 } 95 96 /** 97 * g_emblemed_icon_new: 98 * @icon: a #GIcon 99 * @emblem: a #GEmblem 100 * 101 * Creates a new emblemed icon for @icon with the emblem @emblem. 102 * 103 * Returns: a new #GIcon 104 * 105 * Since: 2.18 106 **/ 107 GIcon * 108 g_emblemed_icon_new (GIcon *icon, 109 GEmblem *emblem) 110 { 111 GEmblemedIcon *emblemed; 112 113 g_return_val_if_fail (G_IS_ICON (icon), NULL); 114 g_return_val_if_fail (!G_IS_EMBLEM (icon), NULL); 115 g_return_val_if_fail (G_IS_EMBLEM (emblem), NULL); 116 117 emblemed = G_EMBLEMED_ICON (g_object_new (G_TYPE_EMBLEMED_ICON, NULL)); 118 emblemed->icon = g_object_ref (icon); 119 120 g_emblemed_icon_add_emblem (emblemed, emblem); 121 122 return G_ICON (emblemed); 123 } 124 125 126 /** 127 * g_emblemed_icon_get_icon: 128 * @emblemed: a #GEmblemedIcon 129 * 130 * Gets the main icon for @emblemed. 131 * 132 * Returns: a #GIcon that is owned by @emblemed 133 * 134 * Since: 2.18 135 **/ 136 GIcon * 137 g_emblemed_icon_get_icon (GEmblemedIcon *emblemed) 138 { 139 g_return_val_if_fail (G_IS_EMBLEMED_ICON (emblemed), NULL); 140 141 return emblemed->icon; 142 } 143 144 /** 145 * g_emblemed_icon_get_emblems: 146 * @emblemed: a #GEmblemedIcon 147 * 148 * Gets the list of emblems for the @icon. 149 * 150 * Returns: a #GList of #GEmblem <!-- -->s that is owned by @emblemed 151 * 152 * Since: 2.18 153 **/ 154 155 GList * 156 g_emblemed_icon_get_emblems (GEmblemedIcon *emblemed) 157 { 158 g_return_val_if_fail (G_IS_EMBLEMED_ICON (emblemed), NULL); 159 160 return emblemed->emblems; 161 } 162 163 164 /** 165 * g_emblemed_icon_add_emblem: 166 * @emblemed: a #GEmblemedIcon 167 * @emblem: a #GEmblem 168 * 169 * Adds @emblem to the #GList of #GEmblem <!-- -->s. 170 * 171 * Since: 2.18 172 **/ 173 void 174 g_emblemed_icon_add_emblem (GEmblemedIcon *emblemed, 175 GEmblem *emblem) 176 { 177 g_return_if_fail (G_IS_EMBLEMED_ICON (emblemed)); 178 g_return_if_fail (G_IS_EMBLEM (emblem)); 179 180 g_object_ref (emblem); 181 emblemed->emblems = g_list_append (emblemed->emblems, emblem); 182 } 183 184 static guint 185 g_emblemed_icon_hash (GIcon *icon) 186 { 187 GEmblemedIcon *emblemed = G_EMBLEMED_ICON (icon); 188 GList *list; 189 guint hash = g_icon_hash (emblemed->icon); 190 191 for (list = emblemed->emblems; list != NULL; list = list->next) 192 hash ^= g_icon_hash (G_ICON (list->data)); 193 194 return hash; 195 } 196 197 static gint 198 g_emblem_comp (GEmblem *a, 199 GEmblem *b) 200 { 201 guint hash_a = g_icon_hash (G_ICON (a)); 202 guint hash_b = g_icon_hash (G_ICON (b)); 203 204 if(hash_a < hash_b) 205 return -1; 206 207 if(hash_a == hash_b) 208 return 0; 209 210 return 1; 211 } 212 213 static gboolean 214 g_emblemed_icon_equal (GIcon *icon1, 215 GIcon *icon2) 216 { 217 GEmblemedIcon *emblemed1 = G_EMBLEMED_ICON (icon1); 218 GEmblemedIcon *emblemed2 = G_EMBLEMED_ICON (icon2); 219 GList *list1, *list2; 220 221 if (!g_icon_equal (emblemed1->icon, emblemed2->icon)) 222 return FALSE; 223 224 list1 = emblemed1->emblems; 225 list2 = emblemed2->emblems; 226 227 list1 = g_list_sort (list1, (GCompareFunc) g_emblem_comp); 228 list2 = g_list_sort (list2, (GCompareFunc) g_emblem_comp); 229 230 while (list1 && list2) 231 { 232 if (!g_icon_equal (G_ICON (list1->data), G_ICON (list2->data))) 233 return FALSE; 234 235 list1 = list1->next; 236 list2 = list2->next; 237 } 238 239 return list1 == NULL && list2 == NULL; 240 } 241 242 static gboolean 243 g_emblemed_icon_to_tokens (GIcon *icon, 244 GPtrArray *tokens, 245 gint *out_version) 246 { 247 GEmblemedIcon *emblemed_icon = G_EMBLEMED_ICON (icon); 248 GList *l; 249 char *s; 250 251 /* GEmblemedIcons are encoded as 252 * 253 * <encoded_icon> [<encoded_emblem_icon>]* 254 */ 255 256 g_return_val_if_fail (out_version != NULL, FALSE); 257 258 *out_version = 0; 259 260 s = g_icon_to_string (emblemed_icon->icon); 261 if (s == NULL) 262 return FALSE; 263 264 g_ptr_array_add (tokens, s); 265 266 for (l = emblemed_icon->emblems; l != NULL; l = l->next) 267 { 268 GIcon *emblem_icon = G_ICON (l->data); 269 270 s = g_icon_to_string (emblem_icon); 271 if (s == NULL) 272 return FALSE; 273 274 g_ptr_array_add (tokens, s); 275 } 276 277 return TRUE; 278 } 279 280 static GIcon * 281 g_emblemed_icon_from_tokens (gchar **tokens, 282 gint num_tokens, 283 gint version, 284 GError **error) 285 { 286 GEmblemedIcon *emblemed_icon; 287 int n; 288 289 emblemed_icon = NULL; 290 291 if (version != 0) 292 { 293 g_set_error (error, 294 G_IO_ERROR, 295 G_IO_ERROR_INVALID_ARGUMENT, 296 _("Can't handle version %d of GEmblemedIcon encoding"), 297 version); 298 goto fail; 299 } 300 301 if (num_tokens < 1) 302 { 303 g_set_error (error, 304 G_IO_ERROR, 305 G_IO_ERROR_INVALID_ARGUMENT, 306 _("Malformed number of tokens (%d) in GEmblemedIcon encoding"), 307 num_tokens); 308 goto fail; 309 } 310 311 emblemed_icon = g_object_new (G_TYPE_EMBLEMED_ICON, NULL); 312 emblemed_icon->icon = g_icon_new_for_string (tokens[0], error); 313 if (emblemed_icon->icon == NULL) 314 goto fail; 315 316 for (n = 1; n < num_tokens; n++) 317 { 318 GIcon *emblem; 319 320 emblem = g_icon_new_for_string (tokens[n], error); 321 if (emblem == NULL) 322 goto fail; 323 324 if (!G_IS_EMBLEM (emblem)) 325 { 326 g_set_error_literal (error, 327 G_IO_ERROR, 328 G_IO_ERROR_INVALID_ARGUMENT, 329 _("Expected a GEmblem for GEmblemedIcon")); 330 g_object_unref (emblem); 331 goto fail; 332 } 333 334 emblemed_icon->emblems = g_list_append (emblemed_icon->emblems, emblem); 335 } 336 337 return G_ICON (emblemed_icon); 338 339 fail: 340 if (emblemed_icon != NULL) 341 g_object_unref (emblemed_icon); 342 return NULL; 343 } 344 345 static void 346 g_emblemed_icon_icon_iface_init (GIconIface *iface) 347 { 348 iface->hash = g_emblemed_icon_hash; 349 iface->equal = g_emblemed_icon_equal; 350 iface->to_tokens = g_emblemed_icon_to_tokens; 351 iface->from_tokens = g_emblemed_icon_from_tokens; 352 } 353 354 #define __G_EMBLEMED_ICON_C__ 355 #include "gioaliasdef.c" 356