/* GTK - The GIMP Toolkit
- * gtkfilesystem.c: Abstract file system interfaces
+ * gtkfilesystem.c: Filesystem abstraction functions.
* Copyright (C) 2003, Red Hat, Inc.
+ * Copyright (C) 2007-2008 Carlos Garnacho
*
- * 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 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.
+ * 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.
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Carlos Garnacho <carlos@imendio.com>
*/
-#include <config.h>
-#include <gmodule.h>
+#include "config.h"
+
+#include <string.h>
+
+#include <glib/gi18n-lib.h>
+
+#include "gtkfilechooser.h"
#include "gtkfilesystem.h"
#include "gtkicontheme.h"
-#include "gtkmodules.h"
-#include "gtkintl.h"
-#include "gtkalias.h"
-#include "gtkstock.h"
+#include "gtkprivate.h"
-#include <string.h>
+/* #define DEBUG_MODE */
+#ifdef DEBUG_MODE
+#define DEBUG(x) g_debug (x);
+#else
+#define DEBUG(x)
+#endif
-struct _GtkFileInfo
-{
- GtkFileTime modification_time;
- gint64 size;
- gchar *display_name;
- gchar *display_key;
- gchar *mime_type;
- gchar *icon_name;
- guint is_folder : 1;
- guint is_hidden : 1;
+#define FILES_PER_QUERY 100
+
+/* The pointers we return for a GtkFileSystemVolume are opaque tokens; they are
+ * really pointers to GDrive, GVolume or GMount objects. We need an extra
+ * token for the fake "File System" volume. So, we'll return a pointer to
+ * this particular string.
+ */
+static const gchar *root_volume_token = N_("File System");
+#define IS_ROOT_VOLUME(volume) ((gpointer) (volume) == (gpointer) root_volume_token)
+
+enum {
+ PROP_0,
+ PROP_FILE,
+ PROP_ENUMERATOR,
+ PROP_ATTRIBUTES
};
-static void gtk_file_system_base_init (gpointer g_class);
-static void gtk_file_folder_base_init (gpointer g_class);
+enum {
+ BOOKMARKS_CHANGED,
+ VOLUMES_CHANGED,
+ FS_LAST_SIGNAL
+};
-GQuark
-gtk_file_system_error_quark (void)
-{
- return g_quark_from_static_string ("gtk-file-system-error-quark");
-}
+enum {
+ FILES_ADDED,
+ FILES_REMOVED,
+ FILES_CHANGED,
+ FINISHED_LOADING,
+ DELETED,
+ FOLDER_LAST_SIGNAL
+};
+
+static guint fs_signals [FS_LAST_SIGNAL] = { 0, };
-/*****************************************
- * GtkFileInfo *
- *****************************************/
-GType
-gtk_file_info_get_type (void)
+typedef struct AsyncFuncData AsyncFuncData;
+
+struct GtkFileSystemPrivate
{
- static GType our_type = 0;
-
- if (our_type == 0)
- our_type = g_boxed_type_register_static (I_("GtkFileInfo"),
- (GBoxedCopyFunc) gtk_file_info_copy,
- (GBoxedFreeFunc) gtk_file_info_free);
+ GVolumeMonitor *volume_monitor;
- return our_type;
-}
+ /* This list contains elements that can be
+ * of type GDrive, GVolume and GMount
+ */
+ GSList *volumes;
+
+ /* This list contains GtkFileSystemBookmark structs */
+ GSList *bookmarks;
-GtkFileInfo *
-gtk_file_info_new (void)
+ GFileMonitor *bookmarks_monitor;
+};
+
+struct AsyncFuncData
{
- GtkFileInfo *info;
-
- info = g_new0 (GtkFileInfo, 1);
+ GtkFileSystem *file_system;
+ GFile *file;
+ GCancellable *cancellable;
+ gchar *attributes;
- return info;
-}
+ gpointer callback;
+ gpointer data;
+};
-GtkFileInfo *
-gtk_file_info_copy (GtkFileInfo *info)
+struct GtkFileSystemBookmark
{
- GtkFileInfo *new_info;
-
- g_return_val_if_fail (info != NULL, NULL);
-
- new_info = g_memdup (info, sizeof (GtkFileInfo));
- if (new_info->display_name)
- new_info->display_name = g_strdup (new_info->display_name);
- if (new_info->display_key)
- new_info->display_key = g_strdup (new_info->display_key);
- if (new_info->mime_type)
- new_info->mime_type = g_strdup (new_info->mime_type);
- if (new_info->icon_name)
- new_info->icon_name = g_strdup (new_info->icon_name);
- if (new_info->display_key)
- new_info->display_key = g_strdup (new_info->display_key);
-
- return new_info;
-}
+ GFile *file;
+ gchar *label;
+};
+G_DEFINE_TYPE (GtkFileSystem, _gtk_file_system, G_TYPE_OBJECT)
+
+
+/* GtkFileSystemBookmark methods */
void
-gtk_file_info_free (GtkFileInfo *info)
+_gtk_file_system_bookmark_free (GtkFileSystemBookmark *bookmark)
{
- g_return_if_fail (info != NULL);
-
- if (info->display_name)
- g_free (info->display_name);
- if (info->mime_type)
- g_free (info->mime_type);
- if (info->display_key)
- g_free (info->display_key);
- if (info->icon_name)
- g_free (info->icon_name);
-
- g_free (info);
+ g_object_unref (bookmark->file);
+ g_free (bookmark->label);
+ g_slice_free (GtkFileSystemBookmark, bookmark);
}
-G_CONST_RETURN gchar *
-gtk_file_info_get_display_name (const GtkFileInfo *info)
+/* GtkFileSystem methods */
+static void
+volumes_changed (GVolumeMonitor *volume_monitor,
+ gpointer volume,
+ gpointer user_data)
{
- g_return_val_if_fail (info != NULL, NULL);
-
- return info->display_name;
-}
+ GtkFileSystem *file_system;
-/**
- * gtk_file_info_get_display_key:
- * @info: a #GtkFileInfo
- *
- * Returns for the collation key for the display name for @info.
- * This is useful when sorting a bunch of #GtkFileInfo structures
- * since the collate key will be only computed once.
- *
- * Return value: The collate key for the display name, or %NULL
- * if the display name hasn't been set.
- **/
-G_CONST_RETURN gchar *
-gtk_file_info_get_display_key (const GtkFileInfo *info)
-{
- g_return_val_if_fail (info != NULL, NULL);
+ gdk_threads_enter ();
- if (!info->display_key && info->display_name)
- {
- /* Since info->display_key is only a cache, we cast off the const
- */
- ((GtkFileInfo *)info)->display_key = g_utf8_collate_key_for_filename (info->display_name, -1);
- }
-
- return info->display_key;
+ file_system = GTK_FILE_SYSTEM (user_data);
+ g_signal_emit (file_system, fs_signals[VOLUMES_CHANGED], 0, volume);
+ gdk_threads_leave ();
}
-void
-gtk_file_info_set_display_name (GtkFileInfo *info,
- const gchar *display_name)
+static void
+gtk_file_system_dispose (GObject *object)
{
- g_return_if_fail (info != NULL);
+ GtkFileSystem *file_system = GTK_FILE_SYSTEM (object);
+ GtkFileSystemPrivate *priv = file_system->priv;
- if (display_name == info->display_name)
- return;
+ DEBUG ("dispose");
- if (info->display_name)
- g_free (info->display_name);
- if (info->display_key)
+ if (priv->volumes)
{
- g_free (info->display_key);
- info->display_key = NULL;
+ g_slist_foreach (priv->volumes, (GFunc) g_object_unref, NULL);
+ g_slist_free (priv->volumes);
+ priv->volumes = NULL;
}
- info->display_name = g_strdup (display_name);
-}
+ if (priv->volume_monitor)
+ {
+ g_signal_handlers_disconnect_by_func (priv->volume_monitor, volumes_changed, object);
+ g_object_unref (priv->volume_monitor);
+ priv->volume_monitor = NULL;
+ }
-gboolean
-gtk_file_info_get_is_folder (const GtkFileInfo *info)
-{
- g_return_val_if_fail (info != NULL, FALSE);
-
- return info->is_folder;
+ G_OBJECT_CLASS (_gtk_file_system_parent_class)->dispose (object);
}
-void
-gtk_file_info_set_is_folder (GtkFileInfo *info,
- gboolean is_folder)
+static void
+gtk_file_system_finalize (GObject *object)
{
- g_return_if_fail (info != NULL);
+ GtkFileSystem *file_system = GTK_FILE_SYSTEM (object);
+ GtkFileSystemPrivate *priv = file_system->priv;
- info->is_folder = is_folder != FALSE;
-}
+ DEBUG ("finalize");
-gboolean
-gtk_file_info_get_is_hidden (const GtkFileInfo *info)
-{
- g_return_val_if_fail (info != NULL, FALSE);
-
- return info->is_hidden;
-}
+ if (priv->bookmarks_monitor)
+ g_object_unref (priv->bookmarks_monitor);
-void
-gtk_file_info_set_is_hidden (GtkFileInfo *info,
- gboolean is_hidden)
-{
- g_return_if_fail (info != NULL);
+ if (priv->bookmarks)
+ {
+ g_slist_foreach (priv->bookmarks, (GFunc) _gtk_file_system_bookmark_free, NULL);
+ g_slist_free (priv->bookmarks);
+ }
- info->is_hidden = is_hidden != FALSE;
+ G_OBJECT_CLASS (_gtk_file_system_parent_class)->finalize (object);
}
-G_CONST_RETURN gchar *
-gtk_file_info_get_mime_type (const GtkFileInfo *info)
+static void
+_gtk_file_system_class_init (GtkFileSystemClass *class)
{
- g_return_val_if_fail (info != NULL, NULL);
-
- return info->mime_type;
-}
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
-void
-gtk_file_info_set_mime_type (GtkFileInfo *info,
- const gchar *mime_type)
-{
- g_return_if_fail (info != NULL);
-
- if (info->mime_type)
- g_free (info->mime_type);
+ object_class->dispose = gtk_file_system_dispose;
+ object_class->finalize = gtk_file_system_finalize;
- info->mime_type = g_strdup (mime_type);
-}
+ fs_signals[BOOKMARKS_CHANGED] =
+ g_signal_new ("bookmarks-changed",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkFileSystemClass, bookmarks_changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
-GtkFileTime
-gtk_file_info_get_modification_time (const GtkFileInfo *info)
-{
- g_return_val_if_fail (info != NULL, 0);
+ fs_signals[VOLUMES_CHANGED] =
+ g_signal_new ("volumes-changed",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkFileSystemClass, volumes_changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
- return info->modification_time;
+ g_type_class_add_private (object_class, sizeof (GtkFileSystemPrivate));
}
-void
-gtk_file_info_set_modification_time (GtkFileInfo *info,
- GtkFileTime modification_time)
+static GFile *
+get_legacy_bookmarks_file (void)
{
- g_return_if_fail (info != NULL);
-
- info->modification_time = modification_time;
-}
+ GFile *file;
+ gchar *filename;
-gint64
-gtk_file_info_get_size (const GtkFileInfo *info)
-{
- g_return_val_if_fail (info != NULL, 0);
-
- return info->size;
-}
+ filename = g_build_filename (g_get_home_dir (), ".gtk-bookmarks", NULL);
+ file = g_file_new_for_path (filename);
+ g_free (filename);
-void
-gtk_file_info_set_size (GtkFileInfo *info,
- gint64 size)
-{
- g_return_if_fail (info != NULL);
- g_return_if_fail (size >= 0);
-
- info->size = size;
+ return file;
}
-void
-gtk_file_info_set_icon_name (GtkFileInfo *info,
- const gchar *icon_name)
+static GFile *
+get_bookmarks_file (void)
{
- g_return_if_fail (info != NULL);
-
- if (info->icon_name)
- g_free (info->icon_name);
+ GFile *file;
+ gchar *filename;
- info->icon_name = g_strdup (icon_name);
-}
+ filename = g_build_filename (g_get_user_config_dir (), "gtk-3.0", "bookmarks", NULL);
+ file = g_file_new_for_path (filename);
+ g_free (filename);
-G_CONST_RETURN gchar *
-gtk_file_info_get_icon_name (const GtkFileInfo *info)
-{
- g_return_val_if_fail (info != NULL, NULL);
-
- return info->icon_name;
+ return file;
}
-GdkPixbuf *
-gtk_file_info_render_icon (const GtkFileInfo *info,
- GtkWidget *widget,
- gint pixel_size,
- GError **error)
+static GSList *
+read_bookmarks (GFile *file)
{
- GdkPixbuf *pixbuf = NULL;
+ gchar *contents;
+ gchar **lines, *space;
+ GSList *bookmarks = NULL;
+ gint i;
+
+ if (!g_file_load_contents (file, NULL, &contents,
+ NULL, NULL, NULL))
+ return NULL;
- g_return_val_if_fail (info != NULL, NULL);
- g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
+ lines = g_strsplit (contents, "\n", -1);
- if (info->icon_name)
+ for (i = 0; lines[i]; i++)
{
- if (g_path_is_absolute (info->icon_name))
- pixbuf = gdk_pixbuf_new_from_file_at_size (info->icon_name,
- pixel_size,
- pixel_size,
- NULL);
- else
- {
- GtkIconTheme *icon_theme;
+ GtkFileSystemBookmark *bookmark;
- icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
- if (gtk_icon_theme_has_icon (icon_theme, info->icon_name))
- pixbuf = gtk_icon_theme_load_icon (icon_theme, info->icon_name,
- pixel_size, 0, NULL);
- }
- }
+ if (!*lines[i])
+ continue;
- if (!pixbuf)
- {
- /* load a fallback icon */
- pixbuf = gtk_widget_render_icon (widget,
- gtk_file_info_get_is_folder (info)
- ? GTK_STOCK_DIRECTORY : GTK_STOCK_FILE,
- GTK_ICON_SIZE_SMALL_TOOLBAR,
- NULL);
- if (!pixbuf && error)
- g_set_error (error,
- GTK_FILE_SYSTEM_ERROR,
- GTK_FILE_SYSTEM_ERROR_FAILED,
- _("Could not get a stock icon for %s\n"),
- info->icon_name);
- }
+ if (!g_utf8_validate (lines[i], -1, NULL))
+ continue;
- return pixbuf;
-}
+ bookmark = g_slice_new0 (GtkFileSystemBookmark);
-/*****************************************
- * GtkFileSystemHandle *
- *****************************************/
+ if ((space = strchr (lines[i], ' ')) != NULL)
+ {
+ space[0] = '\0';
+ bookmark->label = g_strdup (space + 1);
+ }
-enum
-{
- PROP_0,
- PROP_CANCELLED
-};
+ bookmark->file = g_file_new_for_uri (lines[i]);
+ bookmarks = g_slist_prepend (bookmarks, bookmark);
+ }
-G_DEFINE_TYPE (GtkFileSystemHandle, gtk_file_system_handle, G_TYPE_OBJECT)
+ bookmarks = g_slist_reverse (bookmarks);
+ g_strfreev (lines);
+ g_free (contents);
-static void
-gtk_file_system_handle_init (GtkFileSystemHandle *handle)
-{
- handle->file_system = NULL;
- handle->cancelled = FALSE;
+ return bookmarks;
}
static void
-gtk_file_system_handle_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
+save_bookmarks (GFile *bookmarks_file,
+ GSList *bookmarks)
{
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-}
+ GError *error = NULL;
+ GString *contents;
+ GSList *l;
+ GFile *parent_file;
+ gchar *path;
-static void
-gtk_file_system_handle_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GtkFileSystemHandle *handle = GTK_FILE_SYSTEM_HANDLE (object);
+ contents = g_string_new ("");
- switch (prop_id)
+ for (l = bookmarks; l; l = l->next)
{
- case PROP_CANCELLED:
- g_value_set_boolean (value, handle->cancelled);
- break;
+ GtkFileSystemBookmark *bookmark = l->data;
+ gchar *uri;
+
+ uri = g_file_get_uri (bookmark->file);
+ if (!uri)
+ continue;
+
+ g_string_append (contents, uri);
+
+ if (bookmark->label)
+ g_string_append_printf (contents, " %s", bookmark->label);
+
+ g_string_append_c (contents, '\n');
+ g_free (uri);
+ }
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
+ parent_file = g_file_get_parent (bookmarks_file);
+ path = g_file_get_path (parent_file);
+ if (g_mkdir_with_parents (path, 0700) == 0)
+ {
+ if (!g_file_replace_contents (bookmarks_file,
+ contents->str,
+ strlen (contents->str),
+ NULL, FALSE, 0, NULL,
+ NULL, &error))
+ {
+ g_critical ("%s", error->message);
+ g_error_free (error);
+ }
}
+ g_free (path);
+ g_object_unref (parent_file);
+ g_string_free (contents, TRUE);
}
static void
-gtk_file_system_handle_class_init (GtkFileSystemHandleClass *klass)
+bookmarks_file_changed (GFileMonitor *monitor,
+ GFile *file,
+ GFile *other_file,
+ GFileMonitorEvent event,
+ gpointer data)
{
- GObjectClass *o_class;
-
- o_class = (GObjectClass *)klass;
- o_class->set_property = gtk_file_system_handle_set_property;
- o_class->get_property = gtk_file_system_handle_get_property;
-
- g_object_class_install_property (o_class,
- PROP_CANCELLED,
- g_param_spec_boolean ("cancelled",
- P_("Cancelled"),
- P_("Whether or not the operation has been successfully cancelled"),
- FALSE,
- G_PARAM_READABLE));
+ GtkFileSystem *file_system = GTK_FILE_SYSTEM (data);
+ GtkFileSystemPrivate *priv = file_system->priv;
+
+ switch (event)
+ {
+ case G_FILE_MONITOR_EVENT_CHANGED:
+ case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
+ case G_FILE_MONITOR_EVENT_CREATED:
+ case G_FILE_MONITOR_EVENT_DELETED:
+ g_slist_foreach (priv->bookmarks, (GFunc) _gtk_file_system_bookmark_free, NULL);
+ g_slist_free (priv->bookmarks);
+
+ priv->bookmarks = read_bookmarks (file);
+
+ gdk_threads_enter ();
+ g_signal_emit (data, fs_signals[BOOKMARKS_CHANGED], 0);
+ gdk_threads_leave ();
+ break;
+ default:
+ /* ignore at the moment */
+ break;
+ }
}
-/*****************************************
- * GtkFileSystem *
- *****************************************/
-GType
-gtk_file_system_get_type (void)
+static gboolean
+mount_referenced_by_volume_activation_root (GList *volumes, GMount *mount)
{
- static GType file_system_type = 0;
+ GList *l;
+ GFile *mount_root;
+ gboolean ret;
+
+ ret = FALSE;
- if (!file_system_type)
+ mount_root = g_mount_get_root (mount);
+
+ for (l = volumes; l != NULL; l = l->next)
{
- static const GTypeInfo file_system_info =
- {
- sizeof (GtkFileSystemIface), /* class_size */
- gtk_file_system_base_init, /* base_init */
- NULL, /* base_finalize */
- };
-
- file_system_type = g_type_register_static (G_TYPE_INTERFACE,
- I_("GtkFileSystem"),
- &file_system_info, 0);
-
- g_type_interface_add_prerequisite (file_system_type, G_TYPE_OBJECT);
+ GVolume *volume = G_VOLUME (l->data);
+ GFile *volume_activation_root;
+
+ volume_activation_root = g_volume_get_activation_root (volume);
+ if (volume_activation_root != NULL)
+ {
+ if (g_file_has_prefix (volume_activation_root, mount_root))
+ {
+ ret = TRUE;
+ g_object_unref (volume_activation_root);
+ break;
+ }
+ g_object_unref (volume_activation_root);
+ }
}
- return file_system_type;
+ g_object_unref (mount_root);
+ return ret;
}
static void
-gtk_file_system_base_init (gpointer g_class)
-{
- static gboolean initialized = FALSE;
+get_volumes_list (GtkFileSystem *file_system)
+{
+ GtkFileSystemPrivate *priv = file_system->priv;
+ GList *l, *ll;
+ GList *drives;
+ GList *volumes;
+ GList *mounts;
+ GDrive *drive;
+ GVolume *volume;
+ GMount *mount;
+
+ if (priv->volumes)
+ {
+ g_slist_foreach (priv->volumes, (GFunc) g_object_unref, NULL);
+ g_slist_free (priv->volumes);
+ priv->volumes = NULL;
+ }
+
+ /* first go through all connected drives */
+ drives = g_volume_monitor_get_connected_drives (priv->volume_monitor);
+
+ for (l = drives; l != NULL; l = l->next)
+ {
+ drive = l->data;
+ volumes = g_drive_get_volumes (drive);
+
+ if (volumes)
+ {
+ for (ll = volumes; ll != NULL; ll = ll->next)
+ {
+ volume = ll->data;
+ mount = g_volume_get_mount (volume);
+
+ if (mount)
+ {
+ /* Show mounted volume */
+ priv->volumes = g_slist_prepend (priv->volumes, g_object_ref (mount));
+ g_object_unref (mount);
+ }
+ else
+ {
+ /* Do show the unmounted volumes in the sidebar;
+ * this is so the user can mount it (in case automounting
+ * is off).
+ *
+ * Also, even if automounting is enabled, this gives a visual
+ * cue that the user should remember to yank out the media if
+ * he just unmounted it.
+ */
+ priv->volumes = g_slist_prepend (priv->volumes, g_object_ref (volume));
+ }
+
+ g_object_unref (volume);
+ }
- if (!initialized)
+ g_list_free (volumes);
+ }
+ else if (g_drive_is_media_removable (drive) && !g_drive_is_media_check_automatic (drive))
+ {
+ /* If the drive has no mountable volumes and we cannot detect media change.. we
+ * display the drive in the sidebar so the user can manually poll the drive by
+ * right clicking and selecting "Rescan..."
+ *
+ * This is mainly for drives like floppies where media detection doesn't
+ * work.. but it's also for human beings who like to turn off media detection
+ * in the OS to save battery juice.
+ */
+
+ priv->volumes = g_slist_prepend (priv->volumes, g_object_ref (drive));
+ }
+
+ g_object_unref (drive);
+ }
+
+ g_list_free (drives);
+
+ /* add all volumes that is not associated with a drive */
+ volumes = g_volume_monitor_get_volumes (priv->volume_monitor);
+
+ for (l = volumes; l != NULL; l = l->next)
{
- GType iface_type = G_TYPE_FROM_INTERFACE (g_class);
-
- g_signal_new (I_("volumes-changed"),
- iface_type,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GtkFileSystemIface, volumes_changed),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
- g_signal_new (I_("bookmarks-changed"),
- iface_type,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GtkFileSystemIface, bookmarks_changed),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
- initialized = TRUE;
+ volume = l->data;
+ drive = g_volume_get_drive (volume);
+
+ if (drive)
+ {
+ g_object_unref (drive);
+ continue;
+ }
+
+ mount = g_volume_get_mount (volume);
+
+ if (mount)
+ {
+ /* show this mount */
+ priv->volumes = g_slist_prepend (priv->volumes, g_object_ref (mount));
+ g_object_unref (mount);
+ }
+ else
+ {
+ /* see comment above in why we add an icon for a volume */
+ priv->volumes = g_slist_prepend (priv->volumes, g_object_ref (volume));
+ }
+
+ g_object_unref (volume);
}
-}
-GSList *
-gtk_file_system_list_volumes (GtkFileSystem *file_system)
-{
- g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
+ /* add mounts that has no volume (/etc/mtab mounts, ftp, sftp,...) */
+ mounts = g_volume_monitor_get_mounts (priv->volume_monitor);
- return GTK_FILE_SYSTEM_GET_IFACE (file_system)->list_volumes (file_system);
-}
+ for (l = mounts; l != NULL; l = l->next)
+ {
+ mount = l->data;
+ volume = g_mount_get_volume (mount);
-GtkFileSystemHandle *
-gtk_file_system_get_folder (GtkFileSystem *file_system,
- const GtkFilePath *path,
- GtkFileInfoType types,
- GtkFileSystemGetFolderCallback callback,
- gpointer data)
-{
- g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
- g_return_val_if_fail (path != NULL, NULL);
- g_return_val_if_fail (callback != NULL, NULL);
+ if (volume)
+ {
+ g_object_unref (volume);
+ continue;
+ }
- return GTK_FILE_SYSTEM_GET_IFACE (file_system)->get_folder (file_system, path, types, callback, data);
-}
+ /* if there's exists one or more volumes with an activation root inside the mount,
+ * don't display the mount
+ */
+ if (mount_referenced_by_volume_activation_root (volumes, mount))
+ {
+ g_object_unref (mount);
+ continue;
+ }
-GtkFileSystemHandle *
-gtk_file_system_get_info (GtkFileSystem *file_system,
- const GtkFilePath *path,
- GtkFileInfoType types,
- GtkFileSystemGetInfoCallback callback,
- gpointer data)
-{
- g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
- g_return_val_if_fail (path != NULL, NULL);
- g_return_val_if_fail (callback != NULL, NULL);
+ /* show this mount */
+ priv->volumes = g_slist_prepend (priv->volumes, g_object_ref (mount));
+ g_object_unref (mount);
+ }
- return GTK_FILE_SYSTEM_GET_IFACE (file_system)->get_info (file_system, path, types, callback, data);
+ g_list_free (volumes);
+
+ g_list_free (mounts);
}
-GtkFileSystemHandle *
-gtk_file_system_create_folder (GtkFileSystem *file_system,
- const GtkFilePath *path,
- GtkFileSystemCreateFolderCallback callback,
- gpointer data)
-{
- g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
- g_return_val_if_fail (path != NULL, NULL);
- g_return_val_if_fail (callback != NULL, NULL);
+static void
+_gtk_file_system_init (GtkFileSystem *file_system)
+{
+ GtkFileSystemPrivate *priv;
+ GFile *bookmarks_file;
+ GError *error = NULL;
+
+ DEBUG ("init");
+
+ file_system->priv = G_TYPE_INSTANCE_GET_PRIVATE (file_system,
+ GTK_TYPE_FILE_SYSTEM,
+ GtkFileSystemPrivate);
+ priv = file_system->priv;
+
+ /* Volumes */
+ priv->volume_monitor = g_volume_monitor_get ();
+
+ g_signal_connect (priv->volume_monitor, "mount-added",
+ G_CALLBACK (volumes_changed), file_system);
+ g_signal_connect (priv->volume_monitor, "mount-removed",
+ G_CALLBACK (volumes_changed), file_system);
+ g_signal_connect (priv->volume_monitor, "mount-changed",
+ G_CALLBACK (volumes_changed), file_system);
+ g_signal_connect (priv->volume_monitor, "volume-added",
+ G_CALLBACK (volumes_changed), file_system);
+ g_signal_connect (priv->volume_monitor, "volume-removed",
+ G_CALLBACK (volumes_changed), file_system);
+ g_signal_connect (priv->volume_monitor, "volume-changed",
+ G_CALLBACK (volumes_changed), file_system);
+ g_signal_connect (priv->volume_monitor, "drive-connected",
+ G_CALLBACK (volumes_changed), file_system);
+ g_signal_connect (priv->volume_monitor, "drive-disconnected",
+ G_CALLBACK (volumes_changed), file_system);
+ g_signal_connect (priv->volume_monitor, "drive-changed",
+ G_CALLBACK (volumes_changed), file_system);
+
+ /* Bookmarks */
+ bookmarks_file = get_bookmarks_file ();
+ priv->bookmarks = read_bookmarks (bookmarks_file);
+ if (!priv->bookmarks)
+ {
+ GFile *legacy_bookmarks_file;
- return GTK_FILE_SYSTEM_GET_IFACE (file_system)->create_folder (file_system, path, callback, data);
-}
+ /* Read the legacy one and write it to the new one */
+ legacy_bookmarks_file = get_legacy_bookmarks_file ();
+ priv->bookmarks = read_bookmarks (legacy_bookmarks_file);
+ save_bookmarks (bookmarks_file, priv->bookmarks);
-void
-gtk_file_system_cancel_operation (GtkFileSystemHandle *handle)
-{
- g_return_if_fail (GTK_IS_FILE_SYSTEM_HANDLE (handle));
+ g_object_unref (legacy_bookmarks_file);
+ }
+
+ priv->bookmarks_monitor = g_file_monitor_file (bookmarks_file,
+ G_FILE_MONITOR_NONE,
+ NULL, &error);
+ if (error)
+ {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ }
+ else
+ g_signal_connect (priv->bookmarks_monitor, "changed",
+ G_CALLBACK (bookmarks_file_changed), file_system);
- GTK_FILE_SYSTEM_GET_IFACE (handle->file_system)->cancel_operation (handle);
+ g_object_unref (bookmarks_file);
}
-/**
- * gtk_file_system_get_volume_for_path:
- * @file_system: a #GtkFileSystem
- * @path: a #GtkFilePath
- *
- * Queries the file system volume that corresponds to a specific path.
- * There might not be a volume for all paths (consinder for instance remote
- * shared), so this can return NULL.
- *
- * Return value: the #GtkFileSystemVolume that corresponds to the specified
- * @path, or NULL if there is no such volume. You should free this value with
- * gtk_file_system_volume_free().
- **/
-GtkFileSystemVolume *
-gtk_file_system_get_volume_for_path (GtkFileSystem *file_system,
- const GtkFilePath *path)
+/* GtkFileSystem public methods */
+GtkFileSystem *
+_gtk_file_system_new (void)
{
- g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
- g_return_val_if_fail (path != NULL, NULL);
-
- return GTK_FILE_SYSTEM_GET_IFACE (file_system)->get_volume_for_path (file_system, path);
+ return g_object_new (GTK_TYPE_FILE_SYSTEM, NULL);
}
-/**
- * gtk_file_system_volume_free:
- * @file_system: a #GtkFileSystem
- * @volume: a #GtkFileSystemVolume
- *
- * Frees a #GtkFileSystemVolume structure as returned by
- * gtk_file_system_list_volumes().
- **/
-void
-gtk_file_system_volume_free (GtkFileSystem *file_system,
- GtkFileSystemVolume *volume)
+GSList *
+_gtk_file_system_list_volumes (GtkFileSystem *file_system)
{
- g_return_if_fail (GTK_IS_FILE_SYSTEM (file_system));
- g_return_if_fail (volume != NULL);
+ GtkFileSystemPrivate *priv = file_system->priv;
+ GSList *list;
- GTK_FILE_SYSTEM_GET_IFACE (file_system)->volume_free (file_system, volume);
-}
+ DEBUG ("list_volumes");
-/**
- * gtk_file_system_volume_get_base_path:
- * @file_system: a #GtkFileSystem
- * @volume: a #GtkFileSystemVolume
- *
- * Queries the base path for a volume. For example, a CD-ROM device may yield a
- * path of "/mnt/cdrom".
- *
- * Return value: a #GtkFilePath with the base mount path of the specified
- * @volume.
- **/
-GtkFilePath *
-gtk_file_system_volume_get_base_path (GtkFileSystem *file_system,
- GtkFileSystemVolume *volume)
-{
- g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
- g_return_val_if_fail (volume != NULL, NULL);
+ get_volumes_list (file_system);
- return GTK_FILE_SYSTEM_GET_IFACE (file_system)->volume_get_base_path (file_system, volume);
-}
+ list = g_slist_copy (priv->volumes);
-/**
- * gtk_file_system_volume_get_is_mounted:
- * @file_system: a #GtkFileSystem
- * @volume: a #GtkFileSystemVolume
- *
- * Queries whether a #GtkFileSystemVolume is mounted or not. If it is not, it
- * can be mounted with gtk_file_system_volume_mount().
- *
- * Return value: TRUE if the @volume is mounted, FALSE otherwise.
- **/
-gboolean
-gtk_file_system_volume_get_is_mounted (GtkFileSystem *file_system,
- GtkFileSystemVolume *volume)
-{
- g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), FALSE);
- g_return_val_if_fail (volume != NULL, FALSE);
+#ifndef G_OS_WIN32
+ /* Prepend root volume */
+ list = g_slist_prepend (list, (gpointer) root_volume_token);
+#endif
- return GTK_FILE_SYSTEM_GET_IFACE (file_system)->volume_get_is_mounted (file_system, volume);
+ return list;
}
-/**
- * gtk_file_system_volume_mount:
- * @file_system: a #GtkFileSystem
- * @volume: a #GtkFileSystemVolume
- * @error: location to store error, or %NULL
- *
- * Tries to mount an unmounted volume. This may cause the "volumes-changed"
- * signal in the @file_system to be emitted.
- *
- * Return value: TRUE if the @volume was mounted successfully, FALSE otherwise.
- **/
-/* FIXME XXX: update documentation above */
-GtkFileSystemHandle *
-gtk_file_system_volume_mount (GtkFileSystem *file_system,
- GtkFileSystemVolume *volume,
- GtkFileSystemVolumeMountCallback callback,
- gpointer data)
+GSList *
+_gtk_file_system_list_bookmarks (GtkFileSystem *file_system)
{
- g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
- g_return_val_if_fail (volume != NULL, NULL);
- g_return_val_if_fail (callback != NULL, NULL);
+ GtkFileSystemPrivate *priv = file_system->priv;
+ GSList *bookmarks, *files = NULL;
+
+ DEBUG ("list_bookmarks");
+
+ bookmarks = priv->bookmarks;
+
+ while (bookmarks)
+ {
+ GtkFileSystemBookmark *bookmark;
- return GTK_FILE_SYSTEM_GET_IFACE (file_system)->volume_mount (file_system, volume, callback, data);
+ bookmark = bookmarks->data;
+ bookmarks = bookmarks->next;
+
+ files = g_slist_prepend (files, g_object_ref (bookmark->file));
+ }
+
+ return g_slist_reverse (files);
}
-/**
- * gtk_file_system_volume_get_display_name:
- * @file_system: a #GtkFileSystem
- * @volume: a #GtkFileSystemVolume
- *
- * Queries the human-readable name for a @volume. This string can be displayed
- * in a list of volumes that can be accessed, for example.
- *
- * Return value: A string with the human-readable name for a #GtkFileSystemVolume.
- **/
-char *
-gtk_file_system_volume_get_display_name (GtkFileSystem *file_system,
- GtkFileSystemVolume *volume)
+static void
+free_async_data (AsyncFuncData *async_data)
{
- g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
- g_return_val_if_fail (volume != NULL, NULL);
+ g_object_unref (async_data->file_system);
+ g_object_unref (async_data->file);
+ g_object_unref (async_data->cancellable);
- return GTK_FILE_SYSTEM_GET_IFACE (file_system)->volume_get_display_name (file_system, volume);
+ g_free (async_data->attributes);
+ g_free (async_data);
}
-/**
- * gtk_file_system_volume_render_icon:
- * @file_system: a #GtkFileSystem
- * @volume: a #GtkFileSystemVolume
- * @widget: Reference widget to render icons.
- * @pixel_size: Size of the icon.
- * @error: location to store error, or %NULL
- *
- * Renders an icon suitable for a file #GtkFileSystemVolume.
- *
- * Return value: A #GdkPixbuf containing an icon, or NULL if the icon could not
- * be rendered. In the latter case, the @error value will be set as
- * appropriate.
- **/
-GdkPixbuf *
-gtk_file_system_volume_render_icon (GtkFileSystem *file_system,
- GtkFileSystemVolume *volume,
- GtkWidget *widget,
- gint pixel_size,
- GError **error)
+static void
+query_info_callback (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
{
- gchar *icon_name;
- GdkPixbuf *pixbuf = NULL;
+ AsyncFuncData *async_data;
+ GError *error = NULL;
+ GFileInfo *file_info;
+ GFile *file;
- g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
- g_return_val_if_fail (volume != NULL, NULL);
- g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
- g_return_val_if_fail (pixel_size > 0, NULL);
- g_return_val_if_fail (error == NULL || *error == NULL, NULL);
-
- icon_name = gtk_file_system_volume_get_icon_name (file_system, volume,
- error);
- if (icon_name)
- {
- GtkIconTheme *icon_theme;
+ DEBUG ("query_info_callback");
- icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
- if (gtk_icon_theme_has_icon (icon_theme, icon_name))
- pixbuf = gtk_icon_theme_load_icon (icon_theme,
- icon_name, pixel_size, 0, NULL);
- g_free (icon_name);
+ file = G_FILE (source_object);
+ async_data = (AsyncFuncData *) user_data;
+ file_info = g_file_query_info_finish (file, result, &error);
+
+ if (async_data->callback)
+ {
+ gdk_threads_enter ();
+ ((GtkFileSystemGetInfoCallback) async_data->callback) (async_data->cancellable,
+ file_info, error, async_data->data);
+ gdk_threads_leave ();
}
- if (!pixbuf)
- pixbuf = gtk_widget_render_icon (widget,
- GTK_STOCK_HARDDISK,
- GTK_ICON_SIZE_SMALL_TOOLBAR,
- NULL);
+ if (file_info)
+ g_object_unref (file_info);
- return pixbuf;
+ if (error)
+ g_error_free (error);
+
+ free_async_data (async_data);
}
-/**
- * gtk_file_system_volume_get_icon_name:
- * @file_system: a #GtkFileSystem
- * @volume: a #GtkFileSystemVolume
- * @error: location to store error, or %NULL
- *
- * Gets an icon name suitable for a #GtkFileSystemVolume.
- *
- * Return value: An icon name which can be used for rendering an icon for
- * this volume, or %NULL if no icon name could be found. In the latter
- * case, the @error value will be set as appropriate.
- **/
-gchar *
-gtk_file_system_volume_get_icon_name (GtkFileSystem *file_system,
- GtkFileSystemVolume *volume,
- GError **error)
+GCancellable *
+_gtk_file_system_get_info (GtkFileSystem *file_system,
+ GFile *file,
+ const gchar *attributes,
+ GtkFileSystemGetInfoCallback callback,
+ gpointer data)
{
+ GCancellable *cancellable;
+ AsyncFuncData *async_data;
+
g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
- g_return_val_if_fail (volume != NULL, NULL);
- g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+ g_return_val_if_fail (G_IS_FILE (file), NULL);
- return GTK_FILE_SYSTEM_GET_IFACE (file_system)->volume_get_icon_name (file_system,
- volume,
- error);
-}
+ cancellable = g_cancellable_new ();
-/**
- * gtk_file_system_get_parent:
- * @file_system: a #GtkFileSystem
- * @path: base path name
- * @parent: location to store parent path name
- * @error: location to store error, or %NULL
- *
- * Gets the name of the parent folder of a path. If the path has no parent, as when
- * you request the parent of a file system root, then @parent will be set to %NULL.
- *
- * Return value: %TRUE if the operation was successful: @parent will be set to
- * the name of the @path's parent, or to %NULL if @path is already a file system
- * root. If the operation fails, this function returns %FALSE, sets @parent to
- * NULL, and sets the @error value if it is specified.
- **/
-gboolean
-gtk_file_system_get_parent (GtkFileSystem *file_system,
- const GtkFilePath *path,
- GtkFilePath **parent,
- GError **error)
-{
- gboolean result;
-
- g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), FALSE);
- g_return_val_if_fail (path != NULL, FALSE);
- g_return_val_if_fail (parent != NULL, FALSE);
- g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ async_data = g_new0 (AsyncFuncData, 1);
+ async_data->file_system = g_object_ref (file_system);
+ async_data->file = g_object_ref (file);
+ async_data->cancellable = g_object_ref (cancellable);
- *parent = NULL;
+ async_data->callback = callback;
+ async_data->data = data;
- result = GTK_FILE_SYSTEM_GET_IFACE (file_system)->get_parent (file_system, path, parent, error);
- g_assert (result || *parent == NULL);
+ g_file_query_info_async (file,
+ attributes,
+ G_FILE_QUERY_INFO_NONE,
+ G_PRIORITY_DEFAULT,
+ cancellable,
+ query_info_callback,
+ async_data);
- return result;
+ return cancellable;
}
-GtkFilePath *
-gtk_file_system_make_path (GtkFileSystem *file_system,
- const GtkFilePath *base_path,
- const gchar *display_name,
- GError **error)
+static void
+drive_poll_for_media_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
{
- g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
- g_return_val_if_fail (base_path != NULL, NULL);
- g_return_val_if_fail (display_name != NULL, NULL);
- g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+ AsyncFuncData *async_data;
+ GError *error = NULL;
- return GTK_FILE_SYSTEM_GET_IFACE (file_system)->make_path (file_system, base_path, display_name, error);
+ g_drive_poll_for_media_finish (G_DRIVE (source_object), result, &error);
+ async_data = (AsyncFuncData *) user_data;
+
+ gdk_threads_enter ();
+ ((GtkFileSystemVolumeMountCallback) async_data->callback) (async_data->cancellable,
+ (GtkFileSystemVolume *) source_object,
+ error, async_data->data);
+ gdk_threads_leave ();
+
+ if (error)
+ g_error_free (error);
}
-/**
- * gtk_file_system_parse:
- * @file_system: a #GtkFileSystem
- * @base_path: reference folder with respect to which relative
- * paths should be interpreted.
- * @str: the string to parse
- * @folder: location to store folder portion of result, or %NULL
- * @file_part: location to store file portion of result, or %NULL
- * @error: location to store error, or %NULL
- *
- * Given a string entered by a user, parse it (possibly using
- * heuristics) into a folder path and a UTF-8 encoded
- * filename part. (Suitable for passing to gtk_file_system_make_path())
- *
- * Note that the returned filename point may point to a subfolder
- * of the returned folder. Adding a trailing path separator is needed
- * to enforce the interpretation as a folder name.
- *
- * If parsing fails because the syntax of @str is not understood,
- * and error of type GTK_FILE_SYSTEM_ERROR_BAD_FILENAME will
- * be set in @error and %FALSE returned.
- *
- * If parsing fails because a path was encountered that doesn't
- * exist on the filesystem, then an error of type
- * %GTK_FILE_SYSTEM_ERROR_NONEXISTENT will be set in @error
- * and %FALSE returned. (This only applies to parsing relative paths,
- * not to interpretation of @file_part. No check is made as
- * to whether @file_part exists.)
- *
- * Return value: %TRUE if the parsing succeeds, otherwise, %FALSE.
- **/
-gboolean
-gtk_file_system_parse (GtkFileSystem *file_system,
- const GtkFilePath *base_path,
- const gchar *str,
- GtkFilePath **folder,
- gchar **file_part,
- GError **error)
+static void
+volume_mount_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
{
- GtkFilePath *tmp_folder = NULL;
- gchar *tmp_file_part = NULL;
- gboolean result;
-
- g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), FALSE);
- g_return_val_if_fail (base_path != NULL, FALSE);
- g_return_val_if_fail (str != NULL, FALSE);
- g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
- result = GTK_FILE_SYSTEM_GET_IFACE (file_system)->parse (file_system, base_path, str,
- &tmp_folder, &tmp_file_part,
- error);
- g_assert (result || (tmp_folder == NULL && tmp_file_part == NULL));
-
- if (folder)
- *folder = tmp_folder;
- else
- gtk_file_path_free (tmp_folder);
+ AsyncFuncData *async_data;
+ GError *error = NULL;
- if (file_part)
- *file_part = tmp_file_part;
- else
- g_free (tmp_file_part);
-
- return result;
-}
+ g_volume_mount_finish (G_VOLUME (source_object), result, &error);
+ async_data = (AsyncFuncData *) user_data;
+ gdk_threads_enter ();
+ ((GtkFileSystemVolumeMountCallback) async_data->callback) (async_data->cancellable,
+ (GtkFileSystemVolume *) source_object,
+ error, async_data->data);
+ gdk_threads_leave ();
-gchar *
-gtk_file_system_path_to_uri (GtkFileSystem *file_system,
- const GtkFilePath *path)
-{
- g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
- g_return_val_if_fail (path != NULL, NULL);
-
- return GTK_FILE_SYSTEM_GET_IFACE (file_system)->path_to_uri (file_system, path);
+ if (error)
+ g_error_free (error);
}
-gchar *
-gtk_file_system_path_to_filename (GtkFileSystem *file_system,
- const GtkFilePath *path)
+GCancellable *
+_gtk_file_system_mount_volume (GtkFileSystem *file_system,
+ GtkFileSystemVolume *volume,
+ GMountOperation *mount_operation,
+ GtkFileSystemVolumeMountCallback callback,
+ gpointer data)
{
- g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
- g_return_val_if_fail (path != NULL, NULL);
-
- return GTK_FILE_SYSTEM_GET_IFACE (file_system)->path_to_filename (file_system, path);
-}
+ GCancellable *cancellable;
+ AsyncFuncData *async_data;
+ gboolean handled = FALSE;
-GtkFilePath *
-gtk_file_system_uri_to_path (GtkFileSystem *file_system,
- const gchar *uri)
-{
- g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
- g_return_val_if_fail (uri != NULL, NULL);
-
- return GTK_FILE_SYSTEM_GET_IFACE (file_system)->uri_to_path (file_system, uri);
-}
+ DEBUG ("volume_mount");
-GtkFilePath *
-gtk_file_system_filename_to_path (GtkFileSystem *file_system,
- const gchar *filename)
-{
- g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
- g_return_val_if_fail (filename != NULL, NULL);
+ cancellable = g_cancellable_new ();
- return GTK_FILE_SYSTEM_GET_IFACE (file_system)->filename_to_path (file_system, filename);
-}
+ async_data = g_new0 (AsyncFuncData, 1);
+ async_data->file_system = g_object_ref (file_system);
+ async_data->cancellable = g_object_ref (cancellable);
-/**
- * gtk_file_system_path_is_local:
- * @filesystem: a #GtkFileSystem
- * @path: A #GtkFilePath from that filesystem
- *
- * Checks whether a #GtkFilePath is local; that is whether
- * gtk_file_system_path_to_filename would return non-%NULL.
- *
- * Return value: %TRUE if the path is loca
- **/
-gboolean
-gtk_file_system_path_is_local (GtkFileSystem *file_system,
- const GtkFilePath *path)
-{
- gchar *filename;
- gboolean result;
-
- g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), FALSE);
- g_return_val_if_fail (path != NULL, FALSE);
+ async_data->callback = callback;
+ async_data->data = data;
- filename = gtk_file_system_path_to_filename (file_system, path);
- result = filename != NULL;
- g_free (filename);
+ if (G_IS_DRIVE (volume))
+ {
+ /* this path happens for drives that are not polled by the OS and where the last media
+ * check indicated that no media was available. So the thing to do here is to
+ * invoke poll_for_media() on the drive
+ */
+ g_drive_poll_for_media (G_DRIVE (volume), cancellable, drive_poll_for_media_cb, async_data);
+ handled = TRUE;
+ }
+ else if (G_IS_VOLUME (volume))
+ {
+ g_volume_mount (G_VOLUME (volume), G_MOUNT_MOUNT_NONE, mount_operation, cancellable, volume_mount_cb, async_data);
+ handled = TRUE;
+ }
- return result;
+ if (!handled)
+ free_async_data (async_data);
+
+ return cancellable;
}
-/**
- * gtk_file_system_insert_bookmark:
- * @file_system: a #GtkFileSystem
- * @path: path of the bookmark to add
- * @position: index in the bookmarks list at which the @path should be inserted; use 0
- * for the beginning, and -1 or the number of bookmarks itself for the end of the list.
- * @error: location to store error, or %NULL
- *
- * Adds a path for a folder to the user's bookmarks list. If the operation
- * succeeds, the "bookmarks_changed" signal will be emitted. Bookmark paths are
- * unique; if you try to insert a @path that already exists, the operation will
- * fail and the @error will be set to #GTK_FILE_SYSTEM_ERROR_ALREADY_EXISTS. To
- * reorder the list of bookmarks, use gtk_file_system_remove_bookmark() to
- * remove the path in question, and call gtk_file_system_insert_bookmark() with
- * the new position for the path.
- *
- * Return value: TRUE if the operation succeeds, FALSE otherwise. In the latter case,
- * the @error value will be set.
- **/
-gboolean
-gtk_file_system_insert_bookmark (GtkFileSystem *file_system,
- const GtkFilePath *path,
- gint position,
- GError **error)
+static void
+enclosing_volume_mount_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
{
- g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), FALSE);
- g_return_val_if_fail (path != NULL, FALSE);
+ GtkFileSystemVolume *volume;
+ AsyncFuncData *async_data;
+ GError *error = NULL;
- return GTK_FILE_SYSTEM_GET_IFACE (file_system)->insert_bookmark (file_system, path, position, error);
-}
+ async_data = (AsyncFuncData *) user_data;
+ g_file_mount_enclosing_volume_finish (G_FILE (source_object), result, &error);
+ volume = _gtk_file_system_get_volume_for_file (async_data->file_system, G_FILE (source_object));
-/**
- * gtk_file_system_remove_bookmark:
- * @file_system: a #GtkFileSystem
- * @path: path of the bookmark to remove
- * @error: location to store error, or %NULL
- *
- * Removes a bookmark folder from the user's bookmarks list. If the operation
- * succeeds, the "bookmarks_changed" signal will be emitted. If you try to remove
- * a @path which does not exist in the bookmarks list, the operation will fail
- * and the @error will be set to GTK_FILE_SYSTEM_ERROR_NONEXISTENT.
- *
- * Return value: TRUE if the operation succeeds, FALSE otherwise. In the latter
- * case, the @error value will be set.
- **/
-gboolean
-gtk_file_system_remove_bookmark (GtkFileSystem *file_system,
- const GtkFilePath *path,
- GError **error)
-{
- g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), FALSE);
- g_return_val_if_fail (path != NULL, FALSE);
+ /* Silently drop G_IO_ERROR_ALREADY_MOUNTED error for gvfs backends without visible mounts. */
+ /* Better than doing query_info with additional I/O every time. */
+ if (error && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_ALREADY_MOUNTED))
+ g_clear_error (&error);
- return GTK_FILE_SYSTEM_GET_IFACE (file_system)->remove_bookmark (file_system, path, error);
-}
+ gdk_threads_enter ();
+ ((GtkFileSystemVolumeMountCallback) async_data->callback) (async_data->cancellable, volume,
+ error, async_data->data);
+ gdk_threads_leave ();
-/**
- * gtk_file_system_list_bookmarks:
- * @file_system: a #GtkFileSystem
- *
- * Queries the list of bookmarks in the file system.
- *
- * Return value: A list of #GtkFilePath, or NULL if there are no configured
- * bookmarks. You should use gtk_file_paths_free() to free this list.
- *
- * See also: gtk_file_system_get_supports_bookmarks()
- **/
-GSList *
-gtk_file_system_list_bookmarks (GtkFileSystem *file_system)
-{
- g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
+ if (error)
+ g_error_free (error);
- return GTK_FILE_SYSTEM_GET_IFACE (file_system)->list_bookmarks (file_system);
+ _gtk_file_system_volume_unref (volume);
}
-/**
- * gtk_file_system_get_bookmark_label:
- * @file_system: a #GtkFileSystem
- * @path: path of the bookmark
- *
- * Gets the label to display for a bookmark, or %NULL.
- *
- * Returns: the label for the bookmark @path
- *
- * Since: 2.8
- */
-gchar *
-gtk_file_system_get_bookmark_label (GtkFileSystem *file_system,
- const GtkFilePath *path)
+GCancellable *
+_gtk_file_system_mount_enclosing_volume (GtkFileSystem *file_system,
+ GFile *file,
+ GMountOperation *mount_operation,
+ GtkFileSystemVolumeMountCallback callback,
+ gpointer data)
{
- GtkFileSystemIface *iface;
+ GCancellable *cancellable;
+ AsyncFuncData *async_data;
g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
- g_return_val_if_fail (path != NULL, NULL);
+ g_return_val_if_fail (G_IS_FILE (file), NULL);
- iface = GTK_FILE_SYSTEM_GET_IFACE (file_system);
- if (iface->get_bookmark_label)
- return iface->get_bookmark_label (file_system, path);
+ DEBUG ("mount_enclosing_volume");
- return NULL;
-}
+ cancellable = g_cancellable_new ();
-/**
- * gtk_file_system_set_bookmark_label:
- * @file_system: a #GtkFileSystem
- * @path: path of the bookmark
- * @label: the label for the bookmark, or %NULL to display
- * the path itself
- *
- * Sets the label to display for a bookmark.
- *
- * Since: 2.8
- */
-void
-gtk_file_system_set_bookmark_label (GtkFileSystem *file_system,
- const GtkFilePath *path,
- const gchar *label)
-{
- GtkFileSystemIface *iface;
+ async_data = g_new0 (AsyncFuncData, 1);
+ async_data->file_system = g_object_ref (file_system);
+ async_data->file = g_object_ref (file);
+ async_data->cancellable = g_object_ref (cancellable);
- g_return_if_fail (GTK_IS_FILE_SYSTEM (file_system));
- g_return_if_fail (path != NULL);
+ async_data->callback = callback;
+ async_data->data = data;
- iface = GTK_FILE_SYSTEM_GET_IFACE (file_system);
- if (iface->set_bookmark_label)
- iface->set_bookmark_label (file_system, path, label);
+ g_file_mount_enclosing_volume (file,
+ G_MOUNT_MOUNT_NONE,
+ mount_operation,
+ cancellable,
+ enclosing_volume_mount_cb,
+ async_data);
+ return cancellable;
}
-/*****************************************
- * GtkFileFolder *
- *****************************************/
-GType
-gtk_file_folder_get_type (void)
+gboolean
+_gtk_file_system_insert_bookmark (GtkFileSystem *file_system,
+ GFile *file,
+ gint position,
+ GError **error)
{
- static GType file_folder_type = 0;
+ GtkFileSystemPrivate *priv = file_system->priv;
+ GSList *bookmarks;
+ GtkFileSystemBookmark *bookmark;
+ gboolean result = TRUE;
+ GFile *bookmarks_file;
+
+ bookmarks = priv->bookmarks;
- if (!file_folder_type)
+ while (bookmarks)
{
- static const GTypeInfo file_folder_info =
- {
- sizeof (GtkFileFolderIface), /* class_size */
- gtk_file_folder_base_init, /* base_init */
- NULL, /* base_finalize */
- };
-
- file_folder_type = g_type_register_static (G_TYPE_INTERFACE,
- I_("GtkFileFolder"),
- &file_folder_info, 0);
-
- g_type_interface_add_prerequisite (file_folder_type, G_TYPE_OBJECT);
- }
+ bookmark = bookmarks->data;
+ bookmarks = bookmarks->next;
- return file_folder_type;
-}
+ if (g_file_equal (bookmark->file, file))
+ {
+ /* File is already in bookmarks */
+ result = FALSE;
+ break;
+ }
+ }
-static void
-gtk_file_folder_base_init (gpointer g_class)
-{
- static gboolean initialized = FALSE;
-
- if (!initialized)
+ if (!result)
{
- GType iface_type = G_TYPE_FROM_INTERFACE (g_class);
-
- g_signal_new (I_("deleted"),
- iface_type,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GtkFileFolderIface, deleted),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
- g_signal_new (I_("files-added"),
- iface_type,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GtkFileFolderIface, files_added),
- NULL, NULL,
- g_cclosure_marshal_VOID__POINTER,
- G_TYPE_NONE, 1,
- G_TYPE_POINTER);
- g_signal_new (I_("files-changed"),
- iface_type,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GtkFileFolderIface, files_changed),
- NULL, NULL,
- g_cclosure_marshal_VOID__POINTER,
- G_TYPE_NONE, 1,
- G_TYPE_POINTER);
- g_signal_new (I_("files-removed"),
- iface_type,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GtkFileFolderIface, files_removed),
- NULL, NULL,
- g_cclosure_marshal_VOID__POINTER,
- G_TYPE_NONE, 1,
- G_TYPE_POINTER);
- g_signal_new (I_("finished-loading"),
- iface_type,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GtkFileFolderIface, finished_loading),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
- initialized = TRUE;
+ gchar *uri = g_file_get_uri (file);
+
+ g_set_error (error,
+ GTK_FILE_CHOOSER_ERROR,
+ GTK_FILE_CHOOSER_ERROR_ALREADY_EXISTS,
+ "%s already exists in the bookmarks list",
+ uri);
+
+ g_free (uri);
+
+ return FALSE;
}
+
+ bookmark = g_slice_new0 (GtkFileSystemBookmark);
+ bookmark->file = g_object_ref (file);
+
+ priv->bookmarks = g_slist_insert (priv->bookmarks, bookmark, position);
+
+ bookmarks_file = get_bookmarks_file ();
+ save_bookmarks (bookmarks_file, priv->bookmarks);
+ g_object_unref (bookmarks_file);
+
+ g_signal_emit (file_system, fs_signals[BOOKMARKS_CHANGED], 0);
+
+ return TRUE;
}
gboolean
-gtk_file_folder_list_children (GtkFileFolder *folder,
- GSList **children,
- GError **error)
+_gtk_file_system_remove_bookmark (GtkFileSystem *file_system,
+ GFile *file,
+ GError **error)
{
- gboolean result;
- GSList *tmp_children = NULL;
-
- g_return_val_if_fail (GTK_IS_FILE_FOLDER (folder), FALSE);
- g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ GtkFileSystemPrivate *priv = file_system->priv;
+ GtkFileSystemBookmark *bookmark;
+ GSList *bookmarks;
+ gboolean result = FALSE;
+ GFile *bookmarks_file;
- result = GTK_FILE_FOLDER_GET_IFACE (folder)->list_children (folder, &tmp_children, error);
- g_assert (result || tmp_children == NULL);
+ if (!priv->bookmarks)
+ return FALSE;
- if (children)
- *children = tmp_children;
- else
- gtk_file_paths_free (tmp_children);
+ bookmarks = priv->bookmarks;
- return result;
-}
+ while (bookmarks)
+ {
+ bookmark = bookmarks->data;
-GtkFileInfo *
-gtk_file_folder_get_info (GtkFileFolder *folder,
- const GtkFilePath *path,
- GError **error)
-{
- g_return_val_if_fail (GTK_IS_FILE_FOLDER (folder), NULL);
- g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+ if (g_file_equal (bookmark->file, file))
+ {
+ result = TRUE;
+ priv->bookmarks = g_slist_remove_link (priv->bookmarks, bookmarks);
+ _gtk_file_system_bookmark_free (bookmark);
+ g_slist_free_1 (bookmarks);
+ break;
+ }
- return GTK_FILE_FOLDER_GET_IFACE (folder)->get_info (folder, path, error);
-}
+ bookmarks = bookmarks->next;
+ }
-gboolean
-gtk_file_folder_is_finished_loading (GtkFileFolder *folder)
-{
- GtkFileFolderIface *iface;
+ if (!result)
+ {
+ gchar *uri = g_file_get_uri (file);
- g_return_val_if_fail (GTK_IS_FILE_FOLDER (folder), TRUE);
+ g_set_error (error,
+ GTK_FILE_CHOOSER_ERROR,
+ GTK_FILE_CHOOSER_ERROR_NONEXISTENT,
+ "%s does not exist in the bookmarks list",
+ uri);
- iface = GTK_FILE_FOLDER_GET_IFACE (folder);
- if (!iface->is_finished_loading)
- return TRUE;
- else
- return iface->is_finished_loading (folder);
-}
+ g_free (uri);
+ return FALSE;
+ }
-/*****************************************
- * GtkFilePath modules *
- *****************************************/
+ bookmarks_file = get_bookmarks_file ();
+ save_bookmarks (bookmarks_file, priv->bookmarks);
+ g_object_unref (bookmarks_file);
-/* We make these real functions in case either copy or free are implemented as macros
- */
-static gpointer
-gtk_file_path_real_copy (gpointer boxed)
-{
- return gtk_file_path_copy ((GtkFilePath *) boxed);
-}
+ g_signal_emit (file_system, fs_signals[BOOKMARKS_CHANGED], 0);
-static void
-gtk_file_path_real_free (gpointer boxed)
-{
- gtk_file_path_free (boxed);
+ return TRUE;
}
-GType
-gtk_file_path_get_type (void)
+gchar *
+_gtk_file_system_get_bookmark_label (GtkFileSystem *file_system,
+ GFile *file)
{
- static GType our_type = 0;
-
- if (our_type == 0)
- our_type = g_boxed_type_register_static (I_("GtkFilePath"),
- (GBoxedCopyFunc) gtk_file_path_real_copy,
- (GBoxedFreeFunc) gtk_file_path_real_free);
+ GtkFileSystemPrivate *priv = file_system->priv;
+ GSList *bookmarks;
+ gchar *label = NULL;
- return our_type;
-}
+ DEBUG ("get_bookmark_label");
+ bookmarks = priv->bookmarks;
-GSList *
-gtk_file_paths_sort (GSList *paths)
-{
- return g_slist_sort (paths, (GCompareFunc)strcmp);
+ while (bookmarks)
+ {
+ GtkFileSystemBookmark *bookmark;
+
+ bookmark = bookmarks->data;
+ bookmarks = bookmarks->next;
+
+ if (g_file_equal (file, bookmark->file))
+ {
+ label = g_strdup (bookmark->label);
+ break;
+ }
+ }
+
+ return label;
}
-/**
- * gtk_file_paths_copy:
- * @paths: A #GSList of #GtkFilePath structures.
- *
- * Copies a list of #GtkFilePath structures.
- *
- * Return value: A copy of @paths. Since the contents of the list are copied as
- * well, you should use gtk_file_paths_free() to free the result.
- **/
-GSList *
-gtk_file_paths_copy (GSList *paths)
+void
+_gtk_file_system_set_bookmark_label (GtkFileSystem *file_system,
+ GFile *file,
+ const gchar *label)
{
- GSList *head, *tail, *l;
+ GtkFileSystemPrivate *priv = file_system->priv;
+ gboolean changed = FALSE;
+ GFile *bookmarks_file;
+ GSList *bookmarks;
- head = tail = NULL;
+ DEBUG ("set_bookmark_label");
- for (l = paths; l; l = l->next)
- {
- GtkFilePath *path;
- GSList *node;
+ bookmarks = priv->bookmarks;
- path = l->data;
- node = g_slist_alloc ();
+ while (bookmarks)
+ {
+ GtkFileSystemBookmark *bookmark;
- if (tail)
- tail->next = node;
- else
- head = node;
+ bookmark = bookmarks->data;
+ bookmarks = bookmarks->next;
- node->data = gtk_file_path_copy (path);
- tail = node;
+ if (g_file_equal (file, bookmark->file))
+ {
+ g_free (bookmark->label);
+ bookmark->label = g_strdup (label);
+ changed = TRUE;
+ break;
+ }
}
- return head;
+ bookmarks_file = get_bookmarks_file ();
+ save_bookmarks (bookmarks_file, priv->bookmarks);
+ g_object_unref (bookmarks_file);
+
+ if (changed)
+ g_signal_emit_by_name (file_system, "bookmarks-changed", 0);
}
-void
-gtk_file_paths_free (GSList *paths)
+GtkFileSystemVolume *
+_gtk_file_system_get_volume_for_file (GtkFileSystem *file_system,
+ GFile *file)
{
- GSList *tmp_list;
+ GMount *mount;
- for (tmp_list = paths; tmp_list; tmp_list = tmp_list->next)
- gtk_file_path_free (tmp_list->data);
+ DEBUG ("get_volume_for_file");
- g_slist_free (paths);
-}
+ mount = g_file_find_enclosing_mount (file, NULL, NULL);
-/*****************************************
- * GtkFileSystem modules *
- *****************************************/
+ if (!mount && g_file_is_native (file))
+ return (GtkFileSystemVolume *) root_volume_token;
-typedef struct _GtkFileSystemModule GtkFileSystemModule;
-typedef struct _GtkFileSystemModuleClass GtkFileSystemModuleClass;
+ return (GtkFileSystemVolume *) mount;
+}
-struct _GtkFileSystemModule
+/* GtkFileSystemVolume public methods */
+gchar *
+_gtk_file_system_volume_get_display_name (GtkFileSystemVolume *volume)
{
- GTypeModule parent_instance;
-
- GModule *library;
+ DEBUG ("volume_get_display_name");
- void (*init) (GTypeModule *module);
- void (*exit) (void);
- GtkFileSystem * (*create) (void);
+ if (IS_ROOT_VOLUME (volume))
+ return g_strdup (_(root_volume_token));
+ if (G_IS_DRIVE (volume))
+ return g_drive_get_name (G_DRIVE (volume));
+ else if (G_IS_MOUNT (volume))
+ return g_mount_get_name (G_MOUNT (volume));
+ else if (G_IS_VOLUME (volume))
+ return g_volume_get_name (G_VOLUME (volume));
- gchar *path;
-};
+ return NULL;
+}
-struct _GtkFileSystemModuleClass
+gboolean
+_gtk_file_system_volume_is_mounted (GtkFileSystemVolume *volume)
{
- GTypeModuleClass parent_class;
-};
+ gboolean mounted;
-G_DEFINE_TYPE (GtkFileSystemModule, _gtk_file_system_module, G_TYPE_TYPE_MODULE)
-#define GTK_TYPE_FILE_SYSTEM_MODULE (_gtk_file_system_module_get_type ())
-#define GTK_FILE_SYSTEM_MODULE(module) (G_TYPE_CHECK_INSTANCE_CAST ((module), GTK_TYPE_FILE_SYSTEM_MODULE, GtkFileSystemModule))
+ DEBUG ("volume_is_mounted");
+ if (IS_ROOT_VOLUME (volume))
+ return TRUE;
-static GSList *loaded_file_systems;
+ mounted = FALSE;
-static gboolean
-gtk_file_system_module_load (GTypeModule *module)
-{
- GtkFileSystemModule *fs_module = GTK_FILE_SYSTEM_MODULE (module);
-
- fs_module->library = g_module_open (fs_module->path, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
- if (!fs_module->library)
+ if (G_IS_MOUNT (volume))
+ mounted = TRUE;
+ else if (G_IS_VOLUME (volume))
{
- g_warning (g_module_error());
- return FALSE;
+ GMount *mount;
+
+ mount = g_volume_get_mount (G_VOLUME (volume));
+
+ if (mount)
+ {
+ mounted = TRUE;
+ g_object_unref (mount);
+ }
}
-
- /* extract symbols from the lib */
- if (!g_module_symbol (fs_module->library, "fs_module_init",
- (gpointer *)&fs_module->init) ||
- !g_module_symbol (fs_module->library, "fs_module_exit",
- (gpointer *)&fs_module->exit) ||
- !g_module_symbol (fs_module->library, "fs_module_create",
- (gpointer *)&fs_module->create))
+
+ return mounted;
+}
+
+GFile *
+_gtk_file_system_volume_get_root (GtkFileSystemVolume *volume)
+{
+ GFile *file = NULL;
+
+ DEBUG ("volume_get_base");
+
+ if (IS_ROOT_VOLUME (volume))
+ return g_file_new_for_uri ("file:///");
+
+ if (G_IS_MOUNT (volume))
+ file = g_mount_get_root (G_MOUNT (volume));
+ else if (G_IS_VOLUME (volume))
{
- g_warning (g_module_error());
- g_module_close (fs_module->library);
-
- return FALSE;
+ GMount *mount;
+
+ mount = g_volume_get_mount (G_VOLUME (volume));
+
+ if (mount)
+ {
+ file = g_mount_get_root (mount);
+ g_object_unref (mount);
+ }
}
-
- /* call the filesystems's init function to let it */
- /* setup anything it needs to set up. */
- fs_module->init (module);
- return TRUE;
+ return file;
}
-static void
-gtk_file_system_module_unload (GTypeModule *module)
+static GdkPixbuf *
+get_pixbuf_from_gicon (GIcon *icon,
+ GtkWidget *widget,
+ gint icon_size,
+ GError **error)
{
- GtkFileSystemModule *fs_module = GTK_FILE_SYSTEM_MODULE (module);
-
- fs_module->exit();
+ GdkScreen *screen;
+ GtkIconTheme *icon_theme;
+ GtkIconInfo *icon_info;
+ GdkPixbuf *pixbuf;
+
+ screen = gtk_widget_get_screen (GTK_WIDGET (widget));
+ icon_theme = gtk_icon_theme_get_for_screen (screen);
+
+ icon_info = gtk_icon_theme_lookup_by_gicon (icon_theme,
+ icon,
+ icon_size,
+ GTK_ICON_LOOKUP_USE_BUILTIN);
+
+ if (!icon_info)
+ return NULL;
- g_module_close (fs_module->library);
- fs_module->library = NULL;
+ pixbuf = gtk_icon_info_load_icon (icon_info, error);
+ g_object_unref (icon_info);
- fs_module->init = NULL;
- fs_module->exit = NULL;
- fs_module->create = NULL;
+ return pixbuf;
}
-/* This only will ever be called if an error occurs during
- * initialization
- */
-static void
-gtk_file_system_module_finalize (GObject *object)
+GdkPixbuf *
+_gtk_file_system_volume_render_icon (GtkFileSystemVolume *volume,
+ GtkWidget *widget,
+ gint icon_size,
+ GError **error)
{
- GtkFileSystemModule *module = GTK_FILE_SYSTEM_MODULE (object);
+ GIcon *icon = NULL;
+ GdkPixbuf *pixbuf;
+
+ DEBUG ("volume_get_icon_name");
+
+ if (IS_ROOT_VOLUME (volume))
+ icon = g_themed_icon_new ("drive-harddisk");
+ else if (G_IS_DRIVE (volume))
+ icon = g_drive_get_icon (G_DRIVE (volume));
+ else if (G_IS_VOLUME (volume))
+ icon = g_volume_get_icon (G_VOLUME (volume));
+ else if (G_IS_MOUNT (volume))
+ icon = g_mount_get_icon (G_MOUNT (volume));
- g_free (module->path);
+ if (!icon)
+ return NULL;
- G_OBJECT_CLASS (_gtk_file_system_module_parent_class)->finalize (object);
+ pixbuf = get_pixbuf_from_gicon (icon, widget, icon_size, error);
+
+ g_object_unref (icon);
+
+ return pixbuf;
}
-static void
-_gtk_file_system_module_class_init (GtkFileSystemModuleClass *class)
+GtkFileSystemVolume *
+_gtk_file_system_volume_ref (GtkFileSystemVolume *volume)
{
- GTypeModuleClass *module_class = G_TYPE_MODULE_CLASS (class);
- GObjectClass *gobject_class = G_OBJECT_CLASS (class);
-
- module_class->load = gtk_file_system_module_load;
- module_class->unload = gtk_file_system_module_unload;
+ if (IS_ROOT_VOLUME (volume))
+ return volume;
+
+ if (G_IS_MOUNT (volume) ||
+ G_IS_VOLUME (volume) ||
+ G_IS_DRIVE (volume))
+ g_object_ref (volume);
- gobject_class->finalize = gtk_file_system_module_finalize;
+ return volume;
}
-static void
-_gtk_file_system_module_init (GtkFileSystemModule *fs_module)
+void
+_gtk_file_system_volume_unref (GtkFileSystemVolume *volume)
{
-}
+ /* Root volume doesn't need to be freed */
+ if (IS_ROOT_VOLUME (volume))
+ return;
+ if (G_IS_MOUNT (volume) ||
+ G_IS_VOLUME (volume) ||
+ G_IS_DRIVE (volume))
+ g_object_unref (volume);
+}
-static GtkFileSystem *
-_gtk_file_system_module_create (GtkFileSystemModule *fs_module)
+/* GFileInfo helper functions */
+GdkPixbuf *
+_gtk_file_info_render_icon (GFileInfo *info,
+ GtkWidget *widget,
+ gint icon_size)
{
- GtkFileSystem *fs;
-
- if (g_type_module_use (G_TYPE_MODULE (fs_module)))
- {
- fs = fs_module->create ();
- g_type_module_unuse (G_TYPE_MODULE (fs_module));
- return fs;
- }
- return NULL;
-}
+ GIcon *icon;
+ GdkPixbuf *pixbuf = NULL;
+ const gchar *thumbnail_path;
+ thumbnail_path = g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH);
-GtkFileSystem *
-_gtk_file_system_create (const char *file_system_name)
-{
- GSList *l;
- char *module_path;
- GtkFileSystemModule *fs_module;
- GtkFileSystem *fs;
+ if (thumbnail_path)
+ pixbuf = gdk_pixbuf_new_from_file_at_size (thumbnail_path,
+ icon_size, icon_size,
+ NULL);
- for (l = loaded_file_systems; l != NULL; l = l->next)
+ if (!pixbuf)
{
- fs_module = l->data;
-
- if (strcmp (G_TYPE_MODULE (fs_module)->name, file_system_name) == 0)
- return _gtk_file_system_module_create (fs_module);
- }
+ icon = g_file_info_get_icon (info);
- fs = NULL;
- if (g_module_supported ())
- {
- module_path = _gtk_find_module (file_system_name, "filesystems");
+ if (icon)
+ pixbuf = get_pixbuf_from_gicon (icon, widget, icon_size, NULL);
- if (module_path)
+ if (!pixbuf)
{
- fs_module = g_object_new (GTK_TYPE_FILE_SYSTEM_MODULE, NULL);
-
- g_type_module_set_name (G_TYPE_MODULE (fs_module), file_system_name);
- fs_module->path = g_strdup (module_path);
-
- loaded_file_systems = g_slist_prepend (loaded_file_systems,
- fs_module);
-
- fs = _gtk_file_system_module_create (fs_module);
+ /* Use general fallback for all files without icon */
+ icon = g_themed_icon_new ("text-x-generic");
+ pixbuf = get_pixbuf_from_gicon (icon, widget, icon_size, NULL);
+ g_object_unref (icon);
}
-
- g_free (module_path);
}
+
+ return pixbuf;
+}
+
+gboolean
+_gtk_file_info_consider_as_directory (GFileInfo *info)
+{
+ GFileType type = g_file_info_get_file_type (info);
- return fs;
+ return (type == G_FILE_TYPE_DIRECTORY ||
+ type == G_FILE_TYPE_MOUNTABLE ||
+ type == G_FILE_TYPE_SHORTCUT);
}
-#define __GTK_FILE_SYSTEM_C__
-#include "gtkaliasdef.c"
+gboolean
+_gtk_file_has_native_path (GFile *file)
+{
+ char *local_file_path;
+ gboolean has_native_path;
+
+ /* Don't use g_file_is_native(), as we want to support FUSE paths if available */
+ local_file_path = g_file_get_path (file);
+ has_native_path = (local_file_path != NULL);
+ g_free (local_file_path);
+
+ return has_native_path;
+}