[Xfce4-commits] <thunar:master> Use ThunarDevice in the tree side pane.

Nick Schermer noreply at xfce.org
Sat Oct 13 16:12:20 CEST 2012


Updating branch refs/heads/master
         to 3dee1594752e97e7958abbfb029ce59ce026fe8f (commit)
       from 24a3e95c1c840c5104f9918d413002737489c9ef (commit)

commit 3dee1594752e97e7958abbfb029ce59ce026fe8f
Author: Nick Schermer <nick at xfce.org>
Date:   Sun Oct 7 01:16:53 2012 +0200

    Use ThunarDevice in the tree side pane.

 thunar/thunar-browser.h                 |    2 +-
 thunar/thunar-device.c                  |   45 ++++
 thunar/thunar-gio-extensions.c          |   29 --
 thunar/thunar-gio-extensions.h          |    1 -
 thunar/thunar-shortcuts-icon-renderer.c |   32 +---
 thunar/thunar-tree-model.c              |  336 ++++++++++---------------
 thunar/thunar-tree-model.h              |    4 +-
 thunar/thunar-tree-view.c               |  426 +++++++++++++++----------------
 8 files changed, 384 insertions(+), 491 deletions(-)

diff --git a/thunar/thunar-browser.h b/thunar/thunar-browser.h
index 77dae0a..f0ebce9 100644
--- a/thunar/thunar-browser.h
+++ b/thunar/thunar-browser.h
@@ -74,7 +74,7 @@ void  thunar_browser_poke_volume   (ThunarBrowser                 *browser,
                                     ThunarBrowserPokeVolumeFunc    func,
                                     gpointer                       user_data);
 void  thunar_browser_poke_location (ThunarBrowser                 *browser,
-                                    GFile                           *location,
+                                    GFile                         *location,
                                     gpointer                       widget,
                                     ThunarBrowserPokeLocationFunc  func,
                                     gpointer                       user_data);
diff --git a/thunar/thunar-device.c b/thunar/thunar-device.c
index 0178014..3ea4f92 100644
--- a/thunar/thunar-device.c
+++ b/thunar/thunar-device.c
@@ -281,6 +281,38 @@ thunar_device_mount_eject_finish (GObject      *object,
 
 
 static void
+thunar_device_volume_mount_finished (GObject      *object,
+                                     GAsyncResult *result,
+                                     gpointer      user_data)
+{
+  ThunarDeviceOperation *operation = user_data;
+  GError                *error = NULL;
+
+  _thunar_return_if_fail (G_IS_VOLUME (object));
+  _thunar_return_if_fail (G_IS_ASYNC_RESULT (result));
+  
+  /* finish the eject */
+  if (!g_volume_eject_with_operation_finish (G_VOLUME (object), result, &error))
+    {
+      /* unset the error if a helper program has already interacted with the user */
+      if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_FAILED_HANDLED)
+          || g_error_matches (error, G_IO_ERROR, G_IO_ERROR_ALREADY_MOUNTED)
+          || g_error_matches (error, G_IO_ERROR, G_IO_ERROR_PENDING))
+        g_clear_error (&error);
+    }
+
+  /* callback */
+  (operation->callback) (operation->device, error, operation->user_data);
+
+  /* cleanup */
+  if (error != NULL)
+    g_error_free (error);
+  thunar_device_operation_free (operation);
+}
+
+
+
+static void
 thunar_device_volume_eject_finish (GObject      *object,
                                    GAsyncResult *result,
                                    gpointer      user_data)
@@ -554,10 +586,23 @@ thunar_device_mount (ThunarDevice         *device,
                      ThunarDeviceCallback  callback,
                      gpointer              user_data)
 {
+  ThunarDeviceOperation *operation;
+  
   _thunar_return_if_fail (THUNAR_IS_DEVICE (device));
   _thunar_return_if_fail (G_IS_MOUNT_OPERATION (mount_operation));
   _thunar_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
   _thunar_return_if_fail (callback != NULL);
+  
+  if (G_IS_VOLUME (device->device))
+    {
+      operation = thunar_device_operation_new (device, callback, user_data);
+      g_volume_mount (G_VOLUME (device->device),
+                      G_MOUNT_MOUNT_NONE,
+                      mount_operation,
+                      cancellable,
+                      thunar_device_volume_mount_finished,
+                      operation);
+    }
 }
 
 
diff --git a/thunar/thunar-gio-extensions.c b/thunar/thunar-gio-extensions.c
index ae52cda..1432fff 100644
--- a/thunar/thunar-gio-extensions.c
+++ b/thunar/thunar-gio-extensions.c
@@ -549,35 +549,6 @@ thunar_g_volume_is_mounted (GVolume *volume)
 
 
 
