[file-roller] Ask overwrite confirmation when extracting files with drag&drop



commit 8e2f58d8a56eb2dd27448274c732d3f0324401b5
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Tue Feb 21 00:37:53 2012 +0100

    Ask overwrite confirmation when extracting files with drag&drop
    
    [new feature, bug #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 9ce1b62..7b1922c 100644
--- a/src/dlg-extract.c
+++ b/src/dlg-extract.c
@@ -236,7 +236,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 3aab45f..e0452c1 100644
--- a/src/fr-window.c
+++ b/src/fr-window.c
@@ -135,14 +135,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;
 
 
@@ -4212,7 +4213,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);
@@ -6507,13 +6508,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;
 
@@ -6527,6 +6529,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;
 }
@@ -6541,6 +6544,7 @@ extract_to_data_new (const char *extract_to_dir)
 				 FALSE,
 				 TRUE,
 				 FALSE,
+				 FALSE,
 				 FALSE);
 }
 
@@ -6618,7 +6622,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,
@@ -6629,7 +6634,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,
@@ -6643,15 +6648,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;
@@ -6663,7 +6836,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,
@@ -6676,6 +6850,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;
@@ -6743,18 +6922,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);
 }
 
 
@@ -8618,7 +8796,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 8b4f72e..b8afcc1 100644
--- a/src/fr-window.h
+++ b/src/fr-window.h
@@ -155,7 +155,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 4ea9476..28c78ab 100644
--- a/src/typedefs.h
+++ b/src/typedefs.h
@@ -49,6 +49,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,



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]