changeset 2295:38f6ecad0b53

Issue #332 Rename function can delete files https://github.com/BestImageViewer/geeqie/issues/332 During a Rename operation, if the user assigns a single destination filename to multiple source files, an error dialog is shown and the operation is aborted.
author Colin Clark <cclark@mcb.net>
date Wed, 13 Apr 2016 18:53:12 +0100
parents 00773211590e
children a987ea1ea4f8
files src/filedata.c src/filedata.h src/typedefs.h src/utilops.c
diffstat 4 files changed, 96 insertions(+), 52 deletions(-) [+]
line wrap: on
line diff
--- a/src/filedata.c	Tue Apr 12 21:35:11 2016 +0200
+++ b/src/filedata.c	Wed Apr 13 18:53:12 2016 +0100
@@ -2184,10 +2184,12 @@
  * it should detect all possible problems with the planned operation
  */
 
-gint file_data_verify_ci(FileData *fd)
+gint file_data_verify_ci(FileData *fd, GList *list)
 {
 	gint ret = CHANGE_OK;
 	gchar *dir;
+	GList *work = NULL;
+	FileData *fd1 = NULL;
 
 	if (!fd->change)
 		{
@@ -2397,6 +2399,26 @@
 		g_free(dest_dir);
 		}
 
+	/* During a rename operation, check if another planned destination file has
+	 * the same filename
+	 */
+ 	if(fd->change->type == FILEDATA_CHANGE_RENAME)
+		{
+		work = list;
+		while (work)
+			{
+			fd1 = work->data;
+			work = work->next;
+			if (fd1 != NULL && fd != fd1 )
+				{
+				if (!strcmp(fd->change->dest, fd1->change->dest))
+					{
+					ret |= CHANGE_DUPLICATE_DEST;
+					}
+				}
+			}
+		}
+
 	fd->change->error = ret;
 	if (ret == 0) DEBUG_1("Change checked: OK: %s", fd->path);
 
@@ -2405,19 +2427,19 @@
 }
 
 
-gint file_data_sc_verify_ci(FileData *fd)
+gint file_data_sc_verify_ci(FileData *fd, GList *list)
 {
 	GList *work;
 	gint ret;
 
-	ret = file_data_verify_ci(fd);
+	ret = file_data_verify_ci(fd, list);
 
 	work = fd->sidecar_files;
 	while (work)
 		{
 		FileData *sfd = work->data;
 
-		ret |= file_data_verify_ci(sfd);
+		ret |= file_data_verify_ci(sfd, list);
 		work = work->next;
 		}
 
@@ -2500,6 +2522,12 @@
 		g_string_append(result, _("there are unsaved metadata changes for the file"));
 		}
 
+	if (error & CHANGE_DUPLICATE_DEST)
+		{
+		if (result->len > 0) g_string_append(result, ", ");
+		g_string_append(result, _("another destination file has the same filename"));
+		}
+
 	return g_string_free(result, FALSE);
 }
 
@@ -2526,7 +2554,7 @@
 		fd = work->data;
 		work = work->next;
 
-		error = with_sidecars ? file_data_sc_verify_ci(fd) : file_data_verify_ci(fd);
+		error = with_sidecars ? file_data_sc_verify_ci(fd, list) : file_data_verify_ci(fd, list);
 		all_errors |= error;
 		common_errors &= error;
 
--- a/src/filedata.h	Tue Apr 12 21:35:11 2016 +0200
+++ b/src/filedata.h	Wed Apr 13 18:53:12 2016 +0100
@@ -125,7 +125,7 @@
 
 gchar *file_data_get_error_string(gint error);
 
-gint file_data_verify_ci(FileData *fd);
+gint file_data_verify_ci(FileData *fd, GList *list);
 gint file_data_verify_ci_list(GList *list, gchar **desc, gboolean with_sidecars);
 
 gboolean file_data_perform_ci(FileData *fd);
@@ -135,7 +135,7 @@
 
 void file_data_set_regroup_when_finished(FileData *fd, gboolean enable);
 
-gint file_data_sc_verify_ci(FileData *fd);
+gint file_data_sc_verify_ci(FileData *fd, GList *list);
 
 gboolean file_data_sc_perform_ci(FileData *fd);
 gboolean file_data_sc_apply_ci(FileData *fd);