-gboolean 
-thunar_g_volume_is_present (GVolume *volume)
-{
-  gboolean has_media = FALSE;
-  gboolean is_shadowed = FALSE;
-  GDrive  *drive;
-  GMount  *mount;
-
-  _thunar_return_val_if_fail (G_IS_VOLUME (volume), FALSE);
-
-  drive = g_volume_get_drive (volume);
-  if (drive != NULL)
-    {
-      has_media = g_drive_has_media (drive);
-      g_object_unref (drive);
-    }
-
-  mount = g_volume_get_mount (volume);
-  if (mount != NULL)
-    {
-      is_shadowed = g_mount_is_shadowed (mount);
-      g_object_unref (mount);
-    }
-
-  return has_media && !is_shadowed;
-}
-
-
-
 gboolean
 thunar_g_app_info_launch (GAppInfo          *info,
                           GFile             *working_directory,
diff --git a/thunar/thunar-gio-extensions.h b/thunar/thunar-gio-extensions.h
index 7afb1dd..c6e8cf7 100644
--- a/thunar/thunar-gio-extensions.h
+++ b/thunar/thunar-gio-extensions.h
@@ -71,7 +71,6 @@ void      thunar_g_file_list_free                   (GList             *list);
 
 gboolean  thunar_g_volume_is_removable              (GVolume           *volume);
 gboolean  thunar_g_volume_is_mounted                (GVolume           *volume);
-gboolean  thunar_g_volume_is_present                (GVolume           *volume);
 
 gboolean  thunar_g_app_info_launch                  (GAppInfo          *info,
                                                      GFile             *working_directory,
diff --git a/thunar/thunar-shortcuts-icon-renderer.c b/thunar/thunar-shortcuts-icon-renderer.c
index 3797140..b49de6a 100644
--- a/thunar/thunar-shortcuts-icon-renderer.c
+++ b/thunar/thunar-shortcuts-icon-renderer.c
@@ -36,7 +36,6 @@
 enum
 {
   PROP_0,
-  PROP_VOLUME,
   PROP_DEVICE,
   PROP_GICON,
 };
@@ -71,7 +70,6 @@ struct _ThunarShortcutsIconRenderer
 {
   ThunarIconRenderer __parent__;
 
-  GVolume           *volume;
   ThunarDevice      *device;
   GIcon             *gicon;
 };
@@ -97,18 +95,6 @@ thunar_shortcuts_icon_renderer_class_init (ThunarShortcutsIconRendererClass *kla
   gtkcell_renderer_class->render = thunar_shortcuts_icon_renderer_render;
 
   /**
-   * ThunarShortcutsIconRenderer:volume:
-   *
-   * The #GVolume for which to render an icon or %NULL to fallback
-   * to the default icon renderering (see #ThunarIconRenderer).
-   **/
-  g_object_class_install_property (gobject_class,
-                                   PROP_VOLUME,
-                                   g_param_spec_object ("volume", "volume", "volume",
-                                                        G_TYPE_VOLUME,
-                                                        EXO_PARAM_READWRITE));
-
-  /**
    * ThunarShortcutsIconRenderer:device:
    *
    * The #ThunarDevice for which to render an icon or %NULL to fallback
@@ -150,9 +136,6 @@ thunar_shortcuts_icon_renderer_finalize (GObject *object)
 {
   ThunarShortcutsIconRenderer *renderer = THUNAR_SHORTCUTS_ICON_RENDERER (object);
 
-  if (G_UNLIKELY (renderer->volume != NULL))
-    g_object_unref (renderer->volume);
-
   if (G_UNLIKELY (renderer->device != NULL))
     g_object_unref (renderer->device);
 
@@ -174,10 +157,6 @@ thunar_shortcuts_icon_renderer_get_property (GObject    *object,
 
   switch (prop_id)
     {
-    case PROP_VOLUME:
-      g_value_set_object (value, renderer->volume);
-      break;
-
     case PROP_DEVICE:
       g_value_set_object (value, renderer->device);
       break;
@@ -204,12 +183,6 @@ thunar_shortcuts_icon_renderer_set_property (GObject      *object,
 
   switch (prop_id)
     {
-    case PROP_VOLUME:
-      if (G_UNLIKELY (renderer->volume != NULL))
-        g_object_unref (renderer->volume);
-      renderer->volume = g_value_dup_object (value);
-      break;
-
     case PROP_DEVICE:
       if (G_UNLIKELY (renderer->device != NULL))
         g_object_unref (renderer->device);
@@ -249,8 +222,7 @@ thunar_shortcuts_icon_renderer_render (GtkCellRenderer     *renderer,
   GIcon                       *gicon;
 
   /* check if we have a volume set */
-  if (G_UNLIKELY (shortcuts_icon_renderer->volume != NULL
-      || shortcuts_icon_renderer->gicon != NULL
+  if (G_UNLIKELY (shortcuts_icon_renderer->gicon != NULL
       ||  shortcuts_icon_renderer->device != NULL))
     {
       /* load the volume icon */
@@ -259,8 +231,6 @@ thunar_shortcuts_icon_renderer_render (GtkCellRenderer     *renderer,
       /* look up the icon info */
       if (shortcuts_icon_renderer->gicon != NULL)
         gicon = g_object_ref (shortcuts_icon_renderer->gicon);
-      else if (shortcuts_icon_renderer->volume != NULL)
-        gicon = g_volume_get_icon (shortcuts_icon_renderer->volume);
       else
         gicon = thunar_device_get_icon (shortcuts_icon_renderer->device);
 
diff --git a/thunar/thunar-tree-model.c b/thunar/thunar-tree-model.c
index df7c34d..4cbf0e5 100644
--- a/thunar/thunar-tree-model.c
+++ b/thunar/thunar-tree-model.c
@@ -36,6 +36,7 @@
 #include <thunar/thunar-preferences.h>
 #include <thunar/thunar-private.h>
 #include <thunar/thunar-tree-model.h>
+#include <thunar/thunar-device-monitor.h>
 
 
 
@@ -114,22 +115,19 @@ static void                 thunar_tree_model_cleanup_idle_destroy    (gpointer
 static void                 thunar_tree_model_file_changed            (ThunarFileMonitor      *file_monitor,
                                                                        ThunarFile             *file,
                                                                        ThunarTreeModel        *model);
-static void                 thunar_tree_model_mount_pre_unmount       (GVolumeMonitor         *volume_monitor,
-                                                                       GMount                 *mount,
+static void                 thunar_tree_model_device_added            (ThunarDeviceMonitor    *device_monitor,
+                                                                       ThunarDevice           *device,
                                                                        ThunarTreeModel        *model);
-static void                 thunar_tree_model_volume_added            (GVolumeMonitor         *volume_monitor,
-                                                                       GVolume                *volume,
+static void                 thunar_tree_model_device_removed          (ThunarDeviceMonitor    *device_monitor,
+                                                                       ThunarDevice           *device,
                                                                        ThunarTreeModel        *model);
-static void                 thunar_tree_model_volume_removed          (GVolumeMonitor         *volume_monitor,
-                                                                       GVolume                *volume,
-                                                                       ThunarTreeModel        *model);
-static void                 thunar_tree_model_volume_changed          (GVolumeMonitor         *volume_monitor,
-                                                                       GVolume                *volume,
+static void                 thunar_tree_model_device_changed          (ThunarDeviceMonitor    *device_monitor,
+                                                                       ThunarDevice           *device,
                                                                        ThunarTreeModel        *model);
 static ThunarTreeModelItem *thunar_tree_model_item_new_with_file      (ThunarTreeModel        *model,
                                                                        ThunarFile             *file) G_GNUC_MALLOC;
-static ThunarTreeModelItem *thunar_tree_model_item_new_with_volume    (ThunarTreeModel        *model,
-                                                                       GVolume                *volume) G_GNUC_MALLOC;
+static ThunarTreeModelItem *thunar_tree_model_item_new_with_device    (ThunarTreeModel        *model,
+                                                                       ThunarDevice           *device) G_GNUC_MALLOC;
 static void                 thunar_tree_model_item_free               (ThunarTreeModelItem    *item);
 static void                 thunar_tree_model_item_reset              (ThunarTreeModelItem    *item);
 static void                 thunar_tree_model_item_load_folder        (ThunarTreeModelItem    *item);
@@ -183,9 +181,8 @@ struct _ThunarTreeModel
   gint                        stamp;
 #endif
 
-  /* removable volumes */
-  GVolumeMonitor             *volume_monitor;
-  GList                      *hidden_volumes;
+  /* removable devices */
+  ThunarDeviceMonitor        *device_monitor;
 
   ThunarFileMonitor          *file_monitor;
 
@@ -205,7 +202,7 @@ struct _ThunarTreeModelItem
   guint            load_idle_id;
   ThunarFile      *file;
   ThunarFolder    *folder;
-  GVolume         *volume;
+  ThunarDevice    *device;
   ThunarTreeModel *model;
 
   /* list of children of this node that are
@@ -282,7 +279,7 @@ thunar_tree_model_init (ThunarTreeModel *model)
   GFile               *desktop;
   GFile               *home;
   GList               *system_paths = NULL;
-  GList               *volumes;
+  GList               *devices;
   GList               *lp;
   GNode               *node;
 
@@ -305,11 +302,10 @@ thunar_tree_model_init (ThunarTreeModel *model)
   model->root = g_node_new (NULL);
 
   /* connect to the volume monitor */
-  model->volume_monitor = g_volume_monitor_get ();
-  g_signal_connect (model->volume_monitor, "mount-pre-unmount", G_CALLBACK (thunar_tree_model_mount_pre_unmount), model);
-  g_signal_connect (model->volume_monitor, "volume-added", G_CALLBACK (thunar_tree_model_volume_added), model);
-  g_signal_connect (model->volume_monitor, "volume-removed", G_CALLBACK (thunar_tree_model_volume_removed), model);
-  g_signal_connect (model->volume_monitor, "volume-changed", G_CALLBACK (thunar_tree_model_volume_changed), model);
+  model->device_monitor = thunar_device_monitor_get ();
+  g_signal_connect (model->device_monitor, "device-added", G_CALLBACK (thunar_tree_model_device_added), model);
+  g_signal_connect (model->device_monitor, "device-removed", G_CALLBACK (thunar_tree_model_device_removed), model);
+  g_signal_connect (model->device_monitor, "device-changed", G_CALLBACK (thunar_tree_model_device_changed), model);
 
   /* add the home folder to the system paths */
   home = thunar_g_file_new_for_home ();
@@ -360,14 +356,14 @@ thunar_tree_model_init (ThunarTreeModel *model)
   g_list_free (system_paths);
   g_object_unref (home);
 
-  /* setup the initial volumes */
-  volumes = g_volume_monitor_get_volumes (model->volume_monitor);
-  for (lp = volumes; lp != NULL; lp = lp->next)
+  /* setup the initial devices */
+  devices = thunar_device_monitor_get_devices (model->device_monitor);
+  for (lp = devices; lp != NULL; lp = lp->next)
     {
-      thunar_tree_model_volume_added (model->volume_monitor, lp->data, model);
+      thunar_tree_model_device_added (model->device_monitor, lp->data, model);
       g_object_unref (lp->data);
     }
-  g_list_free (volumes);
+  g_list_free (devices);
 }
 
 
@@ -385,16 +381,13 @@ thunar_tree_model_finalize (GObject *object)
   g_signal_handlers_disconnect_by_func (model->file_monitor, thunar_tree_model_file_changed, model);
   g_object_unref (model->file_monitor);
 
-  /* release all hidden volumes */
-  g_list_free_full (model->hidden_volumes, g_object_unref);
-
   /* release all resources allocated to the model */
   g_node_traverse (model->root, G_POST_ORDER, G_TRAVERSE_ALL, -1, thunar_tree_model_node_traverse_free, NULL);
   g_node_destroy (model->root);
 
   /* disconnect from the volume monitor */
-  g_signal_handlers_disconnect_matched (model->volume_monitor, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, model);
-  g_object_unref (model->volume_monitor);
+  g_signal_handlers_disconnect_matched (model->device_monitor, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, model);
+  g_object_unref (model->device_monitor);
 
   (*G_OBJECT_CLASS (thunar_tree_model_parent_class)->finalize) (object);
 }
@@ -476,8 +469,8 @@ thunar_tree_model_get_column_type (GtkTreeModel *tree_model,
     case THUNAR_TREE_MODEL_COLUMN_ATTR:
       return PANGO_TYPE_ATTR_LIST;
 
-    case THUNAR_TREE_MODEL_COLUMN_VOLUME:
-      return G_TYPE_VOLUME;
+    case THUNAR_TREE_MODEL_COLUMN_DEVICE:
+      return THUNAR_TYPE_DEVICE;
 
     default:
       _thunar_assert_not_reached ();
@@ -613,8 +606,8 @@ thunar_tree_model_get_value (GtkTreeModel *tree_model,
 
     case THUNAR_TREE_MODEL_COLUMN_NAME:
       g_value_init (value, G_TYPE_STRING);
-      if (G_LIKELY (item != NULL && item->volume != NULL))
-        g_value_take_string (value, g_volume_get_name (item->volume));
+      if (G_LIKELY (item != NULL && item->device != NULL))
+        g_value_take_string (value, thunar_device_get_name (item->device));
       else if (G_LIKELY (item != NULL && item->file != NULL))
         g_value_set_static_string (value, thunar_file_get_display_name (item->file));
       else
@@ -629,9 +622,9 @@ thunar_tree_model_get_value (GtkTreeModel *tree_model,
         g_value_set_boxed (value, thunar_pango_attr_list_italic ());
       break;
 
-    case THUNAR_TREE_MODEL_COLUMN_VOLUME:
-      g_value_init (value, G_TYPE_VOLUME);
-      g_value_set_object (value, (item != NULL) ? item->volume : NULL);
+    case THUNAR_TREE_MODEL_COLUMN_DEVICE:
+      g_value_init (value, THUNAR_TYPE_DEVICE);
+      g_value_set_object (value, (item != NULL) ? item->device : NULL);
       break;
 
     default:
@@ -959,128 +952,72 @@ thunar_tree_model_file_changed (ThunarFileMonitor *file_monitor,
 
 
 static void
-thunar_tree_model_volume_changed (GVolumeMonitor  *volume_monitor,
-                                  GVolume         *volume,
-                                  ThunarTreeModel *model)
+thunar_tree_model_device_changed (ThunarDeviceMonitor *device_monitor,
+                                  ThunarDevice        *device,
+                                  ThunarTreeModel     *model)
 {
   ThunarTreeModelItem *item = NULL;
   GtkTreePath         *path;
   GtkTreeIter          iter;
-  GMount              *mount;
   GFile               *mount_point;
   GNode               *node;
-  GList               *lp;
 
-  _thunar_return_if_fail (G_IS_VOLUME_MONITOR (volume_monitor));
-  _thunar_return_if_fail (model->volume_monitor == volume_monitor);
-  _thunar_return_if_fail (G_IS_VOLUME (volume));
+  _thunar_return_if_fail (THUNAR_IS_DEVICE_MONITOR (device_monitor));
+  _thunar_return_if_fail (model->device_monitor == device_monitor);
+  _thunar_return_if_fail (THUNAR_IS_DEVICE (device));
   _thunar_return_if_fail (THUNAR_IS_TREE_MODEL (model));
+  
+  /* lookup the volume in the item list */
+  for (node = model->root->children; node != NULL; node = node->next)
+    {
+      item = THUNAR_TREE_MODEL_ITEM (node->data);
+      if (item->device == device)
+        break;
+    }
 
-  /* check if the volume is on the hidden list */
-  lp = g_list_find (model->hidden_volumes, volume);
-  if (G_LIKELY (lp != NULL))
+  /* verify that we actually found the item */
+  _thunar_assert (item != NULL);
+  _thunar_assert (item->device == device);
+  
+  /* check if the volume is mounted and we don't have a file yet */
+  if (thunar_device_is_mounted (device) && item->file == NULL)
     {
-      /* check if we need to display the volume now */
-      if (thunar_g_volume_is_removable (volume) && thunar_g_volume_is_present (volume))
+      mount_point = thunar_device_get_root (device);
+      if (mount_point != NULL)
         {
-          /* remove the volume from the list of hidden volumes */
-          model->hidden_volumes = g_list_delete_link (model->hidden_volumes, lp);
-
-          /* allocate a new item for the volume */
-          item = thunar_tree_model_item_new_with_volume (model, volume);
-
-          /* insert before the last child of the root (the "File System" node) */
-          node = g_node_last_child (model->root);
-          node = g_node_insert_data_before (model->root, node, item);
-
-          /* determine the iterator for the new node */
-          GTK_TREE_ITER_INIT (iter, model->stamp, node);
-
-          /* tell the view about the new node */
-          path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter);
-          gtk_tree_model_row_inserted (GTK_TREE_MODEL (model), path, &iter);
-          gtk_tree_path_free (path);
+          /* try to determine the file for the mount point */
+          item->file = thunar_file_get (mount_point, NULL);
 
-          /* add the dummy node */
-          thunar_tree_model_node_insert_dummy (node, model);
+          /* because the volume node is already reffed, we need to load the folder manually here */
+          thunar_tree_model_item_load_folder (item);
 
-          /* drop our reference on the volume */
-          g_object_unref (volume);
+          g_object_unref (mount_point);
         }
     }
-  else
+  else if (!thunar_device_is_mounted (device) && item->file != NULL)
     {
-      /* lookup the volume in the item list */
-      for (node = model->root->children; node != NULL; node = node->next)
-        {
-          item = THUNAR_TREE_MODEL_ITEM (node->data);
-          if (item->volume == volume)
-            break;
-        }
-
-      /* verify that we actually found the item */
-      _thunar_assert (item != NULL);
-      _thunar_assert (item->volume == volume);
-
-      /* check if we need to hide the volume now */
-      if (!thunar_g_volume_is_removable (volume) || !thunar_g_volume_is_present (volume))
-        {
-          /* need to ref here, because the volumes_removed() handler will drop the reference */
-          g_object_ref (volume);
-
-          /* use "volume-removed" handler to hide the volume */
-          thunar_tree_model_volume_removed (model->volume_monitor, volume, model);
-
-          /* move the volume to the hidden list */
-          model->hidden_volumes = g_list_prepend (model->hidden_volumes, volume);
-        }
-      else
-        {
-          /* check if the volume is mounted and we don't have a file yet */
-          if (thunar_g_volume_is_mounted (volume) && item->file == NULL)
-            {
-              mount = g_volume_get_mount (volume);
-
-              if (G_LIKELY (mount != NULL))
-                {
-                  mount_point = g_mount_get_root (mount);
-                
-                  /* try to determine the file for the mount point */
-                  item->file = thunar_file_get (mount_point, NULL);
-
-                  /* because the volume node is already reffed, we need to load the folder manually here */
-                  thunar_tree_model_item_load_folder (item);
-
-                  g_object_unref (mount_point);
-                  g_object_unref (mount);
-                }
-            }
-          else if (!thunar_g_volume_is_mounted (volume) && item->file != NULL)
-            {
-              /* reset the item for the node */
-              thunar_tree_model_item_reset (item);
-
-              /* release all child nodes */
-              while (node->children != NULL)
-                g_node_traverse (node->children, G_POST_ORDER, G_TRAVERSE_ALL, -1, thunar_tree_model_node_traverse_remove, model);
-
-              /* append the dummy node */
-              thunar_tree_model_node_insert_dummy (node, model);
-            }
-
-          /* generate an iterator for the item */
-          GTK_TREE_ITER_INIT (iter, model->stamp, node);
-
-          /* tell the view that the volume has changed in some way */
-          path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter);
-          gtk_tree_model_row_changed (GTK_TREE_MODEL (model), path, &iter);
-          gtk_tree_path_free (path);
-        }
+      /* reset the item for the node */
+      thunar_tree_model_item_reset (item);
+    
+      /* release all child nodes */
+      while (node->children != NULL)
+        g_node_traverse (node->children, G_POST_ORDER, G_TRAVERSE_ALL, -1, thunar_tree_model_node_traverse_remove, model);
+    
+      /* append the dummy node */
+      thunar_tree_model_node_insert_dummy (node, model);
     }
-}
+  
+  /* generate an iterator for the item */
+  GTK_TREE_ITER_INIT (iter, model->stamp, node);
 
+  /* tell the view that the volume has changed in some way */
+  path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter);
+  gtk_tree_model_row_changed (GTK_TREE_MODEL (model), path, &iter);
+  gtk_tree_path_free (path);
+}
 
 
+#if 0
 static void
 thunar_tree_model_mount_pre_unmount (GVolumeMonitor         *volume_monitor,
                                      GMount                 *mount,
@@ -1121,63 +1058,68 @@ thunar_tree_model_mount_pre_unmount (GVolumeMonitor         *volume_monitor,
   /* add the dummy node */
   thunar_tree_model_node_insert_dummy (node, model);
 }
-
+#endif
 
 
 static void
-thunar_tree_model_volume_added (GVolumeMonitor         *volume_monitor,
-                                GVolume                *volume,
-                                ThunarTreeModel        *model)
+thunar_tree_model_device_added (ThunarDeviceMonitor *device_monitor,
+                                ThunarDevice        *device,
+                                ThunarTreeModel     *model)
 {
-  _thunar_return_if_fail (G_IS_VOLUME_MONITOR (volume_monitor));
-  _thunar_return_if_fail (model->volume_monitor == volume_monitor);
-  _thunar_return_if_fail (G_IS_VOLUME (volume));
+  ThunarTreeModelItem *item;
+  GtkTreePath         *path;
+  GtkTreeIter          iter;
+  GNode               *node;
+  
+  _thunar_return_if_fail (THUNAR_IS_DEVICE_MONITOR (device_monitor));
+  _thunar_return_if_fail (model->device_monitor == device_monitor);
+  _thunar_return_if_fail (THUNAR_IS_DEVICE (device));
   _thunar_return_if_fail (THUNAR_IS_TREE_MODEL (model));
 
-  /* place the volume on the hidden list */
-  model->hidden_volumes = g_list_prepend (model->hidden_volumes, g_object_ref (volume));
+  /* allocate a new item for the volume */
+  item = thunar_tree_model_item_new_with_device (model, device);
 
-  /* and let the "volume-changed" handler place the volume where appropriate */
-  thunar_tree_model_volume_changed (volume_monitor, volume, model);
+  /* insert before the last child of the root (the "File System" node) */
+  node = g_node_last_child (model->root);
+  node = g_node_insert_data_before (model->root, node, item);
+
+  /* determine the iterator for the new node */
+  GTK_TREE_ITER_INIT (iter, model->stamp, node);
+
+  /* tell the view about the new node */
+  path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter);
+  gtk_tree_model_row_inserted (GTK_TREE_MODEL (model), path, &iter);
+  gtk_tree_path_free (path);
+
+  /* add the dummy node */
+  thunar_tree_model_node_insert_dummy (node, model);
 }
 
 
 
 static void
-thunar_tree_model_volume_removed (GVolumeMonitor         *volume_monitor,
-                                  GVolume                *volume,
-                                  ThunarTreeModel        *model)
+thunar_tree_model_device_removed (ThunarDeviceMonitor *device_monitor,
+                                  ThunarDevice        *device,
+                                  ThunarTreeModel     *model)
 {
   GNode *node;
-  GList *lp;
 
-  _thunar_return_if_fail (G_IS_VOLUME_MONITOR (volume_monitor));
-  _thunar_return_if_fail (model->volume_monitor == volume_monitor);
-  _thunar_return_if_fail (G_IS_VOLUME (volume));
+  _thunar_return_if_fail (THUNAR_IS_DEVICE_MONITOR (device_monitor));
+  _thunar_return_if_fail (model->device_monitor == device_monitor);
+  _thunar_return_if_fail (THUNAR_IS_DEVICE (device));
   _thunar_return_if_fail (THUNAR_IS_TREE_MODEL (model));
 
-  /* check if the volume is on the hidden list */
-  lp = g_list_find (model->hidden_volumes, volume);
-  if (G_LIKELY (lp != NULL))
-    {
-      /* remove the volume from the hidden list and drop our reference */
-      model->hidden_volumes = g_list_delete_link (model->hidden_volumes, lp);
-      g_object_unref (volume);
-    }
-  else
-    {
-      /* must be a visible volume then... */
-      for (node = model->root->children; node != NULL; node = node->next)
-        if (THUNAR_TREE_MODEL_ITEM (node->data)->volume == volume)
-          break;
+  /* find the device */
+  for (node = model->root->children; node != NULL; node = node->next)
+    if (THUNAR_TREE_MODEL_ITEM (node->data)->device == device)
+      break;
 
-      /* something is broken if we don't have an item here */
-      _thunar_assert (node != NULL);
-      _thunar_assert (THUNAR_TREE_MODEL_ITEM (node->data)->volume == volume);
+  /* something is broken if we don't have an item here */
+  _thunar_assert (node != NULL);
+  _thunar_assert (THUNAR_TREE_MODEL_ITEM (node->data)->device == device);
 
-      /* drop the node from the model */
-      g_node_traverse (node, G_POST_ORDER, G_TRAVERSE_ALL, -1, thunar_tree_model_node_traverse_remove, model);
-    }
+  /* drop the node from the model */
+  g_node_traverse (node, G_POST_ORDER, G_TRAVERSE_ALL, -1, thunar_tree_model_node_traverse_remove, model);
 }
 
 
@@ -1198,31 +1140,25 @@ thunar_tree_model_item_new_with_file (ThunarTreeModel *model,
 
 
 static ThunarTreeModelItem*
-thunar_tree_model_item_new_with_volume (ThunarTreeModel *model,
-                                        GVolume         *volume)
+thunar_tree_model_item_new_with_device (ThunarTreeModel *model,
+                                        ThunarDevice    *device)
 {
   ThunarTreeModelItem *item;
-  GMount              *mount;
   GFile               *mount_point;
 
   item = g_slice_new0 (ThunarTreeModelItem);
-  item->volume = g_object_ref (G_OBJECT (volume));
+  item->device = g_object_ref (G_OBJECT (device));
   item->model = model;
 
   /* check if the volume is mounted */
-  if (thunar_g_volume_is_mounted (volume))
+  if (thunar_device_is_mounted (device))
     {
-      mount = g_volume_get_mount (volume);
-      
-      if (G_LIKELY (mount != NULL))
+      mount_point = thunar_device_get_root (device);
+      if (G_LIKELY (mount_point != NULL))
         {
-          mount_point = g_mount_get_root (mount);
-
           /* try to determine the file for the mount point */
           item->file = thunar_file_get (mount_point, NULL);
-
           g_object_unref (mount_point);
-          g_object_unref (mount);
         }
     }
 
@@ -1235,8 +1171,8 @@ static void
 thunar_tree_model_item_free (ThunarTreeModelItem *item)
 {
   /* disconnect from the volume */
-  if (G_UNLIKELY (item->volume != NULL))
-    g_object_unref (item->volume);
+  if (G_UNLIKELY (item->device != NULL))
+    g_object_unref (item->device);
 
   /* reset the remaining resources */
   thunar_tree_model_item_reset (item);
@@ -1287,10 +1223,10 @@ thunar_tree_model_item_reset (ThunarTreeModelItem *item)
 static void
 thunar_tree_model_item_load_folder (ThunarTreeModelItem *item)
 {
-  _thunar_return_if_fail (item->file != NULL || item->volume != NULL);
+  _thunar_return_if_fail (item->file != NULL || item->device != NULL);
 
   /* schedule the "load" idle source (if not already done) */
-  if (G_LIKELY (item->load_idle_id == 0 && item->folder == NULL))
+  if (G_LIKELY (item->load_idle_id == 0 && item->device == NULL))
     {
       item->load_idle_id = g_idle_add_full (G_PRIORITY_HIGH, thunar_tree_model_item_load_idle,
                                             item, thunar_tree_model_item_load_idle_destroy);
@@ -1482,7 +1418,6 @@ static gboolean
 thunar_tree_model_item_load_idle (gpointer user_data)
 {
   ThunarTreeModelItem *item = user_data;
-  GMount              *mount;
   GFile               *mount_point;
   GList               *files;
 #ifndef NDEBUG
@@ -1504,19 +1439,14 @@ thunar_tree_model_item_load_idle (gpointer user_data)
   GDK_THREADS_ENTER ();
 
   /* check if we don't have a file yet and this is a mounted volume */
-  if (item->file == NULL && item->volume != NULL && thunar_g_volume_is_mounted (item->volume))
+  if (item->file == NULL && item->device != NULL && thunar_device_is_mounted (item->device))
     {
-      mount = g_volume_get_mount (item->volume);
-
-      if (G_LIKELY (mount != NULL))
+      mount_point = thunar_device_get_root (item->device);
+      if (G_LIKELY (mount_point != NULL))
         {
-          mount_point = g_mount_get_root (mount);
-
           /* try to determine the file for the mount point */
           item->file = thunar_file_get (mount_point, NULL);
-
           g_object_unref (mount_point);
-          g_object_unref (mount);
         }
     }
 
diff --git a/thunar/thunar-tree-model.h b/thunar/thunar-tree-model.h
index 826fb86..d7e971d 100644
--- a/thunar/thunar-tree-model.h
+++ b/thunar/thunar-tree-model.h
@@ -43,7 +43,7 @@ typedef gboolean (* ThunarTreeModelVisibleFunc) (ThunarTreeModel *model,
  * @THUNAR_TREE_MODEL_COLUMN_FILE   : the index of the file column.
  * @THUNAR_TREE_MODEL_COLUMN_NAME   : the index of the name column.
  * @THUNAR_TREE_MODEL_COLUMN_ATTR   : the index of the #PangoAttrList column.
- * @THUNAR_TREE_MODEL_COLUMN_VOLUME : the index of the #GVolume column.
+ * @THUNAR_TREE_MODEL_COLUMN_DEVICE : the index of the #ThunarDevice column.
  *
  * Columns exported by the #ThunarTreeModel using the
  * #GtkTreeModel interface.
@@ -53,7 +53,7 @@ typedef enum
   THUNAR_TREE_MODEL_COLUMN_FILE,
   THUNAR_TREE_MODEL_COLUMN_NAME,
   THUNAR_TREE_MODEL_COLUMN_ATTR,
-  THUNAR_TREE_MODEL_COLUMN_VOLUME,
+  THUNAR_TREE_MODEL_COLUMN_DEVICE,
   THUNAR_TREE_MODEL_N_COLUMNS,
 } ThunarTreeModelColumn;
 
diff --git a/thunar/thunar-tree-view.c b/thunar/thunar-tree-view.c
index 7e311e7..09c996d 100644
--- a/thunar/thunar-tree-view.c
+++ b/thunar/thunar-tree-view.c
@@ -3,18 +3,18 @@
  * Copyright (c) 2006      Benedikt Meurer <benny at xfce.org>
  * Copyright (c) 2009-2011 Jannis Pohlmann <jannis at xfce.org>
  *
- * This program is free software; you can redistribute it and/or 
+ * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of 
+ * published by the Free Software Foundation; either version 2 of
  * the License, or (at your option) any later version.
  *
  * This program 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 
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
- * You should have received a copy of the GNU General Public 
- * License along with this program; if not, write to the Free 
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the Free
  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301, USA.
  */
@@ -44,6 +44,7 @@
 #include <thunar/thunar-simple-job.h>
 #include <thunar/thunar-tree-model.h>
 #include <thunar/thunar-tree-view.h>
+#include <thunar/thunar-device.h>
 
 
 
@@ -144,17 +145,18 @@ static gboolean                 thunar_tree_view_find_closest_ancestor        (T
                                                                                GtkTreePath            **ancestor_return,
                                                                                gboolean                *exact_return);
 static ThunarFile              *thunar_tree_view_get_selected_file            (ThunarTreeView          *view);
-static GVolume                 *thunar_tree_view_get_selected_volume          (ThunarTreeView          *view);
+static ThunarDevice            *thunar_tree_view_get_selected_device          (ThunarTreeView          *view);
 static void                     thunar_tree_view_action_copy                  (ThunarTreeView          *view);
 static void                     thunar_tree_view_action_create_folder         (ThunarTreeView          *view);
 static void                     thunar_tree_view_action_cut                   (ThunarTreeView          *view);
 static void                     thunar_tree_view_action_delete                (ThunarTreeView          *view);
 static void                     thunar_tree_view_action_rename                (ThunarTreeView          *view);
 static void                     thunar_tree_view_action_eject                 (ThunarTreeView          *view);
+static void                     thunar_tree_view_action_unmount               (ThunarTreeView          *view);
 static void                     thunar_tree_view_action_empty_trash           (ThunarTreeView          *view);
 static void                     thunar_tree_view_action_mount                 (ThunarTreeView          *view);
-static void                     thunar_tree_view_mount_finish                 (GObject                 *object,
-                                                                               GAsyncResult            *result,
+static void                     thunar_tree_view_mount_finish                 (ThunarDevice            *device,
+                                                                               const GError            *error,
                                                                                gpointer                 user_data);
 static void                     thunar_tree_view_mount                        (ThunarTreeView          *view,
                                                                                gboolean                 open_after_mounting,
@@ -210,7 +212,7 @@ struct _ThunarTreeView
   GtkCellRenderer        *icon_renderer;
   ThunarFile             *current_directory;
   ThunarTreeModel        *model;
-  
+
   ThunarxProviderFactory *provider_factory;
 
   /* whether to display hidden/backup files */
@@ -405,7 +407,7 @@ thunar_tree_view_init (ThunarTreeView *view)
   gtk_tree_view_column_pack_start (column, view->icon_renderer, FALSE);
   gtk_tree_view_column_set_attributes (column, view->icon_renderer,
                                        "file", THUNAR_TREE_MODEL_COLUMN_FILE,
-                                       "volume", THUNAR_TREE_MODEL_COLUMN_VOLUME,
+                                       "device", THUNAR_TREE_MODEL_COLUMN_DEVICE,
                                        NULL);
 
   /* sync the "emblems" property of the icon renderer with the "tree-icon-emblems" preference
@@ -570,7 +572,7 @@ thunar_tree_view_set_current_directory (ThunarNavigator *navigator,
 
                   break;
                 }
-            
+
               /* get the file parent */
               file_parent = thunar_file_get_parent (file, NULL);
 
@@ -592,8 +594,8 @@ thunar_tree_view_set_current_directory (ThunarNavigator *navigator,
       /* take a reference on the directory */
       g_object_ref (G_OBJECT (current_directory));
 
-      /* update the filter if the new current directory, or one of it's parents, is 
-       * hidden. we don't have to check this if refiltering needs to be done 
+      /* update the filter if the new current directory, or one of it's parents, is
+       * hidden. we don't have to check this if refiltering needs to be done
        * anyway */
       if (!needs_refiltering && !view->show_hidden)
         {
@@ -983,18 +985,18 @@ thunar_tree_view_test_expand_row (GtkTreeView *tree_view,
   ThunarTreeView          *view = THUNAR_TREE_VIEW (tree_view);
   GtkWidget               *window;
   gboolean                 expandable = TRUE;
-  GVolume                 *volume;
+  ThunarDevice            *device;
 
-  /* determine the volume for the iterator */
-  gtk_tree_model_get (GTK_TREE_MODEL (view->model), iter, THUNAR_TREE_MODEL_COLUMN_VOLUME, &volume, -1);
+  /* determine the device for the iterator */
+  gtk_tree_model_get (GTK_TREE_MODEL (view->model), iter, THUNAR_TREE_MODEL_COLUMN_DEVICE, &device, -1);
 
-  /* check if we have a volume */
-  if (G_UNLIKELY (volume != NULL))
+  /* check if we have a device */
+  if (G_UNLIKELY (device != NULL))
     {
-      /* check if we need to mount the volume first */
-      if (!thunar_g_volume_is_mounted (volume))
+      /* check if we need to mount the device first */
+      if (!thunar_device_is_mounted (device))
         {
-          /* we need to mount the volume before we can expand the row */
+          /* we need to mount the device before we can expand the row */
           expandable = FALSE;
 
           /* allocate a mount data struct */
@@ -1004,17 +1006,20 @@ thunar_tree_view_test_expand_row (GtkTreeView *tree_view,
           window = gtk_widget_get_toplevel (GTK_WIDGET (view));
           mount_operation = gtk_mount_operation_new (GTK_WINDOW (window));
 
-          /* try to mount the volume and expand the row on success. the
+          /* try to mount the device and expand the row on success. the
            * data is destroyed in the finish callback */
-          g_volume_mount (volume, G_MOUNT_MOUNT_NONE, mount_operation, NULL,
-                          thunar_tree_view_mount_finish, data);
+          thunar_device_mount (device,
+                               mount_operation,
+                               NULL,
+                               thunar_tree_view_mount_finish,
+                               data);
 
           /* release the mount operation */
           g_object_unref (mount_operation);
         }
 
-      /* release the volume */
-      g_object_unref (G_OBJECT (volume));
+      /* release the device */
+      g_object_unref (G_OBJECT (device));
     }
 
   /* cancel the cursor idle source if not expandable */
@@ -1066,24 +1071,24 @@ thunar_tree_view_context_menu (ThunarTreeView *view,
                                GtkTreeModel   *model,
                                GtkTreeIter    *iter)
 {
-  GVolume    *volume;
-  ThunarFile *parent_file;
-  ThunarFile *file;
-  GtkWidget  *image;
-  GtkWidget  *menu;
-  GtkWidget  *item;
-  GtkWidget  *window;
-  GList      *providers, *lp;
-  GList      *actions = NULL, *tmp;
+  ThunarDevice *device;
+  ThunarFile   *parent_file;
+  ThunarFile   *file;
+  GtkWidget    *image;
+  GtkWidget    *menu;
+  GtkWidget    *item;
+  GtkWidget    *window;
+  GList        *providers, *lp;
+  GList        *actions = NULL, *tmp;
 
   /* verify that we're connected to the clipboard manager */
   if (G_UNLIKELY (view->clipboard == NULL))
     return;
 
-  /* determine the file and volume for the given iter */
+  /* determine the file and device for the given iter */
   gtk_tree_model_get (model, iter,
                       THUNAR_TREE_MODEL_COLUMN_FILE, &file,
-                      THUNAR_TREE_MODEL_COLUMN_VOLUME, &volume,
+                      THUNAR_TREE_MODEL_COLUMN_DEVICE, &device,
                       -1);
 
   /* prepare the popup menu */
@@ -1093,7 +1098,7 @@ thunar_tree_view_context_menu (ThunarTreeView *view,
   item = gtk_image_menu_item_new_with_mnemonic (_("_Open"));
   g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (thunar_tree_view_action_open), view);
   gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
-  gtk_widget_set_sensitive (item, (file != NULL || volume != NULL));
+  gtk_widget_set_sensitive (item, (file != NULL || device != NULL));
   gtk_widget_show (item);
 
   /* set the stock icon */
@@ -1104,7 +1109,7 @@ thunar_tree_view_context_menu (ThunarTreeView *view,
   item = gtk_image_menu_item_new_with_mnemonic (_("Open in New Window"));
   g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (thunar_tree_view_action_open_in_new_window), view);
   gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
-  gtk_widget_set_sensitive (item, (file != NULL || volume != NULL));
+  gtk_widget_set_sensitive (item, (file != NULL || device != NULL));
   gtk_widget_show (item);
 
   /* append a separator item */
@@ -1112,20 +1117,34 @@ thunar_tree_view_context_menu (ThunarTreeView *view,
   gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
   gtk_widget_show (item);
 
-  if (G_UNLIKELY (volume != NULL))
+  if (G_UNLIKELY (device != NULL))
     {
-      /* append the "Mount Volume" menu action */
-      item = gtk_image_menu_item_new_with_mnemonic (_("_Mount Volume"));
-      gtk_widget_set_sensitive (item, !thunar_g_volume_is_mounted (volume));
-      g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (thunar_tree_view_action_mount), view);
-      gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
-      gtk_widget_show (item);
+      if (thunar_device_get_kind (device) == THUNAR_DEVICE_KIND_VOLUME)
+        {
+          /* append the "Mount" menu action */
+          item = gtk_image_menu_item_new_with_mnemonic (_("_Mount"));
+          gtk_widget_set_visible (item, thunar_device_can_mount (device));
+          g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (thunar_tree_view_action_mount), view);
+          gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+
+          /* append the "Unmount" menu action */
+          item = gtk_image_menu_item_new_with_mnemonic (_("_Unmount"));
+          gtk_widget_set_visible (item, thunar_device_can_unmount (device));
+          g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (thunar_tree_view_action_unmount), view);
+          gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
 
-      /* check if the volume is present and can be ejected */
-      if (thunar_g_volume_is_present (volume) && thunar_g_volume_is_removable (volume))
+          /* append the "Eject" menu action */
+          item = gtk_image_menu_item_new_with_mnemonic (_("_Eject"));
+          g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (thunar_tree_view_action_eject), view);
+          gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+          gtk_widget_set_sensitive (item, thunar_device_can_eject (device));
+          gtk_widget_show (item);
+        }
+      else
         {
-          /* append the "Eject Volume" menu action */
-          item = gtk_image_menu_item_new_with_mnemonic (_("E_ject Volume"));
+          /* append the "Mount Volume" menu action */
+          item = gtk_image_menu_item_new_with_mnemonic (_("Disconn_ect"));
+          gtk_widget_set_sensitive (item, thunar_device_can_eject (device));
           g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (thunar_tree_view_action_eject), view);
           gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
           gtk_widget_show (item);
@@ -1169,8 +1188,8 @@ thunar_tree_view_context_menu (ThunarTreeView *view,
 
   if (G_LIKELY (file != NULL))
     {
-      /* "Cut" and "Copy" don't make much sense for volumes */
-      if (G_LIKELY (volume == NULL))
+      /* "Cut" and "Copy" don't make much sense for devices */
+      if (G_LIKELY (device == NULL))
         {
           /* determine the parent file (required to determine "Cut" sensitivity) */
           parent_file = thunar_file_get_parent (file, NULL);
@@ -1213,8 +1232,8 @@ thunar_tree_view_context_menu (ThunarTreeView *view,
       image = gtk_image_new_from_stock (GTK_STOCK_PASTE, GTK_ICON_SIZE_MENU);
       gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
 
-      /* "Delete" and "Rename" don't make much sense for volumes */
-      if (G_LIKELY (volume == NULL))
+      /* "Delete" and "Rename" don't make much sense for devices */
+      if (G_LIKELY (device == NULL))
         {
           /* determine the parent file (required to determine "Delete" sensitivity) */
           parent_file = thunar_file_get_parent (file, NULL);
@@ -1255,7 +1274,7 @@ thunar_tree_view_context_menu (ThunarTreeView *view,
       item = gtk_separator_menu_item_new ();
       gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
       gtk_widget_show (item);
-      
+
       /* add the providers menu for non-trashed items */
       if (G_LIKELY (!thunar_file_is_trashed (file)))
         {
@@ -1265,7 +1284,7 @@ thunar_tree_view_context_menu (ThunarTreeView *view,
             {
               /* determine the toplevel window we belong to */
               window = gtk_widget_get_toplevel (GTK_WIDGET (view));
-              
+
               /* load the actions offered by the menu providers */
               for (lp = providers; lp != NULL; lp = lp->next)
                 {
@@ -1317,8 +1336,8 @@ thunar_tree_view_context_menu (ThunarTreeView *view,
                        (event != NULL) ? event->time : gtk_get_current_event_time ());
 
   /* cleanup */
-  if (G_UNLIKELY (volume != NULL))
-    g_object_unref (G_OBJECT (volume));
+  if (G_UNLIKELY (device != NULL))
+    g_object_unref (G_OBJECT (device));
   if (G_LIKELY (file != NULL))
     g_object_unref (G_OBJECT (file));
 }
@@ -1477,7 +1496,7 @@ thunar_tree_view_get_selected_file (ThunarTreeView *view)
 
   /* determine file for the selected row */
   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (view));
-  
+
   /* avoid dealing with invalid selections (may occur when the mount_finish()
    * handler is called and the tree view has been hidden already) */
   if (!GTK_IS_TREE_SELECTION (selection))
@@ -1491,20 +1510,20 @@ thunar_tree_view_get_selected_file (ThunarTreeView *view)
 
 
 
-static GVolume*
-thunar_tree_view_get_selected_volume (ThunarTreeView *view)
+static ThunarDevice*
+thunar_tree_view_get_selected_device (ThunarTreeView *view)
 {
   GtkTreeSelection *selection;
-  GVolume          *volume = NULL;
+  ThunarDevice     *device = NULL;
   GtkTreeModel     *model;
   GtkTreeIter       iter;
 
   /* determine file for the selected row */
   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (view));
   if (gtk_tree_selection_get_selected (selection, &model, &iter))
-    gtk_tree_model_get (model, &iter, THUNAR_TREE_MODEL_COLUMN_VOLUME, &volume, -1);
+    gtk_tree_model_get (model, &iter, THUNAR_TREE_MODEL_COLUMN_DEVICE, &device, -1);
 
-  return volume;
+  return device;
 }
 
 
@@ -1556,9 +1575,9 @@ thunar_tree_view_action_create_folder (ThunarTreeView *view)
     return;
 
   /* ask the user to enter a name for the new folder */
-  name = thunar_show_create_dialog (GTK_WIDGET (view), 
-                                    "inode/directory", 
-                                    _("New Folder"), 
+  name = thunar_show_create_dialog (GTK_WIDGET (view),
+                                    "inode/directory",
+                                    _("New Folder"),
                                     _("Create New Folder"));
   if (G_LIKELY (name != NULL))
     {
@@ -1694,14 +1713,14 @@ thunar_tree_view_action_rename (ThunarTreeView *view)
   ThunarJob  *job;
 
   _thunar_return_if_fail (THUNAR_IS_TREE_VIEW (view));
-  
+
   /* determine the selected file */
   file = thunar_tree_view_get_selected_file (view);
   if (G_LIKELY (file != NULL))
-    {  
+    {
       /* get the toplevel window */
       window = gtk_widget_get_toplevel (GTK_WIDGET (view));
-      
+
       /* run the rename dialog */
       job = thunar_dialogs_show_rename_file (GTK_WINDOW (window), file);
       if (G_LIKELY (job != NULL))
@@ -1709,7 +1728,7 @@ thunar_tree_view_action_rename (ThunarTreeView *view)
           g_signal_connect (job, "error", G_CALLBACK (thunar_tree_view_rename_error), view);
           g_signal_connect (job, "finished", G_CALLBACK (thunar_tree_view_rename_finished), view);
         }
-      
+
       /* release the file */
       g_object_unref (file);
     }
@@ -1718,139 +1737,113 @@ thunar_tree_view_action_rename (ThunarTreeView *view)
 
 
 static void
-thunar_tree_view_action_eject_finish (GObject      *object,
-                                      GAsyncResult *result,
+thunar_tree_view_action_eject_finish (ThunarDevice *device,
+                                      const GError *error,
                                       gpointer      user_data)
 {
   ThunarTreeView *view = THUNAR_TREE_VIEW (user_data);
-  GtkWidget      *window;
-  GVolume        *volume = G_VOLUME (object);
-  GError         *error = NULL;
-  gchar          *volume_name;
+  gchar          *device_name;
 
-  _thunar_return_if_fail (G_IS_VOLUME (object));
-  _thunar_return_if_fail (G_IS_ASYNC_RESULT (result));
+  _thunar_return_if_fail (THUNAR_IS_DEVICE (device));
   _thunar_return_if_fail (THUNAR_IS_TREE_VIEW (view));
 
   /* check if there was an error */
-  if (!g_volume_eject_with_operation_finish (volume, result, &error))
+  if (error != NULL)
     {
-      /* ignore GIO errors already handled */
-      if (error->domain != G_IO_ERROR || error->code != G_IO_ERROR_FAILED_HANDLED)
-        {
-          window = gtk_widget_get_toplevel (GTK_WIDGET (view));
+      /* display an error dialog to inform the user */
+      device_name = thunar_device_get_name (device);
+      thunar_dialogs_show_error (GTK_WIDGET (view), error, _("Failed to eject \"%s\""), device_name);
+      g_free (device_name);
+    }
 
-          /* display an error dialog to inform the user */
-          volume_name = g_volume_get_name (volume);
-          thunar_dialogs_show_error (window, error, _("Failed to eject \"%s\""), volume_name);
-          g_free (volume_name);
+  g_object_unref (view);
+}
 
-          g_error_free (error);
-        }
-    }
 
-#ifdef HAVE_LIBNOTIFY
-  thunar_notify_eject_finish (volume);
-#endif
 
-  g_object_unref (view);
+static void
+thunar_tree_view_action_eject (ThunarTreeView *view)
+{
+  ThunarDevice    *device;
+  GMountOperation *mount_operation;
+  GtkWidget       *window;
+
+  _thunar_return_if_fail (THUNAR_IS_TREE_VIEW (view));
+
+  /* determine the selected device */
+  device = thunar_tree_view_get_selected_device (view);
+  if (G_LIKELY (device != NULL))
+    {
+      /* prepare a mount operation */
+      window = gtk_widget_get_toplevel (GTK_WIDGET (view));
+      mount_operation = gtk_mount_operation_new (GTK_WINDOW (window));
+
+      /* eject */
+      thunar_device_eject (device,
+                           mount_operation,
+                           NULL,
+                           thunar_tree_view_action_eject_finish,
+                           g_object_ref (view));
+
+      /* release the device */
+      g_object_unref (device);
+      g_object_unref (mount_operation);
+    }
 }
 
 
 
 static void
-thunar_tree_view_action_unmount_finish (GObject      *object,
-                                        GAsyncResult *result,
+thunar_tree_view_action_unmount_finish (ThunarDevice *device,
+                                        const GError *error,
                                         gpointer      user_data)
 {
   ThunarTreeView *view = THUNAR_TREE_VIEW (user_data);
-  GtkWidget      *window;
-  GMount         *mount = G_MOUNT (object);
-  GError         *error = NULL;
-  gchar          *mount_name;
+  gchar          *device_name;
 
-  _thunar_return_if_fail (G_IS_MOUNT (object));
-  _thunar_return_if_fail (G_IS_ASYNC_RESULT (result));
+  _thunar_return_if_fail (THUNAR_IS_DEVICE (device));
   _thunar_return_if_fail (THUNAR_IS_TREE_VIEW (view));
 
   /* check if there was an error */
-  if (!g_mount_unmount_with_operation_finish (mount, result, &error))
+  if (error != NULL)
     {
-      /* ignore GIO errors already handled */
-      if (error->domain != G_IO_ERROR || error->code != G_IO_ERROR_FAILED_HANDLED)
-        {
-          window = gtk_widget_get_toplevel (GTK_WIDGET (view));
-
-          /* display an error dialog to inform the user */
-          mount_name = g_mount_get_name (mount);
-          thunar_dialogs_show_error (window, error, _("Failed to eject \"%s\""), mount_name);
-          g_free (mount_name);
-
-          g_error_free (error);
-        }
+      /* display an error dialog to inform the user */
+      device_name = thunar_device_get_name (device);
+      thunar_dialogs_show_error (GTK_WIDGET (view), error, _("Failed to unmount \"%s\""), device_name);
+      g_free (device_name);
     }
 
-#ifdef HAVE_LIBNOTIFY
-  thunar_notify_unmount_finish (mount);
-#endif
-
   g_object_unref (view);
 }
 
 
 
 static void
-thunar_tree_view_action_eject (ThunarTreeView *view)
+thunar_tree_view_action_unmount (ThunarTreeView *view)
 {
-  GVolume         *volume;
-  GMount          *mount;
+  ThunarDevice    *device;
   GMountOperation *mount_operation;
   GtkWidget       *window;
 
   _thunar_return_if_fail (THUNAR_IS_TREE_VIEW (view));
 
-  /* determine the selected volume */
-  volume = thunar_tree_view_get_selected_volume (view);
-  if (G_LIKELY (volume != NULL))
+  /* determine the selected device */
+  device = thunar_tree_view_get_selected_device (view);
+  if (G_LIKELY (device != NULL))
     {
       /* prepare a mount operation */
       window = gtk_widget_get_toplevel (GTK_WIDGET (view));
       mount_operation = gtk_mount_operation_new (GTK_WINDOW (window));
 
-      /* determine what the appropriate method is: eject or unmount */
-      if (g_volume_can_eject (volume))
-        {
-#ifdef HAVE_LIBNOTIFY
-          thunar_notify_eject (volume);
-#endif
+      /* eject */
+      thunar_device_unmount (device,
+                             mount_operation,
+                             NULL,
+                             thunar_tree_view_action_unmount_finish,
+                             g_object_ref (view));
 
-          /* try to to eject the volume asynchronously */
-          g_volume_eject_with_operation (volume, G_MOUNT_UNMOUNT_NONE, mount_operation, NULL,
-                                         thunar_tree_view_action_eject_finish,
-                                         g_object_ref (view));
-        }
-      else
-        {
-          /* determine the mount of the volume */
-          mount = g_volume_get_mount (volume);
-          if (G_LIKELY (mount != NULL))
-            {
-#ifdef HAVE_LIBNOTIFY
-              thunar_notify_unmount (mount);
-#endif
-
-              /* the volume is mounted, try to unmount the mount */
-              g_mount_unmount_with_operation (mount, G_MOUNT_UNMOUNT_NONE, mount_operation, NULL,
-                                              thunar_tree_view_action_unmount_finish,
-                                              g_object_ref (view));
-
-              /* release the mount */
-              g_object_unref (mount);
-            }
-        }
-
-      /* release the volume */
-      g_object_unref (volume);
+      /* release the device */
+      g_object_unref (device);
       g_object_unref (mount_operation);
     }
 }
@@ -1882,39 +1875,21 @@ thunar_tree_view_action_mount (ThunarTreeView *view)
 
 
 static void
-thunar_tree_view_mount_finish (GObject      *object,
-                               GAsyncResult *result,
+thunar_tree_view_mount_finish (ThunarDevice *device,
+                               const GError *error,
                                gpointer      user_data)
 {
   ThunarTreeViewMountData *data = user_data;
-  GtkWidget               *window;
-  GVolume                 *volume = G_VOLUME (object);
-  GError                  *error = NULL;
-  gchar                   *volume_name;
+  gchar                   *device_name;
 
-  _thunar_return_if_fail (G_IS_VOLUME (object));
-  _thunar_return_if_fail (G_IS_ASYNC_RESULT (result));
+  _thunar_return_if_fail (THUNAR_IS_DEVICE (device));
   _thunar_return_if_fail (data != NULL && THUNAR_IS_TREE_VIEW (data->view));
 
-  /* check if there was an error */
-  if (!g_volume_mount_finish (volume, result, &error))
+  if (error != NULL)
     {
-      /* ignore GIO already handled errors or errors due to pending mount actions */
-      if (error->domain != G_IO_ERROR 
-          || (error->code != G_IO_ERROR_FAILED_HANDLED 
-              && error->code != G_IO_ERROR_ALREADY_MOUNTED
-              && error->code != G_IO_ERROR_PENDING))
-        {
-          window = gtk_widget_get_toplevel (GTK_WIDGET (data->view));
-
-          /* display an error dialog to inform the user */
-          volume_name = g_volume_get_name (volume);
-          thunar_dialogs_show_error (window, error, _("Failed to mount \"%s\""), volume_name);
-          g_free (volume_name);
-
-          /* free the error */
-          g_error_free (error);
-        }
+      device_name = thunar_device_get_name (device);
+      thunar_dialogs_show_error (GTK_WIDGET (data->view), error, _("Failed to mount \"%s\""), device_name);
+      g_free (device_name);
     }
   else
     {
@@ -1944,36 +1919,39 @@ thunar_tree_view_mount (ThunarTreeView *view,
   ThunarTreeViewMountData *data;
   GMountOperation         *mount_operation;
   GtkWidget               *window;
-  GVolume                 *volume;
+  ThunarDevice            *device;
 
   _thunar_return_if_fail (THUNAR_IS_TREE_VIEW (view));
 
-  /* determine the selected volume */
-  volume = thunar_tree_view_get_selected_volume (view);
-  if (volume != NULL)
+  /* determine the selected device */
+  device = thunar_tree_view_get_selected_device (view);
+  if (device != NULL)
     {
-      /* check if we need to mount the volume at all */
-      if (!thunar_g_volume_is_mounted (volume))
+      /* check if we need to mount the device at all */
+      if (!thunar_device_is_mounted (device))
         {
           /* allocate mount data */
-          data = thunar_tree_view_mount_data_new (view, NULL, open_after_mounting, 
+          data = thunar_tree_view_mount_data_new (view, NULL, open_after_mounting,
                                                   open_in_new_window);
 
           /* allocate a GTK+ mount operation */
           window = gtk_widget_get_toplevel (GTK_WIDGET (view));
           mount_operation = gtk_mount_operation_new (GTK_WINDOW (window));
 
-          /* try to mount the volume and expand the row on success. the
+          /* try to mount the device and expand the row on success. the
            * data is destroyed in the finish callback */
-          g_volume_mount (volume, G_MOUNT_MOUNT_NONE, mount_operation, NULL,
-                          thunar_tree_view_mount_finish, data);
+          thunar_device_mount (device,
+                               mount_operation,
+                               NULL,
+                               thunar_tree_view_mount_finish,
+                               data);
 
           /* release the mount operation */
           g_object_unref (mount_operation);
         }
 
-      /* release the volume */
-      g_object_unref (volume);
+      /* release the device */
+      g_object_unref (device);
     }
 }
 
@@ -1982,23 +1960,23 @@ thunar_tree_view_mount (ThunarTreeView *view,
 static void
 thunar_tree_view_action_open (ThunarTreeView *view)
 {
-  ThunarFile *file;
-  GVolume    *volume;
+  ThunarFile   *file;
+  ThunarDevice *device;
 
   _thunar_return_if_fail (THUNAR_IS_TREE_VIEW (view));
 
-  /* determine the selected volume and file */
-  volume = thunar_tree_view_get_selected_volume (view);
+  /* determine the selected device and file */
+  device = thunar_tree_view_get_selected_device (view);
   file = thunar_tree_view_get_selected_file (view);
 
-  if (volume != NULL)
+  if (device != NULL)
     {
-      if (thunar_g_volume_is_mounted (volume))
+      if (thunar_device_is_mounted (device))
         thunar_tree_view_open_selection (view);
       else
         thunar_tree_view_mount (view, TRUE, FALSE);
-      
-      g_object_unref (volume);
+
+      g_object_unref (device);
     }
   else if (file != NULL)
     {
@@ -2031,23 +2009,23 @@ thunar_tree_view_open_selection (ThunarTreeView *view)
 static void
 thunar_tree_view_action_open_in_new_window (ThunarTreeView *view)
 {
-  ThunarFile *file;
-  GVolume    *volume;
+  ThunarFile   *file;
+  ThunarDevice *device;
 
   _thunar_return_if_fail (THUNAR_IS_TREE_VIEW (view));
 
-  /* determine the selected volume and file */
-  volume = thunar_tree_view_get_selected_volume (view);
+  /* determine the selected device and file */
+  device = thunar_tree_view_get_selected_device (view);
   file = thunar_tree_view_get_selected_file (view);
 
-  if (volume != NULL)
+  if (device != NULL)
     {
-      if (thunar_g_volume_is_mounted (volume))
+      if (thunar_device_is_mounted (device))
         thunar_tree_view_open_selection_in_new_window (view);
       else
         thunar_tree_view_mount (view, TRUE, FALSE);
-      
-      g_object_unref (volume);
+
+      g_object_unref (device);
     }
   else if (file != NULL)
     {
@@ -2072,7 +2050,7 @@ thunar_tree_view_open_selection_in_new_window (ThunarTreeView *view)
     {
       /* open a new window for the selected folder */
       application = thunar_application_get ();
-      thunar_application_open_window (application, file, 
+      thunar_application_open_window (application, file,
                                       gtk_widget_get_screen (GTK_WIDGET (view)), NULL);
       g_object_unref (application);
       g_object_unref (file);
@@ -2210,10 +2188,10 @@ thunar_tree_view_selection_func (GtkTreeSelection *selection,
                                  gboolean          path_currently_selected,
                                  gpointer          user_data)
 {
-  GtkTreeIter  iter;
-  ThunarFile  *file;
-  gboolean     result = FALSE;
-  GVolume     *volume;
+  GtkTreeIter   iter;
+  ThunarFile   *file;
+  gboolean      result = FALSE;
+  ThunarDevice *device;
 
   /* every row may be unselected at any time */
   if (path_currently_selected)
@@ -2234,15 +2212,15 @@ thunar_tree_view_selection_func (GtkTreeSelection *selection,
         }
       else
         {
-          /* but maybe the row has a volume */
-          gtk_tree_model_get (model, &iter, THUNAR_TREE_MODEL_COLUMN_VOLUME, &volume, -1);
-          if (G_LIKELY (volume != NULL))
+          /* but maybe the row has a device */
+          gtk_tree_model_get (model, &iter, THUNAR_TREE_MODEL_COLUMN_DEVICE, &device, -1);
+          if (G_LIKELY (device != NULL))
             {
-              /* rows with volumes can also be selected */
+              /* rows with devices can also be selected */
               result = TRUE;
 
-              /* release volume */
-              g_object_unref (volume);
+              /* release device */
+              g_object_unref (device);
             }
         }
     }


More information about the Xfce4-commits mailing list