]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkfilesystem.c
Updated Bulgarian translation
[~andy/gtk] / gtk / gtkfilesystem.c
index c78ae77d3898505f68898edf622e41fb70fd4174..a4a289653b9c3f601538076c05e7c2ae7ded939e 100644 (file)
  * Authors: Carlos Garnacho <carlos@imendio.com>
  */
 
-#include <gtk/gtk.h>
-#include <glib/gi18n.h>
+#include "config.h"
+
 #include <string.h>
 
+#include <glib/gi18n-lib.h>
+
+#include "gtkfilechooser.h"
 #include "gtkfilesystem.h"
+#include "gtkicontheme.h"
 #include "gtkprivate.h"
 
 /* #define DEBUG_MODE */
@@ -34,8 +38,6 @@
 #define DEBUG(x)
 #endif
 
-#define GTK_FILE_SYSTEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_FILE_SYSTEM, GtkFileSystemPrivate))
-#define GTK_FOLDER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_FOLDER, GtkFolderPrivate))
 #define FILES_PER_QUERY 100
 
 /* The pointers we return for a GtkFileSystemVolume are opaque tokens; they are
@@ -71,8 +73,6 @@ enum {
 static guint fs_signals [FS_LAST_SIGNAL] = { 0, };
 static guint folder_signals [FOLDER_LAST_SIGNAL] = { 0, };
 
-typedef struct GtkFileSystemPrivate GtkFileSystemPrivate;
-typedef struct GtkFolderPrivate GtkFolderPrivate;
 typedef struct AsyncFuncData AsyncFuncData;
 
 struct GtkFileSystemPrivate
@@ -120,27 +120,21 @@ struct GtkFileSystemBookmark
   gchar *label;
 };
 
-G_DEFINE_TYPE (GtkFileSystem, gtk_file_system, G_TYPE_OBJECT)
-
-G_DEFINE_TYPE (GtkFolder, gtk_folder, G_TYPE_OBJECT)
+G_DEFINE_TYPE (GtkFileSystem, _gtk_file_system, G_TYPE_OBJECT)
 
+G_DEFINE_TYPE (GtkFolder, _gtk_folder, G_TYPE_OBJECT)
 
-static void _gtk_folder_set_finished_loading (GtkFolder *folder,
-                                             gboolean   finished_loading);
-static void _gtk_folder_add_file             (GtkFolder *folder,
-                                             GFile     *file,
-                                             GFileInfo *info);
 
+static void gtk_folder_set_finished_loading (GtkFolder *folder,
+                                            gboolean   finished_loading);
+static void gtk_folder_add_file             (GtkFolder *folder,
+                                            GFile     *file,
+                                            GFileInfo *info);
 
-GQuark
-gtk_file_system_error_quark (void)
-{
-  return g_quark_from_static_string ("gtk-file-system-error-quark");
-}
 
 /* GtkFileSystemBookmark methods */
 void
