From f08cdc035951b55335a6088f805f2068fffb8446 Mon Sep 17 00:00:00 2001 From: Colin Clark Date: Sun, 23 May 2021 10:00:14 +0100 Subject: [PATCH] Fix #777: Slow deduplication https://github.com/BestImageViewer/geeqie/issues/777 Use FileUtilDoneFunc to update the UI once, when the entire delete operation has completed. --- src/dupe.c | 30 +++++++++++++++++++++++++++--- src/utilops.c | 12 +++++++++--- src/utilops.h | 1 + 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/src/dupe.c b/src/dupe.c index 4002d50c..d1c73ab6 100644 --- a/src/dupe.c +++ b/src/dupe.c @@ -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 diff --git a/src/utilops.c b/src/utilops.c index e65430ca..222c95bd 100644 --- a/src/utilops.c +++ b/src/utilops.c @@ -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) diff --git a/src/utilops.h b/src/utilops.h index 43a6b2a6..1a5eca4a 100644 --- a/src/utilops.h +++ b/src/utilops.h @@ -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); -- 2.20.1