From 010ed5dddef21c17e2ced71d38d7ff6597f4f438 Mon Sep 17 00:00:00 2001 From: Colin Clark Date: Wed, 13 Apr 2016 18:53:12 +0100 Subject: [PATCH] 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. --- src/filedata.c | 38 ++++++++++++++++--- src/filedata.h | 4 +- src/typedefs.h | 1 + src/utilops.c | 101 ++++++++++++++++++++++++++++--------------------- 4 files changed, 94 insertions(+), 50 deletions(-) diff --git a/src/filedata.c b/src/filedata.c index cf24f7ad..9515d2b6 100644 --- a/src/filedata.c +++ b/src/filedata.c @@ -2184,10 +2184,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) { @@ -2397,6 +2399,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); @@ -2405,19 +2427,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; } @@ -2500,6 +2522,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); } @@ -2526,7 +2554,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 9dc70a4b..6512938c 100644 --- a/src/filedata.h +++ b/src/filedata.h @@ -125,7 +125,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); @@ -135,7 +135,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 b9034602..ca34ef6c 100644 --- a/src/typedefs.h +++ b/src/typedefs.h @@ -165,6 +165,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 709dc9ef..15f32dda 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) { -- 2.20.1