From 09f448bd6a358e1f72ccbf71ed5db19ffb93fcab Mon Sep 17 00:00:00 2001 From: infirit Date: Wed, 19 Nov 2014 18:55:14 +0100 Subject: Ask overwrite confirmation when extracting files with drag&drop Based on FR commit: 8e2f58d8a56eb2dd27448274c732d3f0324401b5 From: Paolo Bacchilega Gnome bug: http://bugzilla.gnome.org/show_bug.cgi?id=590609 --- src/dlg-extract.c | 2 +- src/fr-window.c | 256 +++++++++++++++++++++++++++++++++++++++++++++--------- src/fr-window.h | 2 +- src/typedefs.h | 6 ++ 4 files changed, 225 insertions(+), 41 deletions(-) diff --git a/src/dlg-extract.c b/src/dlg-extract.c index b4c5228..9cdc272 100644 --- a/src/dlg-extract.c +++ b/src/dlg-extract.c @@ -237,7 +237,7 @@ extract_cb (GtkWidget *w, extract_to_dir, base_dir, skip_newer, - overwrite, + overwrite ? FR_OVERWRITE_YES : FR_OVERWRITE_NO, junk_paths, TRUE); diff --git a/src/fr-window.c b/src/fr-window.c index 3087a80..776c09e 100644 --- a/src/fr-window.c +++ b/src/fr-window.c @@ -140,14 +140,15 @@ typedef enum { typedef struct { - GList *file_list; - char *extract_to_dir; - char *base_dir; - gboolean skip_older; - gboolean overwrite; - gboolean junk_paths; - char *password; - gboolean extract_here; + GList *file_list; + char *extract_to_dir; + char *base_dir; + gboolean skip_older; + FrOverwrite overwrite; + gboolean junk_paths; + char *password; + gboolean extract_here; + gboolean ask_to_open_destination; } ExtractData; @@ -4144,7 +4145,7 @@ file_list_drag_end (GtkWidget *widget, window->priv->drag_destination_folder, window->priv->drag_base_dir, FALSE, - TRUE, + FR_OVERWRITE_ASK, FALSE, FALSE); path_list_free (window->priv->drag_file_list); @@ -6454,13 +6455,14 @@ fr_window_archive_remove (FrWindow *window, static ExtractData* -extract_data_new (GList *file_list, - const char *extract_to_dir, - const char *base_dir, - gboolean skip_older, - gboolean overwrite, - gboolean junk_paths, - gboolean extract_here) +extract_data_new (GList *file_list, + const char *extract_to_dir, + const char *base_dir, + gboolean skip_older, + FrOverwrite overwrite, + gboolean junk_paths, + gboolean extract_here, + gboolean ask_to_open_destination) { ExtractData *edata; @@ -6474,6 +6476,7 @@ extract_data_new (GList *file_list, if (base_dir != NULL) edata->base_dir = g_strdup (base_dir); edata->extract_here = extract_here; + edata->ask_to_open_destination = ask_to_open_destination; return edata; } @@ -6488,6 +6491,7 @@ extract_to_data_new (const char *extract_to_dir) FALSE, TRUE, FALSE, + FALSE, FALSE); } @@ -6565,7 +6569,8 @@ fr_window_archive_extract_here (FrWindow *window, skip_older, overwrite, junk_paths, - TRUE); + TRUE, + FALSE); fr_window_set_current_batch_action (window, FR_BATCH_ACTION_EXTRACT, edata, @@ -6576,7 +6581,7 @@ fr_window_archive_extract_here (FrWindow *window, return; } - window->priv->ask_to_open_destination_after_extraction = FALSE; + window->priv->ask_to_open_destination_after_extraction = edata->ask_to_open_destination; fr_process_clear (window->archive->process); if (fr_archive_extract_here (window->archive, @@ -6590,15 +6595,183 @@ fr_window_archive_extract_here (FrWindow *window, } +/* -- fr_window_archive_extract -- */ + + +typedef struct { + FrWindow *window; + ExtractData *edata; + GList *current_file; +} OverwriteData; + + +#define _FR_RESPONSE_OVERWRITE_YES_ALL 100 +#define _FR_RESPONSE_OVERWRITE_YES 101 +#define _FR_RESPONSE_OVERWRITE_NO 102 + + +static void +_fr_window_archive_extract_from_edata (FrWindow *window, + ExtractData *edata) +{ + window->priv->ask_to_open_destination_after_extraction = edata->ask_to_open_destination; + + fr_process_clear (window->archive->process); + fr_archive_extract (window->archive, + edata->file_list, + edata->extract_to_dir, + edata->base_dir, + edata->skip_older, + edata->overwrite == FR_OVERWRITE_YES, + edata->junk_paths, + window->priv->password); + fr_process_start (window->archive->process); +} + + +static gboolean _fr_window_ask_overwrite_dialog (OverwriteData *odata); + + +static void +overwrite_dialog_response_cb (GtkDialog *dialog, + int response_id, + gpointer user_data) +{ + OverwriteData *odata = user_data; + gboolean do_not_extract = FALSE; + + switch (response_id) { + case _FR_RESPONSE_OVERWRITE_YES_ALL: + odata->edata->overwrite = FR_OVERWRITE_YES; + break; + + case _FR_RESPONSE_OVERWRITE_YES: + odata->current_file = odata->current_file->next; + break; + + case _FR_RESPONSE_OVERWRITE_NO: + { + /* remove the file from the list to extract */ + GList *next = odata->current_file->next; + odata->edata->file_list = g_list_remove_link (odata->edata->file_list, odata->current_file); + path_list_free (odata->current_file); + odata->current_file = next; + } + break; + + case GTK_RESPONSE_DELETE_EVENT: + case GTK_RESPONSE_CANCEL: + do_not_extract = TRUE; + break; + + default: + break; + } + + gtk_widget_destroy (GTK_WIDGET (dialog)); + + if (do_not_extract) { + fr_window_stop_batch (odata->window); + g_free (odata); + return; + } + + _fr_window_ask_overwrite_dialog (odata); +} + + +static gboolean +_fr_window_ask_overwrite_dialog (OverwriteData *odata) +{ + gboolean do_not_extract = FALSE; + + while ((odata->edata->overwrite == FR_OVERWRITE_ASK) && (odata->current_file != NULL)) { + char *path; + char *dest_uri; + GFile *file; + GFileInfo *info; + GFileType file_type; + + path = g_uri_escape_string ((char *) odata->current_file->data, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH, TRUE); + dest_uri = g_strdup_printf ("%s/%s", odata->edata->extract_to_dir, path); + file = g_file_new_for_uri (dest_uri); + info = g_file_query_info (file, + G_FILE_ATTRIBUTE_STANDARD_TYPE "," G_FILE_ATTRIBUTE_STANDARD_NAME "," G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, + G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, + NULL, + NULL); + + g_free (dest_uri); + g_free (path); + + if (info == NULL) { + g_object_unref (file); + odata->current_file = odata->current_file->next; + continue; + } + + file_type = g_file_info_get_file_type (info); + if ((file_type != G_FILE_TYPE_UNKNOWN) && (file_type != G_FILE_TYPE_DIRECTORY)) { + char *msg; + GFile *parent; + char *parent_name; + char *details; + GtkWidget *d; + + msg = g_strdup_printf (_("Replace file \"%s\"?"), g_file_info_get_display_name (info)); + parent = g_file_get_parent (file); + parent_name = g_file_get_parse_name (parent); + details = g_strdup_printf (_("Another file with the same name already exists in \"%s\"."), parent_name); + d = _gtk_message_dialog_new (GTK_WINDOW (odata->window), + GTK_DIALOG_MODAL, + GTK_STOCK_DIALOG_QUESTION, + msg, + details, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + _("Replace _All"), _FR_RESPONSE_OVERWRITE_YES_ALL, + _("_Skip"), _FR_RESPONSE_OVERWRITE_NO, + _("_Replace"), _FR_RESPONSE_OVERWRITE_YES, + NULL); + gtk_dialog_set_default_response (GTK_DIALOG (d), _FR_RESPONSE_OVERWRITE_YES); + g_signal_connect (d, + "response", + G_CALLBACK (overwrite_dialog_response_cb), + odata); + gtk_widget_show (d); + + g_free (parent_name); + g_object_unref (parent); + g_object_unref (info); + g_object_unref (file); + + return; + } + + g_object_unref (info); + g_object_unref (file); + } + + if (do_not_extract) { + fr_window_stop_batch (odata->window); + g_free (odata); + return; + } + + odata->edata->overwrite = FR_OVERWRITE_YES; + _fr_window_archive_extract_from_edata (odata->window, odata->edata); + g_free (odata); +} + + void -fr_window_archive_extract (FrWindow *window, - GList *file_list, - const char *extract_to_dir, - const char *base_dir, - gboolean skip_older, - gboolean overwrite, - gboolean junk_paths, - gboolean ask_to_open_destination) +fr_window_archive_extract (FrWindow *window, + GList *file_list, + const char *extract_to_dir, + const char *base_dir, + gboolean skip_older, + FrOverwrite overwrite, + gboolean junk_paths, + gboolean ask_to_open_destination) { ExtractData *edata; gboolean do_not_extract = FALSE; @@ -6610,7 +6783,8 @@ fr_window_archive_extract (FrWindow *window, skip_older, overwrite, junk_paths, - FALSE); + FALSE, + ask_to_open_destination); fr_window_set_current_batch_action (window, FR_BATCH_ACTION_EXTRACT, @@ -6623,6 +6797,11 @@ fr_window_archive_extract (FrWindow *window, } if (! uri_is_dir (edata->extract_to_dir)) { + + /* There is nothing to ask if the destination doesn't exist. */ + if (edata->overwrite == FR_OVERWRITE_ASK) + edata->overwrite = FR_OVERWRITE_YES; + if (! ForceDirectoryCreation) { GtkWidget *d; int r; @@ -6686,18 +6865,17 @@ fr_window_archive_extract (FrWindow *window, return; } - window->priv->ask_to_open_destination_after_extraction = ask_to_open_destination; + if (edata->overwrite == FR_OVERWRITE_ASK) { + OverwriteData *odata; - fr_process_clear (window->archive->process); - fr_archive_extract (window->archive, - edata->file_list, - edata->extract_to_dir, - edata->base_dir, - edata->skip_older, - edata->overwrite, - edata->junk_paths, - window->priv->password); - fr_process_start (window->archive->process); + odata = g_new0 (OverwriteData, 1); + odata->window = window; + odata->edata = edata; + odata->current_file = odata->edata->file_list; + _fr_window_ask_overwrite_dialog (odata); + } + else + _fr_window_archive_extract_from_edata (window, edata); } @@ -8566,7 +8744,7 @@ fr_window_exec_batch_action (FrWindow *window, window->priv->extract_default_dir, NULL, FALSE, - TRUE, + FR_OVERWRITE_ASK, FALSE, TRUE); } diff --git a/src/fr-window.h b/src/fr-window.h index cb1f38c..77e5d4b 100644 --- a/src/fr-window.h +++ b/src/fr-window.h @@ -151,7 +151,7 @@ void fr_window_archive_extract (FrWindow *window, const char *extract_to_dir, const char *base_dir, gboolean skip_older, - gboolean overwrite, + FrOverwrite overwrite, gboolean junk_paths, gboolean ask_to_open_destination); void fr_window_archive_extract_here (FrWindow *window, diff --git a/src/typedefs.h b/src/typedefs.h index 8e687de..e25ed73 100644 --- a/src/typedefs.h +++ b/src/typedefs.h @@ -50,6 +50,12 @@ typedef enum { FR_COMPRESSION_MAXIMUM } FrCompression; +typedef enum { + FR_OVERWRITE_YES, + FR_OVERWRITE_NO, + FR_OVERWRITE_ASK +} FrOverwrite; + typedef enum { /*< skip >*/ FR_PROC_ERROR_NONE, FR_PROC_ERROR_GENERIC, -- cgit v1.2.1