diff --git a/configure.ac.in b/configure.ac.in
index c2ee379764a82206e5830b54ece9f00cca5b11d1..b9ea8e3713cd07cd30bd7257644c791ff21c42c1 100644
--- a/configure.ac.in
+++ b/configure.ac.in
@@ -146,10 +146,10 @@ dnl ***********************************
 dnl *** Check for required packages ***
 dnl ***********************************
 XDT_CHECK_PACKAGE([EXO], [exo-2], [4.17.0])
-XDT_CHECK_PACKAGE([GLIB], [glib-2.0], [2.50.0])
-XDT_CHECK_PACKAGE([GIO], [gio-2.0], [2.50.0])
-XDT_CHECK_PACKAGE([GTHREAD], [gthread-2.0], [2.50.0])
-XDT_CHECK_PACKAGE([GMODULE], [gmodule-2.0], [2.50.0])
+XDT_CHECK_PACKAGE([GLIB], [glib-2.0], [2.56.0])
+XDT_CHECK_PACKAGE([GIO], [gio-2.0], [2.56.0])
+XDT_CHECK_PACKAGE([GTHREAD], [gthread-2.0], [2.56.0])
+XDT_CHECK_PACKAGE([GMODULE], [gmodule-2.0], [2.56.0])
 XDT_CHECK_PACKAGE([GTK], [gtk+-3.0], [3.22.0])
 XDT_CHECK_PACKAGE([GDK_PIXBUF], [gdk-pixbuf-2.0], [2.14.0])
 XDT_CHECK_PACKAGE([LIBXFCE4UTIL], [libxfce4util-1.0], [4.17.0])
@@ -158,8 +158,8 @@ XDT_CHECK_PACKAGE([LIBXFCE4KBD_PRIVATE], [libxfce4kbd-private-3], [4.12.0])
 XDT_CHECK_PACKAGE([XFCONF], [libxfconf-0], [4.12.0])
 XDT_CHECK_PACKAGE([PANGO], [pango], [1.38.0])
 
-AC_DEFINE(GLIB_VERSION_MIN_REQUIRED, GLIB_VERSION_2_50, [Ignore post 2.50 deprecations])
-AC_DEFINE(GLIB_VERSION_MAX_ALLOWED, GLIB_VERSION_2_50, [Prevent post 2.50 APIs])
+AC_DEFINE(GLIB_VERSION_MIN_REQUIRED, GLIB_VERSION_2_56, [Ignore post 2.56 deprecations])
+AC_DEFINE(GLIB_VERSION_MAX_ALLOWED, GLIB_VERSION_2_56, [Prevent post 2.56 APIs])
 
 dnl ******************************
 dnl *** GObject Instrospection ***
diff --git a/docs/reference/thunarx/thunarx.actions b/docs/reference/thunarx/thunarx.actions
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/thunar/thunar-enum-types.c b/thunar/thunar-enum-types.c
index f79f19377663745a0d9c76527bccfc8ae012c8c4..6b6e8153715e3ab2618183a45fdc36bf6501a9bb 100644
--- a/thunar/thunar-enum-types.c
+++ b/thunar/thunar-enum-types.c
@@ -524,3 +524,26 @@ thunar_file_mode_get_type (void)
     }
   return type;
 }
+
+
+
+GType
+thunar_use_partial_get_type (void)
+{
+  static GType type = G_TYPE_INVALID;
+
+  if (G_UNLIKELY (type == G_TYPE_INVALID))
+    {
+      static const GEnumValue values[] =
+      {
+        { THUNAR_USE_PARTIAL_MODE_DISABLED,    "THUNAR_USE_PARTIAL_MODE_NEVER",    N_("Never"),},
+        { THUNAR_USE_PARTIAL_MODE_REMOTE_ONLY, "THUNAR_USE_PARTIAL_MODE_REMOTE",   N_("Only for remote location"),},
+        { THUNAR_USE_PARTIAL_MODE_ALWAYS,      "THUNAR_USE_PARTIAL_MODE_ALWAYS",   N_("Always"),},
+        { 0,                                NULL,                               NULL,},
+      };
+
+      type = g_enum_register_static (I_("ThunarUsePartialMode"), values);
+    }
+
+  return type;
+}
diff --git a/thunar/thunar-enum-types.h b/thunar/thunar-enum-types.h
index b0908a4ce89055dc688bbe87ef1ccb658697fe46..39405320706f9342f84ce238ca364dcf3e3607eb 100644
--- a/thunar/thunar-enum-types.h
+++ b/thunar/thunar-enum-types.h
@@ -328,6 +328,25 @@ GType thunar_file_mode_get_type (void) G_GNUC_CONST;
 
 
 
