From 83ac3e389fce49f12882ce10350e0e1ad8db0f16 Mon Sep 17 00:00:00 2001
From: Alexander Schwinn <alexxcons@xfce.org>
Date: Thu, 11 Mar 2021 14:25:45 +0100
Subject: [PATCH] Use thunar-menu and launcher in shortcuts view (Issue #198)

Instead of creating a separate, foreign context menu, and to have the
same menu-items than on tree-view.

That will result in the following additional menu items for
shortcuts-view:
- UCA's on mounted devices
- Menu item "Properties" on available bookmarks and mounted devices
- Menu item "SendTo" on available bookmarks and mounted devices
- Menu item "create folder" on available bookmarks and mounted devices
- Menu item "open with" on available bookmarks and mounted devices
- Menu itema "copy/paste" on available bookmarks and mounted devices
- Show menu-items tooltip text in the statusbar
---
 thunar/thunar-menu.c           |   6 +-
 thunar/thunar-menu.h           |   1 +
 thunar/thunar-shortcuts-pane.c |   6 +-
 thunar/thunar-shortcuts-view.c | 884 ++++++++++-----------------------
 4 files changed, 270 insertions(+), 627 deletions(-)

diff --git a/thunar/thunar-menu.c b/thunar/thunar-menu.c
index bbf6e8fd5..96cac77f8 100644
--- a/thunar/thunar-menu.c
+++ b/thunar/thunar-menu.c
@@ -249,7 +249,7 @@ thunar_menu_add_sections (ThunarMenu         *menu,
 {
   GtkWidget *window;
   gboolean   item_added;
-  gboolean   force = menu->type == THUNAR_MENU_TYPE_WINDOW || menu->type == THUNAR_MENU_TYPE_CONTEXT_TREE_VIEW;
+  gboolean   force = menu->type == THUNAR_MENU_TYPE_WINDOW || menu->type == THUNAR_MENU_TYPE_CONTEXT_TREE_VIEW || menu->type == THUNAR_MENU_TYPE_CONTEXT_SHORTCUTS_VIEW;
 
   _thunar_return_val_if_fail (THUNAR_IS_MENU (menu), FALSE);
 
@@ -258,8 +258,8 @@ thunar_menu_add_sections (ThunarMenu         *menu,
       item_added = FALSE;
       item_added |= (thunar_launcher_append_menu_item (menu->launcher, GTK_MENU_SHELL (menu), THUNAR_LAUNCHER_ACTION_CREATE_FOLDER, force) != NULL);
 
-      /* No document creation for tree-view */
-      if (menu->type != THUNAR_MENU_TYPE_CONTEXT_TREE_VIEW)
+      /* No document creation for side pane views */
+      if (menu->type != THUNAR_MENU_TYPE_CONTEXT_TREE_VIEW && menu->type != THUNAR_MENU_TYPE_CONTEXT_SHORTCUTS_VIEW)
         item_added |= (thunar_launcher_append_menu_item (menu->launcher, GTK_MENU_SHELL (menu), THUNAR_LAUNCHER_ACTION_CREATE_DOCUMENT, force) != NULL);
       if (item_added)
          xfce_gtk_menu_append_seperator (GTK_MENU_SHELL (menu));
diff --git a/thunar/thunar-menu.h b/thunar/thunar-menu.h
index a4ed55c84..3fd5abad8 100644
--- a/thunar/thunar-menu.h
+++ b/thunar/thunar-menu.h
@@ -42,6 +42,7 @@ typedef enum
   THUNAR_MENU_TYPE_CONTEXT_LOCATION_BUTTONS,
   THUNAR_MENU_TYPE_CONTEXT_RENAMER,
   THUNAR_MENU_TYPE_CONTEXT_TREE_VIEW,
+  THUNAR_MENU_TYPE_CONTEXT_SHORTCUTS_VIEW,
   N_THUNAR_MENU_TYPE,
 } ThunarMenuType;
 
diff --git a/thunar/thunar-shortcuts-pane.c b/thunar/thunar-shortcuts-pane.c
index 7e4f8fb1c..554d1769a 100644
--- a/thunar/thunar-shortcuts-pane.c
+++ b/thunar/thunar-shortcuts-pane.c
@@ -167,9 +167,9 @@ thunar_shortcuts_pane_init (ThunarShortcutsPane *shortcuts_pane)
   /* add widget to css class */
   gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (shortcuts_pane)), "shortcuts-pane");
 
-  /* connect the "shortcut-activated" signal */
-  g_signal_connect_swapped (G_OBJECT (shortcuts_pane->view), "shortcut-activated", G_CALLBACK (thunar_navigator_change_directory), shortcuts_pane);
-  g_signal_connect_swapped (G_OBJECT (shortcuts_pane->view), "shortcut-activated-tab", G_CALLBACK (thunar_navigator_open_new_tab), shortcuts_pane);
+  exo_binding_new (G_OBJECT (shortcuts_pane), "current-directory", G_OBJECT (shortcuts_pane->view), "current-directory");
+  g_signal_connect_swapped (G_OBJECT (shortcuts_pane->view), "change-directory", G_CALLBACK (thunar_navigator_change_directory), shortcuts_pane);
+  g_signal_connect_swapped (G_OBJECT (shortcuts_pane->view), "open_new_tab", G_CALLBACK (thunar_navigator_open_new_tab), shortcuts_pane);
 }
 
 
diff --git a/thunar/thunar-shortcuts-view.c b/thunar/thunar-shortcuts-view.c
index 428c75e24..97f12e2ff 100644
--- a/thunar/thunar-shortcuts-view.c
+++ b/thunar/thunar-shortcuts-view.c
@@ -33,6 +33,7 @@
 
 #include <gdk/gdkkeysyms.h>
 
+#include <thunar/thunar-navigator.h>
 #include <thunar/thunar-application.h>
 #include <thunar/thunar-browser.h>
 #include <thunar/thunar-device-monitor.h>
@@ -40,6 +41,7 @@
 #include <thunar/thunar-dnd.h>
 #include <thunar/thunar-gio-extensions.h>
 #include <thunar/thunar-gtk-extensions.h>
+#include <thunar/thunar-menu.h>
 #include <thunar/thunar-preferences.h>
 #include <thunar/thunar-private.h>
 #include <thunar/thunar-shortcuts-icon-renderer.h>
@@ -48,12 +50,11 @@
 
 
 
-/* Identifiers for signals */
+/* Property identifiers */
 enum
 {
-  SHORTCUT_ACTIVATED,
-  SHORTCUT_ACTIVATED_TAB,
-  LAST_SIGNAL,
+  PROP_0,
+  PROP_CURRENT_DIRECTORY,
 };
 
 /* Identifiers for DnD target types */
@@ -73,8 +74,19 @@ typedef enum
 OpenTarget;
 
 
