(root)/
glib-2.79.0/
gio/
gemblem.c
       1  /* GIO - GLib Input, Output and Streaming Library
       2   *
       3   * Copyright (C) 2008 Clemens N. Buss <cebuzz@gmail.com>
       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  
      21  #include <config.h>
      22  
      23  #include "gicon.h"
      24  #include "gemblem.h"
      25  #include "glibintl.h"
      26  #include "gioenums.h"
      27  #include "gioenumtypes.h"
      28  #include "gioerror.h"
      29  #include <stdlib.h>
      30  #include <string.h>
      31  
      32  
      33  /**
      34   * GEmblem:
      35   *
      36   * `GEmblem` is an implementation of [iface@Gio.Icon] that supports
      37   * having an emblem, which is an icon with additional properties.
      38   * It can than be added to a [class@Gio.EmblemedIcon].
      39   *
      40   * Currently, only metainformation about the emblem's origin is
      41   * supported. More may be added in the future.
      42   */
      43  
      44  static void g_emblem_iface_init (GIconIface *iface);
      45  
      46  struct _GEmblem
      47  {
      48    GObject parent_instance;
      49  
      50    GIcon *icon;
      51    GEmblemOrigin origin;
      52  };
      53  
      54  struct _GEmblemClass
      55  {
      56    GObjectClass parent_class;
      57  };
      58  
      59  enum
      60  {
      61    PROP_0_GEMBLEM,
      62    PROP_ICON,
      63    PROP_ORIGIN
      64  };
      65  
      66  G_DEFINE_TYPE_WITH_CODE (GEmblem, g_emblem, G_TYPE_OBJECT,
      67                           G_IMPLEMENT_INTERFACE (G_TYPE_ICON, g_emblem_iface_init))
      68  
      69  static void
      70  g_emblem_get_property (GObject    *object,
      71                         guint       prop_id,
      72                         GValue     *value,
      73                         GParamSpec *pspec)
      74  {
      75    GEmblem *emblem = G_EMBLEM (object);
      76  
      77    switch (prop_id)
      78      {
      79        case PROP_ICON:
      80          g_value_set_object (value, emblem->icon);
      81  	break;
      82  
      83        case PROP_ORIGIN:
      84          g_value_set_enum (value, emblem->origin);
      85          break;
      86  
      87        default:
      88          G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      89          break;
      90    }
      91  }
      92  
      93  static void
      94  g_emblem_set_property (GObject      *object,
      95                         guint         prop_id,
      96                         const GValue *value,
      97                         GParamSpec   *pspec)
      98  {
      99    GEmblem *emblem = G_EMBLEM (object);
     100  
     101    switch (prop_id)
     102      {
     103        case PROP_ICON:
     104          emblem->icon = g_value_dup_object (value);
     105          break;
     106  
     107        case PROP_ORIGIN:
     108          emblem->origin = g_value_get_enum (value);
     109          break;
     110  
     111        default:
     112          G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     113          break;
     114      }
     115  }
     116  
     117  static void
     118  g_emblem_finalize (GObject *object)
     119  {
     120    GEmblem *emblem = G_EMBLEM (object);
     121  
     122    if (emblem->icon)
     123      g_object_unref (emblem->icon);
     124  
     125    (*G_OBJECT_CLASS (g_emblem_parent_class)->finalize) (object);
     126  }
     127  
     128  static void
     129  g_emblem_class_init (GEmblemClass *klass)
     130  {
     131    GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
     132  
     133    gobject_class->finalize = g_emblem_finalize;
     134    gobject_class->set_property = g_emblem_set_property;
     135    gobject_class->get_property = g_emblem_get_property;
     136  
     137    /**
     138     * GEmblem:origin:
     139     *
     140     * The origin the emblem is derived from.
     141     *
     142     * Since: 2.18
     143     */
     144    g_object_class_install_property (gobject_class,
     145                                     PROP_ORIGIN,
     146                                     g_param_spec_enum ("origin", NULL, NULL,
     147                                                        G_TYPE_EMBLEM_ORIGIN,
     148                                                        G_EMBLEM_ORIGIN_UNKNOWN,
     149                                                        G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
     150  
     151    /**
     152     * GEmblem:icon:
     153     *
     154     * The actual icon of the emblem.
     155     *
     156     * Since: 2.18
     157     */
     158    g_object_class_install_property (gobject_class,
     159                                     PROP_ICON,
     160                                     g_param_spec_object ("icon", NULL, NULL,
     161                                                        G_TYPE_OBJECT,
     162                                                        G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
     163  
     164  }
     165  
     166  static void
     167  g_emblem_init (GEmblem *emblem)
     168  {
     169  }
     170  
     171  /**
     172   * g_emblem_new:
     173   * @icon: a GIcon containing the icon.
     174   *
     175   * Creates a new emblem for @icon.
     176   *
     177   * Returns: a new #GEmblem.
     178   *
     179   * Since: 2.18
     180   */
     181  GEmblem *
     182  g_emblem_new (GIcon *icon)
     183  {
     184    GEmblem* emblem;
     185  
     186    g_return_val_if_fail (icon != NULL, NULL);
     187    g_return_val_if_fail (G_IS_ICON (icon), NULL);
     188    g_return_val_if_fail (!G_IS_EMBLEM (icon), NULL);
     189  
     190    emblem = g_object_new (G_TYPE_EMBLEM, NULL);
     191    emblem->icon = g_object_ref (icon);
     192    emblem->origin = G_EMBLEM_ORIGIN_UNKNOWN;
     193  
     194    return emblem;
     195  }
     196  
     197  /**
     198   * g_emblem_new_with_origin:
     199   * @icon: a GIcon containing the icon.
     200   * @origin: a GEmblemOrigin enum defining the emblem's origin
     201   *
     202   * Creates a new emblem for @icon.
     203   *
     204   * Returns: a new #GEmblem.
     205   *
     206   * Since: 2.18
     207   */
     208  GEmblem *
     209  g_emblem_new_with_origin (GIcon         *icon,
     210                            GEmblemOrigin  origin)
     211  {
     212    GEmblem* emblem;
     213  
     214    g_return_val_if_fail (icon != NULL, NULL);
     215    g_return_val_if_fail (G_IS_ICON (icon), NULL);
     216    g_return_val_if_fail (!G_IS_EMBLEM (icon), NULL);
     217  
     218    emblem = g_object_new (G_TYPE_EMBLEM, NULL);
     219    emblem->icon = g_object_ref (icon);
     220    emblem->origin = origin;
     221  
     222    return emblem;
     223  }
     224  
     225  /**
     226   * g_emblem_get_icon:
     227   * @emblem: a #GEmblem from which the icon should be extracted.
     228   *
     229   * Gives back the icon from @emblem.
     230   *
     231   * Returns: (transfer none): a #GIcon. The returned object belongs to
     232   *          the emblem and should not be modified or freed.
     233   *
     234   * Since: 2.18
     235   */
     236  GIcon *
     237  g_emblem_get_icon (GEmblem *emblem)
     238  {
     239    g_return_val_if_fail (G_IS_EMBLEM (emblem), NULL);
     240  
     241    return emblem->icon;
     242  }
     243  
     244  
     245  /**
     246   * g_emblem_get_origin:
     247   * @emblem: a #GEmblem
     248   *
     249   * Gets the origin of the emblem.
     250   *
     251   * Returns: (transfer none): the origin of the emblem
     252   *
     253   * Since: 2.18
     254   */
     255  GEmblemOrigin
     256  g_emblem_get_origin (GEmblem *emblem)
     257  {
     258    g_return_val_if_fail (G_IS_EMBLEM (emblem), G_EMBLEM_ORIGIN_UNKNOWN);
     259  
     260    return emblem->origin;
     261  }
     262  
     263  static guint
     264  g_emblem_hash (GIcon *icon)
     265  {
     266    GEmblem *emblem = G_EMBLEM (icon);
     267    guint hash;
     268  
     269    hash  = g_icon_hash (g_emblem_get_icon (emblem));
     270    hash ^= emblem->origin;
     271  
     272    return hash;
     273  }
     274  
     275  static gboolean
     276  g_emblem_equal (GIcon *icon1,
     277                  GIcon *icon2)
     278  {
     279    GEmblem *emblem1 = G_EMBLEM (icon1);
     280    GEmblem *emblem2 = G_EMBLEM (icon2);
     281  
     282    return emblem1->origin == emblem2->origin &&
     283           g_icon_equal (emblem1->icon, emblem2->icon);
     284  }
     285  
     286  static gboolean
     287  g_emblem_to_tokens (GIcon *icon,
     288  		    GPtrArray *tokens,
     289  		    gint  *out_version)
     290  {
     291    GEmblem *emblem = G_EMBLEM (icon);
     292    char *s;
     293  
     294    /* GEmblem are encoded as
     295     *
     296     * <origin> <icon>
     297     */
     298  
     299    g_return_val_if_fail (out_version != NULL, FALSE);
     300  
     301    *out_version = 0;
     302  
     303    s = g_icon_to_string (emblem->icon);
     304    if (s == NULL)
     305      return FALSE;
     306  
     307    g_ptr_array_add (tokens, s);
     308  
     309    s = g_strdup_printf ("%d", emblem->origin);
     310    g_ptr_array_add (tokens, s);
     311  
     312    return TRUE;
     313  }
     314  
     315  static GIcon *
     316  g_emblem_from_tokens (gchar  **tokens,
     317  		      gint     num_tokens,
     318  		      gint     version,
     319  		      GError **error)
     320  {
     321    GEmblem *emblem;
     322    GIcon *icon;
     323    GEmblemOrigin origin;
     324  
     325    emblem = NULL;
     326  
     327    if (version != 0)
     328      {
     329        g_set_error (error,
     330                     G_IO_ERROR,
     331                     G_IO_ERROR_INVALID_ARGUMENT,
     332                     _("Can’t handle version %d of GEmblem encoding"),
     333                     version);
     334        return NULL;
     335      }
     336  
     337    if (num_tokens != 2)
     338      {
     339        g_set_error (error,
     340                     G_IO_ERROR,
     341                     G_IO_ERROR_INVALID_ARGUMENT,
     342                     _("Malformed number of tokens (%d) in GEmblem encoding"),
     343                     num_tokens);
     344        return NULL;
     345      }
     346  
     347    icon = g_icon_new_for_string (tokens[0], error);
     348  
     349    if (icon == NULL)
     350      return NULL;
     351  
     352    origin = atoi (tokens[1]);
     353  
     354    emblem = g_emblem_new_with_origin (icon, origin);
     355    g_object_unref (icon);
     356  
     357    return G_ICON (emblem);
     358  }
     359  
     360  static GVariant *
     361  g_emblem_serialize (GIcon *icon)
     362  {
     363    GEmblem *emblem = G_EMBLEM (icon);
     364    GVariant *icon_data;
     365    GEnumValue *origin;
     366    GVariant *result;
     367  
     368    icon_data = g_icon_serialize (emblem->icon);
     369    if (!icon_data)
     370      return NULL;
     371  
     372    origin = g_enum_get_value (g_type_class_peek (G_TYPE_EMBLEM_ORIGIN), emblem->origin);
     373    result = g_variant_new_parsed ("('emblem', <(%v, {'origin': <%s>})>)",
     374                                   icon_data, origin ? origin->value_nick : "unknown");
     375    g_variant_unref (icon_data);
     376  
     377    return result;
     378  }
     379  
     380  static void
     381  g_emblem_iface_init (GIconIface *iface)
     382  {
     383    iface->hash  = g_emblem_hash;
     384    iface->equal = g_emblem_equal;
     385    iface->to_tokens = g_emblem_to_tokens;
     386    iface->from_tokens = g_emblem_from_tokens;
     387    iface->serialize = g_emblem_serialize;
     388  }