From d73422735a1d60d1b014cf40b273e7391389e678 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Tue, 21 Oct 2008 12:58:45 +0000 Subject: Patch from David Zeuthen 2008-10-21 Alexander Larsson Patch from David Zeuthen * common/Makefile.am: * common/gvfsicon.[ch]: Added GVfsIcon object for GVfs backend specific icons. * common/gmountspec.[ch]: Make sure to/from string works correctly to roundtrip GMountSpec:s Make GMountSpec a boxed type * common/gvfsdaemonprotocol.h: Add OpenIconForRead operation * client/Makefile.am: * client/gvfsiconloadable.[ch]: In gvfs client side, implement GLoadableIcon for GVfsIcon type. * client/gdaemonvfs.c: Make sure that we add the GLoadableIcon interface for GVfsIcon on load * daemon/Makefile.am: * daemon/gvfsbackend.[ch]: * daemon/gvfsjobopeniconforread.[ch]: Add new job type for OpenIconForRead op * daemon/gvfsbackendgphoto2.c: Implement OpenIconForRead for icon previews. svn path=/trunk/; revision=2070 --- common/Makefile.am | 1 + common/gmountspec.c | 107 ++++++++++++++++- common/gmountspec.h | 8 +- common/gvfsdaemonprotocol.h | 1 + common/gvfsicon.c | 282 ++++++++++++++++++++++++++++++++++++++++++++ common/gvfsicon.h | 69 +++++++++++ 6 files changed, 465 insertions(+), 3 deletions(-) create mode 100644 common/gvfsicon.c create mode 100644 common/gvfsicon.h (limited to 'common') diff --git a/common/Makefile.am b/common/Makefile.am index 2fbb908b..12dd9e83 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -16,6 +16,7 @@ libgvfscommon_la_SOURCES = \ gmountsource.c gmountsource.h \ gmounttracker.c gmounttracker.h \ gvfsdaemonprotocol.c gvfsdaemonprotocol.h \ + gvfsicon.h gvfsicon.c \ $(NULL) libgvfscommon_la_LIBADD = \ diff --git a/common/gmountspec.c b/common/gmountspec.c index 7d8fa57e..bee872fc 100644 --- a/common/gmountspec.c +++ b/common/gmountspec.c @@ -455,6 +455,8 @@ char * g_mount_spec_to_string (GMountSpec *spec) { GString *str; + char *k; + char *v; int i; if (spec == NULL) @@ -466,13 +468,102 @@ g_mount_spec_to_string (GMountSpec *spec) { GMountSpecItem *item = &g_array_index (spec->items, GMountSpecItem, i); - g_string_append_printf (str, "%s='%s',", item->key, item->value); + k = g_uri_escape_string (item->key, NULL, TRUE); + v = g_uri_escape_string (item->value, NULL, TRUE); + g_string_append_printf (str, "%s=%s,", k, v); + g_free (k); + g_free (v); } - g_string_append_printf (str, "mount_prefix='%s'", spec->mount_prefix); + k = g_uri_escape_string ("__mount_prefix", NULL, TRUE); + v = g_uri_escape_string (spec->mount_prefix, NULL, TRUE); + g_string_append_printf (str, "%s=%s", k, v); + g_free (k); + g_free (v); return g_string_free (str, FALSE); } +GMountSpec * +g_mount_spec_new_from_string (const gchar *str, + GError **error) +{ + GArray *items; + GMountSpec *mount_spec; + char **kv_pairs; + char *mount_prefix; + int i; + + g_return_val_if_fail (str != NULL, NULL); + + mount_spec = NULL; + mount_prefix = NULL; + items = g_array_new (FALSE, TRUE, sizeof (GMountSpecItem)); + + kv_pairs = g_strsplit (str, ",", 0); + for (i = 0; kv_pairs[i] != NULL; i++) + { + char **tokens; + GMountSpecItem item; + + tokens = g_strsplit (kv_pairs[i], "=", 0); + if (g_strv_length (tokens) != 2) + { + g_set_error (error, + G_IO_ERROR, + G_IO_ERROR_INVALID_ARGUMENT, + "Encountered invalid key/value pair '%s' while decoding GMountSpec", + kv_pairs[i]); + g_strfreev (tokens); + g_strfreev (kv_pairs); + goto fail; + } + + item.key = g_uri_unescape_string (tokens[0], NULL); + item.value = g_uri_unescape_string (tokens[1], NULL); + + if (strcmp (item.key, "__mount_prefix") == 0) + { + g_free (item.key); + mount_prefix = item.value; + } + else + { + g_array_append_val (items, item); + } + + g_strfreev (tokens); + } + g_strfreev (kv_pairs); + + if (mount_prefix == NULL) + { + g_set_error (error, + G_IO_ERROR, + G_IO_ERROR_INVALID_ARGUMENT, + "Didn't find __mount_prefix while decoding '%s' GMountSpec", + str); + goto fail; + } + + /* this constructor takes ownership of the data we pass in */ + mount_spec = g_mount_spec_new_from_data (items, + mount_prefix); + + return mount_spec; + + fail: + for (i = 0; i < items->len; i++) + { + GMountSpecItem *item = &g_array_index (items, GMountSpecItem, i); + g_free (item->key); + g_free (item->value); + } + g_array_free (items, TRUE); + g_free (mount_prefix); + return NULL; +} + + char * g_mount_spec_canonicalize_path (const char *path) { @@ -532,3 +623,15 @@ g_mount_spec_canonicalize_path (const char *path) return canon; } + +GType +g_type_mount_spec_get_gtype (void) +{ + static GType type_id = 0; + + if (type_id == 0) + type_id = g_boxed_type_register_static (g_intern_static_string ("GMountSpec"), + (GBoxedCopyFunc) g_mount_spec_ref, + (GBoxedFreeFunc) g_mount_spec_unref); + return type_id; +} diff --git a/common/gmountspec.h b/common/gmountspec.h index 55ac5c63..879c39b8 100644 --- a/common/gmountspec.h +++ b/common/gmountspec.h @@ -92,11 +92,17 @@ const char *g_mount_spec_get (GMountSpec *spec, const char *key); const char *g_mount_spec_get_type (GMountSpec *spec); -/* For debugging */ char * g_mount_spec_to_string (GMountSpec *spec); +GMountSpec *g_mount_spec_new_from_string (const gchar *str, + GError **error); + char * g_mount_spec_canonicalize_path (const char *path); + +#define G_TYPE_MOUNT_SPEC (g_type_mount_spec_get_gtype ()) +GType g_type_mount_spec_get_gtype (void) G_GNUC_CONST; + G_END_DECLS diff --git a/common/gvfsdaemonprotocol.h b/common/gvfsdaemonprotocol.h index 7061d97c..38f7d0d3 100644 --- a/common/gvfsdaemonprotocol.h +++ b/common/gvfsdaemonprotocol.h @@ -49,6 +49,7 @@ G_BEGIN_DECLS #define G_VFS_DBUS_MOUNT_OP_SET_ATTRIBUTE "SetAttribute" #define G_VFS_DBUS_MOUNT_OP_QUERY_SETTABLE_ATTRIBUTES "QuerySettableAttributes" #define G_VFS_DBUS_MOUNT_OP_QUERY_WRITABLE_NAMESPACES "QueryWritableNamespaces" +#define G_VFS_DBUS_MOUNT_OP_OPEN_ICON_FOR_READ "OpenIconForRead" /* Progress callback interface for copy and move */ #define G_VFS_DBUS_PROGRESS_INTERFACE "org.gtk.vfs.Progress" diff --git a/common/gvfsicon.c b/common/gvfsicon.c new file mode 100644 index 00000000..29dacbd8 --- /dev/null +++ b/common/gvfsicon.c @@ -0,0 +1,282 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2008 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: David Zeuthen + */ + +#include +#include +#include + +#include "gvfsicon.h" + +static void g_vfs_icon_icon_iface_init (GIconIface *iface); + +/* Because of the way dependencies are currently set up, the + * GLoadableIcon interface is in client/gvfsiconloadable.c and is + * added in g_io_module_load() in client/gdaemonvfs.c. + */ + +enum +{ + PROP_0, + PROP_MOUNT_SPEC, + PROP_ICON_ID +}; + +G_DEFINE_TYPE_EXTENDED (GVfsIcon, + g_vfs_icon, + G_TYPE_OBJECT, + 0, + G_IMPLEMENT_INTERFACE (G_TYPE_ICON, + g_vfs_icon_icon_iface_init)) + +static void +g_vfs_icon_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GVfsIcon *icon = G_VFS_ICON (object); + + switch (prop_id) + { + case PROP_MOUNT_SPEC: + g_value_set_boxed (value, icon->mount_spec); + break; + + case PROP_ICON_ID: + g_value_set_string (value, icon->icon_id); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +g_vfs_icon_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GVfsIcon *icon = G_VFS_ICON (object); + + switch (prop_id) + { + case PROP_MOUNT_SPEC: + icon->mount_spec = g_mount_spec_ref (g_value_get_boxed (value)); + break; + + case PROP_ICON_ID: + icon->icon_id = g_strdup (g_value_get_string (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +g_vfs_icon_finalize (GObject *object) +{ + GVfsIcon *vfs_icon; + + vfs_icon = G_VFS_ICON (object); + + if (vfs_icon->mount_spec != NULL) + g_mount_spec_unref (vfs_icon->mount_spec); + g_free (vfs_icon->icon_id); + + G_OBJECT_CLASS (g_vfs_icon_parent_class)->finalize (object); +} + +static void +g_vfs_icon_class_init (GVfsIconClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->get_property = g_vfs_icon_get_property; + gobject_class->set_property = g_vfs_icon_set_property; + gobject_class->finalize = g_vfs_icon_finalize; + + /** + * GVfsIcon:mount-spec: + * + * The mount spec. + */ + g_object_class_install_property (gobject_class, + PROP_MOUNT_SPEC, + g_param_spec_boxed ("mount-spec", + "Mount Spec", + "Mount Spec", + G_TYPE_MOUNT_SPEC, + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE | + G_PARAM_STATIC_NAME | + G_PARAM_STATIC_BLURB | + G_PARAM_STATIC_NICK)); + + /** + * GVfsIcon:icon-id: + * + * The id of the icon. + */ + g_object_class_install_property (gobject_class, + PROP_ICON_ID, + g_param_spec_string ("icon-id", + "Icon identifier", + "Icon identifier", + NULL, + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE | + G_PARAM_STATIC_NAME | + G_PARAM_STATIC_BLURB | + G_PARAM_STATIC_NICK)); +} + +static void +g_vfs_icon_init (GVfsIcon *file) +{ +} + +GMountSpec * +g_vfs_icon_get_mount_spec (GVfsIcon *vfs_icon) +{ + g_return_val_if_fail (G_VFS_IS_ICON (vfs_icon), NULL); + return g_mount_spec_ref (vfs_icon->mount_spec); +} + +const gchar * +g_vfs_icon_get_icon_id (GVfsIcon *vfs_icon) +{ + g_return_val_if_fail (G_VFS_IS_ICON (vfs_icon), NULL); + return vfs_icon->icon_id; +} + + +GIcon * +g_vfs_icon_new (GMountSpec *mount_spec, + const gchar *icon_id) +{ + return G_ICON (g_object_new (G_VFS_TYPE_ICON, + "mount-spec", mount_spec, + "icon-id", icon_id, + NULL)); +} + +static guint +g_vfs_icon_hash (GIcon *icon) +{ + GVfsIcon *vfs_icon = G_VFS_ICON (icon); + + return g_mount_spec_hash (vfs_icon->mount_spec) ^ g_str_hash (vfs_icon->icon_id); +} + +static int +safe_strcmp (const char *a, + const char *b) +{ + if (a == NULL) + a = ""; + if (b == NULL) + b = ""; + + return strcmp (a, b); +} + +static gboolean +g_vfs_icon_equal (GIcon *icon1, + GIcon *icon2) +{ + GVfsIcon *vfs1 = G_VFS_ICON (icon1); + GVfsIcon *vfs2 = G_VFS_ICON (icon2); + + return g_mount_spec_equal (vfs1->mount_spec, vfs2->mount_spec) && + (safe_strcmp (vfs1->icon_id, vfs2->icon_id) == 0); +} + +static gboolean +g_vfs_icon_to_tokens (GIcon *icon, + GPtrArray *tokens, + gint *out_version) +{ + GVfsIcon *vfs_icon = G_VFS_ICON (icon); + char *s; + + g_return_val_if_fail (out_version != NULL, FALSE); + + *out_version = 0; + + s = g_mount_spec_to_string (vfs_icon->mount_spec); + g_ptr_array_add (tokens, s); + g_ptr_array_add (tokens, vfs_icon->icon_id); + + return TRUE; +} + +static GIcon * +g_vfs_icon_from_tokens (gchar **tokens, + gint num_tokens, + gint version, + GError **error) +{ + GMountSpec *mount_spec; + GIcon *icon; + + icon = NULL; + + if (version != 0) + { + g_set_error (error, + G_IO_ERROR, + G_IO_ERROR_INVALID_ARGUMENT, + _("Can't handle version %d of GVfsIcon encoding"), + version); + goto out; + } + + if (num_tokens != 2) + { + g_set_error_literal (error, + G_IO_ERROR, + G_IO_ERROR_INVALID_ARGUMENT, + _("Malformed input data for GVfsIcon")); + goto out; + } + + mount_spec = g_mount_spec_new_from_string (tokens[0], error); + if (mount_spec == NULL) + goto out; + + icon = g_vfs_icon_new (mount_spec, tokens[1]); + g_mount_spec_unref (mount_spec); + + out: + return icon; +} + +static void +g_vfs_icon_icon_iface_init (GIconIface *iface) +{ + iface->hash = g_vfs_icon_hash; + iface->equal = g_vfs_icon_equal; + iface->to_tokens = g_vfs_icon_to_tokens; + iface->from_tokens = g_vfs_icon_from_tokens; +} diff --git a/common/gvfsicon.h b/common/gvfsicon.h new file mode 100644 index 00000000..b32c2ba4 --- /dev/null +++ b/common/gvfsicon.h @@ -0,0 +1,69 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2008 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: David Zeuthen + */ + +#ifndef __G_VFS_ICON_H__ +#define __G_VFS_ICON_H__ + +#include +#include + +G_BEGIN_DECLS + +#define G_VFS_TYPE_ICON (g_vfs_icon_get_type ()) +#define G_VFS_ICON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_ICON, GVfsIcon)) +#define G_VFS_ICON_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_ICON, GVfsIconClass)) +#define G_VFS_IS_ICON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_ICON)) +#define G_VFS_IS_ICON_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_ICON)) +#define G_VFS_ICON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_ICON, GVfsIconClass)) + +/** + * GVfsIcon: + * + * An object for referencing icons originating from a #GVfsBackend + */ +typedef struct _GVfsIcon GVfsIcon; +typedef struct _GVfsIconClass GVfsIconClass; + +struct _GVfsIcon +{ + GObject parent_instance; + + GMountSpec *mount_spec; + char *icon_id; +}; + +struct _GVfsIconClass +{ + GObjectClass parent_class; +}; + +GType g_vfs_icon_get_type (void) G_GNUC_CONST; + +GIcon *g_vfs_icon_new (GMountSpec *mount_spec, + const gchar *icon_id); + +GMountSpec *g_vfs_icon_get_mount_spec (GVfsIcon *vfs_icon); +const gchar *g_vfs_icon_get_icon_id (GVfsIcon *vfs_icon); + +G_END_DECLS + +#endif /* __G_VFS_ICON_H__ */ -- cgit v1.2.1