[Xfce4-commits] <thunar:master> Check free space before copying (bug #5658).

Nick Schermer noreply at xfce.org
Sun Sep 30 21:38:01 CEST 2012


Updating branch refs/heads/master
         to ecad36219b96785e0549dd8ca133123a90c09a42 (commit)
       from 0901472b684d8621bbbbc50c04d95eb5783206f8 (commit)

commit ecad36219b96785e0549dd8ca133123a90c09a42
Author: Nick Schermer <nick at xfce.org>
Date:   Sun Sep 30 21:36:40 2012 +0200

    Check free space before copying (bug #5658).

 thunar/thunar-dialogs.c      |   29 ++++++++----
 thunar/thunar-enum-types.c   |    1 +
 thunar/thunar-enum-types.h   |    2 +
 thunar/thunar-job.c          |   28 +++++++++++
 thunar/thunar-job.h          |    3 +
 thunar/thunar-transfer-job.c |  105 ++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 159 insertions(+), 9 deletions(-)

diff --git a/thunar/thunar-dialogs.c b/thunar/thunar-dialogs.c
index dc8b903..0021d2d 100644
--- a/thunar/thunar-dialogs.c
+++ b/thunar/thunar-dialogs.c
@@ -360,7 +360,8 @@ thunar_dialogs_show_job_ask (GtkWindow        *parent,
   GString     *secondary = g_string_sized_new (256);
   GString     *primary = g_string_sized_new (256);
   gint         response;
-  gint         n, m;
+  gint         n;
+  gboolean     has_cancel = FALSE;
 
   _thunar_return_val_if_fail (parent == NULL || GTK_IS_WINDOW (parent), THUNAR_JOB_RESPONSE_CANCEL);
   _thunar_return_val_if_fail (g_utf8_validate (question, -1, NULL), THUNAR_JOB_RESPONSE_CANCEL);
@@ -411,13 +412,10 @@ thunar_dialogs_show_job_ask (GtkWindow        *parent,
     gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (message), "%s", secondary->str);
 
   /* add the buttons based on the possible choices */
-  for (n = 5; n >= 0; --n)
+  for (n = 6; n >= 0; --n)
     {
-      /* "Cancel" should be the last button, but "Retry" was added last */
-      m = (n == 5) ? 3 : (n == 3) ? 5 : n;
-
       /* check if the response is set */
-      response = choices & (1 << m);
+      response = choices & (1 << n);
       if (response == 0)
         continue;
 
@@ -443,11 +441,15 @@ thunar_dialogs_show_job_ask (GtkWindow        *parent,
           mnemonic = _("_Retry");
           break;
 
-        case THUNAR_JOB_RESPONSE_CANCEL:
-          response = GTK_RESPONSE_CANCEL;
-          mnemonic = _("_Cancel");
+        case THUNAR_JOB_RESPONSE_FORCE:
+          mnemonic = _("Copy _Anyway");
           break;
 
+        case THUNAR_JOB_RESPONSE_CANCEL:
+          /* cancel is always the last option */
+          has_cancel = TRUE;
+          continue;
+
         default:
           g_assert_not_reached ();
           break;
@@ -461,6 +463,15 @@ thunar_dialogs_show_job_ask (GtkWindow        *parent,
       gtk_dialog_set_default_response (GTK_DIALOG (message), response);
     }
 
+  if (has_cancel)
+    {
+      button = gtk_button_new_with_mnemonic (_("_Cancel"));
+      gtk_widget_set_can_default (button, TRUE);
+      gtk_dialog_add_action_widget (GTK_DIALOG (message), button, GTK_RESPONSE_CANCEL);
+      gtk_widget_show (button);
+      gtk_dialog_set_default_response (GTK_DIALOG (message), GTK_RESPONSE_CANCEL);
+    }
+
   /* run the question dialog */
   response = gtk_dialog_run (GTK_DIALOG (message));
   gtk_widget_destroy (message);
diff --git a/thunar/thunar-enum-types.c b/thunar/thunar-enum-types.c
index d671338..35654a9 100644
--- a/thunar/thunar-enum-types.c
+++ b/thunar/thunar-enum-types.c
@@ -240,6 +240,7 @@ thunar_job_response_get_type (void)
 	      { THUNAR_JOB_RESPONSE_CANCEL,  "THUNAR_JOB_RESPONSE_CANCEL",  "cancel"  },
 	      { THUNAR_JOB_RESPONSE_NO_ALL,  "THUNAR_JOB_RESPONSE_NO_ALL",  "no-all"  },
 	      { THUNAR_JOB_RESPONSE_RETRY,   "THUNAR_JOB_RESPONSE_RETRY",   "retry"   },
+	      { THUNAR_JOB_RESPONSE_FORCE,   "THUNAR_JOB_RESPONSE_FORCE",   "force"   },
 	      { 0,                           NULL,                          NULL      }
 	    };
 
diff --git a/thunar/thunar-enum-types.h b/thunar/thunar-enum-types.h
index 7df8ee8..b950052 100644
--- a/thunar/thunar-enum-types.h
+++ b/thunar/thunar-enum-types.h
@@ -204,6 +204,7 @@ GType          thunar_zoom_level_get_type     (void) G_GNUC_CONST;
  * @THUNAR_JOB_RESPONSE_NO_ALL  :
  * @THUNAR_JOB_RESPONSE_CANCEL  :
  * @THUNAR_JOB_RESPONSE_RETRY   :
+ * @THUNAR_JOB_RESPONSE_FORCE   :
  *
  * Possible responses for the ThunarJob::ask signal.
  **/
@@ -215,6 +216,7 @@ typedef enum /*< flags >*/
   THUNAR_JOB_RESPONSE_CANCEL  = 1 << 3,
   THUNAR_JOB_RESPONSE_NO_ALL  = 1 << 4,
   THUNAR_JOB_RESPONSE_RETRY   = 1 << 5,
+  THUNAR_JOB_RESPONSE_FORCE   = 1 << 6,
 } ThunarJobResponse;
 
 GType thunar_job_response_get_type (void) G_GNUC_CONST;
diff --git a/thunar/thunar-job.c b/thunar/thunar-job.c
index 0cd0389..0cd0c38 100644
--- a/thunar/thunar-job.c
+++ b/thunar/thunar-job.c
@@ -519,6 +519,34 @@ thunar_job_ask_skip (ThunarJob   *job,
 
 
 gboolean
+thunar_job_ask_no_size (ThunarJob   *job,
+                        const gchar *format,
+                        ...)
+{
+  ThunarJobResponse response;
+  va_list           var_args;
+
+  _thunar_return_val_if_fail (THUNAR_IS_JOB (job), THUNAR_JOB_RESPONSE_CANCEL);
+  _thunar_return_val_if_fail (format != NULL, THUNAR_JOB_RESPONSE_CANCEL);
+
+  /* check if the user already cancelled the job */
+  if (G_UNLIKELY (exo_job_is_cancelled (EXO_JOB (job))))
+    return THUNAR_JOB_RESPONSE_CANCEL;
+
+  /* ask the user what he wants to do */
+  va_start (var_args, format);
+  response = _thunar_job_ask_valist (job, format, var_args,
+                                     _("There is not enough space on the destination. Try to remove files to make space."),
+                                     THUNAR_JOB_RESPONSE_FORCE
+                                     | THUNAR_JOB_RESPONSE_CANCEL);
+  va_end (var_args);
+
+  return (response == THUNAR_JOB_RESPONSE_FORCE);
+}
+
+
+
+gboolean
 thunar_job_files_ready (ThunarJob *job,
                         GList     *file_list)
 {
diff --git a/thunar/thunar-job.h b/thunar/thunar-job.h
index 8ed8a8b..f1f636b 100644
--- a/thunar/thunar-job.h
+++ b/thunar/thunar-job.h
@@ -84,6 +84,9 @@ ThunarJobResponse thunar_job_ask_replace            (ThunarJob       *job,
 ThunarJobResponse thunar_job_ask_skip               (ThunarJob       *job,
                                                      const gchar     *format,
                                                      ...);
+gboolean          thunar_job_ask_no_size            (ThunarJob       *job,
+                                                     const gchar     *format,
+                                                     ...);
 gboolean          thunar_job_files_ready            (ThunarJob       *job,
                                                      GList           *file_list);
 void              thunar_job_new_files              (ThunarJob       *job,
diff --git a/thunar/thunar-transfer-job.c b/thunar/thunar-transfer-job.c
index 650d27f..178a5bc 100644
--- a/thunar/thunar-transfer-job.c
+++ b/thunar/thunar-transfer-job.c
@@ -667,6 +667,96 @@ retry_remove:
 }
 
 
+
+static gboolean
+thunar_transfer_job_veryify_destination (ThunarTransferJob  *transfer_job,
+                                         GError            **error)
+{
+  GFileInfo *filesystem_info;
+  guint64     free_space;
+  GFile     *dest;
+  GFileInfo *dest_info;
+  gchar     *dest_name = NULL;
+  gchar     *base_name;
+  gboolean   succeed = TRUE;
+  gchar     *size_string;
+
+  _thunar_return_val_if_fail (THUNAR_IS_TRANSFER_JOB (transfer_job), FALSE);
+
+  /* no target file list */
+  if (transfer_job->target_file_list == NULL)
+    return TRUE;
+
+  /* total size is nul, should be fine */
+  if (transfer_job->total_size == 0)
+    return TRUE;
+
+  /* for all actions in thunar use the same target directory so
+   * although not all files are checked, this should work nicely */
+  dest = g_file_get_parent (G_FILE (transfer_job->target_file_list->data));
+
+  /* query information about the filesystem */
+  filesystem_info = g_file_query_filesystem_info (dest, THUNARX_FILESYSTEM_INFO_NAMESPACE,
+                                                  exo_job_get_cancellable (EXO_JOB (transfer_job)),
+                                                  NULL);
+
+  /* unable to query the info, this could happen on some backends */
+  if (filesystem_info == NULL)
+    {
+      g_object_unref (G_OBJECT (dest));
+      return TRUE;
+    }
+
+  /* some info about the file */
+  dest_info = g_file_query_info (dest, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, 0,
+                                 exo_job_get_cancellable (EXO_JOB (transfer_job)),
+                                 NULL);
+  if (dest_info != NULL)
+    {
+      dest_name = g_strdup (g_file_info_get_display_name (dest_info));
+      g_object_unref (G_OBJECT (dest_info));
+    }
+
+  if (dest_name == NULL)
+    {
+      base_name = g_file_get_basename (dest);
+      dest_name = g_filename_display_name (base_name);
+      g_free (base_name);
+    }
+
+  if (g_file_info_has_attribute (filesystem_info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE))
+    {
+      free_space = g_file_info_get_attribute_uint64 (filesystem_info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE);
+      if (transfer_job->total_size > free_space)
+        {
+          size_string = g_format_size (transfer_job->total_size - free_space);
+          succeed = thunar_job_ask_no_size (THUNAR_JOB (transfer_job),
+                                             _("Error while copying to \"%s\": %s more space is "
+                                               "required to copy to the destination"),
+                                            dest_name, size_string);
+          g_free (size_string);
+        }
+    }
+
+  if (succeed && g_file_info_get_attribute_boolean (filesystem_info, G_FILE_ATTRIBUTE_FILESYSTEM_READONLY))
+    {
+      g_set_error (error, G_IO_ERROR, G_IO_ERROR_READ_ONLY,
+                   _("Error while copying to \"%s\": The destination is read-only"),
+                   dest_name);
+
+      /* meh */
+      succeed = FALSE;
+    }
+
+  g_object_unref (filesystem_info);
+  g_object_unref (G_OBJECT (dest));
+  g_free (dest_name);
+
+  return succeed;
+}
+
+
+
 static gboolean
 thunar_transfer_job_execute (ExoJob  *job,
                              GError **error)
@@ -856,6 +946,21 @@ thunar_transfer_job_execute (ExoJob  *job,
   /* continue if there were no errors yet */
   if (G_LIKELY (err == NULL))
     {
+      /* check destination */
+      if (!thunar_transfer_job_veryify_destination (transfer_job, &err))
+        {
+          if (err != NULL)
+            {
+              g_propagate_error (error, err);
+              return FALSE;
+            }
+          else
+            {
+              /* pretend nothing happened */
+              return TRUE;
+            }
+        }
+
       /* transfer starts now */
       transfer_job->start_time = g_get_real_time ();
 


More information about the Xfce4-commits mailing list