From 64b3e53dd4f9a9779478831f2449306f4ac927b8 Mon Sep 17 00:00:00 2001 From: Colin Clark Date: Sun, 28 May 2017 19:30:41 +0100 Subject: [PATCH] Fix #477: similarity duplicate search https://github.com/BestImageViewer/geeqie/issues/477 Additional find dupes option: sort groups with the lowest number of matches to the top of the results list --- .../GuideImageSearchFindingDuplicates.xml | 10 ++++- src/dupe.c | 45 +++++++++++++++++++ src/options.c | 1 + src/options.h | 1 + src/rcfile.c | 2 + 5 files changed, 58 insertions(+), 1 deletion(-) diff --git a/doc/docbook/GuideImageSearchFindingDuplicates.xml b/doc/docbook/GuideImageSearchFindingDuplicates.xml index b963f334..29606d0f 100644 --- a/doc/docbook/GuideImageSearchFindingDuplicates.xml +++ b/doc/docbook/GuideImageSearchFindingDuplicates.xml @@ -185,6 +185,14 @@ Ignore Rotation When checked, the rotational orientation of images will be ignored. +
+ Sort + + The normal sort order is for groups (in the case of Similarity checks) with the highest number of near-100% matches to be at the top of the list. + + If this box is checked, groups with the lowest number of matches are placed at the top of the list. + +
Compare two file sets Sometimes it is useful to compare one group of files to another, different group of files. Enable this check box to compare two groups of files. When enabled, a second list will appear and files can be added to this list using the same methods for the main list. @@ -202,4 +210,4 @@
- + diff --git a/src/dupe.c b/src/dupe.c index c04e5011..932606e4 100644 --- a/src/dupe.c +++ b/src/dupe.c @@ -1066,6 +1066,20 @@ static void dupe_match_sort_groups(GList *list) } } +static gint dupe_match_totals_sort_cb(gconstpointer a, gconstpointer b) +{ + DupeItem *da = (DupeItem *)a; + DupeItem *db = (DupeItem *)b; + + if (g_list_length(da->group) > g_list_length(db->group)) return -1; + if (g_list_length(da->group) < g_list_length(db->group)) return 1; + + if (da->group_rank < db->group_rank) return -1; + if (da->group_rank > db->group_rank) return 1; + + return 0; +} + static gint dupe_match_rank_sort_cb(gconstpointer a, gconstpointer b) { DupeItem *da = (DupeItem *)a; @@ -1099,6 +1113,15 @@ static GList *dupe_match_rank_sort(GList *source_list) return g_list_sort(list, dupe_match_rank_sort_cb); } +/* returns allocated GList of dupes sorted by totals */ +static GList *dupe_match_totals_sort(GList *source_list) +{ + source_list = g_list_sort(source_list, dupe_match_totals_sort_cb); + + source_list = g_list_first(source_list); + return g_list_reverse(source_list); +} + static void dupe_match_rank(DupeWindow *dw) { GList *list; @@ -1116,6 +1139,11 @@ static void dupe_match_rank(DupeWindow *dw) if (required_debug_level(2)) dupe_match_print_list(list); list = dupe_match_rank_sort(list); + if (options->sort_totals) + { + list = dupe_match_totals_sort(list); + } + if (required_debug_level(2)) dupe_match_print_list(list); g_list_free(dw->dupes); dw->dupes = list; @@ -2648,6 +2676,15 @@ static void dupe_second_set_toggle_cb(GtkWidget *widget, gpointer data) dupe_window_recompare(dw); } +static void dupe_sort_totals_toggle_cb(GtkWidget *widget, gpointer data) +{ + DupeWindow *dw = data; + + options->sort_totals = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); + dupe_window_recompare(dw); + +} + /* *------------------------------------------------------------------- * match type menu @@ -3331,6 +3368,14 @@ DupeWindow *dupe_window_new() gtk_container_add(GTK_CONTAINER(frame), dw->status_label); gtk_widget_show(dw->status_label); + button = gtk_check_button_new_with_label(_("Sort")); + gtk_widget_set_tooltip_text(GTK_WIDGET(button), "Sort by group totals"); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), options->sort_totals); + g_signal_connect(G_OBJECT(button), "toggled", + G_CALLBACK(dupe_sort_totals_toggle_cb), dw); + gtk_box_pack_start(GTK_BOX(status_box), button, FALSE, FALSE, PREF_PAD_SPACE); + gtk_widget_show(button); + label = gtk_label_new(_("Custom Threshold")); gtk_box_pack_start(GTK_BOX(status_box), label, FALSE, FALSE, PREF_PAD_SPACE); gtk_widget_show(label); diff --git a/src/options.c b/src/options.c index 5477dffc..9a1ff342 100644 --- a/src/options.c +++ b/src/options.c @@ -48,6 +48,7 @@ ConfOptions *init_options(ConfOptions *options) options->dnd_icon_size = 48; options->duplicates_similarity_threshold = 99; options->rot_invariant_sim = TRUE; + options->sort_totals = FALSE; options->file_filter.disable = FALSE; options->file_filter.show_dot_directory = FALSE; diff --git a/src/options.h b/src/options.h index 9fb78f83..f538dedc 100644 --- a/src/options.h +++ b/src/options.h @@ -45,6 +45,7 @@ struct _ConfOptions gboolean duplicates_thumbnails; guint duplicates_select_type; gboolean rot_invariant_sim; + gboolean sort_totals; gint open_recent_list_maxsize; gint dnd_icon_size; diff --git a/src/rcfile.c b/src/rcfile.c index 52aa2b90..cf2f4746 100644 --- a/src/rcfile.c +++ b/src/rcfile.c @@ -322,6 +322,7 @@ static void write_global_attributes(GString *outstr, gint indent) WRITE_NL(); WRITE_UINT(*options, duplicates_select_type); WRITE_NL(); WRITE_BOOL(*options, duplicates_thumbnails); WRITE_NL(); WRITE_BOOL(*options, rot_invariant_sim); + WRITE_NL(); WRITE_BOOL(*options, sort_totals); WRITE_SEPARATOR(); WRITE_NL(); WRITE_BOOL(*options, mousewheel_scrolls); @@ -606,6 +607,7 @@ static gboolean load_global_params(const gchar **attribute_names, const gchar ** if (READ_UINT_CLAMP(*options, duplicates_select_type, 0, DUPE_SELECT_GROUP2)) continue; if (READ_BOOL(*options, duplicates_thumbnails)) continue; if (READ_BOOL(*options, rot_invariant_sim)) continue; + if (READ_BOOL(*options, sort_totals)) continue; if (READ_BOOL(*options, progressive_key_scrolling)) continue; if (READ_UINT_CLAMP(*options, keyboard_scroll_step, 1, 32)) continue; -- 2.20.1