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 
     25 #include "gfileicon.h"
     26 #include "gfile.h"
     27 #include "gicon.h"
     28 #include "glibintl.h"
     29 #include "gloadableicon.h"
     30 #include "ginputstream.h"
     31 #include "gsimpleasyncresult.h"
     32 #include "gioerror.h"
     33 
     34 #include "gioalias.h"
     35 
     36 /**
     37  * SECTION:gfileicon
     38  * @short_description: Icons pointing to an image file
     39  * @include: gio/gio.h
     40  * @see_also: #GIcon, #GLoadableIcon
     41  *
     42  * #GFileIcon specifies an icon by pointing to an image file
     43  * to be used as icon.
     44  *
     45  **/
     46 
     47 static void g_file_icon_icon_iface_init          (GIconIface          *iface);
     48 static void g_file_icon_loadable_icon_iface_init (GLoadableIconIface  *iface);
     49 static void g_file_icon_load_async               (GLoadableIcon       *icon,
     50 						  int                  size,
     51 						  GCancellable        *cancellable,
     52 						  GAsyncReadyCallback  callback,
     53 						  gpointer             user_data);
     54 
     55 struct _GFileIcon
     56 {
     57   GObject parent_instance;
     58 
     59   GFile *file;
     60 };
     61 
     62 struct _GFileIconClass
     63 {
     64   GObjectClass parent_class;
     65 };
     66 
     67 enum
     68 {
     69   PROP_0,
     70   PROP_FILE
     71 };
     72 
     73 G_DEFINE_TYPE_WITH_CODE (GFileIcon, g_file_icon, G_TYPE_OBJECT,
     74                          G_IMPLEMENT_INTERFACE (G_TYPE_ICON,
     75                                                 g_file_icon_icon_iface_init)
     76                          G_IMPLEMENT_INTERFACE (G_TYPE_LOADABLE_ICON,
     77                                                 g_file_icon_loadable_icon_iface_init))
     78 
     79 static void
     80 g_file_icon_get_property (GObject    *object,
     81                           guint       prop_id,
     82                           GValue     *value,
     83                           GParamSpec *pspec)
     84 {
     85   GFileIcon *icon = G_FILE_ICON (object);
     86 
     87   switch (prop_id)
     88     {
     89       case PROP_FILE:
     90         g_value_set_object (value, icon->file);
     91         break;
     92 
     93       default:
     94         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     95     }
     96 }
     97 
     98 static void
     99 g_file_icon_set_property (GObject      *object,
    100                           guint         prop_id,
    101                           const GValue *value,
    102                           GParamSpec   *pspec)
    103 {
    104   GFileIcon *icon = G_FILE_ICON (object);
    105 
    106   switch (prop_id)
    107     {
    108       case PROP_FILE:
    109         icon->file = G_FILE (g_value_dup_object (value));
    110         break;
    111 
    112       default:
    113         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
    114     }
    115 }
    116 
    117 static void
    118 g_file_icon_finalize (GObject *object)
    119 {
    120   GFileIcon *icon;
    121 
    122   icon = G_FILE_ICON (object);
    123 
    124   g_object_unref (icon->file);
    125 
    126   G_OBJECT_CLASS (g_file_icon_parent_class)->finalize (object);
    127 }
    128 
    129 static void
    130 g_file_icon_class_init (GFileIconClass *klass)
    131 {
    132   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
    133 
    134   gobject_class->get_property = g_file_icon_get_property;
    135   gobject_class->set_property = g_file_icon_set_property;
    136   gobject_class->finalize = g_file_icon_finalize;
    137 
    138   /**
    139    * GFileIcon:file:
    140    *
    141    * The file containing the icon.
    142    */
    143   g_object_class_install_property (gobject_class, PROP_FILE,
    144                                    g_param_spec_object ("file",
    145                                                         _("file"),
    146                                                         _("The file containing the icon"),
    147                                                         G_TYPE_FILE,
    148                                                         G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK));
    149 }
    150 
    151 static void
    152 g_file_icon_init (GFileIcon *file)
    153 {
    154 }
    155 
    156 /**
    157  * g_file_icon_new:
    158  * @file: a #GFile.
    159  *
    160  * Creates a new icon for a file.
    161  *
    162  * Returns: a #GIcon for the given @file, or %NULL on error.
    163  **/
    164 GIcon *
    165 g_file_icon_new (GFile *file)
    166 {
    167   g_return_val_if_fail (G_IS_FILE (file), NULL);
    168 
    169   return G_ICON (g_object_new (G_TYPE_FILE_ICON, "file", file, NULL));
    170 }
    171 
    172 /**
    173  * g_file_icon_get_file:
    174  * @icon: a #GIcon.
    175  *
    176  * Gets the #GFile associated with the given @icon.
    177  *
    178  * Returns: a #GFile, or %NULL.
    179  **/
    180 GFile *
    181 g_file_icon_get_file (GFileIcon *icon)
    182 {
    183   g_return_val_if_fail (G_IS_FILE_ICON (icon), NULL);
    184 
    185   return icon->file;
    186 }
    187 
    188 static guint
    189 g_file_icon_hash (GIcon *icon)
    190 {
    191   GFileIcon *file_icon = G_FILE_ICON (icon);
    192 
    193   return g_file_hash (file_icon->file);
    194 }
    195 
    196 static gboolean
    197 g_file_icon_equal (GIcon *icon1,
    198 		   GIcon *icon2)
    199 {
    200   GFileIcon *file1 = G_FILE_ICON (icon1);
    201   GFileIcon *file2 = G_FILE_ICON (icon2);
    202 
    203   return g_file_equal (file1->file, file2->file);
    204 }
    205 
    206 static gboolean
    207 g_file_icon_to_tokens (GIcon *icon,
    208 		       GPtrArray *tokens,
    209                        gint  *out_version)
    210 {
    211   GFileIcon *file_icon = G_FILE_ICON (icon);
    212 
    213   g_return_val_if_fail (out_version != NULL, FALSE);
    214 
    215   *out_version = 0;
    216 
    217   g_ptr_array_add (tokens, g_file_get_uri (file_icon->file));
    218   return TRUE;
    219 }
    220 
    221 static GIcon *
    222 g_file_icon_from_tokens (gchar  **tokens,
    223                          gint     num_tokens,
    224                          gint     version,
    225                          GError **error)
    226 {
    227   GIcon *icon;
    228   GFile *file;
    229 
    230   icon = NULL;
    231 
    232   if (version != 0)
    233     {
    234       g_set_error (error,
    235                    G_IO_ERROR,
    236                    G_IO_ERROR_INVALID_ARGUMENT,
    237                    _("Can't handle version %d of GFileIcon encoding"),
    238                    version);
    239       goto out;
    240     }
    241 
    242   if (num_tokens != 1)
    243     {
    244       g_set_error_literal (error,
    245                            G_IO_ERROR,
    246                            G_IO_ERROR_INVALID_ARGUMENT,
    247                            _("Malformed input data for GFileIcon"));
    248       goto out;
    249     }
    250 
    251   file = g_file_new_for_uri (tokens[0]);
    252   icon = g_file_icon_new (file);
    253   g_object_unref (file);
    254 
    255  out:
    256   return icon;
    257 }
    258 
    259 static void
    260 g_file_icon_icon_iface_init (GIconIface *iface)
    261 {
    262   iface->hash = g_file_icon_hash;
    263   iface->equal = g_file_icon_equal;
    264   iface->to_tokens = g_file_icon_to_tokens;
    265   iface->from_tokens = g_file_icon_from_tokens;
    266 }
    267 
    268 
    269 static GInputStream *
    270 g_file_icon_load (GLoadableIcon  *icon,
    271 		  int            size,
    272 		  char          **type,
    273 		  GCancellable   *cancellable,
    274 		  GError        **error)
    275 {
    276   GFileInputStream *stream;
    277   GFileIcon *file_icon = G_FILE_ICON (icon);
    278 
    279   stream = g_file_read (file_icon->file,
    280 			cancellable,
    281 			error);
    282 
    283   return G_INPUT_STREAM (stream);
    284 }
    285 
    286 typedef struct {
    287   GLoadableIcon *icon;
    288   GAsyncReadyCallback callback;
    289   gpointer user_data;
    290 } LoadData;
    291 
    292 static void
    293 load_data_free (LoadData *data)
    294 {
    295   g_object_unref (data->icon);
    296   g_free (data);
    297 }
    298 
    299 static void
    300 load_async_callback (GObject      *source_object,
    301 		     GAsyncResult *res,
    302 		     gpointer      user_data)
    303 {
    304   GFileInputStream *stream;
    305   GError *error = NULL;
    306   GSimpleAsyncResult *simple;
    307   LoadData *data = user_data;
    308 
    309   stream = g_file_read_finish (G_FILE (source_object), res, &error);
    310 
    311   if (stream == NULL)
    312     {
    313       simple = g_simple_async_result_new_from_error (G_OBJECT (data->icon),
    314 						     data->callback,
    315 						     data->user_data,
    316 						     error);
    317       g_error_free (error);
    318     }
    319   else
    320     {
    321       simple = g_simple_async_result_new (G_OBJECT (data->icon),
    322 					  data->callback,
    323 					  data->user_data,
    324 					  g_file_icon_load_async);
    325 
    326       g_simple_async_result_set_op_res_gpointer (simple,
    327 						 stream,
    328 						 g_object_unref);
    329   }
    330 
    331 
    332   g_simple_async_result_complete (simple);
    333 
    334   load_data_free (data);
    335 }
    336 
    337 static void
    338 g_file_icon_load_async (GLoadableIcon       *icon,
    339                         int                  size,
    340                         GCancellable        *cancellable,
    341                         GAsyncReadyCallback  callback,
    342                         gpointer             user_data)
    343 {
    344   GFileIcon *file_icon = G_FILE_ICON (icon);
    345   LoadData *data;
    346 
    347   data = g_new0 (LoadData, 1);
    348   data->icon = g_object_ref (icon);
    349   data->callback = callback;
    350   data->user_data = user_data;
    351 
    352   g_file_read_async (file_icon->file, 0,
    353 		     cancellable,
    354 		     load_async_callback, data);
    355 
    356 }
    357 
    358 static GInputStream *
    359 g_file_icon_load_finish (GLoadableIcon  *icon,
    360 			 GAsyncResult   *res,
    361 			 char          **type,
    362 			 GError        **error)
    363 {
    364   GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
    365   gpointer op;
    366 
    367   g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_file_icon_load_async);
    368 
    369   if (type)
    370     *type = NULL;
    371 
    372   op = g_simple_async_result_get_op_res_gpointer (simple);
    373   if (op)
    374     return g_object_ref (op);
    375 
    376   return NULL;
    377 }
    378 
    379 static void
    380 g_file_icon_loadable_icon_iface_init (GLoadableIconIface *iface)
    381 {
    382   iface->load = g_file_icon_load;
    383   iface->load_async = g_file_icon_load_async;
    384   iface->load_finish = g_file_icon_load_finish;
    385 }
    386 
    387 #define __G_FILE_ICON_C__
    388 #include "gioaliasdef.c"
    389