(root)/
glib-2.79.0/
gio/
gloadableicon.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  #include "gicon.h"
      25  #include "gloadableicon.h"
      26  #include "gasyncresult.h"
      27  #include "gtask.h"
      28  #include "glibintl.h"
      29  
      30  
      31  /**
      32   * GLoadableIcon:
      33   * 
      34   * `GLoadableIcon` extends the [iface@Gio.Icon] interface and adds the ability
      35   * to load icons from streams.
      36   **/
      37  
      38  static void          g_loadable_icon_real_load_async  (GLoadableIcon        *icon,
      39  						       int                   size,
      40  						       GCancellable         *cancellable,
      41  						       GAsyncReadyCallback   callback,
      42  						       gpointer              user_data);
      43  static GInputStream *g_loadable_icon_real_load_finish (GLoadableIcon        *icon,
      44  						       GAsyncResult         *res,
      45  						       char                **type,
      46  						       GError              **error);
      47  
      48  typedef GLoadableIconIface GLoadableIconInterface;
      49  G_DEFINE_INTERFACE(GLoadableIcon, g_loadable_icon, G_TYPE_ICON)
      50  
      51  static void
      52  g_loadable_icon_default_init (GLoadableIconIface *iface)
      53  {
      54    iface->load_async = g_loadable_icon_real_load_async;
      55    iface->load_finish = g_loadable_icon_real_load_finish;
      56  }
      57  
      58  /**
      59   * g_loadable_icon_load:
      60   * @icon: a #GLoadableIcon.
      61   * @size: an integer.
      62   * @type: (out) (optional): a location to store the type of the loaded
      63   * icon, %NULL to ignore.
      64   * @cancellable: (nullable): optional #GCancellable object, %NULL to
      65   * ignore.
      66   * @error: a #GError location to store the error occurring, or %NULL
      67   * to ignore.
      68   * 
      69   * Loads a loadable icon. For the asynchronous version of this function, 
      70   * see g_loadable_icon_load_async().
      71   * 
      72   * Returns: (transfer full): a #GInputStream to read the icon from.
      73   **/
      74  GInputStream *
      75  g_loadable_icon_load (GLoadableIcon  *icon,
      76  		      int             size,
      77  		      char          **type,
      78  		      GCancellable   *cancellable,
      79  		      GError        **error)
      80  {
      81    GLoadableIconIface *iface;
      82  
      83    g_return_val_if_fail (G_IS_LOADABLE_ICON (icon), NULL);
      84  
      85    iface = G_LOADABLE_ICON_GET_IFACE (icon);
      86  
      87    return (* iface->load) (icon, size, type, cancellable, error);
      88  }
      89  
      90  /**
      91   * g_loadable_icon_load_async:
      92   * @icon: a #GLoadableIcon.
      93   * @size: an integer.
      94   * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore. 
      95   * @callback: (scope async): a #GAsyncReadyCallback
      96   *   to call when the request is satisfied
      97   * @user_data: the data to pass to callback function
      98   * 
      99   * Loads an icon asynchronously. To finish this function, see 
     100   * g_loadable_icon_load_finish(). For the synchronous, blocking 
     101   * version of this function, see g_loadable_icon_load().
     102   **/
     103  void
     104  g_loadable_icon_load_async (GLoadableIcon       *icon,
     105                              int                  size,
     106                              GCancellable        *cancellable,
     107                              GAsyncReadyCallback  callback,
     108                              gpointer             user_data)
     109  {
     110    GLoadableIconIface *iface;
     111    
     112    g_return_if_fail (G_IS_LOADABLE_ICON (icon));
     113  
     114    iface = G_LOADABLE_ICON_GET_IFACE (icon);
     115  
     116    (* iface->load_async) (icon, size, cancellable, callback, user_data);
     117  }
     118  
     119  /**
     120   * g_loadable_icon_load_finish:
     121   * @icon: a #GLoadableIcon.
     122   * @res: a #GAsyncResult.
     123   * @type: (out) (optional): a location to store the type of the loaded
     124   *        icon, %NULL to ignore.
     125   * @error: a #GError location to store the error occurring, or %NULL to 
     126   * ignore.
     127   * 
     128   * Finishes an asynchronous icon load started in g_loadable_icon_load_async().
     129   * 
     130   * Returns: (transfer full): a #GInputStream to read the icon from.
     131   **/
     132  GInputStream *
     133  g_loadable_icon_load_finish (GLoadableIcon  *icon,
     134  			     GAsyncResult   *res,
     135  			     char          **type,
     136  			     GError        **error)
     137  {
     138    GLoadableIconIface *iface;
     139    
     140    g_return_val_if_fail (G_IS_LOADABLE_ICON (icon), NULL);
     141    g_return_val_if_fail (G_IS_ASYNC_RESULT (res), NULL);
     142  
     143    if (g_async_result_legacy_propagate_error (res, error))
     144      return NULL;
     145  
     146    iface = G_LOADABLE_ICON_GET_IFACE (icon);
     147  
     148    return (* iface->load_finish) (icon, res, type, error);
     149  }
     150  
     151  /********************************************
     152   *   Default implementation of async load   *
     153   ********************************************/
     154  
     155  typedef struct {
     156    int size;
     157    char *type;
     158  } LoadData;
     159  
     160  static void
     161  load_data_free (LoadData *data)
     162  {
     163    g_free (data->type);
     164    g_free (data);
     165  }
     166  
     167  static void
     168  load_async_thread (GTask        *task,
     169                     gpointer      source_object,
     170                     gpointer      task_data,
     171                     GCancellable *cancellable)
     172  {
     173    GLoadableIcon *icon = source_object;
     174    LoadData *data = task_data;
     175    GLoadableIconIface *iface;
     176    GInputStream *stream;
     177    GError *error = NULL;
     178  
     179    iface = G_LOADABLE_ICON_GET_IFACE (icon);
     180    stream = iface->load (icon, data->size, &data->type,
     181                          cancellable, &error);
     182  
     183    if (stream)
     184      g_task_return_pointer (task, stream, g_object_unref);
     185    else
     186      g_task_return_error (task, error);
     187  }
     188  
     189  
     190  
     191  static void
     192  g_loadable_icon_real_load_async (GLoadableIcon       *icon,
     193  				 int                  size,
     194  				 GCancellable        *cancellable,
     195  				 GAsyncReadyCallback  callback,
     196  				 gpointer             user_data)
     197  {
     198    GTask *task;
     199    LoadData *data;
     200  
     201    task = g_task_new (icon, cancellable, callback, user_data);
     202    g_task_set_source_tag (task, g_loadable_icon_real_load_async);
     203    data = g_new0 (LoadData, 1);
     204    g_task_set_task_data (task, data, (GDestroyNotify) load_data_free);
     205    g_task_run_in_thread (task, load_async_thread);
     206    g_object_unref (task);
     207  }
     208  
     209  static GInputStream *
     210  g_loadable_icon_real_load_finish (GLoadableIcon        *icon,
     211  				  GAsyncResult         *res,
     212  				  char                **type,
     213  				  GError              **error)
     214  {
     215    GTask *task;
     216    LoadData *data;
     217    GInputStream *stream;
     218  
     219    g_return_val_if_fail (g_task_is_valid (res, icon), NULL);
     220  
     221    task = G_TASK (res);
     222    data = g_task_get_task_data (task);
     223  
     224    stream = g_task_propagate_pointer (task, error);
     225    if (stream && type)
     226      {
     227        *type = data->type;
     228        data->type = NULL;
     229      }
     230  
     231    return stream;
     232  }