-
+static void           thunar_shortcuts_view_navigator_init               (ThunarNavigatorIface     *iface);
 static void           thunar_shortcuts_view_finalize                     (GObject                  *object);
+static void           thunar_shortcuts_view_get_property                 (GObject                  *object,
+                                                                          guint                     prop_id,
+                                                                          GValue                   *value,
+                                                                          GParamSpec               *pspec);
+static void           thunar_shortcuts_view_set_property                 (GObject                  *object,
+                                                                          guint                     prop_id,
+                                                                          const GValue             *value,
+                                                                          GParamSpec               *pspec);
+static ThunarFile*    thunar_shortcuts_view_get_current_directory        (ThunarNavigator          *navigator);
+static void           thunar_shortcuts_view_set_current_directory        (ThunarNavigator          *navigator,
+                                                                          ThunarFile               *current_directory);
 static gboolean       thunar_shortcuts_view_button_press_event           (GtkWidget                *widget,
                                                                           GdkEventButton           *event);
 static gboolean       thunar_shortcuts_view_button_release_event         (GtkWidget                *widget,
@@ -119,12 +131,12 @@ static void           thunar_shortcuts_view_context_menu                 (Thunar
                                                                           GdkEventButton           *event,
                                                                           GtkTreeModel             *model,
                                                                           GtkTreeIter              *iter);
-static void           thunar_shortcuts_view_remove_activated             (GtkWidget                *item,
-                                                                          GtkTreeModel             *model);
+static void           thunar_shortcuts_view_remove_activated             (ThunarShortcutsView      *view,
+                                                                          GtkWidget                *item);
 static void           thunar_shortcuts_view_editing_canceled             (GtkCellRenderer          *renderer,
                                                                           ThunarShortcutsView      *view);
-static void           thunar_shortcuts_view_rename_activated             (GtkWidget                *item,
-                                                                          ThunarShortcutsView      *view);
+static void           thunar_shortcuts_view_rename_activated             (ThunarShortcutsView      *view,
+                                                                          GtkWidget                *item);
 static void           thunar_shortcuts_view_renamed                      (GtkCellRenderer          *renderer,
                                                                           const gchar              *path_string,
                                                                           const gchar              *text,
@@ -142,16 +154,15 @@ static GtkTreePath   *thunar_shortcuts_view_compute_drop_position        (Thunar
 static void           thunar_shortcuts_view_drop_uri_list                (ThunarShortcutsView      *view,
                                                                           GList                    *path_list,
                                                                           GtkTreePath              *dst_path);
-static void           thunar_shortcuts_view_open_clicked                 (ThunarShortcutsView      *view);
 static void           thunar_shortcuts_view_open                         (ThunarShortcutsView      *view,
                                                                           OpenTarget                open_in);
-static void           thunar_shortcuts_view_open_in_new_window_clicked   (ThunarShortcutsView      *view);
-static void           thunar_shortcuts_view_open_in_new_tab_clicked      (ThunarShortcutsView      *view);
-static void           thunar_shortcuts_view_empty_trash                  (ThunarShortcutsView      *view);
-static void           thunar_shortcuts_view_create_shortcut              (ThunarShortcutsView      *view);
 static void           thunar_shortcuts_view_eject                        (ThunarShortcutsView      *view);
-static void           thunar_shortcuts_view_mount                        (ThunarShortcutsView      *view);
-static void           thunar_shortcuts_view_unmount                      (ThunarShortcutsView      *view);
+static void           thunar_shortcuts_view_stop_spinner                 (ThunarShortcutsView      *view,
+                                                                          ThunarDevice             *device,
+                                                                          gpointer                  user_data);
+static void           thunar_shortcuts_view_start_spinner                (ThunarShortcutsView      *view,
+                                                                          ThunarDevice             *device,
+                                                                          gpointer                  user_data);
 
 
 
@@ -189,6 +200,10 @@ struct _ThunarShortcutsView
    * column whenever the shortcuts icon size is changed.
    */
   gulong queue_resize_signal_id;
+
+  /* used to create menu items for the context menu */
+  ThunarLauncher *launcher;
+  ThunarFile     *current_directory;
 };
 
 
@@ -204,14 +219,25 @@ static const GtkTargetEntry drop_targets[] = {
   { "text/uri-list", 0, TEXT_URI_LIST },
 };
 
+/* #XfceGtkActionEntrys provided by this widget */
+typedef enum
+{
+  THUNAR_SHORTCUTS_VIEW_ACTION_RENAME_BOOKMARK,
+  THUNAR_SHORTCUTS_VIEW_ACTION_REMOVE_BOOKMARK,
+} ThunarShortcutsViewAction;
 
+static XfceGtkActionEntry thunar_shortcuts_view_action_entries[] =
+{
+    { THUNAR_SHORTCUTS_VIEW_ACTION_RENAME_BOOKMARK, "<Actions>/ThunarShortcutsView/rename-bookmark", "", XFCE_GTK_MENU_ITEM,       N_("Re_name Shortcut"), NULL, "",            G_CALLBACK (thunar_shortcuts_view_rename_activated), },
+    { THUNAR_SHORTCUTS_VIEW_ACTION_REMOVE_BOOKMARK, "<Actions>/ThunarShortcutsView/remove-bookmark", "", XFCE_GTK_IMAGE_MENU_ITEM, N_("_Remove Shortcut"), NULL, "list-remove", G_CALLBACK (thunar_shortcuts_view_remove_activated), },
+};
 
-static guint view_signals[LAST_SIGNAL];
+#define get_action_entry(id) xfce_gtk_get_action_entry_by_id(thunar_shortcuts_view_action_entries,G_N_ELEMENTS(thunar_shortcuts_view_action_entries),id)
 
 
 
 G_DEFINE_TYPE_WITH_CODE (ThunarShortcutsView, thunar_shortcuts_view, GTK_TYPE_TREE_VIEW,
-                         G_IMPLEMENT_INTERFACE (THUNAR_TYPE_BROWSER, NULL))
+    G_IMPLEMENT_INTERFACE (THUNAR_TYPE_NAVIGATOR, thunar_shortcuts_view_navigator_init))
 
 
 
@@ -224,6 +250,8 @@ thunar_shortcuts_view_class_init (ThunarShortcutsViewClass *klass)
 
   gobject_class = G_OBJECT_CLASS (klass);
   gobject_class->finalize = thunar_shortcuts_view_finalize;
+  gobject_class->get_property = thunar_shortcuts_view_get_property;
+  gobject_class->set_property = thunar_shortcuts_view_set_property;
 
   gtkwidget_class = GTK_WIDGET_CLASS (klass);
   gtkwidget_class->button_press_event = thunar_shortcuts_view_button_press_event;
@@ -239,31 +267,19 @@ thunar_shortcuts_view_class_init (ThunarShortcutsViewClass *klass)
   gtktree_view_class = GTK_TREE_VIEW_CLASS (klass);
   gtktree_view_class->row_activated = thunar_shortcuts_view_row_activated;
 
-  /**
-   * ThunarShortcutsView:shortcut-activated:
-   *
-   * Invoked whenever a shortcut is activated by the user.
-   **/
-  view_signals[SHORTCUT_ACTIVATED] =
-    g_signal_new (I_("shortcut-activated"),
-                  G_TYPE_FROM_CLASS (klass),
-                  G_SIGNAL_RUN_LAST,
-                  0, NULL, NULL,
-                  g_cclosure_marshal_VOID__OBJECT,
-                  G_TYPE_NONE, 1, THUNAR_TYPE_FILE);
-
-  /**
-   * ThunarShortcutsView:shortcut-activated-tab:
-   *
-   * Invoked whenever a shortcut is activated by the user and should be opened in a new tab,
-   **/
-  view_signals[SHORTCUT_ACTIVATED_TAB] =
-    g_signal_new (I_("shortcut-activated-tab"),
-                  G_TYPE_FROM_CLASS (klass),
-                  G_SIGNAL_RUN_LAST,
-                  0, NULL, NULL,
-                  g_cclosure_marshal_VOID__OBJECT,
-                  G_TYPE_NONE, 1, THUNAR_TYPE_FILE);
+  /* Override ThunarNavigator's properties */
+  g_object_class_override_property (gobject_class, PROP_CURRENT_DIRECTORY, "current-directory");
+
+  xfce_gtk_translate_action_entries (thunar_shortcuts_view_action_entries, G_N_ELEMENTS (thunar_shortcuts_view_action_entries));
+}
+
+
+
+static void
+thunar_shortcuts_view_navigator_init (ThunarNavigatorIface *iface)
+{
+  iface->get_current_directory = thunar_shortcuts_view_get_current_directory;
+  iface->set_current_directory = thunar_shortcuts_view_set_current_directory;
 }
 
 