+#define THUNAR_TYPE_USE_PARTIAL_MODE (thunar_use_partial_get_type ())
+
+/**
+ * ThunarUsePartialMode:
+ * @THUNAR_USE_PARTIAL_MODE_DISABLED    : Disable *.partial~
+ * @THUNAR_USE_PARTIAL_MODE_REMOTE_ONLY : Only when src/dst is remote
+ * @THUNAR_USE_PARTIAL_MODE_ALWAYS      : Always copy to *.partial~
+ **/
+typedef enum
+{
+  THUNAR_USE_PARTIAL_MODE_DISABLED,
+  THUNAR_USE_PARTIAL_MODE_REMOTE_ONLY,
+  THUNAR_USE_PARTIAL_MODE_ALWAYS,
+} ThunarUsePartialMode;
+
+GType thunar_use_partial_get_type (void) G_GNUC_CONST;
+
+
+
 /**
  * ThunarNewTabBehavior:
  * @THUNAR_NEW_TAB_BEHAVIOR_FOLLOW_PREFERENCE   : switching to the new tab or not is controlled by a preference.
diff --git a/thunar/thunar-gio-extensions.c b/thunar/thunar-gio-extensions.c
index 46837dc2b222e804c1a4f0b14a1299856f2b9767..a5cd89b1cb903ed5519068e820e9586cba195585 100644
--- a/thunar/thunar-gio-extensions.c
+++ b/thunar/thunar-gio-extensions.c
@@ -645,6 +645,115 @@ thunar_g_file_list_get_type (void)
 
 
 
+/**
+ * thunar_g_file_copy:
+ * @source                 : input #GFile
+ * @destination            : destination #GFile
+ * @flags                  : set of #GFileCopyFlags
+ * @use_partial            : option to use *.partial~
+ * @cancellable            : (nullable): optional GCancellable object
+ * @progress_callback      : (nullable) (scope call): function to callback with progress information
+ * @progress_callback_data : (clousure): user data to pass to @progress_callback
+ * @error                  : (nullable): #GError to set on error
+ *
+ * Calls g_file_copy() if @use_partial is not enabled.
+ * If enabled, copies files to *.partial~ first and then
+ * renames *.partial~ into its original name.
+ *
+ * Return value: %TRUE on success, %FALSE otherwise.
+ **/
+gboolean
+thunar_g_file_copy (GFile                *source,
+                    GFile                *destination,
+                    GFileCopyFlags        flags,
+                    gboolean              use_partial,
+                    GCancellable         *cancellable,
+                    GFileProgressCallback progress_callback,
+                    gpointer              progress_callback_data,
+                    GError              **error)
+{
+  gboolean            success;
+  GFileQueryInfoFlags query_flags;
+  GFileInfo          *info = NULL;
+  GFile              *parent;
+  GFile              *partial;
+  gchar              *partial_name;
+  gchar              *base_name;
+
+  _thunar_return_val_if_fail (g_file_has_parent (destination, NULL), FALSE);
+
+  if (use_partial)
+    {
+      query_flags = (flags & G_FILE_COPY_NOFOLLOW_SYMLINKS) ? G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS : G_FILE_QUERY_INFO_NONE;
+      info = g_file_query_info (source,
+                                G_FILE_ATTRIBUTE_STANDARD_TYPE,
+                                query_flags,
+                                cancellable,
+                                NULL);
+    }
+
+  /* directory does not need .partial */
+  if (info == NULL)
+    {
+      use_partial = FALSE;
+    }
+  else
+    {
+      use_partial = g_file_info_get_file_type (info) == G_FILE_TYPE_REGULAR;
+      g_clear_object (&info);
+    }
+
+  if (!use_partial)
+    {
+      return g_file_copy (source, destination, flags, cancellable, progress_callback, progress_callback_data, error);
+    }
+
+  /* check destination */
+  if (g_file_query_exists (destination, NULL))
+    {
+      /* Try to mimic g_file_copy() error */
+      if (error != NULL)
+        *error = g_error_new (G_IO_ERROR, G_IO_ERROR_EXISTS,
+                              "Error opening file \"%s\": File exists", g_file_peek_path (destination));
+      return FALSE;
+    }
+
+  /* generate partial file name */
+  base_name    = g_file_get_basename (destination);
+  if (base_name == NULL)
+    {
+      base_name = g_strdup ("UNNAMED");
+    }
+
+  /* limit filename length */
+  partial_name = g_strdup_printf ("%.100s.partial~", base_name);
+  parent       = g_file_get_parent (destination);
+
+  /* parent can't be NULL since destination must be a file */
+  partial      = g_file_get_child (parent, partial_name);
+  g_clear_object (&parent);
+  g_free (partial_name);
+
+  /* check if partial file exists */
+  if (g_file_query_exists (partial, NULL))
+    g_file_delete (partial, NULL, error);
+
+  /* copy file to .partial */
+  success = g_file_copy (source, partial, flags, cancellable, progress_callback, progress_callback_data, error);
+
+  /* rename .partial if done without problem */
+  if (success)
+    {
+      success = (g_file_set_display_name (partial, base_name, NULL, error) != NULL);
+    }
+
+  g_clear_object (&partial);
+  g_free (base_name);
+  return success;
+}
+
+
+
 /**
  * thunar_g_file_list_new_from_string:
  * @string : a string representation of an URI list.
diff --git a/thunar/thunar-gio-extensions.h b/thunar/thunar-gio-extensions.h
index 5a84fe4c2c073da69e51655375501072bc191458..aba839c7060ee223236110b6be3bacd4a5cdb316 100644
--- a/thunar/thunar-gio-extensions.h
+++ b/thunar/thunar-gio-extensions.h
@@ -67,6 +67,15 @@ gboolean     thunar_g_file_get_free_space           (GFile                *file,
 gchar       *thunar_g_file_get_free_space_string    (GFile                *file,
                                                      gboolean              file_size_binary);
 
+gboolean     thunar_g_file_copy                     (GFile                *source,
+                                                     GFile                *destination,
+                                                     GFileCopyFlags        flags,
+                                                     gboolean              use_partial,
+                                                     GCancellable         *cancellable,
+                                                     GFileProgressCallback progress_callback,
+                                                     gpointer              progress_callback_data,
+                                                     GError              **error);
+
 /**
  * THUNAR_TYPE_G_FILE_LIST:
  *
@@ -97,7 +106,6 @@ gboolean     thunar_g_app_info_should_show             (GAppInfo          *info)
 
 gboolean     thunar_g_vfs_metadata_is_supported        (void);
 
-
 G_END_DECLS
 
 #endif /* !__THUNAR_GIO_EXTENSIONS_H__ */
