Antoine Vairet recently logged this feature request:
https://sourceforge.net/p/geeqie/feature-requests/99/

But this is actually a serious bug in Geeqie, and it's been around for a long time. In simple terms: the Manual Rename and Formatted Rename functions permit the user to assign a single destination filename to multiple source files. If the operation is executed, one file is renamed and all the others are deleted.

The attached patch file addresses this problem. If the user attempts this action, an error is shown.

[I could think of no reason why a user would want to rename multiple files to a single name, so I coded it as an Error action, rather than a Warning action].


Colin Clark


diff --git a/src/filedata.c b/src/filedata.c
index c99f3a9..6894e85 100644
--- a/src/filedata.c
+++ b/src/filedata.c
@@ -2156,10 +2156,12 @@ gboolean file_data_sc_update_ci_unspecified_list(GList *fd_list, const gchar *de
  * 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)
 		{
@@ -2369,6 +2371,26 @@ gint file_data_verify_ci(FileData *fd)
 		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);
 
@@ -2377,19 +2399,19 @@ gint file_data_verify_ci(FileData *fd)
 }
 
 
-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;
 		}
 
@@ -2472,6 +2494,12 @@ gchar *file_data_get_error_string(gint error)
 		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);
 }
 
@@ -2498,7 +2526,7 @@ gint file_data_verify_ci_list(GList *list, gchar **desc, gboolean with_sidecars)
 		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;
 
diff --git a/src/filedata.h b/src/filedata.h
index 43edc42..9ae197a 100644
--- a/src/filedata.h
+++ b/src/filedata.h
@@ -123,7 +123,7 @@ gboolean file_data_sc_update_ci_unspecified(FileData *fd, const gchar *dest_path
 
 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);
@@ -133,7 +133,7 @@ void file_data_free_ci_list(GList *fd_list);
 
 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);
diff --git a/src/typedefs.h b/src/typedefs.h
index d5a65c8..b848a1d 100644
--- a/src/typedefs.h
+++ b/src/typedefs.h
@@ -164,6 +164,7 @@ typedef enum {
 	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,
diff --git a/src/utilops.c b/src/utilops.c
index 709dc9e..15f32dd 100644
--- a/src/utilops.c
+++ b/src/utilops.c
@@ -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 @@ static GtkWidget *file_util_dialog_add_list(GtkWidget *box, GList *list, gboolea
 		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 @@ void file_util_perform_ci(UtilityData *ud)
 		}
 }
 
-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 @@ static GdkPixbuf *file_util_get_error_icon(FileData *fd, GtkWidget *widget)
 		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 @@ void file_util_check_ci(UtilityData *ud)
 		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 @@ static void file_util_rename_preview_update(UtilityData *ud)
 			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;
 		}
+	else
+		{
+		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));
 
-	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));
+		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));
+			}
 
-	format = gtk_entry_get_text(GTK_ENTRY(ud->format_entry));
+		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)
-		{
-		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));
+			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);
+			}
 		}
 
-	store = gtk_tree_view_get_model(GTK_TREE_VIEW(ud->listview));
-	n = start_n;
+	/* 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)
 		{
-		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_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 @@ static gchar *file_util_details_get_message(UtilityData *ud, FileData *fd, const
 
 	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)
 		{
------------------------------------------------------------------------------
Site24x7 APM Insight: Get Deep Visibility into Application Performance
APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month
Monitor end-to-end web transactions and take corrective actions now
Troubleshoot faster and improve end-user experience. Signup Now!
http://pubads.g.doubleclick.net/gampad/clk?id=272487151&iu=/4140
_______________________________________________
Geeqie-devel mailing list
Geeqie-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/geeqie-devel

Reply via email to