@@ -388,6 +404,14 @@ thunar_shortcuts_view_init (ThunarShortcutsView *view)
 
   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (view));
   gtk_tree_selection_set_select_function (selection, thunar_shortcuts_view_selection_func, NULL, NULL);
+
+  view->launcher =  g_object_new (THUNAR_TYPE_LAUNCHER, "widget", GTK_WIDGET (view), NULL);
+
+  g_signal_connect_swapped (G_OBJECT (view->launcher), "change-directory", G_CALLBACK (thunar_navigator_change_directory), view);
+  g_signal_connect_swapped (G_OBJECT (view->launcher), "open-new-tab", G_CALLBACK (thunar_navigator_open_new_tab), view);
+  g_signal_connect_swapped (G_OBJECT (view->launcher), "device-operation-started", G_CALLBACK (thunar_shortcuts_view_start_spinner), view);
+  g_signal_connect_swapped (G_OBJECT (view->launcher), "device-operation-finished", G_CALLBACK (thunar_shortcuts_view_stop_spinner), view);
+  exo_binding_new (G_OBJECT (view), "current-directory", G_OBJECT (view->launcher), "current-directory");
 }
 
 
@@ -406,6 +430,9 @@ thunar_shortcuts_view_finalize (GObject *object)
   /* disconnect the queue resize signal handler */
   g_signal_handler_disconnect (G_OBJECT (view->preferences), view->queue_resize_signal_id);
 
+  /* reset the current-directory property */
+  thunar_navigator_set_current_directory (THUNAR_NAVIGATOR (view), NULL);
+
   /* disconnect from the preferences object */
   g_signal_handlers_disconnect_matched (G_OBJECT (view->preferences), G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, view);
   g_object_unref (G_OBJECT (view->preferences));
@@ -415,6 +442,88 @@ thunar_shortcuts_view_finalize (GObject *object)
 
 
 