-gtk_file_system_bookmark_free (GtkFileSystemBookmark *bookmark)
+_gtk_file_system_bookmark_free (GtkFileSystemBookmark *bookmark)
 {
   g_object_unref (bookmark->file);
   g_free (bookmark->label);
@@ -165,12 +159,11 @@ volumes_changed (GVolumeMonitor *volume_monitor,
 static void
 gtk_file_system_dispose (GObject *object)
 {
-  GtkFileSystemPrivate *priv;
+  GtkFileSystem *file_system = GTK_FILE_SYSTEM (object);
+  GtkFileSystemPrivate *priv = file_system->priv;
 
   DEBUG ("dispose");
 
-  priv = GTK_FILE_SYSTEM_GET_PRIVATE (object);
-
   if (priv->volumes)
     {
       g_slist_foreach (priv->volumes, (GFunc) g_object_unref, NULL);
@@ -185,32 +178,31 @@ gtk_file_system_dispose (GObject *object)
       priv->volume_monitor = NULL;
     }
 
-  G_OBJECT_CLASS (gtk_file_system_parent_class)->dispose (object);
+  G_OBJECT_CLASS (_gtk_file_system_parent_class)->dispose (object);
 }
 
 static void
 gtk_file_system_finalize (GObject *object)
 {
-  GtkFileSystemPrivate *priv;
+  GtkFileSystem *file_system = GTK_FILE_SYSTEM (object);
+  GtkFileSystemPrivate *priv = file_system->priv;
 
   DEBUG ("finalize");
 
-  priv = GTK_FILE_SYSTEM_GET_PRIVATE (object);
-
   if (priv->bookmarks_monitor)
     g_object_unref (priv->bookmarks_monitor);
 
   if (priv->bookmarks)
     {
-      g_slist_foreach (priv->bookmarks, (GFunc) gtk_file_system_bookmark_free, NULL);
+      g_slist_foreach (priv->bookmarks, (GFunc) _gtk_file_system_bookmark_free, NULL);
       g_slist_free (priv->bookmarks);
     }
 
-  G_OBJECT_CLASS (gtk_file_system_parent_class)->finalize (object);
+  G_OBJECT_CLASS (_gtk_file_system_parent_class)->finalize (object);
 }
 
 static void
-gtk_file_system_class_init (GtkFileSystemClass *class)
+_gtk_file_system_class_init (GtkFileSystemClass *class)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (class);
 
@@ -323,7 +315,7 @@ save_bookmarks (GFile  *bookmarks_file,
                                NULL, FALSE, 0, NULL,
                                NULL, &error))
     {
-      g_critical (error->message);
+      g_critical ("%s", error->message);
       g_error_free (error);
     }
 
@@ -337,9 +329,8 @@ bookmarks_file_changed (GFileMonitor      *monitor,
                        GFileMonitorEvent  event,
                        gpointer           data)
 {
-  GtkFileSystemPrivate *priv;
-
-  priv = GTK_FILE_SYSTEM_GET_PRIVATE (data);
+  GtkFileSystem *file_system = GTK_FILE_SYSTEM (data);
+  GtkFileSystemPrivate *priv = file_system->priv;
 
   switch (event)
     {
@@ -347,7 +338,7 @@ bookmarks_file_changed (GFileMonitor      *monitor,
     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_foreach (priv->bookmarks, (GFunc) _gtk_file_system_bookmark_free, NULL);
       g_slist_free (priv->bookmarks);
 
       priv->bookmarks = read_bookmarks (file);
@@ -362,10 +353,43 @@ bookmarks_file_changed (GFileMonitor      *monitor,
     }
 }
 
+static gboolean
+mount_referenced_by_volume_activation_root (GList *volumes, GMount *mount)
+{
+  GList *l;
+  GFile *mount_root;
+  gboolean ret;
+
+  ret = FALSE;
+
+  mount_root = g_mount_get_root (mount);
+
+  for (l = volumes; l != NULL; l = l->next)
+    {
+      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);
+        }
+    }
+
+  g_object_unref (mount_root);
+  return ret;
+}
+
 static void
 get_volumes_list (GtkFileSystem *file_system)
 {
-  GtkFileSystemPrivate *priv;
+  GtkFileSystemPrivate *priv = file_system->priv;
   GList *l, *ll;
   GList *drives;
   GList *volumes;
@@ -374,8 +398,6 @@ get_volumes_list (GtkFileSystem *file_system)
   GVolume *volume;
   GMount *mount;
 
-  priv = GTK_FILE_SYSTEM_GET_PRIVATE (file_system);
-
   if (priv->volumes)
     {
       g_slist_foreach (priv->volumes, (GFunc) g_object_unref, NULL);
@@ -419,6 +441,8 @@ get_volumes_list (GtkFileSystem *file_system)
 
              g_object_unref (volume);
             }
+  
+           g_list_free (volumes);
         }
       else if (g_drive_is_media_removable (drive) && !g_drive_is_media_check_automatic (drive))
        {
@@ -433,6 +457,8 @@ get_volumes_list (GtkFileSystem *file_system)
 
          priv->volumes = g_slist_prepend (priv->volumes, g_object_ref (drive));
        }
+
+      g_object_unref (drive);
     }
 
   g_list_free (drives);
@@ -464,9 +490,9 @@ get_volumes_list (GtkFileSystem *file_system)
           /* see comment above in why we add an icon for a volume */
           priv->volumes = g_slist_prepend (priv->volumes, g_object_ref (volume));
         }
-    }
 
-  g_list_free (volumes);
+      g_object_unref (volume);
+    }
 
   /* add mounts that has no volume (/etc/mtab mounts, ftp, sftp,...) */
   mounts = g_volume_monitor_get_mounts (priv->volume_monitor);
@@ -482,15 +508,27 @@ get_volumes_list (GtkFileSystem *file_system)
           continue;
         }
 
+      /* 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;
+        }
+
       /* show this mount */
       priv->volumes = g_slist_prepend (priv->volumes, g_object_ref (mount));
+      g_object_unref (mount);
     }
 
+  g_list_free (volumes);
+
   g_list_free (mounts);
 }
 
 static void
-gtk_file_system_init (GtkFileSystem *file_system)
+_gtk_file_system_init (GtkFileSystem *file_system)
 {
   GtkFileSystemPrivate *priv;
   GFile *bookmarks_file;
@@ -498,7 +536,10 @@ gtk_file_system_init (GtkFileSystem *file_system)
 
   DEBUG ("init");
 
-  priv = GTK_FILE_SYSTEM_GET_PRIVATE (file_system);
+  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 ();
@@ -529,7 +570,10 @@ gtk_file_system_init (GtkFileSystem *file_system)
                                                 G_FILE_MONITOR_NONE,
                                                 NULL, &error);
   if (error)