diff --git a/thunar/thunar-preferences-dialog.c b/thunar/thunar-preferences-dialog.c
index 8d3a35e1fa0e0d49878f2d8aee51213603e9641c..89873e934cfef5b9d476216fb1122708fbde16bf 100644
--- a/thunar/thunar-preferences-dialog.c
+++ b/thunar/thunar-preferences-dialog.c
@@ -158,15 +158,16 @@ transform_view_index_to_string (GBinding     *binding,
 
 
 static gboolean
-transform_thumbnail_mode_to_index (GBinding     *binding,
-                                   const GValue *src_value,
-                                   GValue       *dst_value,
-                                   gpointer      user_data)
+transform_enum_value_to_index (GBinding     *binding,
+                         const GValue *src_value,
+                         GValue       *dst_value,
+                         gpointer      user_data)
 {
   GEnumClass *klass;
+  GType     (*type_func)() = user_data;
   guint       n;
 
-  klass = g_type_class_ref (THUNAR_TYPE_THUMBNAIL_MODE);
+  klass = g_type_class_ref (type_func ());
   for (n = 0; n < klass->n_values; ++n)
     if (klass->values[n].value == g_value_get_enum (src_value))
       g_value_set_int (dst_value, n);
@@ -178,51 +179,15 @@ transform_thumbnail_mode_to_index (GBinding     *binding,
 
 
 static gboolean
-transform_thumbnail_index_to_mode (GBinding     *binding,
-                                   const GValue *src_value,
-                                   GValue       *dst_value,
-                                   gpointer      user_data)
+transform_index_to_enum_value (GBinding     *binding,
+                         const GValue *src_value,
+                         GValue       *dst_value,
+                         gpointer      user_data)
 {
   GEnumClass *klass;
+  GType     (*type_func)() = user_data;
 
-  klass = g_type_class_ref (THUNAR_TYPE_THUMBNAIL_MODE);
-  g_value_set_enum (dst_value, klass->values[g_value_get_int (src_value)].value);
-  g_type_class_unref (klass);
-
-  return TRUE;
-}
-
-
-
-static gboolean
-transform_parallel_copy_mode_to_index (GBinding     *binding,
-                                       const GValue *src_value,
-                                       GValue       *dst_value,
-                                       gpointer      user_data)
-{
-  GEnumClass *klass;
-  guint       n;
-
-  klass = g_type_class_ref (THUNAR_TYPE_PARALLEL_COPY_MODE);
-  for (n = 0; n < klass->n_values; ++n)
-    if (klass->values[n].value == g_value_get_enum (src_value))
-      g_value_set_int (dst_value, n);
-  g_type_class_unref (klass);
-
-  return TRUE;
-}
-
-
-
-static gboolean
-transform_parallel_copy_index_to_mode (GBinding     *binding,
-                                       const GValue *src_value,
-                                       GValue       *dst_value,
-                                       gpointer      user_data)
-{
-  GEnumClass *klass;
-
-  klass = g_type_class_ref (THUNAR_TYPE_PARALLEL_COPY_MODE);
+  klass = g_type_class_ref (type_func ());
   g_value_set_enum (dst_value, klass->values[g_value_get_int (src_value)].value);
   g_type_class_unref (klass);
 
@@ -281,6 +246,7 @@ thunar_preferences_dialog_init (ThunarPreferencesDialog *dialog)
   GtkWidget      *ibox;
   GtkWidget      *vbox;
   GtkWidget      *infobar;
+  GEnumClass     *type;
   gchar          *path;
   gchar          *date;
 
@@ -377,9 +343,9 @@ thunar_preferences_dialog_init (ThunarPreferencesDialog *dialog)
                                G_OBJECT (combo),
                                "active",
                                G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE,
-                               transform_thumbnail_mode_to_index,
-                               transform_thumbnail_index_to_mode,
-                               NULL, NULL);
+                               transform_enum_value_to_index,
+                               transform_index_to_enum_value,
+                               (gpointer) thunar_thumbnail_mode_get_type, NULL);
   gtk_widget_set_hexpand (combo, TRUE);
   gtk_grid_attach (GTK_GRID (grid), combo, 1, 1, 1, 1);
   thunar_gtk_label_set_a11y_relation (GTK_LABEL (label), combo);
@@ -849,6 +815,50 @@ thunar_preferences_dialog_init (ThunarPreferencesDialog *dialog)
   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
   gtk_widget_show (frame);
 
+  if (thunar_g_vfs_is_uri_scheme_supported ("trash"))
+    {
+      frame = g_object_new (GTK_TYPE_FRAME, "border-width", 0, "shadow-type", GTK_SHADOW_NONE, NULL);
+      gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
+      gtk_widget_show (frame);
+
+      label = gtk_label_new (_("Context Menu"));
+      gtk_label_set_attributes (GTK_LABEL (label), thunar_pango_attr_list_bold ());
+      gtk_frame_set_label_widget (GTK_FRAME (frame), label);
+      gtk_widget_show (label);
+
+      grid = gtk_grid_new ();
+      gtk_grid_set_column_spacing (GTK_GRID (grid), 12);
+      gtk_grid_set_row_spacing (GTK_GRID (grid), 2);
+      gtk_container_set_border_width (GTK_CONTAINER (grid), 12);
+      gtk_container_add (GTK_CONTAINER (frame), grid);
+      gtk_widget_show (grid);
+
+      button = gtk_check_button_new_with_mnemonic (_("Show action to permanently delete files and folders"));
+      g_object_bind_property (G_OBJECT (dialog->preferences),
+                              "misc-show-delete-action",
+                              G_OBJECT (button),
+                              "active",
+                              G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
+      gtk_widget_set_tooltip_text (button, _("Select this option to show the 'Delete' action in the context menu"));
+      gtk_widget_set_hexpand (button, TRUE);
+      gtk_grid_attach (GTK_GRID (grid), button, 0, 0, 1, 1);
+      gtk_widget_show (button);
+    }
+
+  /*
+     Advanced
+   */
+
+  label = gtk_label_new (_("Advanced"));
+  vbox = g_object_new (GTK_TYPE_BOX, "orientation", GTK_ORIENTATION_VERTICAL, "border-width", 12, "spacing", 18, NULL);
+  gtk_notebook_append_page (GTK_NOTEBOOK (notebook), vbox, label);
+  gtk_widget_show (label);
+  gtk_widget_show (vbox);
+
+  frame = g_object_new (GTK_TYPE_FRAME, "border-width", 0, "shadow-type", GTK_SHADOW_NONE, NULL);
+  gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
+  gtk_widget_show (frame);
+
   label = gtk_label_new (_("File transfer"));
   gtk_label_set_attributes (GTK_LABEL (label), thunar_pango_attr_list_bold ());
   gtk_frame_set_label_widget (GTK_FRAME (frame), label);
@@ -856,8 +866,9 @@ thunar_preferences_dialog_init (ThunarPreferencesDialog *dialog)
 
   grid = gtk_grid_new ();
   gtk_grid_set_column_spacing (GTK_GRID (grid), 12);
-  gtk_grid_set_row_spacing (GTK_GRID (grid), 2);
-  gtk_container_set_border_width (GTK_CONTAINER (grid), 12);
+  gtk_grid_set_row_spacing (GTK_GRID (grid), 6);
+  gtk_widget_set_margin_top (GTK_WIDGET (grid), 6);
+  gtk_widget_set_margin_start (GTK_WIDGET (grid), 12);
   gtk_container_add (GTK_CONTAINER (frame), grid);
   gtk_widget_show (grid);
 
@@ -883,53 +894,45 @@ thunar_preferences_dialog_init (ThunarPreferencesDialog *dialog)
                                G_OBJECT (combo),
                                "active",
                                G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE,
-                               transform_parallel_copy_mode_to_index,
-                               transform_parallel_copy_index_to_mode,
-                               NULL, NULL);
+                               transform_enum_value_to_index,
+                               transform_index_to_enum_value,
+                               (gpointer) thunar_parallel_copy_mode_get_type, NULL);
   gtk_widget_set_hexpand (combo, TRUE);
   gtk_grid_attach (GTK_GRID (grid), combo, 1, 0, 1, 1);
   thunar_gtk_label_set_a11y_relation (GTK_LABEL (label), combo);
   gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo);
   gtk_widget_show (combo);
 