+static void
+thunar_shortcuts_view_get_property (GObject    *object,
+                                    guint       prop_id,
+                                    GValue     *value,
+                                    GParamSpec *pspec)
+{
+  switch (prop_id)
+    {
+    case PROP_CURRENT_DIRECTORY:
+      g_value_set_object (value, thunar_navigator_get_current_directory (THUNAR_NAVIGATOR (object)));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+
+
+static void
+thunar_shortcuts_view_set_property (GObject      *object,
+                                    guint         prop_id,
+                                    const GValue *value,
+                                    GParamSpec   *pspec)
+{
+  switch (prop_id)
+    {
+    case PROP_CURRENT_DIRECTORY:
+      thunar_navigator_set_current_directory (THUNAR_NAVIGATOR (object), g_value_get_object (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+
+
+static ThunarFile*
+thunar_shortcuts_view_get_current_directory (ThunarNavigator *navigator)
+{
+  return THUNAR_SHORTCUTS_VIEW (navigator)->current_directory;
+}
+
+
+
+static void
+thunar_shortcuts_view_set_current_directory (ThunarNavigator *navigator,
+                                             ThunarFile      *current_directory)
+{
+
+  ThunarShortcutsView *view = THUNAR_SHORTCUTS_VIEW (navigator);
+
+  /* check if we already use that directory */
+  if (G_UNLIKELY (view->current_directory == current_directory))
+    return;
+
+  /* check if we have an active directory */
+  if (G_LIKELY (view->current_directory != NULL))
+    {
+      /* disconnect from the previous current directory */
+      g_object_unref (G_OBJECT (view->current_directory));
+    }
+
+  /* activate the new current directory */
+  view->current_directory = current_directory;
+
+  /* connect to the new current directory */
+  if (G_LIKELY (current_directory != NULL))
+    {
+      /* take a reference on the directory */
+      g_object_ref (G_OBJECT (current_directory));
+    }
+
+  /* notify listeners */
+  g_object_notify (G_OBJECT (view), "current-directory");
+}
+
+
+
 static gboolean
 thunar_shortcuts_view_button_press_event (GtkWidget      *widget,
                                           GdkEventButton *event)
@@ -1073,21 +1182,15 @@ thunar_shortcuts_view_context_menu (ThunarShortcutsView *view,
 {
   GtkTreePath         *path;
   ThunarFile          *file;
-  GtkWidget           *image;
-  GtkWidget           *menu;
   GtkWidget           *item;
   GtkWidget           *window;
   gboolean             mutable;
   ThunarDevice        *device;
-  GList               *providers, *lp;
-  GList               *items = NULL, *tmp;
   ThunarShortcutGroup  group;
   gboolean             is_header;
-  GFile               *mount_point;
-  GtkTreeModel        *shortcuts_model;
-  gboolean             can_mount;
-  gboolean             can_unmount;
-  gboolean             can_eject;
+  GFile               *location;
+  GList               *files;
+  ThunarMenu          *context_menu;
 
   /* check if this is an item menu or a header menu */
   gtk_tree_model_get (model, iter, THUNAR_SHORTCUTS_MODEL_COLUMN_IS_HEADER, &is_header, -1);
@@ -1106,208 +1209,103 @@ thunar_shortcuts_view_context_menu (ThunarShortcutsView *view,
   gtk_tree_model_get (model, iter,
                       THUNAR_SHORTCUTS_MODEL_COLUMN_FILE, &file,
                       THUNAR_SHORTCUTS_MODEL_COLUMN_DEVICE, &device,
+                      THUNAR_SHORTCUTS_MODEL_COLUMN_LOCATION, &location,
                       THUNAR_SHORTCUTS_MODEL_COLUMN_MUTABLE, &mutable,
                       THUNAR_SHORTCUTS_MODEL_COLUMN_GROUP, &group,
                       -1);
 
-  /* prepare the popup menu */
-  menu = gtk_menu_new ();
-
-  /* append the "Open" menu action */
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-  item = gtk_image_menu_item_new_with_mnemonic (_("_Open"));
-G_GNUC_END_IGNORE_DEPRECATIONS
-  g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (thunar_shortcuts_view_open_clicked), view);
-  gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
-  gtk_widget_show (item);
-
-  /* set the icon */
-  image = gtk_image_new_from_icon_name ("document-open", GTK_ICON_SIZE_MENU);
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-  gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
-G_GNUC_END_IGNORE_DEPRECATIONS
-
-  /* append the "Open in New Tab" menu action */
-  item = gtk_menu_item_new_with_mnemonic (_("Open in New Tab"));
-  g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (thunar_shortcuts_view_open_in_new_tab_clicked), view);
-  gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
-  gtk_widget_show (item);
-
-  /* append the "Open in New Window" menu action */
-  item = gtk_menu_item_new_with_mnemonic (_("Open in New Window"));
-  g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (thunar_shortcuts_view_open_in_new_window_clicked), view);
-  gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
-  gtk_widget_show (item);
-
-  switch (group)
-    {
-      case THUNAR_SHORTCUT_GROUP_DEVICES_VOLUMES:
-        can_mount = thunar_device_can_mount (device);
-        can_unmount = thunar_device_can_unmount (device);
-        can_eject = thunar_device_can_eject (device);
-
-        if (!can_mount && !can_unmount && !can_eject)
-          break;
+  context_menu = g_object_new (THUNAR_TYPE_MENU, "menu-type", THUNAR_MENU_TYPE_CONTEXT_SHORTCUTS_VIEW,
+                                                 "launcher", view->launcher,
+                                                 "force-section-open", TRUE, NULL);
 
-        /* append a menu separator */
-        item = gtk_separator_menu_item_new ();
-        gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
-        gtk_widget_show (item);
-
-        /* append the "Mount" item */
-        item = gtk_menu_item_new_with_mnemonic (_("_Mount"));
-        gtk_widget_set_visible (item, can_mount);
-        g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (thunar_shortcuts_view_mount), view);
-        gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
-
-        /* append the "Unmount" item */
-        item = gtk_menu_item_new_with_mnemonic (_("_Unmount"));
-        gtk_widget_set_visible (item, can_unmount);
-        g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (thunar_shortcuts_view_unmount), view);
-        gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
-
-        /* append the "Eject" (safely remove drive) item */
-        item = gtk_menu_item_new_with_mnemonic (_("_Eject"));
-        gtk_widget_set_visible (item, can_eject);
-        gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
-        g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (thunar_shortcuts_view_eject), view);
-        break;
+  /* try to determine the ThunarFile of the location, if not set */
+  if (location != NULL && file == NULL)
+    {
+      file = thunar_file_get (location, NULL);
+      if (thunar_file_exists (file) == FALSE)
+        {
+          g_object_unref (G_OBJECT (file));
+          file = NULL;
+        }
+    }
 
-      case THUNAR_SHORTCUT_GROUP_NETWORK_MOUNTS:
-        /* append a menu separator */
-        item = gtk_separator_menu_item_new ();
-        gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
-        gtk_widget_show (item);
-
-        /* get the mount point */
-        mount_point = thunar_device_get_root (device);
-        shortcuts_model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (model));
-
-        /* append the "Create Shortcut" item */
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-        item = gtk_image_menu_item_new_with_mnemonic (_("Create _Shortcut"));
-G_GNUC_END_IGNORE_DEPRECATIONS
-        gtk_widget_set_sensitive (item, mount_point != NULL && !thunar_shortcuts_model_has_bookmark (THUNAR_SHORTCUTS_MODEL (shortcuts_model), mount_point));
-        g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (thunar_shortcuts_view_create_shortcut), view);
-        gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
-        gtk_widget_show (item);
-
-        image = gtk_image_new_from_icon_name ("bookmark-new", GTK_ICON_SIZE_MENU);
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-        gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
-G_GNUC_END_IGNORE_DEPRECATIONS
-
-        if (mount_point != NULL)
+  /* try to determine the ThunarFile of the device, if not set */
+  if (device != NULL && file == NULL && thunar_device_is_mounted (device))
+    {
+      GFile* mount_point = thunar_device_get_root (device);
+      if (G_LIKELY (mount_point != NULL))
+        {
+          file = thunar_file_get (mount_point, NULL);
           g_object_unref (mount_point);
-
-        /* fall-through */
-
-      case THUNAR_SHORTCUT_GROUP_DEVICES_MOUNTS:
-        /* append a menu separator */
-        item = gtk_separator_menu_item_new ();
-        gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
-        gtk_widget_show (item);
-
-        /* append the "Unmount" item */
-        item = gtk_menu_item_new_with_mnemonic (_("_Unmount"));
-        gtk_widget_set_sensitive (item, thunar_device_can_eject (device));
-        g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (thunar_shortcuts_view_eject), view);
-        gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
-        gtk_widget_show (item);
-        break;
-
-      case THUNAR_SHORTCUT_GROUP_PLACES_TRASH:
-        /* append a menu separator */
-        item = gtk_separator_menu_item_new ();
-        gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
-        gtk_widget_show (item);
-
-        /* append the "Empty Trash" menu action */
-        item = gtk_menu_item_new_with_mnemonic (_("_Empty Trash"));
-        gtk_widget_set_sensitive (item, (thunar_file_get_item_count (file) > 0));
-        g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (thunar_shortcuts_view_empty_trash), view);
-        gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
-        gtk_widget_show (item);
-        break;
-
-      default:
-        break;
+        }
     }
 
