From b23a42c3fa1cea7eb52d33d10a9504e38e22eee3 Mon Sep 17 00:00:00 2001
From: Alexander Schwinn <alexxcons@xfce.org>
Date: Sun, 17 May 2020 22:28:19 +0200
Subject: [PATCH] Add possibility to send to shortcuts in launcher (Issue #293)

---
 thunar/thunar-launcher.c       | 47 +++++++++++++++++++
 thunar/thunar-launcher.h       |  1 +
 thunar/thunar-shortcuts-pane.c | 84 ++++++++--------------------------
 thunar/thunar-shortcuts-pane.h |  4 +-
 thunar/thunar-window.c         | 35 ++++++++++++++
 thunar/thunar-window.h         |  2 +
 6 files changed, 106 insertions(+), 67 deletions(-)

diff --git a/thunar/thunar-launcher.c b/thunar/thunar-launcher.c
index 587668ab6..b2290df20 100644
--- a/thunar/thunar-launcher.c
+++ b/thunar/thunar-launcher.c
@@ -132,6 +132,7 @@ static void                    thunar_launcher_action_sendto_desktop      (Thuna
 static void                    thunar_launcher_action_properties          (ThunarLauncher                 *launcher);
 static void                    thunar_launcher_action_sendto_device       (ThunarLauncher                 *launcher,
                                                                            GObject                        *object);
+static void                    thunar_launcher_action_add_shortcuts       (ThunarLauncher                 *launcher);
 static void                    thunar_launcher_action_make_link           (ThunarLauncher                 *launcher);
 static void                    thunar_launcher_action_duplicate           (ThunarLauncher                 *launcher);
 static void                    thunar_launcher_action_rename              (ThunarLauncher                 *launcher);
@@ -235,6 +236,7 @@ static XfceGtkActionEntry thunar_launcher_action_entries[] =
     /* For backward compatibility the old accel paths are re-used. Currently not possible to automatically migrate to new accel paths. */
     /* Waiting for https://gitlab.gnome.org/GNOME/gtk/issues/2375 to be able to fix that */
     { THUNAR_LAUNCHER_ACTION_SENDTO_MENU,      "<Actions>/ThunarWindow/sendto-menu",               "",                  XFCE_GTK_MENU_ITEM,       N_ ("_Send To"),                        NULL,                                                                                            NULL,                   NULL,                                                    },
+    { THUNAR_LAUNCHER_ACTION_SENDTO_SHORTCUTS, "<Actions>/ThunarShortcutsPane/sendto-shortcuts",   "",                  XFCE_GTK_MENU_ITEM,       NULL,                                   NULL,                                                                                            "bookmark-new",         G_CALLBACK (thunar_launcher_action_add_shortcuts),       },
     { THUNAR_LAUNCHER_ACTION_SENDTO_DESKTOP,   "<Actions>/ThunarLauncher/sendto-desktop",          "",                  XFCE_GTK_MENU_ITEM,       NULL,                                   NULL,                                                                                            "user-desktop",         G_CALLBACK (thunar_launcher_action_sendto_desktop),      },
     { THUNAR_LAUNCHER_ACTION_PROPERTIES,       "<Actions>/ThunarStandardView/properties",          "<Alt>Return",       XFCE_GTK_IMAGE_MENU_ITEM, N_ ("_Properties..."),                  N_ ("View the properties of the selected file"),                                                 "document-properties",  G_CALLBACK (thunar_launcher_action_properties),          },
     { THUNAR_LAUNCHER_ACTION_MAKE_LINK,        "<Actions>/ThunarStandardView/make-link",           "",                  XFCE_GTK_MENU_ITEM,       N_ ("Ma_ke Link"),                      NULL,                                                                                            NULL,                   G_CALLBACK (thunar_launcher_action_make_link),           },
@@ -1649,6 +1651,32 @@ thunar_launcher_action_sendto_device (ThunarLauncher *launcher,
 }
 
 
+static void
+thunar_launcher_action_add_shortcuts (ThunarLauncher *launcher)
+{
+  GList           *lp;
+  GtkWidget       *window;
+  const GtkWidget *sidepane;
+
+  _thunar_return_if_fail (THUNAR_IS_LAUNCHER (launcher));
+
+  /* determine the toplevel window we belong to */
+  window = gtk_widget_get_toplevel (launcher->widget);
+  if (THUNAR_IS_WINDOW (window) == FALSE)
+    return;
+  if (thunar_window_has_shortcut_sidepane (THUNAR_WINDOW (window)) == FALSE)
+    return;
+
+  sidepane = thunar_window_get_sidepane (THUNAR_WINDOW (window));
+  if (sidepane != NULL  && THUNAR_IS_SHORTCUTS_PANE (sidepane))
+    {
+      for (lp = launcher->selected_files; lp != NULL; lp = lp->next)
+        thunar_shortcuts_pane_add_shortcut (THUNAR_SHORTCUTS_PANE (sidepane), lp->data);
+    }
+
+}
+
+
 
 static GtkWidget*
 thunar_launcher_build_sendto_submenu (ThunarLauncher *launcher)
@@ -1672,6 +1700,25 @@ thunar_launcher_build_sendto_submenu (ThunarLauncher *launcher)
 
   submenu = gtk_menu_new();
 
+  /* show "sent to shortcut" if only directories are selected */
+  if (launcher->n_selected_directories > 0 && launcher->n_selected_directories == launcher->n_selected_files)
+    {
+      /* determine the toplevel window we belong to */
+      window = gtk_widget_get_toplevel (launcher->widget);
+      if (THUNAR_IS_WINDOW (window) && thunar_window_has_shortcut_sidepane (THUNAR_WINDOW (window)))
+        {
+          action_entry = get_action_entry (THUNAR_LAUNCHER_ACTION_SENDTO_SHORTCUTS);
+          if (action_entry != NULL)
+            {
+              label_text   = ngettext ("Side Pane (Create Shortcut)", "Side Pane (Create Shortcuts)", launcher->n_selected_files);
+              tooltip_text = ngettext ("Add the selected folder to the shortcuts side pane",
+                                       "Add the selected folders to the shortcuts side pane", launcher->n_selected_files);
+              item = xfce_gtk_image_menu_item_new_from_icon_name (label_text, tooltip_text, action_entry->accel_path, action_entry->callback,
+                                                                  G_OBJECT (launcher), action_entry->menu_item_icon_name, GTK_MENU_SHELL (submenu));
+            }
+        }
+    }
+
   /* Check whether at least one files is located in the trash (to en-/disable the "sendto-desktop" action). */
   for (lp = launcher->selected_files; lp != NULL; lp = lp->next)
     {
diff --git a/thunar/thunar-launcher.h b/thunar/thunar-launcher.h
index 9b6c95830..fb7511468 100644
--- a/thunar/thunar-launcher.h
+++ b/thunar/thunar-launcher.h
@@ -44,6 +44,7 @@ typedef enum
   THUNAR_LAUNCHER_ACTION_OPEN_IN_WINDOW,
   THUNAR_LAUNCHER_ACTION_OPEN_WITH_OTHER,
   THUNAR_LAUNCHER_ACTION_SENDTO_MENU,
+  THUNAR_LAUNCHER_ACTION_SENDTO_SHORTCUTS,
   THUNAR_LAUNCHER_ACTION_SENDTO_DESKTOP,
   THUNAR_LAUNCHER_ACTION_PROPERTIES,
   THUNAR_LAUNCHER_ACTION_MAKE_LINK,
diff --git a/thunar/thunar-shortcuts-pane.c b/thunar/thunar-shortcuts-pane.c
index 2cc26a202..60ccd56bc 100644
--- a/thunar/thunar-shortcuts-pane.c
+++ b/thunar/thunar-shortcuts-pane.c
@@ -64,8 +64,6 @@ static void          thunar_shortcuts_pane_set_selected_files    (ThunarComponen
 static GtkUIManager *thunar_shortcuts_pane_get_ui_manager        (ThunarComponent          *component);
 static void          thunar_shortcuts_pane_set_ui_manager        (ThunarComponent          *component,
                                                                   GtkUIManager             *ui_manager);
-static void          thunar_shortcuts_pane_action_shortcuts_add  (GtkAction                *action,
-                                                                  ThunarShortcutsPane      *shortcuts_pane);
 static void          thunar_shortcuts_pane_show_shortcuts_view_padding (GtkWidget          *widget);
 static void          thunar_shortcuts_pane_hide_shortcuts_view_padding (GtkWidget          *widget);
 
@@ -96,7 +94,7 @@ struct _ThunarShortcutsPane
 
 static const GtkActionEntry action_entries[] =
 {
-  { "sendto-shortcuts", "bookmark-new", "", NULL, NULL, G_CALLBACK (thunar_shortcuts_pane_action_shortcuts_add), },
+  { "sendto-shortcuts", "bookmark-new", "", NULL, NULL, G_CALLBACK (NULL), },
 };
 
 
@@ -372,11 +370,6 @@ thunar_shortcuts_pane_set_selected_files (ThunarComponent *component,
                                           GList           *selected_files)
 {
   ThunarShortcutsPane *shortcuts_pane = THUNAR_SHORTCUTS_PANE (component);
-  GtkTreeModel        *model;
-  GtkTreeModel        *child_model;
-  GtkAction           *action;
-  GList               *lp;
-  gint                 n;
 
   /* disconnect from the previously selected files... */
   thunar_g_file_list_free (shortcuts_pane->selected_files);
@@ -384,45 +377,6 @@ thunar_shortcuts_pane_set_selected_files (ThunarComponent *component,
   /* ...and take a copy of the newly selected files */
   shortcuts_pane->selected_files = thunar_g_file_list_copy (selected_files);
 
-  /* check if the selection contains only folders */
-  for (lp = selected_files, n = 0; lp != NULL; lp = lp->next, ++n)
-    if (!thunar_file_is_directory (lp->data))
-      break;
-
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-  /* change the visibility of the "shortcuts-add" action appropriately */
-  action = gtk_action_group_get_action (shortcuts_pane->action_group, "sendto-shortcuts");
-G_GNUC_END_IGNORE_DEPRECATIONS
-  if (lp == NULL && selected_files != NULL)
-    {
-      /* check if atleast one of the selected folders is not already present in the model */
-      model = gtk_tree_view_get_model (GTK_TREE_VIEW (shortcuts_pane->view));
-      if (G_LIKELY (model != NULL))
-        {
-          /* check all selected folders */
-          child_model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (model));
-          for (lp = selected_files; lp != NULL; lp = lp->next)
-            if (!thunar_shortcuts_model_has_bookmark (THUNAR_SHORTCUTS_MODEL (child_model), thunar_file_get_file (lp->data)))
-              break;
-        }
-
-      /* display the action and change the label appropriately */
-      g_object_set (G_OBJECT (action),
-                    "label", ngettext ("Side Pane (Create Shortcut)", "Side Pane (Create Shortcuts)", n),
-                    "sensitive", (lp != NULL),
-                    "tooltip", ngettext ("Add the selected folder to the shortcuts side pane",
-                                         "Add the selected folders to the shortcuts side pane", n),
-                    "visible", TRUE,
-                    NULL);
-    }
-  else
-    {
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-      /* hide the action */
-      gtk_action_set_visible (action, FALSE);
-G_GNUC_END_IGNORE_DEPRECATIONS
-    }
-
   /* notify listeners */
   g_object_notify (G_OBJECT (shortcuts_pane), "selected-files");
 }
@@ -488,36 +442,34 @@ G_GNUC_END_IGNORE_DEPRECATIONS
 
 
 
-static void
-thunar_shortcuts_pane_action_shortcuts_add (GtkAction           *action,
-                                            ThunarShortcutsPane *shortcuts_pane)
+/**
+ * thunar_shortcuts_pane_add_shortcut:
+ * @shortcuts_pane : Instance of a #ThunarShortcutsPane
+ * @file           : #ThunarFile for which a shortcut should be added
+ *
+ * Adds a shortcut for the passed #ThunarFile to the shortcuts_pane.
+ * Only folders will be considered.
+ **/
+void
+thunar_shortcuts_pane_add_shortcut (ThunarShortcutsPane *shortcuts_pane,
+                                    ThunarFile          *file)
 {
   GtkTreeModel *model;
   GtkTreeModel *child_model;
-  GList        *lp;
 
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-  _thunar_return_if_fail (GTK_IS_ACTION (action));
-G_GNUC_END_IGNORE_DEPRECATIONS
   _thunar_return_if_fail (THUNAR_IS_SHORTCUTS_PANE (shortcuts_pane));
+  _thunar_return_if_fail (THUNAR_IS_FILE (file));
 
   /* determine the shortcuts model for the view */
   model = gtk_tree_view_get_model (GTK_TREE_VIEW (shortcuts_pane->view));
   if (G_LIKELY (model != NULL))
     {
-      /* add all selected folders to the model */
       child_model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (model));
-      for (lp = shortcuts_pane->selected_files; lp != NULL; lp = lp->next)
-        if (G_LIKELY (thunar_file_is_directory (lp->data)))
-          {
-            /* append the folder to the shortcuts model */
-            thunar_shortcuts_model_add (THUNAR_SHORTCUTS_MODEL (child_model), NULL, lp->data);
-          }
-
-      /* update the user interface to reflect the new action state */
-      lp = thunar_g_file_list_copy (shortcuts_pane->selected_files);
-      thunar_component_set_selected_files (THUNAR_COMPONENT (shortcuts_pane), lp);
-      thunar_g_file_list_free (lp);
+      if (G_LIKELY (thunar_file_is_directory (file)))
+        {
+          /* append the folder to the shortcuts model */
+          thunar_shortcuts_model_add (THUNAR_SHORTCUTS_MODEL (child_model), NULL, file);
+        }
     }
 }
 
diff --git a/thunar/thunar-shortcuts-pane.h b/thunar/thunar-shortcuts-pane.h
index 3c2161a66..77d76425b 100644
--- a/thunar/thunar-shortcuts-pane.h
+++ b/thunar/thunar-shortcuts-pane.h
@@ -34,7 +34,9 @@ typedef struct _ThunarShortcutsPane      ThunarShortcutsPane;
 #define THUNAR_IS_SHORTCUTS_PANE_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_TYPE_SHORTCUTS_PANE))
 #define THUNAR_SHORTCUTS_PANE_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_TYPE_SHORTCUTS_PANE, ThunarShortcutsPaneClass))
 
-GType      thunar_shortcuts_pane_get_type  (void) G_GNUC_CONST;
+GType      thunar_shortcuts_pane_get_type     (void) G_GNUC_CONST;
+void       thunar_shortcuts_pane_add_shortcut (ThunarShortcutsPane *shortcuts_pane,
+                                               ThunarFile          *file);
 
 G_END_DECLS;
 
diff --git a/thunar/thunar-window.c b/thunar/thunar-window.c
index 291756a6c..29464ea1a 100644
--- a/thunar/thunar-window.c
+++ b/thunar/thunar-window.c
@@ -1298,6 +1298,41 @@ thunar_window_reload (ThunarWindow *window,
 
 
 
+/**
+ * thunar_window_has_shortcut_sidepane:
+ * @window : a #ThunarWindow instance.
+ *
+ * Return value: True, if this window is running a shortcut sidepane
+ **/
+gboolean
+thunar_window_has_shortcut_sidepane (ThunarWindow *window)
+{
+  _thunar_return_val_if_fail (THUNAR_IS_WINDOW (window), FALSE);
+
+  /* check if a side pane is currently active */
+  if (G_LIKELY (window->sidepane != NULL))
+    {
+      return G_OBJECT_TYPE (window->sidepane) == THUNAR_TYPE_SHORTCUTS_PANE;
+    }
+  return FALSE;
+}
+
+
+
+/**
+ * thunar_window_get_sidepane:
+ * @window : a #ThunarWindow instance.
+ *
+ * Return value: (transfer none): The #ThunarSidePane of this window, or NULL if not available
+ **/
+GtkWidget* thunar_window_get_sidepane (ThunarWindow *window)
+{
+  _thunar_return_val_if_fail (THUNAR_IS_WINDOW (window), FALSE);
+  return GTK_WIDGET (window->sidepane);
+}
+
+
+
 static gboolean
 thunar_window_toggle_sidepane (ThunarWindow *window)
 {
diff --git a/thunar/thunar-window.h b/thunar/thunar-window.h
index 0b954d08f..27cb3b45b 100644
--- a/thunar/thunar-window.h
+++ b/thunar/thunar-window.h
@@ -59,6 +59,8 @@ void            thunar_window_update_directories    (ThunarWindow *window,
                                                      ThunarFile   *new_directory);
 void            thunar_window_notebook_insert       (ThunarWindow *window,
                                                      ThunarFile   *directory);
+gboolean        thunar_window_has_shortcut_sidepane (ThunarWindow *window);
+GtkWidget*      thunar_window_get_sidepane          (ThunarWindow *window);
 ThunarLauncher* thunar_window_get_launcher          (ThunarWindow *window);
 
 G_END_DECLS;
-- 
GitLab