Home | History | Annotate | Download | only in gio
      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