-  /* create provider menu items if there is a non-trashed file */
-  if (G_LIKELY (file != NULL && !thunar_file_is_trashed (file)))
+  if (file != NULL)
     {
-      /* load the menu providers from the provider factory */
-      providers = thunarx_provider_factory_list_providers (view->provider_factory, THUNARX_TYPE_MENU_PROVIDER);
-      if (G_LIKELY (providers != NULL))
+      files = g_list_append (NULL, file);
+      g_object_set (G_OBJECT (view->launcher), "current-directory", file, NULL);
+      thunar_launcher_set_selection (view->launcher, files, device, NULL);
+      g_list_free (files);
+      if (thunar_g_file_is_trash    (thunar_file_get_file (file)) ||
+          thunar_g_file_is_computer (thunar_file_get_file (file)) ||
+          thunar_g_file_is_network  (thunar_file_get_file (file)))
         {
-          /* determine the toplevel window we belong to */
-          window = gtk_widget_get_toplevel (GTK_WIDGET (view));
-
-          /* load the menu items offered by the menu providers */
-          for (lp = providers; lp != NULL; lp = lp->next)
-            {
-              tmp = thunarx_menu_provider_get_folder_menu_items (lp->data, window, THUNARX_FILE_INFO (file));
-              items = g_list_concat (items, tmp);
-              g_object_unref (G_OBJECT (lp->data));
-            }
-          g_list_free (providers);
-
-          if (items != NULL)
-            {
-              /* append a menu separator */
-              item = gtk_separator_menu_item_new ();
-              gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
-              gtk_widget_show (item);
-            }
-
-          /* add the menu items to the menu */
-          for (lp = items; lp != NULL; lp = lp->next)
-            {
-              item = thunar_gtk_menu_thunarx_menu_item_new (lp->data, GTK_MENU_SHELL (menu));
-              gtk_widget_show (item);
-            }
-
-          /* cleanup */
-          g_list_free (items);
+          thunar_launcher_append_menu_item (view->launcher, GTK_MENU_SHELL (context_menu), THUNAR_LAUNCHER_ACTION_OPEN, TRUE);
+          thunar_launcher_append_menu_item (view->launcher, GTK_MENU_SHELL (context_menu), THUNAR_LAUNCHER_ACTION_OPEN_IN_TAB, TRUE);
+          thunar_launcher_append_menu_item (view->launcher, GTK_MENU_SHELL (context_menu), THUNAR_LAUNCHER_ACTION_OPEN_IN_WINDOW, TRUE);
+          xfce_gtk_menu_append_seperator (GTK_MENU_SHELL (context_menu));
+          thunar_menu_add_sections (context_menu, THUNAR_MENU_SECTION_EMPTY_TRASH);
+        }
+      else
+        {
+          thunar_menu_add_sections (context_menu, THUNAR_MENU_SECTION_OPEN);
+          thunar_menu_add_sections (context_menu, THUNAR_MENU_SECTION_SENDTO
+                                                | THUNAR_MENU_SECTION_CREATE_NEW_FILES
+                                                | THUNAR_MENU_SECTION_COPY_PASTE
+                                                | THUNAR_MENU_SECTION_CUSTOM_ACTIONS);
         }
+
+      thunar_menu_add_sections (context_menu, THUNAR_MENU_SECTION_MOUNTABLE);
+      thunar_menu_add_sections (context_menu, THUNAR_MENU_SECTION_PROPERTIES);
+    }
+  else if (location != NULL)
+    {
+      g_object_set (G_OBJECT (view->launcher), "selected-location", location, NULL);
+      thunar_launcher_append_menu_item (view->launcher, GTK_MENU_SHELL (context_menu), THUNAR_LAUNCHER_ACTION_OPEN, TRUE);
+      thunar_launcher_append_menu_item (view->launcher, GTK_MENU_SHELL (context_menu), THUNAR_LAUNCHER_ACTION_OPEN_IN_TAB, TRUE);
+      thunar_launcher_append_menu_item (view->launcher, GTK_MENU_SHELL (context_menu), THUNAR_LAUNCHER_ACTION_OPEN_IN_WINDOW, TRUE);
+    }
+  else if (device != NULL)
+    {
+      g_object_set (G_OBJECT (view->launcher), "selected-device", device, NULL);
+      thunar_launcher_append_menu_item (view->launcher, GTK_MENU_SHELL (context_menu), THUNAR_LAUNCHER_ACTION_OPEN, TRUE);
+      thunar_launcher_append_menu_item (view->launcher, GTK_MENU_SHELL (context_menu), THUNAR_LAUNCHER_ACTION_OPEN_IN_TAB, TRUE);
+      thunar_launcher_append_menu_item (view->launcher, GTK_MENU_SHELL (context_menu), THUNAR_LAUNCHER_ACTION_OPEN_IN_WINDOW, TRUE);
+      xfce_gtk_menu_append_seperator (GTK_MENU_SHELL (context_menu));
+      thunar_menu_add_sections (context_menu, THUNAR_MENU_SECTION_MOUNTABLE);
+      if (thunar_device_is_mounted (device))
+        thunar_menu_add_sections (context_menu, THUNAR_MENU_SECTION_PROPERTIES);
     }
+  else
+      g_error("Unknown type");
 
-  /* append the remove menu item */
   if (group == THUNAR_SHORTCUT_GROUP_PLACES_BOOKMARKS)
-    {
-      /* append a menu separator */
-      item = gtk_separator_menu_item_new ();
-      gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
-      gtk_widget_show (item);
-
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-      item = gtk_image_menu_item_new_with_mnemonic (_("_Remove Shortcut"));
-G_GNUC_END_IGNORE_DEPRECATIONS
+  {
+      item = xfce_gtk_menu_item_new_from_action_entry (get_action_entry (THUNAR_SHORTCUTS_VIEW_ACTION_REMOVE_BOOKMARK), G_OBJECT (model), GTK_MENU_SHELL (context_menu));
       g_object_set_data_full (G_OBJECT (item), I_("thunar-shortcuts-row"),
                               gtk_tree_row_reference_new (model, path),
                               (GDestroyNotify) gtk_tree_row_reference_free);
-      g_signal_connect (G_OBJECT (item), "activate", G_CALLBACK (thunar_shortcuts_view_remove_activated), model);
-      gtk_widget_set_sensitive (item, mutable);
-      gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
-      gtk_widget_show (item);
-
-      /* set the remove icon */
-      image = gtk_image_new_from_icon_name ("list-remove", GTK_ICON_SIZE_MENU);
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-      gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
-G_GNUC_END_IGNORE_DEPRECATIONS
-
-      /* append the rename menu item */
-      item = gtk_menu_item_new_with_mnemonic (_("Re_name Shortcut"));
+      item = xfce_gtk_menu_item_new_from_action_entry (get_action_entry (THUNAR_SHORTCUTS_VIEW_ACTION_RENAME_BOOKMARK), G_OBJECT (view), GTK_MENU_SHELL (context_menu));
       g_object_set_data_full (G_OBJECT (item), I_("thunar-shortcuts-row"),
                               gtk_tree_row_reference_new (model, path),
                               (GDestroyNotify) gtk_tree_row_reference_free);
-      g_signal_connect (G_OBJECT (item), "activate", G_CALLBACK (thunar_shortcuts_view_rename_activated), view);
-      gtk_widget_set_sensitive (item, mutable);
-      gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
-      gtk_widget_show (item);
-    }
+  }
+
+  thunar_menu_hide_accel_labels (context_menu);
+  gtk_widget_show_all (GTK_WIDGET (context_menu));
+  window = gtk_widget_get_toplevel (GTK_WIDGET (view));
+  thunar_window_redirect_menu_tooltips_to_statusbar (THUNAR_WINDOW (window), GTK_MENU (context_menu));
+  thunar_gtk_menu_run (GTK_MENU (context_menu));
 
   /* clean up */
   if (G_LIKELY (file != NULL))
