+static gboolean
+g_emblemed_icon_to_tokens (GIcon *icon,
+ GPtrArray *tokens,
+ gint *out_version)
+{
+ GEmblemedIcon *emblemed_icon = G_EMBLEMED_ICON (icon);
+ GList *l;
+ char *s;
+
+ /* GEmblemedIcons are encoded as
+ *
+ * <encoded_icon> [<encoded_emblem_icon>]*
+ */
+
+ g_return_val_if_fail (out_version != NULL, FALSE);
+
+ *out_version = 0;
+
+ s = g_icon_to_string (emblemed_icon->priv->icon);
+ if (s == NULL)
+ return FALSE;
+
+ g_ptr_array_add (tokens, s);
+
+ for (l = emblemed_icon->priv->emblems; l != NULL; l = l->next)
+ {
+ GIcon *emblem_icon = G_ICON (l->data);
+
+ s = g_icon_to_string (emblem_icon);
+ if (s == NULL)
+ return FALSE;
+
+ g_ptr_array_add (tokens, s);
+ }
+
+ return TRUE;
+}
+
+static GIcon *
+g_emblemed_icon_from_tokens (gchar **tokens,
+ gint num_tokens,
+ gint version,
+ GError **error)
+{
+ GEmblemedIcon *emblemed_icon;
+ int n;
+
+ emblemed_icon = NULL;
+
+ if (version != 0)
+ {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_ARGUMENT,
+ _("Can't handle version %d of GEmblemedIcon encoding"),
+ version);
+ goto fail;
+ }
+
+ if (num_tokens < 1)
+ {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_ARGUMENT,
+ _("Malformed number of tokens (%d) in GEmblemedIcon encoding"),
+ num_tokens);
+ goto fail;
+ }
+
+ emblemed_icon = g_object_new (G_TYPE_EMBLEMED_ICON, NULL);
+ emblemed_icon->priv->icon = g_icon_new_for_string (tokens[0], error);
+ if (emblemed_icon->priv->icon == NULL)
+ goto fail;
+
+ for (n = 1; n < num_tokens; n++)
+ {
+ GIcon *emblem;
+
+ emblem = g_icon_new_for_string (tokens[n], error);
+ if (emblem == NULL)
+ goto fail;
+
+ if (!G_IS_EMBLEM (emblem))
+ {
+ g_set_error_literal (error,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_ARGUMENT,
+ _("Expected a GEmblem for GEmblemedIcon"));
+ g_object_unref (emblem);
+ goto fail;
+ }
+
+ emblemed_icon->priv->emblems = g_list_append (emblemed_icon->priv->emblems, emblem);
+ }
+
+ return G_ICON (emblemed_icon);
+
+ fail:
+ if (emblemed_icon != NULL)
+ g_object_unref (emblemed_icon);
+ return NULL;
+}
+
+static GVariant *
+g_emblemed_icon_serialize (GIcon *icon)
+{
+ GEmblemedIcon *emblemed_icon = G_EMBLEMED_ICON (icon);
+ GVariantBuilder builder;
+ GVariant *icon_data;
+ GList *node;
+
+ icon_data = g_icon_serialize (emblemed_icon->priv->icon);
+ if (!icon_data)
+ return NULL;
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("(va(va{sv}))"));
+
+ g_variant_builder_add (&builder, "v", icon_data);
+ g_variant_unref (icon_data);
+
+ g_variant_builder_open (&builder, G_VARIANT_TYPE ("a(va{sv})"));
+ for (node = emblemed_icon->priv->emblems; node != NULL; node = node->next)
+ {
+ icon_data = g_icon_serialize (node->data);
+ if (icon_data)
+ {
+ /* We know how emblems serialise, so do a tweak here to
+ * reduce some of the variant wrapping and redundant storage
+ * of 'emblem' over and again...
+ */
+ if (g_variant_is_of_type (icon_data, G_VARIANT_TYPE ("(sv)")))
+ {
+ const gchar *name;
+ GVariant *content;
+
+ g_variant_get (icon_data, "(&sv)", &name, &content);
+
+ if (g_str_equal (name, "emblem") && g_variant_is_of_type (content, G_VARIANT_TYPE ("(va{sv})")))
+ g_variant_builder_add (&builder, "@(va{sv})", content);
+
+ g_variant_unref (content);
+ }
+
+ g_variant_unref (icon_data);
+ }
+ }
+ g_variant_builder_close (&builder);
+
+ return g_variant_new ("(sv)", "emblemed", g_variant_builder_end (&builder));
+}
+