--- a/src/typedefs.h	Tue Apr 12 21:35:11 2016 +0200
+++ b/src/typedefs.h	Wed Apr 13 18:53:12 2016 +0100
@@ -165,6 +165,7 @@
 	CHANGE_NO_READ_PERM            = 1 << 8,
 	CHANGE_NO_WRITE_PERM_DIR       = 1 << 9,
 	CHANGE_NO_DEST_DIR             = 1 << 10,
+	CHANGE_DUPLICATE_DEST          = 1 << 11,
 	CHANGE_NO_WRITE_PERM_DEST      = 1 << 12,
 	CHANGE_DEST_EXISTS             = 1 << 13,
 	CHANGE_NO_SRC                  = 1 << 14,
--- a/src/utilops.c	Tue Apr 12 21:35:11 2016 +0200
+++ b/src/utilops.c	Wed Apr 13 18:53:12 2016 +0100
@@ -36,7 +36,7 @@
 
 #define DIALOG_WIDTH 750
 
-static GdkPixbuf *file_util_get_error_icon(FileData *fd, GtkWidget *widget);
+static GdkPixbuf *file_util_get_error_icon(FileData *fd, GList *list, GtkWidget *widget);
 
 /*
  *--------------------------------------------------------------------------
@@ -473,7 +473,7 @@
 		gchar *sidecars;
 
 		sidecars = with_sidecars ? file_data_sc_list_to_string(fd) : NULL;
-		GdkPixbuf *icon = file_util_get_error_icon(fd, view);
+		GdkPixbuf *icon = file_util_get_error_icon(fd, list, view);
 		gtk_list_store_append(store, &iter);
 		gtk_list_store_set(store, &iter,
 				   UTILITY_COLUMN_FD, fd,
@@ -891,7 +891,7 @@
 		}
 }
 
-static GdkPixbuf *file_util_get_error_icon(FileData *fd, GtkWidget *widget)
+static GdkPixbuf *file_util_get_error_icon(FileData *fd, GList *list, GtkWidget *widget)
 {
 	static GdkPixbuf *pb_warning;
 	static GdkPixbuf *pb_error;
@@ -913,7 +913,7 @@
 		pb_apply = gtk_widget_render_icon(widget, GTK_STOCK_APPLY, GTK_ICON_SIZE_MENU, NULL);
 		}
 
-	error = file_data_sc_verify_ci(fd);
+	error = file_data_sc_verify_ci(fd, list);
 
 	if (!error) return pb_apply;
 
@@ -957,7 +957,7 @@
 		else if (ud->dir_fd)
 			{
 			g_assert(ud->dir_fd->sidecar_files == NULL); // directories should not have sidecars
-			error = file_data_verify_ci(ud->dir_fd);
+			error = file_data_verify_ci(ud->dir_fd, ud->flist);
 			if (error) desc = file_data_get_error_string(error);
 			}
 		else
@@ -1191,59 +1191,74 @@
 			gtk_tree_model_get(store, &iter, UTILITY_COLUMN_FD, &fd, -1);
 			g_assert(ud->with_sidecars); /* sidecars must be renamed too, it would break the pairing otherwise */
 			file_data_sc_update_ci_rename(fd, dest);
+
 			gtk_list_store_set(GTK_LIST_STORE(store), &iter,
-					   UTILITY_COLUMN_PIXBUF, file_util_get_error_icon(fd, ud->listview),
-					   UTILITY_COLUMN_DEST_PATH, fd->change->dest,
-					   UTILITY_COLUMN_DEST_NAME, filename_from_path(fd->change->dest),
-					   -1);
+				   UTILITY_COLUMN_DEST_PATH, fd->change->dest,
+				   UTILITY_COLUMN_DEST_NAME, filename_from_path(fd->change->dest),
+				   -1);
 			}