@@ -1315,16 +1313,13 @@ G_GNUC_END_IGNORE_DEPRECATIONS
   if (G_UNLIKELY (device != NULL))
     g_object_unref (G_OBJECT (device));
   gtk_tree_path_free (path);
-
-  /* run the menu (taking over the floating reference on menu) */
-  thunar_gtk_menu_run (GTK_MENU (menu));
 }
 
 
 
 static void
-thunar_shortcuts_view_remove_activated (GtkWidget    *item,
-                                        GtkTreeModel *model)
+thunar_shortcuts_view_remove_activated (ThunarShortcutsView *view,
+                                        GtkWidget           *item)
 {
   GtkTreeRowReference *row;
   GtkTreeModel        *child_model;
@@ -1335,10 +1330,10 @@ thunar_shortcuts_view_remove_activated (GtkWidget    *item,
   path = gtk_tree_row_reference_get_path (row);
   if (G_LIKELY (path != NULL))
     {
-      child_path = gtk_tree_model_filter_convert_path_to_child_path (GTK_TREE_MODEL_FILTER (model), path);
+      child_path = gtk_tree_model_filter_convert_path_to_child_path (GTK_TREE_MODEL_FILTER (view), path);
       gtk_tree_path_free (path);
 
-      child_model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (model));
+      child_model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (view));
       thunar_shortcuts_model_remove (THUNAR_SHORTCUTS_MODEL (child_model), child_path);
       gtk_tree_path_free (child_path);
     }
