diff options
author | Alexander Larsson <alexl@redhat.com> | 2008-10-21 12:58:45 +0000 |
---|---|---|
committer | Alexander Larsson <alexl@src.gnome.org> | 2008-10-21 12:58:45 +0000 |
commit | d73422735a1d60d1b014cf40b273e7391389e678 (patch) | |
tree | 63c01910d1ef0d30b1084209c90e21144ee4710b | |
parent | 1078f20f47debb00d0a0f6966b6680ad0473e32f (diff) | |
download | gvfs-d73422735a1d60d1b014cf40b273e7391389e678.tar.gz |
Patch from David Zeuthen
2008-10-21 Alexander Larsson <alexl@redhat.com>
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
-rw-r--r-- | ChangeLog | 30 | ||||
-rw-r--r-- | client/Makefile.am | 1 | ||||
-rw-r--r-- | client/gdaemonvfs.c | 6 | ||||
-rw-r--r-- | client/gvfsiconloadable.c | 431 | ||||
-rw-r--r-- | client/gvfsiconloadable.h | 35 | ||||
-rw-r--r-- | common/Makefile.am | 1 | ||||
-rw-r--r-- | common/gmountspec.c | 107 | ||||
-rw-r--r-- | common/gmountspec.h | 8 | ||||
-rw-r--r-- | common/gvfsdaemonprotocol.h | 1 | ||||
-rw-r--r-- | common/gvfsicon.c | 282 | ||||
-rw-r--r-- | common/gvfsicon.h | 69 | ||||
-rw-r--r-- | daemon/Makefile.am | 1 | ||||
-rw-r--r-- | daemon/gvfsbackend.c | 5 | ||||
-rw-r--r-- | daemon/gvfsbackend.h | 7 | ||||
-rw-r--r-- | daemon/gvfsbackendgphoto2.c | 72 | ||||
-rw-r--r-- | daemon/gvfsjobopeniconforread.c | 142 | ||||
-rw-r--r-- | daemon/gvfsjobopeniconforread.h | 63 |
17 files changed, 1251 insertions, 10 deletions
@@ -1,5 +1,35 @@ 2008-10-21 Alexander Larsson <alexl@redhat.com> + 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. + +2008-10-21 Alexander Larsson <alexl@redhat.com> + * configure.ac: Require glib 2.19.1 for GIcon serialization support diff --git a/client/Makefile.am b/client/Makefile.am index 274d9fd3..b2aea25d 100644 --- a/client/Makefile.am +++ b/client/Makefile.am @@ -33,6 +33,7 @@ vfssources = \ gdaemonfileenumerator.c gdaemonfileenumerator.h \ gdaemonfilemonitor.c gdaemonfilemonitor.h \ gvfsdaemondbus.c gvfsdaemondbus.h \ + gvfsiconloadable.c gvfsiconloadable.h \ gvfsuriutils.c gvfsuriutils.h \ gvfsurimapper.c gvfsurimapper.h \ $(URI_PARSER_SOURCES) \ diff --git a/client/gdaemonvfs.c b/client/gdaemonvfs.c index 6d99c299..94f7e9ba 100644 --- a/client/gdaemonvfs.c +++ b/client/gdaemonvfs.c @@ -36,6 +36,8 @@ #include "gmountspec.h" #include "gvfsurimapper.h" #include "gdaemonvolumemonitor.h" +#include "gvfsicon.h" +#include "gvfsiconloadable.h" #include <glib/gi18n-lib.h> typedef struct { @@ -1129,6 +1131,10 @@ g_io_module_load (GIOModule *module) g_daemon_vfs_register_type (G_TYPE_MODULE (module)); g_daemon_volume_monitor_register_types (G_TYPE_MODULE (module)); + + /* We implement GLoadableIcon only on client side. + see comment in common/giconvfs.c */ + _g_vfs_icon_add_loadable_interface (); g_io_extension_point_implement (G_VFS_EXTENSION_POINT_NAME, G_TYPE_DAEMON_VFS, diff --git a/client/gvfsiconloadable.c b/client/gvfsiconloadable.c new file mode 100644 index 00000000..1c6d54b4 --- /dev/null +++ b/client/gvfsiconloadable.c @@ -0,0 +1,431 @@ +/* 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 <davidz@redhat.com> + */ + +#include <config.h> +#include <string.h> +#include <glib/gi18n-lib.h> + +#include "gvfsicon.h" +#include "gvfsiconloadable.h" +#include "gmounttracker.h" +#include "gvfsdaemondbus.h" +#include "gdaemonvfs.h" +#include "gdaemonfileinputstream.h" +#include "gvfsdaemonprotocol.h" +#include "gdbusutils.h" + +/* see comment in common/giconvfs.c for why the GLoadableIcon interface is here */ + +static DBusMessage * +create_empty_message (GVfsIcon *vfs_icon, + const char *op, + GMountInfo **mount_info_out, + GError **error) +{ + DBusMessage *message; + GMountInfo *mount_info; + + mount_info = _g_daemon_vfs_get_mount_info_sync (vfs_icon->mount_spec, + "/", + error); + + if (mount_info == NULL) + return NULL; + + if (mount_info_out) + *mount_info_out = g_mount_info_ref (mount_info); + + message = + dbus_message_new_method_call (mount_info->dbus_id, + mount_info->object_path, + G_VFS_DBUS_MOUNT_INTERFACE, + op); + + _g_dbus_message_append_args (message, G_DBUS_TYPE_CSTRING, &(vfs_icon->icon_id), 0); + + g_mount_info_unref (mount_info); + return message; +} + +static DBusMessage * +do_sync_path_call (GVfsIcon *vfs_icon, + const char *op, + GMountInfo **mount_info_out, + DBusConnection **connection_out, + GCancellable *cancellable, + GError **error, + int first_arg_type, + ...) +{ + DBusMessage *message, *reply; + va_list var_args; + GError *my_error; + + retry: + message = create_empty_message (vfs_icon, op, mount_info_out, error); + if (!message) + return NULL; + + va_start (var_args, first_arg_type); + _g_dbus_message_append_args_valist (message, + first_arg_type, + var_args); + va_end (var_args); + + + my_error = NULL; + reply = _g_vfs_daemon_call_sync (message, + connection_out, + NULL, NULL, NULL, + cancellable, &my_error); + dbus_message_unref (message); + + if (reply == NULL) + { + if (g_error_matches (my_error, G_VFS_ERROR, G_VFS_ERROR_RETRY)) + { + g_error_free (my_error); + goto retry; + } + g_propagate_error (error, my_error); + } + + return reply; +} + +static GInputStream * +g_vfs_icon_load (GLoadableIcon *icon, + int size, + char **type, + GCancellable *cancellable, + GError **error) +{ + DBusConnection *connection; + int fd; + DBusMessage *reply; + guint32 fd_id; + dbus_bool_t can_seek; + + reply = do_sync_path_call (G_VFS_ICON (icon), + G_VFS_DBUS_MOUNT_OP_OPEN_ICON_FOR_READ, + NULL, + &connection, + cancellable, + error, + 0); + if (reply == NULL) + return NULL; + + if (!dbus_message_get_args (reply, NULL, + DBUS_TYPE_UINT32, &fd_id, + DBUS_TYPE_BOOLEAN, &can_seek, + DBUS_TYPE_INVALID)) + { + dbus_message_unref (reply); + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, + _("Invalid return value from open_icon_for_read")); + return NULL; + } + + dbus_message_unref (reply); + + fd = _g_dbus_connection_get_fd_sync (connection, fd_id); + if (fd == -1) + { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, + _("Didn't get stream file descriptor")); + return NULL; + } + + return G_INPUT_STREAM (g_daemon_file_input_stream_new (fd, can_seek)); +} + + +typedef void (*AsyncPathCallCallback) (DBusMessage *reply, + DBusConnection *connection, + GSimpleAsyncResult *result, + GCancellable *cancellable, + gpointer callback_data); + + +typedef struct { + GSimpleAsyncResult *result; + GVfsIcon *vfs_icon; + char *op; + GCancellable *cancellable; + DBusMessage *args; + AsyncPathCallCallback callback; + gpointer callback_data; + GDestroyNotify notify; +} AsyncPathCall; + + +static void +async_path_call_free (AsyncPathCall *data) +{ + if (data->notify) + data->notify (data->callback_data); + + if (data->result) + g_object_unref (data->result); + g_object_unref (data->vfs_icon); + g_free (data->op); + if (data->cancellable) + g_object_unref (data->cancellable); + if (data->args) + dbus_message_unref (data->args); + g_free (data); +} + +static void +async_path_call_done (DBusMessage *reply, + DBusConnection *connection, + GError *io_error, + gpointer _data) +{ + AsyncPathCall *data = _data; + GSimpleAsyncResult *result; + + if (io_error != NULL) + { + g_simple_async_result_set_from_error (data->result, io_error); + g_simple_async_result_complete (data->result); + async_path_call_free (data); + } + else + { + result = data->result; + g_object_weak_ref (G_OBJECT (result), (GWeakNotify)async_path_call_free, data); + data->result = NULL; + + data->callback (reply, connection, + result, + data->cancellable, + data->callback_data); + + /* Free data here, or later if callback ref:ed the result */ + g_object_unref (result); + } +} + +static void +do_async_path_call_callback (GMountInfo *mount_info, + gpointer _data, + GError *error) +{ + AsyncPathCall *data = _data; + DBusMessage *message; + DBusMessageIter arg_source, arg_dest; + + if (error != NULL) + { + g_simple_async_result_set_from_error (data->result, error); + g_simple_async_result_complete (data->result); + async_path_call_free (data); + return; + } + + message = + dbus_message_new_method_call (mount_info->dbus_id, + mount_info->object_path, + G_VFS_DBUS_MOUNT_INTERFACE, + data->op); + + _g_dbus_message_append_args (message, G_DBUS_TYPE_CSTRING, &(data->vfs_icon->icon_id), 0); + + /* Append more args from data->args */ + + if (data->args) + { + dbus_message_iter_init (data->args, &arg_source); + dbus_message_iter_init_append (message, &arg_dest); + + _g_dbus_message_iter_copy (&arg_dest, &arg_source); + } + + _g_vfs_daemon_call_async (message, + async_path_call_done, data, + data->cancellable); + + dbus_message_unref (message); +} + + +static void +do_async_path_call (GVfsIcon *vfs_icon, + const char *op, + GCancellable *cancellable, + GAsyncReadyCallback op_callback, + gpointer op_callback_data, + AsyncPathCallCallback callback, + gpointer callback_data, + GDestroyNotify notify, + int first_arg_type, + ...) +{ + va_list var_args; + AsyncPathCall *data; + + data = g_new0 (AsyncPathCall, 1); + + data->result = g_simple_async_result_new (G_OBJECT (vfs_icon), + op_callback, op_callback_data, + NULL); + + data->vfs_icon = g_object_ref (vfs_icon); + data->op = g_strdup (op); + if (cancellable) + data->cancellable = g_object_ref (cancellable); + data->callback = callback; + data->callback_data = callback_data; + data->notify = notify; + + if (first_arg_type != 0) + { + data->args = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_CALL); + if (data->args == NULL) + _g_dbus_oom (); + + va_start (var_args, first_arg_type); + _g_dbus_message_append_args_valist (data->args, + first_arg_type, + var_args); + va_end (var_args); + } + + + _g_daemon_vfs_get_mount_info_async (vfs_icon->mount_spec, + "/", + do_async_path_call_callback, + data); +} + +typedef struct { + GSimpleAsyncResult *result; + gboolean can_seek; +} GetFDData; + +static void +load_async_get_fd_cb (int fd, + gpointer callback_data) +{ + GetFDData *data = callback_data; + GFileInputStream *stream; + + if (fd == -1) + { + g_simple_async_result_set_error (data->result, + G_IO_ERROR, G_IO_ERROR_FAILED, + _("Couldn't get stream file descriptor")); + } + else + { + stream = g_daemon_file_input_stream_new (fd, data->can_seek); + g_simple_async_result_set_op_res_gpointer (data->result, stream, g_object_unref); + } + + g_simple_async_result_complete (data->result); + + g_object_unref (data->result); + g_free (data); +} + +static void +load_async_cb (DBusMessage *reply, + DBusConnection *connection, + GSimpleAsyncResult *result, + GCancellable *cancellable, + gpointer callback_data) +{ + guint32 fd_id; + dbus_bool_t can_seek; + GetFDData *get_fd_data; + + if (!dbus_message_get_args (reply, NULL, + DBUS_TYPE_UINT32, &fd_id, + DBUS_TYPE_BOOLEAN, &can_seek, + DBUS_TYPE_INVALID)) + { + g_simple_async_result_set_error (result, + G_IO_ERROR, G_IO_ERROR_FAILED, + _("Invalid return value from open")); + g_simple_async_result_complete (result); + return; + } + + get_fd_data = g_new0 (GetFDData, 1); + get_fd_data->result = g_object_ref (result); + get_fd_data->can_seek = can_seek; + + _g_dbus_connection_get_fd_async (connection, fd_id, + load_async_get_fd_cb, get_fd_data); +} + +static void +g_vfs_icon_load_async (GLoadableIcon *icon, + int size, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + do_async_path_call (G_VFS_ICON (icon), + G_VFS_DBUS_MOUNT_OP_OPEN_ICON_FOR_READ, + cancellable, + callback, user_data, + load_async_cb, NULL, NULL, + 0); +} + +static GInputStream * +g_vfs_icon_load_finish (GLoadableIcon *icon, + GAsyncResult *res, + char **type, + GError **error) +{ + GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res); + gpointer op; + + op = g_simple_async_result_get_op_res_gpointer (simple); + if (op) + return g_object_ref (op); + + return NULL; +} + + +static void +g_vfs_icon_loadable_icon_iface_init (GLoadableIconIface *iface) +{ + iface->load = g_vfs_icon_load; + iface->load_async = g_vfs_icon_load_async; + iface->load_finish = g_vfs_icon_load_finish; +} + +void +_g_vfs_icon_add_loadable_interface (void) +{ + static const GInterfaceInfo g_implement_interface_info = { + (GInterfaceInitFunc) g_vfs_icon_loadable_icon_iface_init + }; + + g_type_add_interface_static (G_VFS_TYPE_ICON, G_TYPE_LOADABLE_ICON, &g_implement_interface_info); +} diff --git a/client/gvfsiconloadable.h b/client/gvfsiconloadable.h new file mode 100644 index 00000000..bda7485a --- /dev/null +++ b/client/gvfsiconloadable.h @@ -0,0 +1,35 @@ +/* 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 <davidz@redhat.com> + */ + +#ifndef __G_VFS_ICON_LOADABLE_H__ +#define __G_VFS_ICON_LOADABLE_H__ + +#include <gio/gio.h> +#include <gmountspec.h> + +G_BEGIN_DECLS + +void _g_vfs_icon_add_loadable_interface (void); + +G_END_DECLS + +#endif /* __G_VFS_ICON_LOADABLE_H__ */ 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 <davidz@redhat.com> + */ + +#include <config.h> +#include <string.h> +#include <glib/gi18n-lib.h> + +#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 <davidz@redhat.com> + */ + +#ifndef __G_VFS_ICON_H__ +#define __G_VFS_ICON_H__ + +#include <gio/gio.h> +#include <gmountspec.h> + +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__ */ diff --git a/daemon/Makefile.am b/daemon/Makefile.am index 57e03080..653018b8 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -120,6 +120,7 @@ libdaemon_la_SOURCES = \ gvfsjobmountmountable.c gvfsjobmountmountable.h \ gvfsjobunmountmountable.c gvfsjobunmountmountable.h \ gvfsjobopenforread.c gvfsjobopenforread.h \ + gvfsjobopeniconforread.c gvfsjobopeniconforread.h \ gvfsjobread.c gvfsjobread.h \ gvfsjobseekread.c gvfsjobseekread.h \ gvfsjobcloseread.c gvfsjobcloseread.h \ diff --git a/daemon/gvfsbackend.c b/daemon/gvfsbackend.c index 4e6e9a53..c0eba0e1 100644 --- a/daemon/gvfsbackend.c +++ b/daemon/gvfsbackend.c @@ -35,6 +35,7 @@ #include "gvfsjobsource.h" #include "gvfsdaemonprotocol.h" #include <gvfsjobopenforread.h> +#include <gvfsjobopeniconforread.h> #include <gvfsjobopenforwrite.h> #include <gvfsjobqueryinfo.h> #include <gvfsjobqueryfsinfo.h> @@ -482,6 +483,10 @@ backend_dbus_handler (DBusConnection *connection, G_VFS_DBUS_MOUNT_OP_OPEN_FOR_READ)) job = g_vfs_job_open_for_read_new (connection, message, backend); else if (dbus_message_is_method_call (message, + G_VFS_DBUS_MOUNT_INTERFACE, + G_VFS_DBUS_MOUNT_OP_OPEN_ICON_FOR_READ)) + job = g_vfs_job_open_icon_for_read_new (connection, message, backend); + else if (dbus_message_is_method_call (message, G_VFS_DBUS_MOUNT_INTERFACE, G_VFS_DBUS_MOUNT_OP_QUERY_INFO)) job = g_vfs_job_query_info_new (connection, message, backend); diff --git a/daemon/gvfsbackend.h b/daemon/gvfsbackend.h index e47f3680..4dcf7409 100644 --- a/daemon/gvfsbackend.h +++ b/daemon/gvfsbackend.h @@ -48,6 +48,7 @@ typedef struct _GVfsJobUnmount GVfsJobUnmount; typedef struct _GVfsJobMountMountable GVfsJobMountMountable; typedef struct _GVfsJobUnmountMountable GVfsJobUnmountMountable; typedef struct _GVfsJobOpenForRead GVfsJobOpenForRead; +typedef struct _GVfsJobOpenIconForRead GVfsJobOpenIconForRead; typedef struct _GVfsJobSeekRead GVfsJobSeekRead; typedef struct _GVfsJobCloseRead GVfsJobCloseRead; typedef struct _GVfsJobRead GVfsJobRead; @@ -138,6 +139,12 @@ struct _GVfsBackendClass gboolean (*try_open_for_read) (GVfsBackend *backend, GVfsJobOpenForRead *job, const char *filename); + void (*open_icon_for_read) (GVfsBackend *backend, + GVfsJobOpenIconForRead *job, + const char *icon_id); + gboolean (*try_open_icon_for_read) (GVfsBackend *backend, + GVfsJobOpenIconForRead *job, + const char *icon_id); void (*close_read) (GVfsBackend *backend, GVfsJobCloseRead *job, GVfsBackendHandle handle); diff --git a/daemon/gvfsbackendgphoto2.c b/daemon/gvfsbackendgphoto2.c index 259ad920..d21d49dc 100644 --- a/daemon/gvfsbackendgphoto2.c +++ b/daemon/gvfsbackendgphoto2.c @@ -41,6 +41,7 @@ #include "gvfsbackendgphoto2.h" #include "gvfsjobopenforread.h" +#include "gvfsjobopeniconforread.h" #include "gvfsjobread.h" #include "gvfsjobseekread.h" #include "gvfsjobqueryinfo.h" @@ -52,6 +53,7 @@ #include "gvfsjobcreatemonitor.h" #include "gvfsmonitor.h" #include "gvfsjobseekwrite.h" +#include "gvfsicon.h" /* showing debug traces */ #if 0 @@ -1132,6 +1134,25 @@ file_get_info (GVfsBackendGphoto2 *gphoto2_backend, mime_type = g_strdup ("application/octet-stream"); g_file_info_set_content_type (info, mime_type); + /* assume that all JPG files, and only all JPG files, has a preview file */ + if (strcmp (mime_type, "image/jpg") == 0 || + strcmp (mime_type, "image/jpeg") == 0) + { + char *icon_id; + GIcon *icon; + GMountSpec *mount_spec; + + mount_spec = g_vfs_backend_get_mount_spec (G_VFS_BACKEND (gphoto2_backend)); + icon_id = g_strdup_printf ("preview:%s/%s", dir + strlen (gphoto2_backend->ignore_prefix), name); + icon = g_vfs_icon_new (mount_spec, + icon_id); + g_file_info_set_attribute_object (info, + G_FILE_ATTRIBUTE_PREVIEW_ICON, + G_OBJECT (icon)); + g_object_unref (icon); + g_free (icon_id); + } + icon = g_content_type_get_icon (mime_type); DEBUG (" got icon %p for mime_type '%s'", icon, mime_type); if (icon != NULL) @@ -1141,7 +1162,6 @@ file_get_info (GVfsBackendGphoto2 *gphoto2_backend, } g_free (mime_type); - if (gp_info.file.fields & GP_FILE_INFO_MTIME) mtime.tv_sec = gp_info.file.mtime; else @@ -1677,9 +1697,10 @@ free_read_handle (ReadHandle *read_handle) } static void -do_open_for_read (GVfsBackend *backend, - GVfsJobOpenForRead *job, - const char *filename) +do_open_for_read_real (GVfsBackend *backend, + GVfsJobOpenForRead *job, + const char *filename, + gboolean get_preview) { int rc; GError *error; @@ -1688,8 +1709,6 @@ do_open_for_read (GVfsBackend *backend, char *dir; char *name; - DEBUG ("open_for_read (%s)", filename); - ensure_not_dirty (gphoto2_backend); split_filename_with_ignore_prefix (gphoto2_backend, filename, &dir, &name); @@ -1724,7 +1743,7 @@ do_open_for_read (GVfsBackend *backend, rc = gp_camera_file_get (gphoto2_backend->camera, dir, name, - GP_FILE_TYPE_NORMAL, + get_preview ? GP_FILE_TYPE_PREVIEW : GP_FILE_TYPE_NORMAL, read_handle->file, gphoto2_backend->context); if (rc != 0) @@ -1763,6 +1782,44 @@ do_open_for_read (GVfsBackend *backend, g_free (dir); } + +static void +do_open_for_read (GVfsBackend *backend, + GVfsJobOpenForRead *job, + const char *filename) +{ + DEBUG ("open_for_read (%s)", filename); + + do_open_for_read_real (backend, + job, + filename, + FALSE); +} + +static void +do_open_icon_for_read (GVfsBackend *backend, + GVfsJobOpenIconForRead *job, + const char *icon_id) +{ + DEBUG ("open_icon_for_read (%s)", icon_id); + + if (g_str_has_prefix (icon_id, "preview:")) + { + do_open_for_read_real (backend, + G_VFS_JOB_OPEN_FOR_READ (job), + icon_id + sizeof ("preview:") - 1, + TRUE); + } + else + { + g_vfs_job_failed (G_VFS_JOB (job), + G_IO_ERROR, + G_IO_ERROR_INVALID_ARGUMENT, + _("Malformed icon identifier '%s'"), + icon_id); + } +} + /* ------------------------------------------------------------------------------------------------- */ static gboolean @@ -3373,6 +3430,7 @@ g_vfs_backend_gphoto2_class_init (GVfsBackendGphoto2Class *klass) backend_class->try_mount = try_mount; backend_class->mount = do_mount; backend_class->unmount = do_unmount; + backend_class->open_icon_for_read = do_open_icon_for_read; backend_class->open_for_read = do_open_for_read; backend_class->try_read = try_read; backend_class->try_seek_on_read = try_seek_on_read; diff --git a/daemon/gvfsjobopeniconforread.c b/daemon/gvfsjobopeniconforread.c new file mode 100644 index 00000000..87936765 --- /dev/null +++ b/daemon/gvfsjobopeniconforread.c @@ -0,0 +1,142 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2006-2007 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: Alexander Larsson <alexl@redhat.com> + */ + +#include <config.h> + +#include <unistd.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> + +#include <glib.h> +#include <dbus/dbus.h> +#include <glib/gi18n.h> +#include "gvfsreadchannel.h" +#include "gvfsjobopeniconforread.h" +#include "gdbusutils.h" +#include "gvfsdaemonutils.h" + +G_DEFINE_TYPE (GVfsJobOpenIconForRead, g_vfs_job_open_icon_for_read, G_VFS_TYPE_JOB_OPEN_FOR_READ) + +static void run (GVfsJob *job); +static gboolean try (GVfsJob *job); + +static void +g_vfs_job_open_icon_for_read_finalize (GObject *object) +{ + GVfsJobOpenIconForRead *job; + + job = G_VFS_JOB_OPEN_ICON_FOR_READ (object); + + if (G_OBJECT_CLASS (g_vfs_job_open_icon_for_read_parent_class)->finalize) + (*G_OBJECT_CLASS (g_vfs_job_open_icon_for_read_parent_class)->finalize) (object); +} + +static void +g_vfs_job_open_icon_for_read_class_init (GVfsJobOpenIconForReadClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GVfsJobClass *job_class = G_VFS_JOB_CLASS (klass); + + gobject_class->finalize = g_vfs_job_open_icon_for_read_finalize; + job_class->run = run; + job_class->try = try; +} + +static void +g_vfs_job_open_icon_for_read_init (GVfsJobOpenIconForRead *job) +{ +} + +GVfsJob * +g_vfs_job_open_icon_for_read_new (DBusConnection *connection, + DBusMessage *message, + GVfsBackend *backend) +{ + GVfsJobOpenIconForRead *job; + GVfsJobOpenForRead *job_open_for_read; + DBusMessage *reply; + DBusError derror; + int path_len; + const char *path_data; + + dbus_error_init (&derror); + if (!dbus_message_get_args (message, &derror, + DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, + &path_data, &path_len, + 0)) + { + reply = dbus_message_new_error (message, + derror.name, + derror.message); + dbus_error_free (&derror); + + dbus_connection_send (connection, reply, NULL); + return NULL; + } + + job = g_object_new (G_VFS_TYPE_JOB_OPEN_ICON_FOR_READ, + "message", message, + "connection", connection, + NULL); + + job_open_for_read = G_VFS_JOB_OPEN_FOR_READ (job); + + job->icon_id = g_strndup (path_data, path_len); + job_open_for_read->backend = backend; + + return G_VFS_JOB (job); +} + +static void +run (GVfsJob *job) +{ + GVfsJobOpenIconForRead *op_job = G_VFS_JOB_OPEN_ICON_FOR_READ (job); + GVfsJobOpenForRead *op_job_open_for_read = G_VFS_JOB_OPEN_FOR_READ (job); + GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job_open_for_read->backend); + + if (class->open_icon_for_read == NULL) + { + g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + _("Operation not supported by backend")); + return; + } + + class->open_icon_for_read (op_job_open_for_read->backend, + op_job, + op_job->icon_id); +} + +static gboolean +try (GVfsJob *job) +{ + GVfsJobOpenIconForRead *op_job = G_VFS_JOB_OPEN_ICON_FOR_READ (job); + GVfsJobOpenForRead *op_job_open_for_read = G_VFS_JOB_OPEN_FOR_READ (job); + GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job_open_for_read->backend); + + if (class->try_open_icon_for_read == NULL) + return FALSE; + + return class->try_open_icon_for_read (op_job_open_for_read->backend, + op_job, + op_job->icon_id); +} diff --git a/daemon/gvfsjobopeniconforread.h b/daemon/gvfsjobopeniconforread.h new file mode 100644 index 00000000..c4ed80e7 --- /dev/null +++ b/daemon/gvfsjobopeniconforread.h @@ -0,0 +1,63 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2006-2007 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: Alexander Larsson <alexl@redhat.com> + */ + +#ifndef __G_VFS_JOB_OPEN_ICON_FOR_READ_H__ +#define __G_VFS_JOB_OPEN_ICON_FOR_READ_H__ + +#include <dbus/dbus.h> +#include <gvfsjobdbus.h> +#include <gvfsbackend.h> +#include <gvfsreadchannel.h> +#include <gvfsjobopenforread.h> + +G_BEGIN_DECLS + +#define G_VFS_TYPE_JOB_OPEN_ICON_FOR_READ (g_vfs_job_open_icon_for_read_get_type ()) +#define G_VFS_JOB_OPEN_ICON_FOR_READ(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_JOB_OPEN_ICON_FOR_READ, GVfsJobOpenIconForRead)) +#define G_VFS_JOB_OPEN_ICON_FOR_READ_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_JOB_OPEN_ICON_FOR_READ, GVfsJobOpenIconForReadClass)) +#define G_VFS_IS_JOB_OPEN_ICON_FOR_READ(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_JOB_OPEN_ICON_FOR_READ)) +#define G_VFS_IS_JOB_OPEN_ICON_FOR_READ_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_JOB_OPEN_ICON_FOR_READ)) +#define G_VFS_JOB_OPEN_ICON_FOR_READ_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_JOB_OPEN_ICON_FOR_READ, GVfsJobOpenIconForReadClass)) + +typedef struct _GVfsJobOpenIconForReadClass GVfsJobOpenIconForReadClass; + +struct _GVfsJobOpenIconForRead +{ + GVfsJobOpenForRead parent_instance; + + char *icon_id; +}; + +struct _GVfsJobOpenIconForReadClass +{ + GVfsJobOpenForReadClass parent_class; +}; + +GType g_vfs_job_open_icon_for_read_get_type (void) G_GNUC_CONST; + +GVfsJob * g_vfs_job_open_icon_for_read_new (DBusConnection *connection, + DBusMessage *message, + GVfsBackend *backend); + +G_END_DECLS + +#endif /* __G_VFS_JOB_OPEN_ICON_FOR_READ_H__ */ |