1 /* GIO - GLib Input, Output and Streaming Library 2 * 3 * Copyright (C) 2006-2007 Red Hat, Inc. 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Lesser General Public 7 * License as published by the Free Software Foundation; either 8 * version 2 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General 16 * Public License along with this library; if not, write to the 17 * Free Software Foundation, Inc., 59 Temple Place, Suite 330, 18 * Boston, MA 02111-1307, USA. 19 * 20 * Author: Alexander Larsson <alexl (at) redhat.com> 21 */ 22 23 #include "config.h" 24 #include "gasyncresult.h" 25 #include "gsimpleasyncresult.h" 26 #include "gicon.h" 27 #include "gloadableicon.h" 28 #include "glibintl.h" 29 30 #include "gioalias.h" 31 32 /** 33 * SECTION:gloadableicon 34 * @short_description: Loadable Icons 35 * @include: gio/gio.h 36 * @see_also: #GIcon, #GThemedIcon 37 * 38 * Extends the #GIcon interface and adds the ability to 39 * load icons from streams. 40 **/ 41 42 static void g_loadable_icon_real_load_async (GLoadableIcon *icon, 43 int size, 44 GCancellable *cancellable, 45 GAsyncReadyCallback callback, 46 gpointer user_data); 47 static GInputStream *g_loadable_icon_real_load_finish (GLoadableIcon *icon, 48 GAsyncResult *res, 49 char **type, 50 GError **error); 51 static void g_loadable_icon_base_init (gpointer g_class); 52 static void g_loadable_icon_class_init (gpointer g_class, 53 gpointer class_data); 54 55 GType 56 g_loadable_icon_get_type (void) 57 { 58 static volatile gsize g_define_type_id__volatile = 0; 59 60 if (g_once_init_enter (&g_define_type_id__volatile)) 61 { 62 const GTypeInfo loadable_icon_info = 63 { 64 sizeof (GLoadableIconIface), /* class_size */ 65 g_loadable_icon_base_init, /* base_init */ 66 NULL, /* base_finalize */ 67 g_loadable_icon_class_init, 68 NULL, /* class_finalize */ 69 NULL, /* class_data */ 70 0, 71 0, /* n_preallocs */ 72 NULL 73 }; 74 GType g_define_type_id = 75 g_type_register_static (G_TYPE_INTERFACE, I_("GLoadableIcon"), 76 &loadable_icon_info, 0); 77 78 g_type_interface_add_prerequisite (g_define_type_id, G_TYPE_ICON); 79 80 g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); 81 } 82 83 return g_define_type_id__volatile; 84 } 85 86 static void 87 g_loadable_icon_class_init (gpointer g_class, 88 gpointer class_data) 89 { 90 GLoadableIconIface *iface = g_class; 91 92 iface->load_async = g_loadable_icon_real_load_async; 93 iface->load_finish = g_loadable_icon_real_load_finish; 94 } 95 96 static void 97 g_loadable_icon_base_init (gpointer g_class) 98 { 99 } 100 101 /** 102 * g_loadable_icon_load: 103 * @icon: a #GLoadableIcon. 104 * @size: an integer. 105 * @type: a location to store the type of the loaded icon, %NULL to ignore. 106 * @cancellable: optional #GCancellable object, %NULL to ignore. 107 * @error: a #GError location to store the error occuring, or %NULL to 108 * ignore. 109 * 110 * Loads a loadable icon. For the asynchronous version of this function, 111 * see g_loadable_icon_load_async(). 112 * 113 * Returns: a #GInputStream to read the icon from. 114 **/ 115 GInputStream * 116 g_loadable_icon_load (GLoadableIcon *icon, 117 int size, 118 char **type, 119 GCancellable *cancellable, 120 GError **error) 121 { 122 GLoadableIconIface *iface; 123 124 g_return_val_if_fail (G_IS_LOADABLE_ICON (icon), NULL); 125 126 iface = G_LOADABLE_ICON_GET_IFACE (icon); 127 128 return (* iface->load) (icon, size, type, cancellable, error); 129 } 130 131 /** 132 * g_loadable_icon_load_async: 133 * @icon: a #GLoadableIcon. 134 * @size: an integer. 135 * @cancellable: optional #GCancellable object, %NULL to ignore. 136 * @callback: a #GAsyncReadyCallback to call when the request is satisfied 137 * @user_data: the data to pass to callback function 138 * 139 * Loads an icon asynchronously. To finish this function, see 140 * g_loadable_icon_load_finish(). For the synchronous, blocking 141 * version of this function, see g_loadable_icon_load(). 142 **/ 143 void 144 g_loadable_icon_load_async (GLoadableIcon *icon, 145 int size, 146 GCancellable *cancellable, 147 GAsyncReadyCallback callback, 148 gpointer user_data) 149 { 150 GLoadableIconIface *iface; 151 152 g_return_if_fail (G_IS_LOADABLE_ICON (icon)); 153 154 iface = G_LOADABLE_ICON_GET_IFACE (icon); 155 156 (* iface->load_async) (icon, size, cancellable, callback, user_data); 157 } 158 159 /** 160 * g_loadable_icon_load_finish: 161 * @icon: a #GLoadableIcon. 162 * @res: a #GAsyncResult. 163 * @type: a location to store the type of the loaded icon, %NULL to ignore. 164 * @error: a #GError location to store the error occuring, or %NULL to 165 * ignore. 166 * 167 * Finishes an asynchronous icon load started in g_loadable_icon_load_async(). 168 * 169 * Returns: a #GInputStream to read the icon from. 170 **/ 171 GInputStream * 172 g_loadable_icon_load_finish (GLoadableIcon *icon, 173 GAsyncResult *res, 174 char **type, 175 GError **error) 176 { 177 GLoadableIconIface *iface; 178 179 g_return_val_if_fail (G_IS_LOADABLE_ICON (icon), NULL); 180 g_return_val_if_fail (G_IS_ASYNC_RESULT (res), NULL); 181 182 if (G_IS_SIMPLE_ASYNC_RESULT (res)) 183 { 184 GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res); 185 if (g_simple_async_result_propagate_error (simple, error)) 186 return NULL; 187 } 188 189 iface = G_LOADABLE_ICON_GET_IFACE (icon); 190 191 return (* iface->load_finish) (icon, res, type, error); 192 } 193 194 /******************************************** 195 * Default implementation of async load * 196 ********************************************/ 197 198 typedef struct { 199 int size; 200 char *type; 201 GInputStream *stream; 202 } LoadData; 203 204 static void 205 load_data_free (LoadData *data) 206 { 207 if (data->stream) 208 g_object_unref (data->stream); 209 g_free (data->type); 210 g_free (data); 211 } 212 213 static void 214 load_async_thread (GSimpleAsyncResult *res, 215 GObject *object, 216 GCancellable *cancellable) 217 { 218 GLoadableIconIface *iface; 219 GInputStream *stream; 220 LoadData *data; 221 GError *error = NULL; 222 char *type = NULL; 223 224 data = g_simple_async_result_get_op_res_gpointer (res); 225 226 iface = G_LOADABLE_ICON_GET_IFACE (object); 227 stream = iface->load (G_LOADABLE_ICON (object), data->size, &type, cancellable, &error); 228 229 if (stream == NULL) 230 { 231 g_simple_async_result_set_from_error (res, error); 232 g_error_free (error); 233 } 234 else 235 { 236 data->stream = stream; 237 data->type = type; 238 } 239 } 240 241 242 243 static void 244 g_loadable_icon_real_load_async (GLoadableIcon *icon, 245 int size, 246 GCancellable *cancellable, 247 GAsyncReadyCallback callback, 248 gpointer user_data) 249 { 250 GSimpleAsyncResult *res; 251 LoadData *data; 252 253 res = g_simple_async_result_new (G_OBJECT (icon), callback, user_data, g_loadable_icon_real_load_async); 254 data = g_new0 (LoadData, 1); 255 g_simple_async_result_set_op_res_gpointer (res, data, (GDestroyNotify) load_data_free); 256 g_simple_async_result_run_in_thread (res, load_async_thread, 0, cancellable); 257 g_object_unref (res); 258 } 259 260 static GInputStream * 261 g_loadable_icon_real_load_finish (GLoadableIcon *icon, 262 GAsyncResult *res, 263 char **type, 264 GError **error) 265 { 266 GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res); 267 LoadData *data; 268 269 g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_loadable_icon_real_load_async); 270 271 data = g_simple_async_result_get_op_res_gpointer (simple); 272 273 if (type) 274 { 275 *type = data->type; 276 data->type = NULL; 277 } 278 279 return g_object_ref (data->stream); 280 } 281 282 #define __G_LOADABLE_ICON_C__ 283 #include "gioaliasdef.c" 284