@@ -1360,8 +1355,8 @@ thunar_shortcuts_view_editing_canceled (GtkCellRenderer     *renderer,
 
 
 static void
-thunar_shortcuts_view_rename_activated (GtkWidget           *item,
-                                        ThunarShortcutsView *view)
+thunar_shortcuts_view_rename_activated (ThunarShortcutsView *view,
+                                        GtkWidget           *item)
 {
   GtkTreeRowReference *row;
   GtkTreeViewColumn   *column;
@@ -1658,127 +1653,6 @@ thunar_shortcuts_view_drop_uri_list (ThunarShortcutsView *view,
 
 
 
-static void
-thunar_shortcuts_view_open_clicked (ThunarShortcutsView *view)
-{
-  _thunar_return_if_fail (THUNAR_IS_SHORTCUTS_VIEW (view));
-  thunar_shortcuts_view_open (view, OPEN_IN_VIEW);
-}
-
-
-
-static void
-thunar_shortcuts_view_poke_file_finish (ThunarBrowser *browser,
-                                        ThunarFile    *file,
-                                        ThunarFile    *target_file,
-                                        GError        *error,
-                                        gpointer       user_data)
-{
-  ThunarApplication *application;
-  OpenTarget         open_in = GPOINTER_TO_UINT (user_data);
-
-  _thunar_return_if_fail (THUNAR_IS_SHORTCUTS_VIEW (browser));
-  _thunar_return_if_fail (THUNAR_IS_FILE (target_file));
-
-  if (error == NULL)
-    {
-      if (open_in == OPEN_IN_WINDOW)
-        {
-          /* open a new window for the target folder */
-          application = thunar_application_get ();
-          thunar_application_open_window (application, target_file,
-                                          gtk_widget_get_screen (GTK_WIDGET (browser)), NULL, TRUE);
-          g_object_unref (application);
-        }
-      else if (open_in == OPEN_IN_TAB)
-        {
-          /* invoke the signal to change to open folder in a new tab */
-          g_signal_emit (browser, view_signals[SHORTCUT_ACTIVATED_TAB], 0, target_file);
-        }
-      else if (thunar_file_check_loaded (target_file))
-        {
-          /* invoke the signal to change to that folder */
-          g_signal_emit (browser, view_signals[SHORTCUT_ACTIVATED], 0, target_file);
-        }
-    }
-  else
-    {
-      thunar_dialogs_show_error (GTK_WIDGET (browser), error, _("Failed to open \"%s\""),
-                                 thunar_file_get_display_name (file));
-    }
-}
-
-
-
-static void
-thunar_shortcuts_view_poke_location_finish (ThunarBrowser *browser,
-                                            GFile         *location,
-                                            ThunarFile    *file,
-                                            ThunarFile    *target_file,
-                                            GError        *error,
-                                            gpointer       user_data)
-{
-  gchar *name;
-
-  _thunar_return_if_fail (THUNAR_IS_SHORTCUTS_VIEW (browser));
-  _thunar_return_if_fail (G_IS_FILE (location));
-
-  /* sotre the new file in the shortcuts model */
-  if (error == NULL)
-    {
-      thunar_shortcuts_view_poke_file_finish (browser, file, target_file, error, user_data);
-    }
-  else
-    {
-      name = thunar_g_file_get_display_name_remote (location);
-      thunar_dialogs_show_error (GTK_WIDGET (browser), error, _("Failed to open \"%s\""), name);
-      g_free (name);
-    }
-}
-
-
-
-static void
-thunar_shortcuts_view_poke_device_finish (ThunarBrowser *browser,
-                                          ThunarDevice  *device,
-                                          ThunarFile    *mount_point,
-                                          GError        *error,
-                                          gpointer       user_data,
-                                          gboolean       cancelled)
-{
-  gchar        *device_name;
-  GtkTreeModel *model;
-  GtkTreeModel *child_model;
-
-  _thunar_return_if_fail (THUNAR_IS_SHORTCUTS_VIEW (browser));
-  _thunar_return_if_fail (THUNAR_IS_DEVICE (device));
-
-  if (cancelled)
-    {
-      /* do nothing */
-    }
-  else if (error == NULL)
-    {
-      thunar_browser_poke_file (browser, mount_point, GTK_WIDGET (browser),
-                                thunar_shortcuts_view_poke_file_finish,
-                                user_data);
-    }
-  else
-    {
-      device_name = thunar_device_get_name (device);
-      thunar_dialogs_show_error (GTK_WIDGET (browser), error,
-                                 _("Failed to mount \"%s\""), device_name);
-      g_free (device_name);
-    }
-
-  /* stop the spinner */
-  model = gtk_tree_view_get_model (GTK_TREE_VIEW (browser));
-  child_model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (model));
-  thunar_shortcuts_model_set_busy (THUNAR_SHORTCUTS_MODEL (child_model), device, FALSE);
-}
-
-
-
 static void
 thunar_shortcuts_view_open (ThunarShortcutsView *view,
                             OpenTarget           open_in)
@@ -1787,9 +1661,9 @@ thunar_shortcuts_view_open (ThunarShortcutsView *view,
   GtkTreeModel     *model;
   GtkTreeIter       iter;
   ThunarFile       *file;
+  GList *files;
   ThunarDevice     *device;
   GFile            *location;
-  GtkTreeModel     *child_model;
 
   _thunar_return_if_fail (THUNAR_IS_SHORTCUTS_VIEW (view));
 
@@ -1809,28 +1683,22 @@ thunar_shortcuts_view_open (ThunarShortcutsView *view,
                           THUNAR_SHORTCUTS_MODEL_COLUMN_LOCATION, &location,
                           -1);
 
-      if (G_LIKELY (THUNAR_IS_DEVICE (device)))
-        {
-          /* start the spinner */
-          child_model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (model));
-          thunar_shortcuts_model_set_busy (THUNAR_SHORTCUTS_MODEL (child_model), device, TRUE);
-
-          thunar_browser_poke_device (THUNAR_BROWSER (view), device, view,
-                                      thunar_shortcuts_view_poke_device_finish,
-                                      GUINT_TO_POINTER (open_in));
-        }
-      else if (file != NULL)
-        {
-          thunar_browser_poke_file (THUNAR_BROWSER (view), file, view,
-                                    thunar_shortcuts_view_poke_file_finish,
-                                    GUINT_TO_POINTER (open_in));
-        }
-      else if (location != NULL)
-        {
-          thunar_browser_poke_location (THUNAR_BROWSER (view), location, view,
-                                        thunar_shortcuts_view_poke_location_finish,
-                                        GUINT_TO_POINTER (open_in));
-        }
+      if (device != NULL)
+         {
+            g_object_set (G_OBJECT (view->launcher), "selected-device", device, NULL);
+         }
+       else if (file != NULL)
+         {
+           files = g_list_append (NULL, file);
+           thunar_launcher_set_selection (view->launcher, files, device, NULL);
+           g_list_free (files);
+         }
+       else if (location != 0)
+         {
+           g_object_set (G_OBJECT (view->launcher), "selected-location", location, NULL);
+         }
+
+      thunar_launcher_activate_selected_files (view->launcher, THUNAR_LAUNCHER_CHANGE_DIRECTORY, NULL);
 
       if (file != NULL)
         g_object_unref (file);
@@ -1846,261 +1714,48 @@ thunar_shortcuts_view_open (ThunarShortcutsView *view,
 
 
 static void
-thunar_shortcuts_view_open_in_new_window_clicked (ThunarShortcutsView *view)
-{
-  _thunar_return_if_fail (THUNAR_IS_SHORTCUTS_VIEW (view));
-  thunar_shortcuts_view_open (view, OPEN_IN_WINDOW);
-}
-
-
-
-static void
-thunar_shortcuts_view_open_in_new_tab_clicked (ThunarShortcutsView *view)
-{
-  _thunar_return_if_fail (THUNAR_IS_SHORTCUTS_VIEW (view));
-  thunar_shortcuts_view_open (view, OPEN_IN_TAB);
-}
-
-
-
-static void
-thunar_shortcuts_view_empty_trash (ThunarShortcutsView *view)
-{
-  ThunarApplication *application;
-
-  _thunar_return_if_fail (THUNAR_IS_SHORTCUTS_VIEW (view));
-
-  /* empty the trash bin (asking the user first) */
-  application = thunar_application_get ();
-  thunar_application_empty_trash (application, GTK_WIDGET (view), NULL);
-  g_object_unref (G_OBJECT (application));
-}
-
-
-
-static void
-thunar_shortcuts_view_create_shortcut (ThunarShortcutsView *view)
-{
-  GtkTreeSelection *selection;
-  GtkTreeModel     *model;
-  GtkTreeIter       iter;
-  ThunarDevice     *device;
-  GFile            *mount_point;
-  GtkTreeModel     *shortcuts_model;
-
-  _thunar_return_if_fail (THUNAR_IS_SHORTCUTS_VIEW (view));
-
-  /* determine the selected item */
-  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (view));
-  if (gtk_tree_selection_get_selected (selection, &model, &iter))
-    {
-      /* determine the device/mount for the shortcut at the given tree iterator */
-      gtk_tree_model_get (model, &iter, THUNAR_SHORTCUTS_MODEL_COLUMN_DEVICE, &device, -1);
-
-      if (G_LIKELY (THUNAR_IS_DEVICE (device)))
-        {
-          /* add the mount point to the model */
-          mount_point = thunar_device_get_root (device);
-          if (mount_point != NULL)
-            {
-              shortcuts_model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (model));
-              thunar_shortcuts_model_add (THUNAR_SHORTCUTS_MODEL (shortcuts_model), NULL, mount_point);
-              g_object_unref (mount_point);
-            }
-
-          g_object_unref (G_OBJECT (device));
-        }
-    }
-}
-
-
-
-static void
-thunar_shortcuts_view_eject_finish (ThunarDevice *device,
-                                    const GError *error,
+thunar_shortcuts_view_start_spinner (ThunarShortcutsView *view,
+                                    ThunarDevice *device,
                                     gpointer      user_data)
 {
-  ThunarShortcutsView *view = THUNAR_SHORTCUTS_VIEW (user_data);
-  gchar               *device_name;
   GtkTreeModel        *model;
   GtkTreeModel        *child_model;
 
   _thunar_return_if_fail (THUNAR_IS_DEVICE (device));
   _thunar_return_if_fail (THUNAR_IS_SHORTCUTS_VIEW (view));
 
-  /* check if there was an error */
-  if (error != NULL)
-    {
-      /* 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);
-    }
-
-  /* stop the spinner */
   model = gtk_tree_view_get_model (GTK_TREE_VIEW (view));
   child_model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (model));
-  thunar_shortcuts_model_set_busy (THUNAR_SHORTCUTS_MODEL (child_model), device, FALSE);
-
-  g_object_unref (view);
-}
-
-
-
-static void
-thunar_shortcuts_view_eject (ThunarShortcutsView *view)
-{
-  GtkTreeSelection *selection;
-  GtkTreeModel     *model;
-  GtkTreeIter       iter;
-  ThunarDevice     *device;
-  GMountOperation  *mount_operation;
-  GtkTreeModel     *child_model;
-
-  _thunar_return_if_fail (THUNAR_IS_SHORTCUTS_VIEW (view));
-
-  /* determine the selected item */
-  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (view));
-  if (gtk_tree_selection_get_selected (selection, &model, &iter))
-    {
-      /* determine the device/mount for the shortcut at the given tree iterator */
-      gtk_tree_model_get (model, &iter, THUNAR_SHORTCUTS_MODEL_COLUMN_DEVICE, &device, -1);
-
-      if (G_LIKELY (THUNAR_IS_DEVICE (device)))
-        {
-          /* prepare a mount operation */
-          mount_operation = thunar_gtk_mount_operation_new (GTK_WIDGET (view));
-
-          /* start the spinner */
-          child_model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (model));
-          thunar_shortcuts_model_set_busy (THUNAR_SHORTCUTS_MODEL (child_model), device, TRUE);
-
-          /* try to unmount */
-          thunar_device_eject (device,
-                               mount_operation,
-                               NULL,
-                               thunar_shortcuts_view_eject_finish,
-                               g_object_ref (view));
-
-          g_object_unref (G_OBJECT (device));
-          g_object_unref (G_OBJECT (mount_operation));
-        }
-    }
-}
-
-
-
-static void
-thunar_shortcuts_view_poke_device_mount_finish (ThunarBrowser *browser,
-                                                ThunarDevice  *device,
-                                                ThunarFile    *mount_point,
-                                                GError        *error,
-                                                gpointer       ignored,
-                                                gboolean       cancelled)
-{
-  gchar        *device_name;
-  GtkTreeModel *model;
-  GtkTreeModel *child_model;
-
-  _thunar_return_if_fail (THUNAR_IS_SHORTCUTS_VIEW (browser));
-  _thunar_return_if_fail (THUNAR_IS_DEVICE (device));
-
-  if (error != NULL)
-    {
-      device_name = thunar_device_get_name (device);
-      thunar_dialogs_show_error (GTK_WIDGET (browser), error,
-                                 _("Failed to mount \"%s\""), device_name);
-      g_free (device_name);
-    }
-
-  /* stop the spinner */
-  model = gtk_tree_view_get_model (GTK_TREE_VIEW (browser));
-  child_model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (model));
-  thunar_shortcuts_model_set_busy (THUNAR_SHORTCUTS_MODEL (child_model), device, FALSE);
+  thunar_shortcuts_model_set_busy (THUNAR_SHORTCUTS_MODEL (child_model), device, TRUE);
 }
 
 
 
 static void