-    g_warning (error->message);
+    {
+      g_warning ("%s", error->message);
+      g_error_free (error);
+    }
   else
     g_signal_connect (priv->bookmarks_monitor, "changed",
                      G_CALLBACK (bookmarks_file_changed), file_system);
@@ -539,41 +583,39 @@ gtk_file_system_init (GtkFileSystem *file_system)
 
 /* GtkFileSystem public methods */
 GtkFileSystem *
-gtk_file_system_new (void)
+_gtk_file_system_new (void)
 {
   return g_object_new (GTK_TYPE_FILE_SYSTEM, NULL);
 }
 
 GSList *
-gtk_file_system_list_volumes (GtkFileSystem *file_system)
+_gtk_file_system_list_volumes (GtkFileSystem *file_system)
 {
-  GtkFileSystemPrivate *priv;
+  GtkFileSystemPrivate *priv = file_system->priv;
   GSList *list;
 
   DEBUG ("list_volumes");
 
-  g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
-
-  priv = GTK_FILE_SYSTEM_GET_PRIVATE (file_system);
-  get_volumes_list (GTK_FILE_SYSTEM (file_system));
+  get_volumes_list (file_system);
 
   list = g_slist_copy (priv->volumes);
 
+#ifndef G_OS_WIN32
   /* Prepend root volume */
   list = g_slist_prepend (list, (gpointer) root_volume_token);
+#endif
 
   return list;
 }
 
 GSList *
-gtk_file_system_list_bookmarks (GtkFileSystem *file_system)
+_gtk_file_system_list_bookmarks (GtkFileSystem *file_system)
 {
-  GtkFileSystemPrivate *priv;
+  GtkFileSystemPrivate *priv = file_system->priv;
   GSList *bookmarks, *files = NULL;
 
   DEBUG ("list_bookmarks");
 
-  priv = GTK_FILE_SYSTEM_GET_PRIVATE (file_system);
   bookmarks = priv->bookmarks;
 
   while (bookmarks)
@@ -589,18 +631,42 @@ gtk_file_system_list_bookmarks (GtkFileSystem *file_system)
   return g_slist_reverse (files);
 }
 
+static gboolean
+is_valid_scheme_character (char c)
+{
+  return g_ascii_isalnum (c) || c == '+' || c == '-' || c == '.';
+}
+
+static gboolean
+has_uri_scheme (const char *str)
+{
+  const char *p;
+
+  p = str;
+
+  if (!is_valid_scheme_character (*p))
+    return FALSE;
+
+  do
+    p++;
+  while (is_valid_scheme_character (*p));
+
+  return (strncmp (p, "://", 3) == 0);
+}
+
 gboolean