-  if (thunar_g_vfs_is_uri_scheme_supported ("trash"))
-    {
-      frame = g_object_new (GTK_TYPE_FRAME, "border-width", 0, "shadow-type", GTK_SHADOW_NONE, NULL);
-      gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
-      gtk_widget_show (frame);
-
-      label = gtk_label_new (_("Context Menu"));
-      gtk_label_set_attributes (GTK_LABEL (label), thunar_pango_attr_list_bold ());
-      gtk_frame_set_label_widget (GTK_FRAME (frame), label);
-      gtk_widget_show (label);
-
-      grid = gtk_grid_new ();
-      gtk_grid_set_column_spacing (GTK_GRID (grid), 12);
-      gtk_grid_set_row_spacing (GTK_GRID (grid), 2);
-      gtk_container_set_border_width (GTK_CONTAINER (grid), 12);
-      gtk_container_add (GTK_CONTAINER (frame), grid);
-      gtk_widget_show (grid);
-
-      button = gtk_check_button_new_with_mnemonic (_("Show action to permanently delete files and folders"));
-      g_object_bind_property (G_OBJECT (dialog->preferences),
-                              "misc-show-delete-action",
-                              G_OBJECT (button),
-                              "active",
-                              G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
-      gtk_widget_set_tooltip_text (button, _("Select this option to show the 'Delete' action in the context menu"));
-      gtk_widget_set_hexpand (button, TRUE);
-      gtk_grid_attach (GTK_GRID (grid), button, 0, 0, 1, 1);
-      gtk_widget_show (button);
-    }
-
-  /*
-     Advanced
-   */
-  label = gtk_label_new (_("Advanced"));
-  vbox = g_object_new (GTK_TYPE_BOX, "orientation", GTK_ORIENTATION_VERTICAL, "border-width", 12, "spacing", 18, NULL);
-  gtk_notebook_append_page (GTK_NOTEBOOK (notebook), vbox, label);
+  label = gtk_label_new_with_mnemonic (_("Use intermediate file on copy"));
+  gtk_label_set_xalign (GTK_LABEL (label), 0.0f);
+  gtk_grid_attach (GTK_GRID (grid), label, 0, 1, 1, 1);
   gtk_widget_show (label);
-  gtk_widget_show (vbox);
+  gtk_widget_set_tooltip_text (label, _("Use intermediate file '*.partial~' to copy files. "
+                                        "This will prevent fragmented files."
+                                        "The new file will only be shown after the copy was successfully finished."));
+
+  combo = gtk_combo_box_text_new ();
+  type = g_type_class_ref (THUNAR_TYPE_USE_PARTIAL_MODE);
+  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo),
+                                  g_enum_get_value (type, THUNAR_USE_PARTIAL_MODE_DISABLED)->value_nick);
+  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo),
+                                  g_enum_get_value (type, THUNAR_USE_PARTIAL_MODE_REMOTE_ONLY)->value_nick);
+  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo),
+                                  g_enum_get_value (type, THUNAR_USE_PARTIAL_MODE_ALWAYS)->value_nick);
+  g_type_class_unref (type);
+  g_object_bind_property_full (G_OBJECT (dialog->preferences),
+                               "misc-transfer-use-partial",
+                               G_OBJECT (combo),
+                               "active",
+                               G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE,
+                               transform_enum_value_to_index,
+                               transform_index_to_enum_value,
+                               (gpointer) thunar_use_partial_get_type, NULL);
+  gtk_widget_set_hexpand (combo, TRUE);
+  gtk_grid_attach (GTK_GRID (grid), combo, 1, 1, 1, 1);
+  thunar_gtk_label_set_a11y_relation (GTK_LABEL (label), combo);
+  gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo);
+  gtk_widget_show (combo);
 
   frame = g_object_new (GTK_TYPE_FRAME, "border-width", 0, "shadow-type", GTK_SHADOW_NONE, NULL);
   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
