From e716baa66bd87b868ab419e0710f1896fdcf3a69 Mon Sep 17 00:00:00 2001
From: Benedikt Meurer <benny@xfce.org>
Date: Sun, 31 Jul 2005 14:47:57 +0000
Subject: [PATCH] 2005-07-31	Benedikt Meurer <benny@xfce.org>

	* thunar/thunar-clipboard-manager.c
	  (thunar_clipboard_manager_contents_received): Properly clear the
	  CLIPBOARD selection after a paste on "cutted data". Manually trigger
	  an "owner-changed" after a successfully initiating the paste operation
	  if either the Xserver or the GTK+ version doesn't support the XFixes
	  extension.
	* thunar-vfs/thunar-vfs-transfer-job.c, configure.in.in: Add work-around
	  for systems that lack the lchmod() system call.
	* thunar/thunar-standard-view.{c,h}: Query all actions from the group
	  when initializing the view to speed up access later.
	* thunar/thunar-standard-view-ui.xml, thunar/thunar-standard-view.c:
	  Add a "paste-into-folder" action, which is only available from the
	  context menu.
	* autogen.sh, configure.in.in: Adopt the version numbering scheme from
	  libexo and ditch the date.




(Old svn revision: 16421)
---
 ChangeLog                            |  18 +++++
 autogen.sh                           |   5 +-
 configure.in.in                      |   5 +-
 thunar-vfs/thunar-vfs-transfer-job.c |  14 +++-
 thunar/thunar-clipboard-manager.c    |  19 +++++
 thunar/thunar-standard-view-ui.xml   |   1 +
 thunar/thunar-standard-view.c        | 104 ++++++++++++++++++++++-----
 thunar/thunar-standard-view.h        |  23 +++---
 8 files changed, 154 insertions(+), 35 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 29f9b2958..70ba67d76 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2005-07-31	Benedikt Meurer <benny@xfce.org>
+
+	* thunar/thunar-clipboard-manager.c
+	  (thunar_clipboard_manager_contents_received): Properly clear the
+	  CLIPBOARD selection after a paste on "cutted data". Manually trigger
+	  an "owner-changed" after a successfully initiating the paste operation
+	  if either the Xserver or the GTK+ version doesn't support the XFixes
+	  extension.
+	* thunar-vfs/thunar-vfs-transfer-job.c, configure.in.in: Add work-around
+	  for systems that lack the lchmod() system call.
+	* thunar/thunar-standard-view.{c,h}: Query all actions from the group
+	  when initializing the view to speed up access later.
+	* thunar/thunar-standard-view-ui.xml, thunar/thunar-standard-view.c:
+	  Add a "paste-into-folder" action, which is only available from the
+	  context menu.
+	* autogen.sh, configure.in.in: Adopt the version numbering scheme from
+	  libexo and ditch the date.
+
 2005-07-31	Benedikt Meurer <benny@xfce.org>
 
 	* thunar/thunar-clipboard-manager.{c,h}: Implement paste support based
diff --git a/autogen.sh b/autogen.sh
index 6968b656b..0fbad6f55 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -19,9 +19,8 @@ EOF
 }
 
 # substitute revision and date
-revision=`svn info $0 | awk '/^Revision: / {printf "%04d\n", $2}'`
-sed -e "s/@DATE@/`date +%Y%m%d`/g" -e "s/@REVISION@/${revision}/g" \
-  < "configure.in.in" > "configure.in"
+revision=`svn info $0 | awk '/^Revision: / {printf "%05d\n", $2}'`
+sed -e "s/@REVISION@/${revision}/g" < "configure.in.in" > "configure.in"
 
 exec xdt-autogen $@
 
diff --git a/configure.in.in b/configure.in.in
index 5702d6bbe..cdbf2cc72 100644
--- a/configure.in.in
+++ b/configure.in.in
@@ -12,8 +12,7 @@ m4_define([thunar_version_minor], [0])
 m4_define([thunar_version_micro], [2])
 m4_define([thunar_version_build], [@REVISION@])
 m4_define([thunar_version_tag], [svn])