-gtk_file_system_parse (GtkFileSystem     *file_system,
-                      GFile             *base_file,
-                      const gchar       *str,
-                      GFile            **folder,
-                      gchar            **file_part,
-                      GError           **error)
+_gtk_file_system_parse (GtkFileSystem     *file_system,
+                       GFile             *base_file,
+                       const gchar       *str,
+                       GFile            **folder,
+                       gchar            **file_part,
+                       GError           **error)
 {
   GFile *file;
   gboolean result = FALSE;
   gboolean is_dir = FALSE;
   gchar *last_slash = NULL;
+  gboolean is_uri;
 
   DEBUG ("parse");
 
@@ -609,7 +675,37 @@ gtk_file_system_parse (GtkFileSystem     *file_system,
 
   last_slash = strrchr (str, G_DIR_SEPARATOR);
 
-  if (str[0] == '~')
+  is_uri = has_uri_scheme (str);
+
+  if (is_uri)
+    {
+      const char *colon;
+      const char *slash_after_hostname;
+
+      colon = strchr (str, ':');
+      g_assert (colon != NULL);
+      g_assert (strncmp (colon, "://", 3) == 0);
+
+      slash_after_hostname = strchr (colon + 3, '/');
+
+      if (slash_after_hostname == NULL)
+       {
+         /* We don't have a full hostname yet.  So, don't switch the folder
+          * until we have seen a full hostname.  Otherwise, completion will
+          * happen for every character the user types for the hostname.
+          */
+
+         *folder = NULL;
+         *file_part = NULL;
+         g_set_error (error,
+                      GTK_FILE_CHOOSER_ERROR,
+                      GTK_FILE_CHOOSER_ERROR_INCOMPLETE_HOSTNAME,
+                      "Incomplete hostname");
+         return FALSE;
+       }
+    }
+
+  if (str[0] == '~' || g_path_is_absolute (str) || is_uri)
     file = g_file_parse_name (str);
   else
     file = g_file_resolve_relative_path (base_file, str);
@@ -639,8 +735,8 @@ gtk_file_system_parse (GtkFileSystem     *file_system,
       if (!parent_file)
        {
          g_set_error (error,
-                      GTK_FILE_SYSTEM_ERROR,
-                      GTK_FILE_SYSTEM_ERROR_NONEXISTENT,
+                      GTK_FILE_CHOOSER_ERROR,
+                      GTK_FILE_CHOOSER_ERROR_NONEXISTENT,
                       "Could not get parent file");
          *folder = NULL;
          *file_part = NULL;
@@ -713,11 +809,11 @@ enumerate_children_callback (GObject      *source_object,
 }
 
 GCancellable *
-gtk_file_system_get_folder (GtkFileSystem                  *file_system,
-                           GFile                          *file,
-                           const gchar                    *attributes,
-                           GtkFileSystemGetFolderCallback  callback,
-                           gpointer                        data)
+_gtk_file_system_get_folder (GtkFileSystem                  *file_system,
+                            GFile                          *file,
+                            const gchar                    *attributes,
+                            GtkFileSystemGetFolderCallback  callback,
+                            gpointer                        data)
 {
   GCancellable *cancellable;
   AsyncFuncData *async_data;
@@ -780,11 +876,11 @@ query_info_callback (GObject      *source_object,
 }
 
 GCancellable *
-gtk_file_system_get_info (GtkFileSystem                *file_system,
-                         GFile                        *file,
-                         const gchar                  *attributes,
-                         GtkFileSystemGetInfoCallback  callback,
-                         gpointer                      data)
+_gtk_file_system_get_info (GtkFileSystem                *file_system,
+                          GFile                        *file,
+                          const gchar                  *attributes,
+                          GtkFileSystemGetInfoCallback  callback,
+                          gpointer                      data)
 {
   GCancellable *cancellable;
   AsyncFuncData *async_data;
@@ -856,11 +952,11 @@ volume_mount_cb (GObject      *source_object,
 }
 
 GCancellable *
-gtk_file_system_mount_volume (GtkFileSystem                    *file_system,
-                             GtkFileSystemVolume              *volume,
-                             GMountOperation                  *mount_operation,
-                             GtkFileSystemVolumeMountCallback  callback,
-                             gpointer                          data)
+_gtk_file_system_mount_volume (GtkFileSystem                    *file_system,
+                              GtkFileSystemVolume              *volume,
+                              GMountOperation                  *mount_operation,
+                              GtkFileSystemVolumeMountCallback  callback,
+                              gpointer                          data)
 {
   GCancellable *cancellable;
   AsyncFuncData *async_data;
@@ -909,7 +1005,12 @@ enclosing_volume_mount_cb (GObject      *source_object,
 
   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));
+  volume = _gtk_file_system_get_volume_for_file (async_data->file_system, G_FILE (source_object));
+
+  /* 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);
 
   gdk_threads_enter ();
   ((GtkFileSystemVolumeMountCallback) async_data->callback) (async_data->cancellable, volume,
@@ -918,14 +1019,16 @@ enclosing_volume_mount_cb (GObject      *source_object,
 
   if (error)
     g_error_free (error);
+
+  _gtk_file_system_volume_unref (volume);
 }
 
 GCancellable *
-gtk_file_system_mount_enclosing_volume (GtkFileSystem                     *file_system,
-                                       GFile                             *file,
-                                       GMountOperation                   *mount_operation,
-                                       GtkFileSystemVolumeMountCallback   callback,
-                                       gpointer                           data)
+_gtk_file_system_mount_enclosing_volume (GtkFileSystem                     *file_system,
+                                        GFile                             *file,
+                                        GMountOperation                   *mount_operation,
+                                        GtkFileSystemVolumeMountCallback   callback,
+                                        gpointer                           data)
 {
   GCancellable *cancellable;
   AsyncFuncData *async_data;
@@ -955,18 +1058,17 @@ gtk_file_system_mount_enclosing_volume (GtkFileSystem                     *file_
 }
 
 gboolean
-gtk_file_system_insert_bookmark (GtkFileSystem  *file_system,
-                                GFile          *file,
-                                gint            position,
-                                GError        **error)
+_gtk_file_system_insert_bookmark (GtkFileSystem  *file_system,
+                                 GFile          *file,
+                                 gint            position,
+                                 GError        **error)
 {
-  GtkFileSystemPrivate *priv;
+  GtkFileSystemPrivate *priv = file_system->priv;
   GSList *bookmarks;
   GtkFileSystemBookmark *bookmark;
   gboolean result = TRUE;
   GFile *bookmarks_file;
 
-  priv = GTK_FILE_SYSTEM_GET_PRIVATE (file_system);
   bookmarks = priv->bookmarks;
 
   while (bookmarks)
@@ -987,8 +1089,8 @@ gtk_file_system_insert_bookmark (GtkFileSystem  *file_system,
       gchar *uri = g_file_get_uri (file);
 
       g_set_error (error,
-                  GTK_FILE_SYSTEM_ERROR,
-                  GTK_FILE_SYSTEM_ERROR_ALREADY_EXISTS,
+                  GTK_FILE_CHOOSER_ERROR,
+                  GTK_FILE_CHOOSER_ERROR_ALREADY_EXISTS,
                   "%s already exists in the bookmarks list",
                   uri);
 
@@ -1012,18 +1114,16 @@ gtk_file_system_insert_bookmark (GtkFileSystem  *file_system,
 }
 
 gboolean
-gtk_file_system_remove_bookmark (GtkFileSystem  *file_system,
-                                GFile          *file,
-                                GError        **error)
+_gtk_file_system_remove_bookmark (GtkFileSystem  *file_system,
+                                 GFile          *file,
+                                 GError        **error)
 {
-  GtkFileSystemPrivate *priv;
+  GtkFileSystemPrivate *priv = file_system->priv;
   GtkFileSystemBookmark *bookmark;
   GSList *bookmarks;
   gboolean result = FALSE;
   GFile *bookmarks_file;
 
-  priv = GTK_FILE_SYSTEM_GET_PRIVATE (file_system);
-
   if (!priv->bookmarks)
     return FALSE;
 
@@ -1037,7 +1137,7 @@ gtk_file_system_remove_bookmark (GtkFileSystem  *file_system,
        {
          result = TRUE;
          priv->bookmarks = g_slist_remove_link (priv->bookmarks, bookmarks);
-         gtk_file_system_bookmark_free (bookmark);
+         _gtk_file_system_bookmark_free (bookmark);
          g_slist_free_1 (bookmarks);
          break;
        }
@@ -1050,8 +1150,8 @@ gtk_file_system_remove_bookmark (GtkFileSystem  *file_system,
       gchar *uri = g_file_get_uri (file);
 
       g_set_error (error,
-                  GTK_FILE_SYSTEM_ERROR,
-                  GTK_FILE_SYSTEM_ERROR_NONEXISTENT,
+                  GTK_FILE_CHOOSER_ERROR,
+                  GTK_FILE_CHOOSER_ERROR_NONEXISTENT,
                   "%s does not exist in the bookmarks list",
                   uri);
 
@@ -1070,16 +1170,15 @@ gtk_file_system_remove_bookmark (GtkFileSystem  *file_system,
 }
 
 gchar *
-gtk_file_system_get_bookmark_label (GtkFileSystem *file_system,
-                                   GFile         *file)
+_gtk_file_system_get_bookmark_label (GtkFileSystem *file_system,
+                                    GFile         *file)
 {
-  GtkFileSystemPrivate *priv;
+  GtkFileSystemPrivate *priv = file_system->priv;
   GSList *bookmarks;
   gchar *label = NULL;
 
   DEBUG ("get_bookmark_label");
 
-  priv = GTK_FILE_SYSTEM_GET_PRIVATE (file_system);
   bookmarks = priv->bookmarks;
 
   while (bookmarks)
@@ -1100,18 +1199,17 @@ gtk_file_system_get_bookmark_label (GtkFileSystem *file_system,
 }
 
 void
-gtk_file_system_set_bookmark_label (GtkFileSystem *file_system,
-                                   GFile         *file,
-                                   const gchar   *label)
+_gtk_file_system_set_bookmark_label (GtkFileSystem *file_system,
+                                    GFile         *file,
+                                    const gchar   *label)
 {
-  GtkFileSystemPrivate *priv;
+  GtkFileSystemPrivate *priv = file_system->priv;
   gboolean changed = FALSE;
   GFile *bookmarks_file;
   GSList *bookmarks;
 
   DEBUG ("set_bookmark_label");
 
-  priv = GTK_FILE_SYSTEM_GET_PRIVATE (file_system);
   bookmarks = priv->bookmarks;
 
   while (bookmarks)
@@ -1123,7 +1221,7 @@ gtk_file_system_set_bookmark_label (GtkFileSystem *file_system,
 
       if (g_file_equal (file, bookmark->file))
        {
-         g_free (bookmark->file);
+          g_free (bookmark->label);
          bookmark->label = g_strdup (label);
          changed = TRUE;
          break;
@@ -1139,15 +1237,13 @@ gtk_file_system_set_bookmark_label (GtkFileSystem *file_system,
 }
 
 GtkFileSystemVolume *
-gtk_file_system_get_volume_for_file (GtkFileSystem *file_system,
-                                    GFile         *file)
+_gtk_file_system_get_volume_for_file (GtkFileSystem *file_system,
+                                     GFile         *file)
 {
-  GtkFileSystemPrivate *priv;
   GMount *mount;
 
   DEBUG ("get_volume_for_file");
 
-  priv = GTK_FILE_SYSTEM_GET_PRIVATE (file_system);
   mount = g_file_find_enclosing_mount (file, NULL, NULL);
 
   if (!mount && g_file_is_native (file))
@@ -1163,9 +1259,8 @@ gtk_folder_set_property (GObject      *object,
                         const GValue *value,
                         GParamSpec   *pspec)
 {
-  GtkFolderPrivate *priv;
-
-  priv = GTK_FOLDER_GET_PRIVATE (object);
+  GtkFolder *folder = GTK_FOLDER (object);
+  GtkFolderPrivate *priv = folder->priv;
 
   switch (prop_id)
     {
@@ -1190,9 +1285,8 @@ gtk_folder_get_property (GObject    *object,
                         GValue     *value,
                         GParamSpec *pspec)
 {
-  GtkFolderPrivate *priv;
-
-  priv = GTK_FOLDER_GET_PRIVATE (object);
+  GtkFolder *folder = GTK_FOLDER (object);
+  GtkFolderPrivate *priv = folder->priv;
 
   switch (prop_id)
     {
@@ -1231,7 +1325,7 @@ query_created_file_info_callback (GObject      *source_object,
     }
 
   folder = GTK_FOLDER (user_data);
-  _gtk_folder_add_file (folder, file, info);
+  gtk_folder_add_file (folder, file, info);
 
   files = g_slist_prepend (NULL, file);
   g_signal_emit (folder, folder_signals[FILES_ADDED], 0, files);
@@ -1247,12 +1341,10 @@ directory_monitor_changed (GFileMonitor      *monitor,
                           GFileMonitorEvent  event,
                           gpointer           data)
 {
-  GtkFolderPrivate *priv;
-  GtkFolder *folder;
+  GtkFolder *folder = GTK_FOLDER (data);
+  GtkFolderPrivate *priv = folder->priv;
   GSList *files;
 
-  folder = GTK_FOLDER (data);
-  priv = GTK_FOLDER_GET_PRIVATE (folder);
   files = g_slist_prepend (NULL, file);
 
   gdk_threads_enter ();
@@ -1288,9 +1380,9 @@ enumerator_files_callback (GObject      *source_object,
                           GAsyncResult *result,
                           gpointer      user_data)
 {
+  GtkFolder *folder = GTK_FOLDER (user_data);
+  GtkFolderPrivate *priv = folder->priv;
   GFileEnumerator *enumerator;
-  GtkFolderPrivate *priv;
-  GtkFolder *folder;
   GError *error = NULL;
   GSList *files = NULL;
   GList *file_infos, *f;
@@ -1300,21 +1392,20 @@ enumerator_files_callback (GObject      *source_object,
 
   if (error)
     {
-      g_warning (error->message);
+      if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+        g_warning ("%s", error->message);
+
       g_error_free (error);
       return;
     }
 
-  folder = GTK_FOLDER (user_data);
-  priv = GTK_FOLDER_GET_PRIVATE (folder);
-
   if (!file_infos)
     {
       g_file_enumerator_close_async (enumerator,
                                     G_PRIORITY_DEFAULT,
                                     NULL, NULL, NULL);
 
-      _gtk_folder_set_finished_loading (folder, TRUE);
+      gtk_folder_set_finished_loading (folder, TRUE);
       return;
     }
 
@@ -1331,7 +1422,7 @@ enumerator_files_callback (GObject      *source_object,
 
       info = f->data;
       child_file = g_file_get_child (priv->folder_file, g_file_info_get_name (info));
-      _gtk_folder_add_file (folder, child_file, info);
+      gtk_folder_add_file (folder, child_file, info);
       files = g_slist_prepend (files, child_file);
     }
 
@@ -1349,14 +1440,17 @@ enumerator_files_callback (GObject      *source_object,
 static void
 gtk_folder_constructed (GObject *object)
 {
-  GtkFolderPrivate *priv;
+  GtkFolder *folder = GTK_FOLDER (object);
+  GtkFolderPrivate *priv = folder->priv;
   GError *error = NULL;
 
-  priv = GTK_FOLDER_GET_PRIVATE (object);
   priv->directory_monitor = g_file_monitor_directory (priv->folder_file, G_FILE_MONITOR_NONE, NULL, &error);
 
   if (error)
-    g_warning (error->message);
+    {
+      g_warning ("%s", error->message);
+      g_error_free (error);
+    }
   else
     g_signal_connect (priv->directory_monitor, "changed",
                      G_CALLBACK (directory_monitor_changed), object);
@@ -1375,9 +1469,8 @@ gtk_folder_constructed (GObject *object)
 static void
 gtk_folder_finalize (GObject *object)
 {
-  GtkFolderPrivate *priv;
-
-  priv = GTK_FOLDER_GET_PRIVATE (object);
+  GtkFolder *folder = GTK_FOLDER (object);
+  GtkFolderPrivate *priv = folder->priv;
 
   g_hash_table_unref (priv->children);
 
@@ -1391,11 +1484,11 @@ gtk_folder_finalize (GObject *object)
   g_object_unref (priv->cancellable);
   g_free (priv->attributes);
 
-  G_OBJECT_CLASS (gtk_folder_parent_class)->finalize (object);
+  G_OBJECT_CLASS (_gtk_folder_parent_class)->finalize (object);
 }
 
 static void
-gtk_folder_class_init (GtkFolderClass *class)
+_gtk_folder_class_init (GtkFolderClass *class)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (class);
 
@@ -1470,11 +1563,9 @@ gtk_folder_class_init (GtkFolderClass *class)
 }
 
 static void
-gtk_folder_init (GtkFolder *folder)
+_gtk_folder_init (GtkFolder *folder)
 {
-  GtkFolderPrivate *priv;
-
-  priv = GTK_FOLDER_GET_PRIVATE (folder);
+  GtkFolderPrivate *priv = folder->priv;
 
   priv->children = g_hash_table_new_full (g_file_hash,
                                          (GEqualFunc) g_file_equal,
@@ -1484,12 +1575,11 @@ gtk_folder_init (GtkFolder *folder)
 }
 
 static void
-_gtk_folder_set_finished_loading (GtkFolder *folder,
-                                 gboolean   finished_loading)
+gtk_folder_set_finished_loading (GtkFolder *folder,
+                                gboolean   finished_loading)
 {
-  GtkFolderPrivate *priv;
+  GtkFolderPrivate *priv = folder->priv;
 
-  priv = GTK_FOLDER_GET_PRIVATE (folder);
   priv->finished_loading = (finished_loading == TRUE);
 
   gdk_threads_enter ();
@@ -1498,13 +1588,11 @@ _gtk_folder_set_finished_loading (GtkFolder *folder,
 }
 
 static void
-_gtk_folder_add_file (GtkFolder *folder,
-                     GFile     *file,
-                     GFileInfo *info)
+gtk_folder_add_file (GtkFolder *folder,
+                    GFile     *file,
+                    GFileInfo *info)
 {
-  GtkFolderPrivate *priv;
-
-  priv = GTK_FOLDER_GET_PRIVATE (folder);
+  GtkFolderPrivate *priv = folder->priv;
 
   g_hash_table_insert (priv->children,
                       g_object_ref (file),
@@ -1512,13 +1600,12 @@ _gtk_folder_add_file (GtkFolder *folder,
 }
 
 GSList *
-gtk_folder_list_children (GtkFolder *folder)
+_gtk_folder_list_children (GtkFolder *folder)
 {
-  GtkFolderPrivate *priv;
+  GtkFolderPrivate *priv = folder->priv;
   GList *files, *elem;
   GSList *children = NULL;
 
-  priv = GTK_FOLDER_GET_PRIVATE (folder);
   files = g_hash_table_get_keys (priv->children);
   children = NULL;
 
@@ -1531,13 +1618,12 @@ gtk_folder_list_children (GtkFolder *folder)
 }
 
 GFileInfo *
-gtk_folder_get_info (GtkFolder  *folder,
-                    GFile      *file)
+_gtk_folder_get_info (GtkFolder  *folder,
+                     GFile      *file)
 {
-  GtkFolderPrivate *priv;
+  GtkFolderPrivate *priv = folder->priv;
   GFileInfo *info;
 
-  priv = GTK_FOLDER_GET_PRIVATE (folder);
   info = g_hash_table_lookup (priv->children, file);
 
   if (!info)
@@ -1547,18 +1633,14 @@ gtk_folder_get_info (GtkFolder  *folder,
 }
 
 gboolean
-gtk_folder_is_finished_loading (GtkFolder *folder)
+_gtk_folder_is_finished_loading (GtkFolder *folder)
 {
-  GtkFolderPrivate *priv;
-
-  priv = GTK_FOLDER_GET_PRIVATE (folder);
-
-  return priv->finished_loading;
+  return folder->priv->finished_loading;
 }
 
 /* GtkFileSystemVolume public methods */
 gchar *
-gtk_file_system_volume_get_display_name (GtkFileSystemVolume *volume)
+_gtk_file_system_volume_get_display_name (GtkFileSystemVolume *volume)
 {
   DEBUG ("volume_get_display_name");
 
@@ -1575,7 +1657,7 @@ gtk_file_system_volume_get_display_name (GtkFileSystemVolume *volume)
 }
 
 gboolean
-gtk_file_system_volume_is_mounted (GtkFileSystemVolume *volume)
+_gtk_file_system_volume_is_mounted (GtkFileSystemVolume *volume)
 {
   gboolean mounted;
 
@@ -1605,7 +1687,7 @@ gtk_file_system_volume_is_mounted (GtkFileSystemVolume *volume)
 }
 
 GFile *
-gtk_file_system_volume_get_root (GtkFileSystemVolume *volume)
+_gtk_file_system_volume_get_root (GtkFileSystemVolume *volume)
 {
   GFile *file = NULL;
 
@@ -1660,85 +1742,25 @@ get_pixbuf_from_gicon (GIcon      *icon,
   return pixbuf;
 }
 
-static GIcon *
-get_icon_for_special_directory (GFile *file)
-{
-  const gchar *special_dir;
-  GFile *special_file;
-
-  special_dir = g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP);
-  special_file = g_file_new_for_path (special_dir);
-
-  if (g_file_equal (file, special_file))
-    {
-      const char *names[] = { 
-        "user-desktop", 
-        "gnome-fs-desktop", 
-        "folder", 
-        "gtk-directory",
-        NULL 
-      };
-      g_object_unref (special_file);
-      return g_themed_icon_new_from_names (names, -1);
-    }
-
-  g_object_unref (special_file);
-  special_dir = g_get_home_dir ();
-  special_file = g_file_new_for_path (special_dir);
-
-  if (g_file_equal (file, special_file))
-    {
-      const char *names[] = { 
-        "user-home", 
-        "gnome-fs-home", 
-        "folder", 
-        "gtk-directory",
-        NULL 
-      };
-      g_object_unref (special_file);
-      return g_themed_icon_new_from_names (names, -1);
-    }
-
-  g_object_unref (special_file);
-
-  return NULL;
-}
-
 GdkPixbuf *
-gtk_file_system_volume_render_icon (GtkFileSystemVolume  *volume,
-                                   GtkWidget            *widget,
-                                   gint                  icon_size,
-                                   GError              **error)
+_gtk_file_system_volume_render_icon (GtkFileSystemVolume  *volume,
+                                    GtkWidget            *widget,
+                                    gint                  icon_size,
+                                    GError              **error)
 {
   GIcon *icon = NULL;
   GdkPixbuf *pixbuf;
-  const char *harddisk_icons[] = { 
-    "drive-harddisk", 
-    "gnome-dev-harddisk", 
-    "gtk-harddisk",
-    NULL
-  };
 
   DEBUG ("volume_get_icon_name");
 
   if (IS_ROOT_VOLUME (volume))
-    icon = g_themed_icon_new_from_names (harddisk_icons, -1);
+    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))
-    {
-      GMount *mount = G_MOUNT (volume);
-      GFile *file;
-
-      file = g_mount_get_root (mount);
-      icon = get_icon_for_special_directory (file);
-      g_object_unref (file);
-
-      if (!icon)
-       icon = g_mount_get_icon (mount);
-    }
+    icon = g_mount_get_icon (G_MOUNT (volume));
 
   if (!icon)
     return NULL;
@@ -1750,8 +1772,22 @@ gtk_file_system_volume_render_icon (GtkFileSystemVolume  *volume,
   return pixbuf;
 }
 
+GtkFileSystemVolume *
+_gtk_file_system_volume_ref (GtkFileSystemVolume *volume)
+{
+  if (IS_ROOT_VOLUME (volume))
+    return volume;
+
+  if (G_IS_MOUNT (volume)  ||
+      G_IS_VOLUME (volume) ||
+      G_IS_DRIVE (volume))
+    g_object_ref (volume);
+
+  return volume;
+}
+
 void
-gtk_file_system_volume_free (GtkFileSystemVolume *volume)
+_gtk_file_system_volume_unref (GtkFileSystemVolume *volume)
 {
   /* Root volume doesn't need to be freed */
   if (IS_ROOT_VOLUME (volume))
@@ -1765,13 +1801,13 @@ gtk_file_system_volume_free (GtkFileSystemVolume *volume)
 
 /* GFileInfo helper functions */
 GdkPixbuf *
-gtk_file_info_render_icon (GFileInfo *info,
+_gtk_file_info_render_icon (GFileInfo *info,
                           GtkWidget *widget,
                           gint       icon_size)
 {
   GIcon *icon;
   GdkPixbuf *pixbuf = NULL;
-  gchar *thumbnail_path;
+  const gchar *thumbnail_path;
 
   thumbnail_path = g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH);
 
@@ -1786,7 +1822,26 @@ gtk_file_info_render_icon (GFileInfo *info,
 
       if (icon)
        pixbuf = get_pixbuf_from_gicon (icon, widget, icon_size, NULL);
+
+      if (!pixbuf)
+       {
+          /* 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);
+       }
     }
 
   return pixbuf;
 }
+
+gboolean
+_gtk_file_info_consider_as_directory (GFileInfo *info)
+{
+  GFileType type = g_file_info_get_file_type (info);
+  
+  return (type == G_FILE_TYPE_DIRECTORY ||
+          type == G_FILE_TYPE_MOUNTABLE ||
+          type == G_FILE_TYPE_SHORTCUT);
+}
+