diff --git a/thunar/thunar-preferences.c b/thunar/thunar-preferences.c
index 6e3b24372aa8e5899f0230b626b70686a08c9e92..071d402a21f5cf7c71ea7950ae421d5249c8a01b 100644
--- a/thunar/thunar-preferences.c
+++ b/thunar/thunar-preferences.c
@@ -106,6 +106,7 @@ enum
   PROP_MISC_CONFIRM_CLOSE_MULTIPLE_TABS,
   PROP_MISC_PARALLEL_COPY_MODE,
   PROP_MISC_WINDOW_ICON,
+  PROP_MISC_TRANSFER_USE_PARTIAL,
   PROP_SHORTCUTS_ICON_EMBLEMS,
   PROP_SHORTCUTS_ICON_SIZE,
   PROP_TREE_ICON_EMBLEMS,
@@ -885,6 +886,19 @@ thunar_preferences_class_init (ThunarPreferencesClass *klass)
                             TRUE,
                             EXO_PARAM_READWRITE);
 
+  /**
+   * ThunarPreferences:misc-transfer-use-partial:
+   *
+   * Whether to use intermediate file(*.partial~) to copy.
+   **/
+  preferences_props[PROP_MISC_TRANSFER_USE_PARTIAL] =
+    g_param_spec_enum ("misc-transfer-use-partial",
+                       "MiscTransferUsePartial",
+                       NULL,
+                       THUNAR_TYPE_USE_PARTIAL_MODE,
+                       THUNAR_USE_PARTIAL_MODE_DISABLED,
+                       EXO_PARAM_READWRITE);
+
   /**
    * ThunarPreferences:misc-confirm-close-multiple-tabs:
    *
diff --git a/thunar/thunar-transfer-job.c b/thunar/thunar-transfer-job.c
index 5baa48bfd77e25fc9eb07562fb5dbfb647c65460..9bdbc99f3b7082a57e1c6c1b12d8cd30d8c16e98 100644
--- a/thunar/thunar-transfer-job.c
+++ b/thunar/thunar-transfer-job.c
@@ -48,6 +48,7 @@ enum
   PROP_0,
   PROP_FILE_SIZE_BINARY,
   PROP_PARALLEL_COPY_MODE,
+  PROP_TRANSFER_USE_PARTIAL,
 };
 
 
@@ -102,6 +103,7 @@ struct _ThunarTransferJob
   ThunarPreferences      *preferences;
   gboolean                file_size_binary;
   ThunarParallelCopyMode  parallel_copy_mode;
+  ThunarUsePartialMode    transfer_use_partial;
 };
 
 struct _ThunarTransferNode
@@ -160,6 +162,20 @@ thunar_transfer_job_class_init (ThunarTransferJobClass *klass)
                                                       THUNAR_TYPE_PARALLEL_COPY_MODE,
                                                       THUNAR_PARALLEL_COPY_MODE_ONLY_LOCAL,
                                                       EXO_PARAM_READWRITE));
+
+  /**
+   * ThunarPropertiesdialog:transfer_use_partial:
+   *
+   * Whether to use intermediate file to copy
+   **/
+  g_object_class_install_property (gobject_class,
+                                   PROP_TRANSFER_USE_PARTIAL,
+                                   g_param_spec_enum ("transfer-use-partial",
+                                                      "TransferUsePartial",
+                                                      NULL,
+                                                      THUNAR_TYPE_USE_PARTIAL_MODE,
+                                                      THUNAR_USE_PARTIAL_MODE_DISABLED,
+                                                      EXO_PARAM_READWRITE));
 }
 
 