-thunar_shortcuts_view_mount (ThunarShortcutsView *view)
-{
-  GtkTreeSelection *selection;
-  GtkTreeModel     *model;
-  GtkTreeIter       iter;
-  ThunarDevice     *device;
-  GtkTreeModel     *child_model;
-
-  _thunar_return_if_fail (THUNAR_IS_SHORTCUTS_VIEW (view));
-
-  /* determine the selected item */
-  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (view));
-
-  /* avoid dealing with invalid selections */
-  if (!GTK_IS_TREE_SELECTION (selection))
-    return;
-
-  if (gtk_tree_selection_get_selected (selection, &model, &iter))
-    {
-      /* determine the file for the shortcut at the given tree iterator */
-      gtk_tree_model_get (model, &iter, THUNAR_SHORTCUTS_MODEL_COLUMN_DEVICE, &device, -1);
-
-      if (G_LIKELY (THUNAR_IS_DEVICE (device)))
-        {
-          /* start the spinner */
-          child_model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (model));
-          thunar_shortcuts_model_set_busy (THUNAR_SHORTCUTS_MODEL (child_model), device, TRUE);
-
-          thunar_browser_poke_device (THUNAR_BROWSER (view), device, view,
-                                      (ThunarBrowserPokeDeviceFunc)thunar_shortcuts_view_poke_device_mount_finish,
-                                      NULL);
-          g_object_unref (device);
-        }
-    }
-}
-
-
-
-static void
-thunar_shortcuts_view_unmount_finish (ThunarDevice *device,
-                                      const GError *error,
-                                      gpointer      user_data)
+thunar_shortcuts_view_stop_spinner (ThunarShortcutsView *view,
+                                    ThunarDevice *device,
+                                    gpointer      user_data)
 {
-  ThunarShortcutsView *view = THUNAR_SHORTCUTS_VIEW (user_data);
-  gchar               *device_name;
   GtkTreeModel        *model;
   GtkTreeModel        *child_model;
 
   _thunar_return_if_fail (THUNAR_IS_DEVICE (device));
   _thunar_return_if_fail (THUNAR_IS_SHORTCUTS_VIEW (view));
 
-  /* check if there was an error */
-  if (error != NULL)
-    {
-      /* 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);
-    }
-
-  /* stop the spinner */
   model = gtk_tree_view_get_model (GTK_TREE_VIEW (view));
   child_model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (model));
   thunar_shortcuts_model_set_busy (THUNAR_SHORTCUTS_MODEL (child_model), device, FALSE);
-
-  g_object_unref (view);
 }
 
 
 
 static void
-thunar_shortcuts_view_unmount (ThunarShortcutsView *view)
+thunar_shortcuts_view_eject (ThunarShortcutsView *view)
 {
   GtkTreeSelection *selection;
   GtkTreeModel     *model;
   GtkTreeIter       iter;
   ThunarDevice     *device;
-  GMountOperation  *mount_operation;
-  GtkTreeModel     *child_model;
 
   _thunar_return_if_fail (THUNAR_IS_SHORTCUTS_VIEW (view));
 
@@ -2113,22 +1768,9 @@ thunar_shortcuts_view_unmount (ThunarShortcutsView *view)
 
       if (G_LIKELY (THUNAR_IS_DEVICE (device)))
         {
-          /* prepare a mount operation */
-          mount_operation = thunar_gtk_mount_operation_new (GTK_WIDGET (view));
-
-          /* start the spinner */
-          child_model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (model));
-          thunar_shortcuts_model_set_busy (THUNAR_SHORTCUTS_MODEL (child_model), device, TRUE);
-
-          /* try to unmount */
-          thunar_device_unmount (device,
-                                 mount_operation,
-                                 NULL,
-                                 thunar_shortcuts_view_unmount_finish,
-                                 g_object_ref (view));
-
+          g_object_set (G_OBJECT (view->launcher), "selected-device", device, NULL);
+          thunar_launcher_action_eject (view->launcher);
           g_object_unref (G_OBJECT (device));
-          g_object_unref (G_OBJECT (mount_operation));
         }
     }
 }
-- 
GitLab