Fix #777: Slow deduplication
authorColin Clark <colin.clark@cclark.uk>
Sun, 23 May 2021 09:00:14 +0000 (10:00 +0100)
committerColin Clark <colin.clark@cclark.uk>
Sun, 23 May 2021 09:00:14 +0000 (10:00 +0100)
https://github.com/BestImageViewer/geeqie/issues/777

Use FileUtilDoneFunc to update the UI once, when the entire delete
operation has completed.

src/dupe.c
src/utilops.c
src/utilops.h

index 4002d50..d1c73ab 100644 (file)
@@ -128,6 +128,7 @@ static GtkWidget *dupe_menu_popup_second(DupeWindow *dw, DupeItem *di);
 static void dupe_dnd_init(DupeWindow *dw);
 
 static void dupe_notify_cb(FileData *fd, NotifyType type, gpointer data);
+static void delete_finished_cb(gboolean success, const gchar *dest_path, gpointer data);
 
 static GtkWidget *submenu_add_export(GtkWidget *menu, GtkWidget **menu_item, GCallback func, gpointer data);
 static void dupe_pop_menu_export_cb(GtkWidget *widget, gpointer data);
@@ -3361,7 +3362,7 @@ static void dupe_menu_delete_cb(GtkWidget *widget, gpointer data)
        DupeWindow *dw = data;
 
        options->file_ops.safe_delete_enable = FALSE;
-       file_util_delete(NULL, dupe_listview_get_selection(dw, dw->listview), dw->window);
+       file_util_delete_notify_done(NULL, dupe_listview_get_selection(dw, dw->listview), dw->window, delete_finished_cb, dw);
 }
 
 static void dupe_menu_move_to_trash_cb(GtkWidget *widget, gpointer data)
@@ -3369,7 +3370,7 @@ static void dupe_menu_move_to_trash_cb(GtkWidget *widget, gpointer data)
        DupeWindow *dw = data;
 
        options->file_ops.safe_delete_enable = TRUE;
-       file_util_delete(NULL, dupe_listview_get_selection(dw, dw->listview), dw->window);
+       file_util_delete_notify_done(NULL, dupe_listview_get_selection(dw, dw->listview), dw->window, delete_finished_cb, dw);
 }
 
 static void dupe_menu_copy_path_cb(GtkWidget *widget, gpointer data)
@@ -5113,7 +5114,7 @@ static void dupe_notify_cb(FileData *fd, NotifyType type, gpointer data)
                case FILEDATA_CHANGE_COPY:
                        break;
                case FILEDATA_CHANGE_DELETE:
-                       while (dupe_item_remove_by_path(dw, fd->path));
+                       /* Update the UI only once, after the operation finishes */
                        break;
                case FILEDATA_CHANGE_UNSPECIFIED:
                case FILEDATA_CHANGE_WRITE_METADATA:
@@ -5122,6 +5123,29 @@ static void dupe_notify_cb(FileData *fd, NotifyType type, gpointer data)
 
 }
 
+/**
+ * @brief Refresh window after a file delete operation
+ * @param success (ud->phase != UTILITY_PHASE_CANCEL) #file_util_dialog_run
+ * @param dest_path Not used
+ * @param data #DupeWindow
+ * 
+ * If the window is refreshed after each file of a large set is deleted,
+ * the UI slows to an unacceptable level. The #FileUtilDoneFunc is used
+ * to call this function once, when the entire delete operation is completed.
+ */
+static void delete_finished_cb(gboolean success, const gchar *dest_path, gpointer data)
+{
+       DupeWindow *dw = data;
+       GList *work;
+
+       if (!success)
+               {
+               return;
+               }
+
+       dupe_window_remove_selection(dw, dw->listview);
+}
+
 /*
  *-------------------------------------------------------------------
  * Export duplicates data
index e65430c..222c95b 100644 (file)
@@ -2180,8 +2180,7 @@ static void file_util_mark_ungrouped_files(GList *work)
                }
 }
 
-
-static void file_util_delete_full(FileData *source_fd, GList *flist, GtkWidget *parent, UtilityPhase phase)
+static void file_util_delete_full(FileData *source_fd, GList *flist, GtkWidget *parent, UtilityPhase phase, FileUtilDoneFunc done_func, gpointer done_data)
 {
        UtilityData *ud;
        GList *ungrouped = NULL;
@@ -2216,6 +2215,8 @@ static void file_util_delete_full(FileData *source_fd, GList *flist, GtkWidget *
        ud->flist = flist;
        ud->content_list = NULL;
        ud->parent = parent;
+       ud->done_data = done_data;
+       ud->done_func = done_func;
 
        ud->details_func = file_util_details_dialog;
        if(options->file_ops.safe_delete_enable)
@@ -3032,7 +3033,12 @@ static gboolean file_util_write_metadata_first(UtilityType type, UtilityPhase ph
 
 void file_util_delete(FileData *source_fd, GList *source_list, GtkWidget *parent)
 {
-       file_util_delete_full(source_fd, source_list, parent, options->file_ops.confirm_delete ? UTILITY_PHASE_START : UTILITY_PHASE_ENTERING);
+       file_util_delete_full(source_fd, source_list, parent, options->file_ops.confirm_delete ? UTILITY_PHASE_START : UTILITY_PHASE_ENTERING, NULL, NULL);
+}
+
+void file_util_delete_notify_done(FileData *source_fd, GList *source_list, GtkWidget *parent, FileUtilDoneFunc done_func, gpointer done_data)
+{
+       file_util_delete_full(source_fd, source_list, parent, options->file_ops.confirm_delete ? UTILITY_PHASE_START : UTILITY_PHASE_ENTERING, done_func, done_data);
 }
 
 void file_util_write_metadata(FileData *source_fd, GList *source_list, GtkWidget *parent, gboolean force_dialog, FileUtilDoneFunc done_func, gpointer done_data)
index 43a6b2a..1a5eca4 100644 (file)
@@ -43,6 +43,7 @@ GenericDialog *file_util_warning_dialog(const gchar *heading, const gchar *messa
 /* all functions takes over the filelist and frees it when done */
 
 void file_util_delete(FileData *source_fd, GList *source_list, GtkWidget *parent);
+void file_util_delete_notify_done(FileData *source_fd, GList *source_list, GtkWidget *parent, FileUtilDoneFunc done_func, gpointer done_data);
 void file_util_move(FileData *source_fd, GList *source_list, const gchar *dest_path, GtkWidget *parent);
 void file_util_copy(FileData *source_fd, GList *source_list, const gchar *dest_path, GtkWidget *parent);
 void file_util_rename(FileData *source_fd, GList *source_list, GtkWidget *parent);