Issue #332 Rename function can delete files
authorColin Clark <cclark@mcb.net>
Wed, 13 Apr 2016 17:53:12 +0000 (18:53 +0100)
committerColin Clark <cclark@mcb.net>
Wed, 13 Apr 2016 17:55:26 +0000 (18:55 +0100)
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
src/filedata.h
src/typedefs.h
src/utilops.c

index cf24f7a..9515d2b 100644 (file)
@@ -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;
 
index 9dc70a4..6512938 100644 (file)
@@ -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);
index b903460..ca34ef6 100644 (file)
@@ -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,
index 709dc9e..15f32dd 100644 (file)
@@ -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)
                {