@@ -174,6 +190,9 @@ thunar_transfer_job_init (ThunarTransferJob *job)
   g_object_bind_property (job->preferences, "misc-parallel-copy-mode",
                           job,              "parallel-copy-mode",
                           G_BINDING_SYNC_CREATE);
+  g_object_bind_property (job->preferences, "misc-transfer-use-partial",
+                          job,              "transfer-use-partial",
+                          G_BINDING_SYNC_CREATE);
 
   job->type = 0;
   job->source_node_list = NULL;
@@ -230,6 +249,9 @@ thunar_transfer_job_get_property (GObject     *object,
     case PROP_PARALLEL_COPY_MODE:
       g_value_set_enum (value, job->parallel_copy_mode);
       break;
+    case PROP_TRANSFER_USE_PARTIAL:
+      g_value_set_enum (value, job->transfer_use_partial);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -254,6 +276,9 @@ thunar_transfer_job_set_property (GObject      *object,
     case PROP_PARALLEL_COPY_MODE:
       job->parallel_copy_mode = g_value_get_enum (value);
       break;
+    case PROP_TRANSFER_USE_PARTIAL:
+      job->transfer_use_partial = g_value_get_enum (value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -415,6 +440,7 @@ ttj_copy_file (ThunarTransferJob *job,
   GFileType  source_type;
   GFileType  target_type;
   gboolean   target_exists;
+  gboolean   use_partial;
   GError    *err = NULL;
 
   _thunar_return_val_if_fail (THUNAR_IS_TRANSFER_JOB (job), FALSE);
@@ -454,10 +480,21 @@ ttj_copy_file (ThunarTransferJob *job,
         }
     }
 
+  switch (job->transfer_use_partial)
+    {
+    case THUNAR_USE_PARTIAL_MODE_REMOTE_ONLY:
+      use_partial = !g_file_is_native (source_file) || !g_file_is_native (target_file);
+      break;
+    case THUNAR_USE_PARTIAL_MODE_ALWAYS:
+      use_partial = TRUE;
+      break;
+    default:
+      use_partial = FALSE;
+    }
   /* try to copy the file */
-  g_file_copy (source_file, target_file, copy_flags,
-               exo_job_get_cancellable (EXO_JOB (job)),
-               thunar_transfer_job_progress, job, &err);
+  thunar_g_file_copy (source_file, target_file, copy_flags, use_partial,
+                      exo_job_get_cancellable (EXO_JOB (job)),
+                      thunar_transfer_job_progress, job, &err);
 
   /**
    * MR !127 notes:
@@ -482,6 +519,7 @@ ttj_copy_file (ThunarTransferJob *job,
   /* check if there were errors */
   if (G_UNLIKELY (err != NULL && err->domain == G_IO_ERROR))
     {
+      g_info ("%s", err->message);
       if (err->code == G_IO_ERROR_WOULD_MERGE
           || (err->code == G_IO_ERROR_EXISTS
               && source_type == G_FILE_TYPE_DIRECTORY
@@ -1119,6 +1157,8 @@ thunar_transfer_job_move_file (ExoJob                *job,
   exo_job_info_message (job, _("Trying to move \"%s\""),
                         g_file_info_get_display_name (info));
 
+  g_info ("%s", g_file_info_get_display_name (info));
+
   move_successful = g_file_move (node->source_file,
                                  tp->data,
                                  move_flags,