-		return;
-		}
-
-
-	front = gtk_entry_get_text(GTK_ENTRY(ud->auto_entry_front));
-	end = gtk_entry_get_text(GTK_ENTRY(ud->auto_entry_end));
-	padding = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(ud->auto_spin_pad));
-
-	format = gtk_entry_get_text(GTK_ENTRY(ud->format_entry));
-
-	if (mode == UTILITY_RENAME_FORMATTED)
-		{
-		start_n = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(ud->format_spin));
 		}
 	else
 		{
-		start_n = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(ud->auto_spin_start));
-		}
-
-	store = gtk_tree_view_get_model(GTK_TREE_VIEW(ud->listview));
-	n = start_n;
-	valid = gtk_tree_model_get_iter_first(store, &iter);
-	while (valid)
-		{
-		gchar *dest;
-		FileData *fd;
-		gtk_tree_model_get(store, &iter, UTILITY_COLUMN_FD, &fd, -1);
+		front = gtk_entry_get_text(GTK_ENTRY(ud->auto_entry_front));
+		end = gtk_entry_get_text(GTK_ENTRY(ud->auto_entry_end));
+		padding = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(ud->auto_spin_pad));
+
+		format = gtk_entry_get_text(GTK_ENTRY(ud->format_entry));
 
 		if (mode == UTILITY_RENAME_FORMATTED)
 			{
-			dest = file_util_rename_multiple_auto_format_name(format, fd->name, n);
+			start_n = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(ud->format_spin));
 			}
 		else
 			{
-			dest = g_strdup_printf("%s%0*d%s", front, padding, n, end);
+			start_n = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(ud->auto_spin_start));
 			}
 
-		g_assert(ud->with_sidecars); /* sidecars must be renamed too, it would break the pairing otherwise */
-		file_data_sc_update_ci_rename(fd, dest);
+		store = gtk_tree_view_get_model(GTK_TREE_VIEW(ud->listview));
+		n = start_n;
+		valid = gtk_tree_model_get_iter_first(store, &iter);
+		while (valid)
+			{
+			gchar *dest;
+			FileData *fd;
+			gtk_tree_model_get(store, &iter, UTILITY_COLUMN_FD, &fd, -1);
+
+			if (mode == UTILITY_RENAME_FORMATTED)
+				{
+				dest = file_util_rename_multiple_auto_format_name(format, fd->name, n);
+				}
+			else
+				{
+				dest = g_strdup_printf("%s%0*d%s", front, padding, n, end);
+				}
+
+			g_assert(ud->with_sidecars); /* sidecars must be renamed too, it would break the pairing otherwise */
+			file_data_sc_update_ci_rename(fd, dest);
+			gtk_list_store_set(GTK_LIST_STORE(store), &iter,
+					   UTILITY_COLUMN_DEST_PATH, fd->change->dest,
+					   UTILITY_COLUMN_DEST_NAME, filename_from_path(fd->change->dest),
+					   -1);
+			g_free(dest);
+
+			n++;
+			valid = gtk_tree_model_iter_next(store, &iter);
+			}
+		}
+
+	/* Check the other entries in the list - if there are
+	 * multiple destination filenames with the same name the
+	 * error icons must be updated
+	 */
+	valid = gtk_tree_model_get_iter_first(store, &iter);
+	while (valid)
+		{
+		FileData *fd;
+		gtk_tree_model_get(store, &iter, UTILITY_COLUMN_FD, &fd, -1);
+
 		gtk_list_store_set(GTK_LIST_STORE(store), &iter,
-				   UTILITY_COLUMN_PIXBUF, file_util_get_error_icon(fd, ud->listview),
-				   UTILITY_COLUMN_DEST_PATH, fd->change->dest,
-				   UTILITY_COLUMN_DEST_NAME, filename_from_path(fd->change->dest),
-				   -1);
-		g_free(dest);
-
-		n++;
+			   UTILITY_COLUMN_PIXBUF, file_util_get_error_icon(fd, ud->flist, ud->listview),
+			   -1);
 		valid = gtk_tree_model_iter_next(store, &iter);
 		}
 
@@ -1782,7 +1797,7 @@
 
 	g_string_append(message, _("\nStatus: "));
 
-	error = ud->with_sidecars ? file_data_sc_verify_ci(fd) : file_data_verify_ci(fd);
+	error = ud->with_sidecars ? file_data_sc_verify_ci(fd, ud->flist) : file_data_verify_ci(fd, ud->flist);
 
 	if (error)
 		{