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