-m4_define([thunar_version_date], [@DATE@])
-m4_define([thunar_version], [thunar_version_major().thunar_version_minor().thunar_version_micro()ifelse(thunar_version_build(), [], [], [.thunar_version_build()])thunar_version_tag()-thunar_version_date()])
+m4_define([thunar_version], [thunar_version_major().thunar_version_minor().thunar_version_micro()ifelse(thunar_version_tag(), [], [], [thunar_version_tag()-thunar_version_build()])])
 
 dnl Initialize autoconf
 AC_COPYRIGHT([Copyright (c) 2004-2005
@@ -48,7 +47,7 @@ AC_CHECK_HEADERS([dirent.h errno.h fcntl.h fstab.h grp.h locale.h \
                   sys/mount.h sys/stat.h sys/time.h sys/param.h time.h])
 
 dnl Check for standard functions
-AC_CHECK_FUNCS([kqueue localtime_r readdir_r setgroupent setpassent])
+AC_CHECK_FUNCS([kqueue lchmod localtime_r readdir_r setgroupent setpassent])
 
 dnl Check for required packages
 XDT_CHECK_PACKAGE([EXO], [exo-0.3], [0.3.1])
diff --git a/thunar-vfs/thunar-vfs-transfer-job.c b/thunar-vfs/thunar-vfs-transfer-job.c
index c3568f6be..fe23258c3 100644
--- a/thunar-vfs/thunar-vfs-transfer-job.c
+++ b/thunar-vfs/thunar-vfs-transfer-job.c
@@ -54,6 +54,7 @@
 #if GLIB_CHECK_VERSION(2,6,0)
 #include <glib/gstdio.h>
 #else
+#define g_chmod(path, mode) (chmod ((path), (mode)))
 #define g_lstat(path, buffer) (lstat ((path), (buffer)))
 #define g_mkdir(path, mode) (mkdir ((path), (mode)))
 #define g_remove(path) (remove ((path)))
@@ -551,7 +552,18 @@ thunar_vfs_transfer_item_copy (ThunarVfsTransferItem *item)
 
           /* apply the original permissions */
           if (!item->skipped && !thunar_vfs_job_cancelled (THUNAR_VFS_JOB (job)))
-            lchmod (target_path, item->mode & ~S_IFMT);
+            {
+#ifdef HAVE_LCHMOD
+              lchmod (target_path, item->mode & ~S_IFMT);
+#else
+              /* some systems lack the lchmod system call, so we have to
+               * work-around that deficiency here by manually checking
+               * whether we have a symlink or a "regular" fs entity.
+               */
+              if (!S_ISLNK (item->mode))
+                g_chmod (target_path, item->mode & ~S_IFMT);
+#endif
+            }
 
           /* if we're moving, we'll have to unlink afterwards */
           if (job->move && !item->skipped && !thunar_vfs_job_cancelled (THUNAR_VFS_JOB (job))
diff --git a/thunar/thunar-clipboard-manager.c b/thunar/thunar-clipboard-manager.c
index 1627bd6e6..fb7b06002 100644
--- a/thunar/thunar-clipboard-manager.c
+++ b/thunar/thunar-clipboard-manager.c
@@ -245,6 +245,7 @@ thunar_clipboard_manager_contents_received (GtkClipboard     *clipboard,
                                             gpointer          user_data)
 {
   ThunarClipboardPasteRequest *request = user_data;
+  ThunarClipboardManager      *manager = THUNAR_CLIPBOARD_MANAGER (request->manager);
   ThunarApplication           *application;
   GtkWidget                   *dialog;
   gboolean                     copy = TRUE;
@@ -284,6 +285,24 @@ thunar_clipboard_manager_contents_received (GtkClipboard     *clipboard,
         thunar_application_move_uris (application, request->window, uri_list, request->target_uri);
       g_object_unref (G_OBJECT (application));
       thunar_vfs_uri_list_free (uri_list);
+
+      /* clear the clipboard if it contained "cutted data"
+       * (gtk_clipboard_clear takes care of not clearing
+       * the selection if we don't own it)
+       */
+      if (G_UNLIKELY (!copy))
+        gtk_clipboard_clear (manager->clipboard);
+
+      /* check the contents of the clipboard again
+       * if either the Xserver or our GTK+ version
+       * doesn't support the XFixes extension.
+       */
+#if GTK_CHECK_VERSION(2,6,0)
+      if (!gdk_display_supports_selection_notification (gtk_clipboard_get_display (manager->clipboard)))
+#endif
+        {
+          thunar_clipboard_manager_owner_changed (manager->clipboard, NULL, manager);
+        }
     }
   else
     {
diff --git a/thunar/thunar-standard-view-ui.xml b/thunar/thunar-standard-view-ui.xml
index b9c0c7c06..e96d0001c 100644
--- a/thunar/thunar-standard-view-ui.xml
+++ b/thunar/thunar-standard-view-ui.xml
@@ -35,6 +35,7 @@
   <popup action="file-context-menu" name="file-context-menu">
     <menuitem action="copy" name="copy" />
     <menuitem action="cut" name="cut" />
+    <menuitem action="paste-into-folder" name="paste-into-folder" />
     <separator />
     <menuitem action="properties" name="properties" />
   </popup>
diff --git a/thunar/thunar-standard-view.c b/thunar/thunar-standard-view.c
index 88cd68daf..2a51be347 100644
--- a/thunar/thunar-standard-view.c
+++ b/thunar/thunar-standard-view.c
@@ -29,6 +29,10 @@
 
 
 
+#define THUNAR_STANDARD_VIEW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), THUNAR_TYPE_STANDARD_VIEW, ThunarStandardViewPrivate))
+
+
+
 enum
 {
   PROP_0,
@@ -77,12 +81,26 @@ static void          thunar_standard_view_action_cut                (GtkAction
                                                                      ThunarStandardView       *standard_view);
 static void          thunar_standard_view_action_paste              (GtkAction                *action,
                                                                      ThunarStandardView       *standard_view);
+static void          thunar_standard_view_action_paste_into_folder  (GtkAction                *action,
+                                                                     ThunarStandardView       *standard_view);
 static void          thunar_standard_view_action_show_hidden_files  (GtkToggleAction          *toggle_action,
                                                                      ThunarStandardView       *standard_view);
 static void          thunar_standard_view_loading_unbound           (gpointer                  user_data);
 
 
 
+struct _ThunarStandardViewPrivate
+{
+  GtkAction *action_properties;
+  GtkAction *action_copy;
+  GtkAction *action_cut;
+  GtkAction *action_paste;
+  GtkAction *action_paste_into_folder;
+  GtkAction *action_show_hidden_files;
+};
+
+
+
 static const GtkActionEntry action_entries[] =
 {
   { "file-context-menu", NULL, N_ ("Context Menu"), NULL, NULL, NULL, },
@@ -90,6 +108,7 @@ static const GtkActionEntry action_entries[] =
   { "copy", GTK_STOCK_COPY, N_ ("_Copy files"), NULL, NULL, G_CALLBACK (thunar_standard_view_action_copy), },
   { "cut", GTK_STOCK_CUT, N_ ("Cu_t files"), NULL, NULL, G_CALLBACK (thunar_standard_view_action_cut), },
   { "paste", GTK_STOCK_PASTE, N_ ("_Paste files"), NULL, NULL, G_CALLBACK (thunar_standard_view_action_paste), },
+  { "paste-into-folder", GTK_STOCK_PASTE, N_ ("Paste files into folder"), NULL, N_ ("_Paste files into the selected folder"), G_CALLBACK (thunar_standard_view_action_paste_into_folder), },
 };
 
 static const GtkToggleActionEntry toggle_action_entries[] =
@@ -155,6 +174,8 @@ thunar_standard_view_class_init (ThunarStandardViewClass *klass)
   GtkWidgetClass *gtkwidget_class;
   GObjectClass   *gobject_class;
 
+  g_type_class_add_private (klass, sizeof (ThunarStandardViewPrivate));
+
   thunar_standard_view_parent_class = g_type_class_peek_parent (klass);
 
   gobject_class = G_OBJECT_CLASS (klass);
@@ -214,6 +235,8 @@ thunar_standard_view_view_init (ThunarViewIface *iface)
 static void
 thunar_standard_view_init (ThunarStandardView *standard_view)
 {
+  standard_view->priv = THUNAR_STANDARD_VIEW_GET_PRIVATE (standard_view);
+
   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (standard_view),
                                   GTK_POLICY_AUTOMATIC,
                                   GTK_POLICY_AUTOMATIC);
@@ -230,6 +253,14 @@ thunar_standard_view_init (ThunarStandardView *standard_view)
                                        G_N_ELEMENTS (toggle_action_entries),
                                        GTK_WIDGET (standard_view));
 
+  /* lookup all actions to speed up access later */
+  standard_view->priv->action_properties = gtk_action_group_get_action (standard_view->action_group, "properties");
+  standard_view->priv->action_copy = gtk_action_group_get_action (standard_view->action_group, "copy");
+  standard_view->priv->action_cut = gtk_action_group_get_action (standard_view->action_group, "cut");
+  standard_view->priv->action_paste = gtk_action_group_get_action (standard_view->action_group, "paste");
+  standard_view->priv->action_paste_into_folder = gtk_action_group_get_action (standard_view->action_group, "paste-into-folder");
+  standard_view->priv->action_show_hidden_files = gtk_action_group_get_action (standard_view->action_group, "show-hidden-files");
+
   standard_view->model = thunar_list_model_new ();
 
   /* be sure to update the statusbar text whenever the number of
@@ -747,6 +778,31 @@ thunar_standard_view_action_paste (GtkAction          *action,
 
 
 
+static void
+thunar_standard_view_action_paste_into_folder (GtkAction          *action,
+                                               ThunarStandardView *standard_view)
+{
+  ThunarFile *file;
+  GtkWidget  *window;
+  GList      *files;
+
+  g_return_if_fail (GTK_IS_ACTION (action));
+  g_return_if_fail (THUNAR_IS_STANDARD_VIEW (standard_view));
+
+  /* determine the first selected directory and paste into it */
+  files = thunar_standard_view_get_selected_files (standard_view);
+  file = (files != NULL) ? THUNAR_FILE (files->data) : NULL;
+  if (G_LIKELY (file != NULL && thunar_file_is_directory (file)))
+    {
+      window = gtk_widget_get_toplevel (GTK_WIDGET (standard_view));
+      thunar_clipboard_manager_paste_uri_list (standard_view->clipboard, thunar_file_get_uri (file), GTK_WINDOW (window));
+    }
+  g_list_foreach (files, (GFunc) g_object_unref, NULL);
+  g_list_free (files);
+}
+
+
+
 static void
 thunar_standard_view_action_show_hidden_files (GtkToggleAction    *toggle_action,
                                                ThunarStandardView *standard_view)
@@ -852,11 +908,11 @@ void
 thunar_standard_view_selection_changed (ThunarStandardView *standard_view)
 {
   ThunarFile *current_directory;
-  GtkAction  *action;
+  gboolean    can_paste_into_folder;
   gboolean    pastable;
   gboolean    writable;
-  GList      *selected_items;
-  gint        n_selected_items;
+  GList      *selected_files;
+  gint        n_selected_files;
 
   g_return_if_fail (THUNAR_IS_STANDARD_VIEW (standard_view));
 
@@ -867,31 +923,39 @@ thunar_standard_view_selection_changed (ThunarStandardView *standard_view)
   /* check whether the clipboard contains data that can be pasted here */
   pastable = (standard_view->clipboard != NULL && thunar_clipboard_manager_get_can_paste (standard_view->clipboard));
 
-  /* determine the number of selected items */
-  selected_items = THUNAR_STANDARD_VIEW_GET_CLASS (standard_view)->get_selected_items (standard_view);
-  n_selected_items = g_list_length (selected_items);
-  g_list_foreach (selected_items, (GFunc) gtk_tree_path_free, NULL);
-  g_list_free (selected_items);
+  /* determine the number of selected files */
+  selected_files = thunar_standard_view_get_selected_files (standard_view);
+  n_selected_files = g_list_length (selected_files);
+
+  /* check whether the only selected file is
+   * folder to which we can paste to */
+  can_paste_into_folder = (n_selected_files == 1)
+                       && thunar_file_is_directory (selected_files->data)
+                       && thunar_file_can_write (selected_files->data);
 
   /* update the "Properties" action */
-  thunarx_gtk_action_group_set_action_sensitive (standard_view->action_group, "properties", (n_selected_items == 1));
+  gtk_action_set_sensitive (standard_view->priv->action_properties, (n_selected_files == 1));
 
   /* update the "Copy file(s)" action */
-  action = gtk_action_group_get_action (standard_view->action_group, "copy");
-  g_object_set (G_OBJECT (action),
-                "label", (n_selected_items > 1) ? _("_Copy files") : _("_Copy file"),
-                "sensitive", (n_selected_items > 0),
+  g_object_set (G_OBJECT (standard_view->priv->action_copy),
+                "label", (n_selected_files > 1) ? _("_Copy files") : _("_Copy file"),
+                "sensitive", (n_selected_files > 0),
                 NULL);
 
   /* update the "Cut file(s)" action */
-  action = gtk_action_group_get_action (standard_view->action_group, "cut");
-  g_object_set (G_OBJECT (action),
-                "label", (n_selected_items > 1) ? _("Cu_t files") : _("Cu_t file"),
-                "sensitive", (n_selected_items > 0) && writable,
+  g_object_set (G_OBJECT (standard_view->priv->action_cut),
+                "label", (n_selected_files > 1) ? _("Cu_t files") : _("Cu_t file"),
+                "sensitive", (n_selected_files > 0) && writable,
                 NULL);
 
   /* update the "Paste file(s)" action */
-  thunarx_gtk_action_group_set_action_sensitive (standard_view->action_group, "paste", writable && pastable);
+  gtk_action_set_sensitive (standard_view->priv->action_paste, writable && pastable);
+
+  /* update the "Paste file(s) Into Folder" action */
+  g_object_set (G_OBJECT (standard_view->priv->action_paste_into_folder),
+                "sensitive", pastable,
+                "visible", can_paste_into_folder,
+                NULL);
 
   /* clear the current status text (will be recalculated on-demand) */
   g_free (standard_view->statusbar_text);
@@ -899,6 +963,10 @@ thunar_standard_view_selection_changed (ThunarStandardView *standard_view)
 
   /* tell everybody that the statusbar text may have changed */
   g_object_notify (G_OBJECT (standard_view), "statusbar-text");
+
+  /* cleanup */
+  g_list_foreach (selected_files, (GFunc) g_object_unref, NULL);
+  g_list_free (selected_files);
 }
 
 
diff --git a/thunar/thunar-standard-view.h b/thunar/thunar-standard-view.h
index 80c286c88..8dde3eb1a 100644
--- a/thunar/thunar-standard-view.h
+++ b/thunar/thunar-standard-view.h
@@ -26,8 +26,9 @@
 
 G_BEGIN_DECLS;
 
-typedef struct _ThunarStandardViewClass ThunarStandardViewClass;
-typedef struct _ThunarStandardView      ThunarStandardView;
+typedef struct _ThunarStandardViewPrivate ThunarStandardViewPrivate;
+typedef struct _ThunarStandardViewClass   ThunarStandardViewClass;
+typedef struct _ThunarStandardView        ThunarStandardView;
 
 #define THUNAR_TYPE_STANDARD_VIEW             (thunar_standard_view_get_type ())
 #define THUNAR_STANDARD_VIEW(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_TYPE_STANDARD_VIEW, ThunarStandardView))
@@ -49,16 +50,18 @@ struct _ThunarStandardView
 {
   GtkScrolledWindow __parent__;
 
-  ThunarClipboardManager *clipboard;
-  ThunarListModel        *model;
-  gchar                  *statusbar_text;
+  ThunarStandardViewPrivate *priv;
 
-  GtkActionGroup         *action_group;
-  GtkUIManager           *ui_manager;
-  guint                   ui_merge_id;
+  ThunarClipboardManager    *clipboard;
+  ThunarListModel           *model;
+  gchar                     *statusbar_text;
 
-  ExoBinding             *loading_binding;
-  gboolean                loading;
+  GtkActionGroup            *action_group;
+  GtkUIManager              *ui_manager;
+  guint                      ui_merge_id;
+
+  ExoBinding                *loading_binding;
+  gboolean                   loading;
 };
 
 GType thunar_standard_view_get_type           (void) G_GNUC_CONST;
-- 
GitLab