Add file class Archive to the Search page
[geeqie.git] / src / dupe.cc
index d26bd46..57f8ba5 100644 (file)
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-#include <inttypes.h>
-
-#include "main.h"
 #include "dupe.h"
 
+#include <sys/time.h>
+#include <sys/types.h>
+
+#include <cinttypes>
+#include <cmath>
+#include <cstdlib>
+#include <cstring>
+
+#include <gdk/gdk.h>
+#include <gio/gio.h>
+#include <glib-object.h>
+
 #include "cache.h"
 #include "collect-table.h"
+#include "collect.h"
+#include "compat.h"
+#include "debug.h"
 #include "dnd.h"
 #include "filedata.h"
 #include "history-list.h"
 #include "image-load.h"
 #include "img-view.h"
+#include "intl.h"
 #include "layout-image.h"
 #include "layout-util.h"
+#include "layout.h"
+#include "main-defines.h"
 #include "md5-util.h"
 #include "menu.h"
 #include "misc.h"
-#include "pixbuf-util.h"
+#include "options.h"
 #include "print.h"
+#include "similar.h"
 #include "thumb.h"
+#include "typedefs.h"
 #include "ui-fileops.h"
 #include "ui-menu.h"
 #include "ui-misc.h"
 #include "ui-tree-edit.h"
+#include "ui-utildlg.h"
 #include "uri-utils.h"
 #include "utilops.h"
 #include "window.h"
 
-#include <math.h>
-
-
-#define DUPE_DEF_WIDTH 800
-#define DUPE_DEF_HEIGHT 400
+enum {
+       DUPE_DEF_WIDTH = 800,
+       DUPE_DEF_HEIGHT = 400
+};
 #define DUPE_PROGRESS_PULSE_STEP 0.0001
 
 /** column assignment order (simply change them here)
@@ -341,7 +358,7 @@ static void dupe_window_update_progress(DupeWindow *dw, const gchar *status, gdo
                                d = dw->setup_count - dw->setup_n;
                                }
 
-                       rem = (t - d) ? (static_cast<gdouble>(dw->setup_time_count / 1000000) / (t - d)) * d : 0;
+                       rem = (t - d) ? (static_cast<gdouble>(dw->setup_time_count / 1000000.0) / (t - d)) * d : 0;
 
                        gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(dw->extra_label), value);
 
@@ -351,7 +368,8 @@ static void dupe_window_update_progress(DupeWindow *dw, const gchar *status, gdo
 
                        return;
                        }
-               else if (force ||
+
+               if (force ||
                         value == 0.0 ||
                         dw->setup_count == 0 ||
                         dw->setup_time_count == 0 ||
@@ -379,6 +397,7 @@ static void dupe_window_update_progress(DupeWindow *dw, const gchar *status, gdo
 static void widget_set_cursor(GtkWidget *widget, gint icon)
 {
        GdkCursor *cursor;
+       GdkDisplay *display;
 
        if (!gtk_widget_get_window(widget)) return;
 
@@ -388,7 +407,8 @@ static void widget_set_cursor(GtkWidget *widget, gint icon)
                }
        else
                {
-               cursor = gdk_cursor_new(static_cast<GdkCursorType>(icon));
+               display = gdk_display_get_default();
+               cursor = gdk_cursor_new_for_display(display, static_cast<GdkCursorType>(icon));
                }
 
        gdk_window_set_cursor(gtk_widget_get_window(widget), cursor);
@@ -466,73 +486,56 @@ static void dupe_item_free(DupeItem *di)
        g_free(di);
 }
 
-static void dupe_list_free(GList *list)
-{
-       GList *work = list;
-       while (work)
-               {
-               auto di = static_cast<DupeItem *>(work->data);
-               work = work->next;
-               dupe_item_free(di);
-               }
-       g_list_free(list);
-}
-
-/*
-static DupeItem *dupe_item_find_fd_by_list(FileData *fd, GList *work)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-function"
+static DupeItem *dupe_item_find_fd_by_list_unused(FileData *fd, GList *work)
 {
        while (work)
                {
-               DupeItem *di = static_cast<DupeItem *>(work->data);
+               auto *di = static_cast<DupeItem *>(work->data);
 
                if (di->fd == fd) return di;
 
                work = work->next;
                }
 
-       return NULL;
+       return nullptr;
 }
-*/
 
-/*
-static DupeItem *dupe_item_find_fd(DupeWindow *dw, FileData *fd)
+static DupeItem *dupe_item_find_fd_unused(DupeWindow *dw, FileData *fd)
 {
        DupeItem *di;
 
-       di = dupe_item_find_fd_by_list(fd, dw->list);
-       if (!di && dw->second_set) di = dupe_item_find_fd_by_list(fd, dw->second_list);
+       di = dupe_item_find_fd_by_list_unused(fd, dw->list);
+       if (!di && dw->second_set) di = dupe_item_find_fd_by_list_unused(fd, dw->second_list);
 
        return di;
 }
-*/
 
-/*
-static DupeItem *dupe_item_find_path_by_list(const gchar *path, GList *work)
+static DupeItem *dupe_item_find_path_by_list_unused(const gchar *path, GList *work)
 {
        while (work)
                {
-               DupeItem *di = static_cast<DupeItem *>(work->data);
+               auto *di = static_cast<DupeItem *>(work->data);
 
                if (strcmp(di->fd->path, path) == 0) return di;
 
                work = work->next;
                }
 
-       return NULL;
+       return nullptr;
 }
-*/
 
-/*
-static DupeItem *dupe_item_find_path(DupeWindow *dw, const gchar *path)
+static DupeItem *dupe_item_find_path_unused(DupeWindow *dw, const gchar *path)
 {
        DupeItem *di;
 
-       di = dupe_item_find_path_by_list(path, dw->list);
-       if (!di && dw->second_set) di = dupe_item_find_path_by_list(path, dw->second_list);
+       di = dupe_item_find_path_by_list_unused(path, dw->list);
+       if (!di && dw->second_set) di = dupe_item_find_path_by_list_unused(path, dw->second_list);
 
        return di;
 }
-*/
+#pragma GCC diagnostic pop
 
 /*
  * ------------------------------------------------------------------
@@ -702,7 +705,7 @@ static void dupe_listview_add(DupeWindow *dw, DupeItem *parent, DupeItem *child)
                text[DUPE_COLUMN_RANK] = g_strdup_printf("%d%s", rank, (di->second) ? " (2)" : "");
                }
 
-       text[DUPE_COLUMN_THUMB] = ("");
+       text[DUPE_COLUMN_THUMB] = nullptr;
        text[DUPE_COLUMN_NAME] = const_cast<gchar *>(di->fd->name);
        text[DUPE_COLUMN_SIZE] = text_from_size(di->fd->size);
        text[DUPE_COLUMN_DATE] = const_cast<gchar *>(text_from_time(di->fd->date));
@@ -805,7 +808,7 @@ static void dupe_listview_remove(DupeWindow *dw, DupeItem *di)
 }
 
 
-static GList *dupe_listview_get_filelist(DupeWindow *UNUSED(dw), GtkWidget *listview)
+static GList *dupe_listview_get_filelist(DupeWindow *, GtkWidget *listview)
 {
        GtkTreeModel *store;
        GtkTreeIter iter;
@@ -827,7 +830,7 @@ static GList *dupe_listview_get_filelist(DupeWindow *UNUSED(dw), GtkWidget *list
 }
 
 
-static GList *dupe_listview_get_selection(DupeWindow *UNUSED(dw), GtkWidget *listview)
+static GList *dupe_listview_get_selection(DupeWindow *, GtkWidget *listview)
 {
        GtkTreeModel *store;
        GtkTreeSelection *selection;
@@ -852,13 +855,12 @@ static GList *dupe_listview_get_selection(DupeWindow *UNUSED(dw), GtkWidget *lis
                        }
                work = work->next;
                }
-       g_list_foreach(slist, static_cast<GFunc>(tree_path_free_wrapper), nullptr);
-       g_list_free(slist);
+       g_list_free_full(slist, reinterpret_cast<GDestroyNotify>(gtk_tree_path_free));
 
        return g_list_reverse(list);
 }
 
-static gboolean dupe_listview_item_is_selected(DupeWindow *UNUSED(dw), DupeItem *di, GtkWidget *listview)
+static gboolean dupe_listview_item_is_selected(DupeWindow *, DupeItem *di, GtkWidget *listview)
 {
        GtkTreeModel *store;
        GtkTreeSelection *selection;
@@ -880,8 +882,7 @@ static gboolean dupe_listview_item_is_selected(DupeWindow *UNUSED(dw), DupeItem
                if (di_n == di) found = TRUE;
                work = work->next;
                }
-       g_list_foreach(slist, static_cast<GFunc>(tree_path_free_wrapper), nullptr);
-       g_list_free(slist);
+       g_list_free_full(slist, reinterpret_cast<GDestroyNotify>(gtk_tree_path_free));
 
        return found;
 }
@@ -1023,20 +1024,21 @@ static void dupe_match_unlink(DupeItem *a, DupeItem *b)
  */
 static void dupe_match_link_clear(DupeItem *parent, gboolean unlink_children)
 {
-       GList *work;
-
-       work = parent->group;
-       while (work)
+       if (unlink_children)
                {
-               auto dm = static_cast<DupeMatch *>(work->data);
-               work = work->next;
+               GList *work;
 
-               if (unlink_children) dupe_match_unlink_child(parent, dm->di);
+               work = parent->group;
+               while (work)
+                       {
+                       auto dm = static_cast<DupeMatch *>(work->data);
+                       work = work->next;
 
-               g_free(dm);
+                       dupe_match_unlink_child(parent, dm->di);
+                       }
                }
 
-       g_list_free(parent->group);
+       g_list_free_full(parent->group, g_free);
        parent->group = nullptr;
        parent->group_rank = 0.0;
 }
@@ -1525,15 +1527,10 @@ static gboolean dupe_match(DupeItem *a, DupeItem *b, DupeMatchType mask, gdouble
                                {
                                return TRUE;
                                }
-                       else
-                               {
-                               return FALSE;
-                               }
-                       }
-               else
-                       {
+
                        return FALSE;
                        }
+               return FALSE;
                }
        if (mask & DUPE_MATCH_NAME_CI_CONTENT)
                {
@@ -1547,15 +1544,11 @@ static gboolean dupe_match(DupeItem *a, DupeItem *b, DupeMatchType mask, gdouble
                                {
                                return TRUE;
                                }
-                       else
-                               {
-                               return FALSE;
-                               }
-                       }
-               else
-                       {
+
                        return FALSE;
                        }
+               return FALSE;
+               
                }
        if (mask & DUPE_MATCH_SIZE)
                {
@@ -1833,10 +1826,8 @@ static gint dupe_match_sort_cb(gconstpointer a, gconstpointer b, gpointer data)
                    {
                        return -1;
                        }
-               else
-                       {
-                       return strcmp(di1->md5sum, di2->md5sum);
-                       }
+
+               return strcmp(di1->md5sum, di2->md5sum);
                }
        if (mask & DUPE_MATCH_DIM)
                {
@@ -2104,7 +2095,7 @@ static void dupe_thumb_do(DupeWindow *dw)
        dupe_listview_set_thumb(dw, di, nullptr);
 }
 
-static void dupe_thumb_error_cb(ThumbLoader *UNUSED(tl), gpointer data)
+static void dupe_thumb_error_cb(ThumbLoader *, gpointer data)
 {
        auto dw = static_cast<DupeWindow *>(data);
 
@@ -2112,7 +2103,7 @@ static void dupe_thumb_error_cb(ThumbLoader *UNUSED(tl), gpointer data)
        dupe_thumb_step(dw);
 }
 
-static void dupe_thumb_done_cb(ThumbLoader *UNUSED(tl), gpointer data)
+static void dupe_thumb_done_cb(ThumbLoader *, gpointer data)
 {
        auto dw = static_cast<DupeWindow *>(data);
 
@@ -2242,7 +2233,7 @@ static void dupe_check_stop(DupeWindow *dw)
        dw->img_loader = nullptr;
 }
 
-static void dupe_check_stop_cb(GtkWidget *UNUSED(widget), gpointer data)
+static void dupe_check_stop_cb(GtkWidget *, gpointer data)
 {
        auto dw = static_cast<DupeWindow *>(data);
 
@@ -2424,6 +2415,7 @@ static gboolean dupe_check_cb(gpointer data)
 {
        auto dw = static_cast<DupeWindow *>(data);
        DupeSearchMatch *search_match_list_item;
+       gchar *progress_text;
 
        if (!dw->idle_id)
                {
@@ -2519,7 +2511,11 @@ static gboolean dupe_check_cb(gpointer data)
                        {
                        if( dw->thread_count < dw->queue_count)
                                {
-                               dupe_window_update_progress(dw, _("Comparing..."), 0.0, FALSE);
+                               progress_text = g_strdup_printf("%s %d%s%d", _("Comparing"), dw->thread_count, "/", dw->queue_count);
+
+                               dupe_window_update_progress(dw, progress_text, (gdouble)dw->thread_count / dw->queue_count, TRUE);
+
+                               g_free(progress_text);
 
                                return G_SOURCE_CONTINUE;
                                }
@@ -2733,19 +2729,20 @@ static void dupe_item_remove(DupeWindow *dw, DupeItem *di)
        dupe_window_update_count(dw, FALSE);
 }
 
-/*
-static gboolean dupe_item_remove_by_path(DupeWindow *dw, const gchar *path)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-function"
+static gboolean dupe_item_remove_by_path_unused(DupeWindow *dw, const gchar *path)
 {
        DupeItem *di;
 
-       di = dupe_item_find_path(dw, path);
+       di = dupe_item_find_path_unused(dw, path);
        if (!di) return FALSE;
 
        dupe_item_remove(dw, di);
 
        return TRUE;
 }
-*/
+#pragma GCC diagnostic pop
 
 static gboolean dupe_files_add_queue_cb(gpointer data)
 {
@@ -2774,7 +2771,8 @@ static gboolean dupe_files_add_queue_cb(gpointer data)
                        }
                else if (isdir(fd->path))
                        {
-                       GList *f, *d;
+                       GList *f;
+                       GList *d;
                        dw->add_files_queue = g_list_remove(dw->add_files_queue, g_list_first(dw->add_files_queue)->data);
 
                        if (filelist_read(fd, &f, &d))
@@ -2823,17 +2821,15 @@ static gboolean dupe_files_add_queue_cb(gpointer data)
                {
                return TRUE;
                }
-       else
-               {
-               dw->add_files_queue_id = 0;
-               dupe_destroy_list_cache(dw);
-               g_idle_add(dupe_check_start_cb, dw);
-               gtk_widget_set_sensitive(dw->controls_box, TRUE);
-               return FALSE;
-               }
+
+       dw->add_files_queue_id = 0;
+       dupe_destroy_list_cache(dw);
+       g_idle_add(dupe_check_start_cb, dw);
+       gtk_widget_set_sensitive(dw->controls_box, TRUE);
+       return FALSE;
 }
 
-static void dupe_files_add(DupeWindow *dw, CollectionData *UNUSED(collection), CollectInfo *info,
+static void dupe_files_add(DupeWindow *dw, CollectionData *, CollectInfo *info,
                           FileData *fd, gboolean recurse)
 {
        DupeItem *di = nullptr;
@@ -2850,7 +2846,8 @@ static void dupe_files_add(DupeWindow *dw, CollectionData *UNUSED(collection), C
                        }
                else if (isdir(fd->path) && recurse)
                        {
-                       GList *f, *d;
+                       GList *f;
+                       GList *d;
                        if (filelist_read(fd, &f, &d))
                                {
                                GList *work;
@@ -2891,10 +2888,8 @@ static void dupe_files_add(DupeWindow *dw, CollectionData *UNUSED(collection), C
                        {
                        return;
                        }
-               else
-                       {
-                       work = work->next;
-                       }
+
+               work = work->next;
                }
 
        if (dw->second_list)
@@ -2907,10 +2902,8 @@ static void dupe_files_add(DupeWindow *dw, CollectionData *UNUSED(collection), C
                                {
                                return;
                                }
-                       else
-                               {
-                               work = work->next;
-                               }
+
+                       work = work->next;
                        }
                }
 
@@ -2994,7 +2987,8 @@ void dupe_window_add_files(DupeWindow *dw, GList *list, gboolean recurse)
                work = work->next;
                if (isdir(fd->path) && !recurse)
                        {
-                       GList *f, *d;
+                       GList *f;
+                       GList *d;
 
                        if (filelist_read(fd, &f, &d))
                                {
@@ -3113,14 +3107,14 @@ static GtkWidget *dupe_display_label(GtkWidget *vbox, const gchar *description,
        hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 10);
 
        label = gtk_label_new(description);
-       gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+       gq_gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
        gtk_widget_show(label);
 
        label = gtk_label_new(text);
-       gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+       gq_gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
        gtk_widget_show(label);
 
-       gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+       gq_gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
        gtk_widget_show(hbox);
 
        return label;
@@ -3133,10 +3127,10 @@ static void dupe_display_stats(DupeWindow *dw, DupeItem *di)
 
        if (!di) return;
 
-       gd = file_util_gen_dlg("Image thumbprint debug info", "thumbprint",
+       gd = file_util_gen_dlg(_("Image thumbprint debug info"), "thumbprint",
                               dw->window, TRUE,
                               nullptr, nullptr);
-       generic_dialog_add_button(gd, GTK_STOCK_CLOSE, nullptr, nullptr, TRUE);
+       generic_dialog_add_button(gd, GQ_ICON_CLOSE, _("Close"), nullptr, TRUE);
 
        dupe_display_label(gd->vbox, "name:", di->fd->name);
        buf = text_from_size(di->fd->size);
@@ -3153,7 +3147,8 @@ static void dupe_display_stats(DupeWindow *dw, DupeItem *di)
                {
                GtkWidget *image;
                GdkPixbuf *pixbuf;
-               gint x, y;
+               gint x;
+               gint y;
                guchar *d_pix;
                guchar *dp;
                gint rs;
@@ -3176,7 +3171,7 @@ static void dupe_display_stats(DupeWindow *dw, DupeItem *di)
                        }
 
                image = gtk_image_new_from_pixbuf(pixbuf);
-               gtk_box_pack_start(GTK_BOX(gd->vbox), image, FALSE, FALSE, 0);
+               gq_gtk_box_pack_start(GTK_BOX(gd->vbox), image, FALSE, FALSE, 0);
                gtk_widget_show(image);
 
                g_object_unref(pixbuf);
@@ -3258,8 +3253,7 @@ static void dupe_window_remove_selection(DupeWindow *dw, GtkWidget *listview)
                if (di) list = g_list_prepend(list, di);
                work = work->next;
                }
-       g_list_foreach(slist, static_cast<GFunc>(tree_path_free_wrapper), nullptr);
-       g_list_free(slist);
+       g_list_free_full(slist, reinterpret_cast<GDestroyNotify>(gtk_tree_path_free));
 
        dw->color_frozen = TRUE;
        work = list;
@@ -3311,21 +3305,21 @@ static void dupe_window_append_file_list(DupeWindow *dw, gint on_second)
  *-------------------------------------------------------------------
  */
 
-static void dupe_menu_view_cb(GtkWidget *UNUSED(widget), gpointer data)
+static void dupe_menu_view_cb(GtkWidget *, gpointer data)
 {
        auto dw = static_cast<DupeWindow *>(data);
 
        if (dw->click_item) dupe_menu_view(dw, dw->click_item, dw->listview, FALSE);
 }
 
-static void dupe_menu_viewnew_cb(GtkWidget *UNUSED(widget), gpointer data)
+static void dupe_menu_viewnew_cb(GtkWidget *, gpointer data)
 {
        auto dw = static_cast<DupeWindow *>(data);
 
        if (dw->click_item) dupe_menu_view(dw, dw->click_item, dw->listview, TRUE);
 }
 
-static void dupe_menu_select_all_cb(GtkWidget *UNUSED(widget), gpointer data)
+static void dupe_menu_select_all_cb(GtkWidget *, gpointer data)
 {
        auto dw = static_cast<DupeWindow *>(data);
        GtkTreeSelection *selection;
@@ -3335,7 +3329,7 @@ static void dupe_menu_select_all_cb(GtkWidget *UNUSED(widget), gpointer data)
        gtk_tree_selection_select_all(selection);
 }
 
-static void dupe_menu_select_none_cb(GtkWidget *UNUSED(widget), gpointer data)
+static void dupe_menu_select_none_cb(GtkWidget *, gpointer data)
 {
        auto dw = static_cast<DupeWindow *>(data);
        GtkTreeSelection *selection;
@@ -3345,7 +3339,7 @@ static void dupe_menu_select_none_cb(GtkWidget *UNUSED(widget), gpointer data)
        gtk_tree_selection_unselect_all(selection);
 }
 
-static void dupe_menu_select_dupes_set1_cb(GtkWidget *UNUSED(widget), gpointer data)
+static void dupe_menu_select_dupes_set1_cb(GtkWidget *, gpointer data)
 {
        auto dw = static_cast<DupeWindow *>(data);
 
@@ -3353,7 +3347,7 @@ static void dupe_menu_select_dupes_set1_cb(GtkWidget *UNUSED(widget), gpointer d
        dupe_listview_select_dupes(dw, DUPE_SELECT_GROUP1);
 }
 
-static void dupe_menu_select_dupes_set2_cb(GtkWidget *UNUSED(widget), gpointer data)
+static void dupe_menu_select_dupes_set2_cb(GtkWidget *, gpointer data)
 {
        auto dw = static_cast<DupeWindow *>(data);
 
@@ -3372,7 +3366,7 @@ static void dupe_menu_edit_cb(GtkWidget *widget, gpointer data)
        dupe_window_edit_selected(dw, key);
 }
 
-static void dupe_menu_print_cb(GtkWidget *UNUSED(widget), gpointer data)
+static void dupe_menu_print_cb(GtkWidget *, gpointer data)
 {
        auto dw = static_cast<DupeWindow *>(data);
        FileData *fd;
@@ -3384,28 +3378,28 @@ static void dupe_menu_print_cb(GtkWidget *UNUSED(widget), gpointer data)
                         dupe_listview_get_filelist(dw, dw->listview), dw->window);
 }
 
-static void dupe_menu_copy_cb(GtkWidget *UNUSED(widget), gpointer data)
+static void dupe_menu_copy_cb(GtkWidget *, gpointer data)
 {
        auto dw = static_cast<DupeWindow *>(data);
 
        file_util_copy(nullptr, dupe_listview_get_selection(dw, dw->listview), nullptr, dw->window);
 }
 
-static void dupe_menu_move_cb(GtkWidget *UNUSED(widget), gpointer data)
+static void dupe_menu_move_cb(GtkWidget *, gpointer data)
 {
        auto dw = static_cast<DupeWindow *>(data);
 
        file_util_move(nullptr, dupe_listview_get_selection(dw, dw->listview), nullptr, dw->window);
 }
 
-static void dupe_menu_rename_cb(GtkWidget *UNUSED(widget), gpointer data)
+static void dupe_menu_rename_cb(GtkWidget *, gpointer data)
 {
        auto dw = static_cast<DupeWindow *>(data);
 
        file_util_rename(nullptr, dupe_listview_get_selection(dw, dw->listview), dw->window);
 }
 
-static void dupe_menu_delete_cb(GtkWidget *UNUSED(widget), gpointer data)
+static void dupe_menu_delete_cb(GtkWidget *, gpointer data)
 {
        auto dw = static_cast<DupeWindow *>(data);
 
@@ -3413,7 +3407,7 @@ static void dupe_menu_delete_cb(GtkWidget *UNUSED(widget), gpointer data)
        file_util_delete_notify_done(nullptr, dupe_listview_get_selection(dw, dw->listview), dw->window, delete_finished_cb, dw);
 }
 
-static void dupe_menu_move_to_trash_cb(GtkWidget *UNUSED(widget), gpointer data)
+static void dupe_menu_move_to_trash_cb(GtkWidget *, gpointer data)
 {
        auto dw = static_cast<DupeWindow *>(data);
 
@@ -3421,42 +3415,42 @@ static void dupe_menu_move_to_trash_cb(GtkWidget *UNUSED(widget), gpointer data)
        file_util_delete_notify_done(nullptr, dupe_listview_get_selection(dw, dw->listview), dw->window, delete_finished_cb, dw);
 }
 
-static void dupe_menu_copy_path_cb(GtkWidget *UNUSED(widget), gpointer data)
+static void dupe_menu_copy_path_cb(GtkWidget *, gpointer data)
 {
        auto dw = static_cast<DupeWindow *>(data);
 
        file_util_copy_path_list_to_clipboard(dupe_listview_get_selection(dw, dw->listview), TRUE);
 }
 
-static void dupe_menu_copy_path_unquoted_cb(GtkWidget *UNUSED(widget), gpointer data)
+static void dupe_menu_copy_path_unquoted_cb(GtkWidget *, gpointer data)
 {
        auto dw = static_cast<DupeWindow *>(data);
 
        file_util_copy_path_list_to_clipboard(dupe_listview_get_selection(dw, dw->listview), FALSE);
 }
 
-static void dupe_menu_remove_cb(GtkWidget *UNUSED(widget), gpointer data)
+static void dupe_menu_remove_cb(GtkWidget *, gpointer data)
 {
        auto dw = static_cast<DupeWindow *>(data);
 
        dupe_window_remove_selection(dw, dw->listview);
 }
 
-static void dupe_menu_clear_cb(GtkWidget *UNUSED(widget), gpointer data)
+static void dupe_menu_clear_cb(GtkWidget *, gpointer data)
 {
        auto dw = static_cast<DupeWindow *>(data);
 
        dupe_window_clear(dw);
 }
 
-static void dupe_menu_close_cb(GtkWidget *UNUSED(widget), gpointer data)
+static void dupe_menu_close_cb(GtkWidget *, gpointer data)
 {
        auto dw = static_cast<DupeWindow *>(data);
 
        dupe_window_close(dw);
 }
 
-static void dupe_menu_popup_destroy_cb(GtkWidget *UNUSED(widget), gpointer data)
+static void dupe_menu_popup_destroy_cb(GtkWidget *, gpointer data)
 {
        auto editmenu_fd_list = static_cast<GList *>(data);
 
@@ -3518,7 +3512,7 @@ static GtkWidget *dupe_menu_popup_main(DupeWindow *dw, DupeItem *di)
 
        menu_item_add_sensitive(menu, _("_View"), on_row,
                                G_CALLBACK(dupe_menu_view_cb), dw);
-       menu_item_add_stock_sensitive(menu, _("View in _new window"), GTK_STOCK_NEW, on_row,
+       menu_item_add_icon_sensitive(menu, _("View in _new window"), GQ_ICON_NEW, on_row,
                                G_CALLBACK(dupe_menu_viewnew_cb), dw);
        menu_item_add_divider(menu);
        menu_item_add_sensitive(menu, _("Select all"), (dw->dupes != nullptr),
@@ -3545,10 +3539,10 @@ static GtkWidget *dupe_menu_popup_main(DupeWindow *dw, DupeItem *di)
                                                                G_CALLBACK(dupe_pop_menu_collections_cb), dw);
        gtk_widget_set_sensitive(item, on_row);
 
-       menu_item_add_stock_sensitive(menu, _("Print..."), GTK_STOCK_PRINT, on_row,
+       menu_item_add_icon_sensitive(menu, _("Print..."), GQ_ICON_PRINT, on_row,
                                G_CALLBACK(dupe_menu_print_cb), dw);
        menu_item_add_divider(menu);
-       menu_item_add_stock_sensitive(menu, _("_Copy..."), GTK_STOCK_COPY, on_row,
+       menu_item_add_icon_sensitive(menu, _("_Copy..."), GQ_ICON_COPY, on_row,
                                G_CALLBACK(dupe_menu_copy_cb), dw);
        menu_item_add_sensitive(menu, _("_Move..."), on_row,
                                G_CALLBACK(dupe_menu_move_cb), dw);
@@ -3560,22 +3554,22 @@ static GtkWidget *dupe_menu_popup_main(DupeWindow *dw, DupeItem *di)
                                G_CALLBACK(dupe_menu_copy_path_unquoted_cb), dw);
 
        menu_item_add_divider(menu);
-       menu_item_add_stock_sensitive(menu,
+       menu_item_add_icon_sensitive(menu,
                                options->file_ops.confirm_move_to_trash ? _("Move to Trash...") :
-                                       _("Move to Trash"), PIXBUF_INLINE_ICON_TRASH, on_row,
+                                       _("Move to Trash"), GQ_ICON_DELETE, on_row,
                                G_CALLBACK(dupe_menu_move_to_trash_cb), dw);
-       menu_item_add_stock_sensitive(menu,
+       menu_item_add_icon_sensitive(menu,
                                options->file_ops.confirm_delete ? _("_Delete...") :
-                                       _("_Delete"), GTK_STOCK_DELETE, on_row,
+                                       _("_Delete"), GQ_ICON_DELETE_SHRED, on_row,
                                G_CALLBACK(dupe_menu_delete_cb), dw);
 
        menu_item_add_divider(menu);
-       menu_item_add_stock_sensitive(menu, _("Rem_ove"), GTK_STOCK_REMOVE, on_row,
+       menu_item_add_icon_sensitive(menu, _("Rem_ove"), GQ_ICON_REMOVE, on_row,
                                G_CALLBACK(dupe_menu_remove_cb), dw);
-       menu_item_add_stock_sensitive(menu, _("C_lear"), GTK_STOCK_CLEAR, (dw->list != nullptr),
+       menu_item_add_icon_sensitive(menu, _("C_lear"), GQ_ICON_CLEAR, (dw->list != nullptr),
                                G_CALLBACK(dupe_menu_clear_cb), dw);
        menu_item_add_divider(menu);
-       menu_item_add_stock(menu, _("Close _window"), GTK_STOCK_CLOSE,
+       menu_item_add_icon(menu, _("Close _window"), GQ_ICON_CLOSE,
                            G_CALLBACK(dupe_menu_close_cb), dw);
 
        return menu;
@@ -3785,7 +3779,7 @@ static void dupe_second_clear(DupeWindow *dw)
        g_list_free(dw->dupes);
        dw->dupes = nullptr;
 
-       dupe_list_free(dw->second_list);
+       g_list_free_full(dw->second_list, reinterpret_cast<GDestroyNotify>(dupe_item_free));
        dw->second_list = nullptr;
 
        dupe_match_reset_list(dw->list);
@@ -3793,21 +3787,21 @@ static void dupe_second_clear(DupeWindow *dw)
        dupe_second_update_status(dw);
 }
 
-static void dupe_second_menu_view_cb(GtkWidget *UNUSED(widget), gpointer data)
+static void dupe_second_menu_view_cb(GtkWidget *, gpointer data)
 {
        auto dw = static_cast<DupeWindow *>(data);
 
        if (dw->click_item) dupe_menu_view(dw, dw->click_item, dw->second_listview, FALSE);
 }
 
-static void dupe_second_menu_viewnew_cb(GtkWidget *UNUSED(widget), gpointer data)
+static void dupe_second_menu_viewnew_cb(GtkWidget *, gpointer data)
 {
        auto dw = static_cast<DupeWindow *>(data);
 
        if (dw->click_item) dupe_menu_view(dw, dw->click_item, dw->second_listview, TRUE);
 }
 
-static void dupe_second_menu_select_all_cb(GtkWidget *UNUSED(widget), gpointer data)
+static void dupe_second_menu_select_all_cb(GtkWidget *, gpointer data)
 {
        GtkTreeSelection *selection;
        auto dw = static_cast<DupeWindow *>(data);
@@ -3816,7 +3810,7 @@ static void dupe_second_menu_select_all_cb(GtkWidget *UNUSED(widget), gpointer d
        gtk_tree_selection_select_all(selection);
 }
 
-static void dupe_second_menu_select_none_cb(GtkWidget *UNUSED(widget), gpointer data)
+static void dupe_second_menu_select_none_cb(GtkWidget *, gpointer data)
 {
        GtkTreeSelection *selection;
        auto dw = static_cast<DupeWindow *>(data);
@@ -3825,14 +3819,14 @@ static void dupe_second_menu_select_none_cb(GtkWidget *UNUSED(widget), gpointer
        gtk_tree_selection_unselect_all(selection);
 }
 
-static void dupe_second_menu_remove_cb(GtkWidget *UNUSED(widget), gpointer data)
+static void dupe_second_menu_remove_cb(GtkWidget *, gpointer data)
 {
        auto dw = static_cast<DupeWindow *>(data);
 
        dupe_window_remove_selection(dw, dw->second_listview);
 }
 
-static void dupe_second_menu_clear_cb(GtkWidget *UNUSED(widget), gpointer data)
+static void dupe_second_menu_clear_cb(GtkWidget *, gpointer data)
 {
        auto dw = static_cast<DupeWindow *>(data);
 
@@ -3856,7 +3850,7 @@ static GtkWidget *dupe_menu_popup_second(DupeWindow *dw, DupeItem *di)
 
        menu_item_add_sensitive(menu, _("_View"), on_row,
                                G_CALLBACK(dupe_second_menu_view_cb), dw);
-       menu_item_add_stock_sensitive(menu, _("View in _new window"), GTK_STOCK_NEW, on_row,
+       menu_item_add_icon_sensitive(menu, _("View in _new window"), GQ_ICON_NEW, on_row,
                                G_CALLBACK(dupe_second_menu_viewnew_cb), dw);
        menu_item_add_divider(menu);
        menu_item_add_sensitive(menu, _("Select all"), notempty,
@@ -3864,12 +3858,12 @@ static GtkWidget *dupe_menu_popup_second(DupeWindow *dw, DupeItem *di)
        menu_item_add_sensitive(menu, _("Select none"), notempty,
                                G_CALLBACK(dupe_second_menu_select_none_cb), dw);
        menu_item_add_divider(menu);
-       menu_item_add_stock_sensitive(menu, _("Rem_ove"), GTK_STOCK_REMOVE, on_row,
+       menu_item_add_icon_sensitive(menu, _("Rem_ove"), GQ_ICON_REMOVE, on_row,
                                      G_CALLBACK(dupe_second_menu_remove_cb), dw);
-       menu_item_add_stock_sensitive(menu, _("C_lear"), GTK_STOCK_CLEAR, notempty,
+       menu_item_add_icon_sensitive(menu, _("C_lear"), GQ_ICON_CLEAR, notempty,
                                   G_CALLBACK(dupe_second_menu_clear_cb), dw);
        menu_item_add_divider(menu);
-       menu_item_add_stock(menu, _("Close _window"), GTK_STOCK_CLOSE,
+       menu_item_add_icon(menu, _("Close _window"), GQ_ICON_CLOSE,
                            G_CALLBACK(dupe_menu_close_cb), dw);
 
        return menu;
@@ -3884,12 +3878,12 @@ static void dupe_second_set_toggle_cb(GtkWidget *widget, gpointer data)
        if (dw->second_set)
                {
                dupe_second_update_status(dw);
-               gtk_table_set_col_spacings(GTK_TABLE(dw->table), PREF_PAD_GAP);
+               gtk_grid_set_column_spacing(GTK_GRID(dw->table), PREF_PAD_GAP);
                gtk_widget_show(dw->second_vbox);
                }
        else
                {
-               gtk_table_set_col_spacings(GTK_TABLE(dw->table), 0);
+               gtk_grid_set_column_spacing(GTK_GRID(dw->table), 0);
                gtk_widget_hide(dw->second_vbox);
                dupe_second_clear(dw);
                }
@@ -3994,7 +3988,9 @@ static void dupe_menu_setup(DupeWindow *dw)
 
 /* this overrides the low default of a GtkCellRenderer from 100 to CELL_HEIGHT_OVERRIDE, something sane for our purposes */
 
-#define CELL_HEIGHT_OVERRIDE 512
+enum {
+       CELL_HEIGHT_OVERRIDE = 512
+};
 
 void cell_renderer_height_override(GtkCellRenderer *renderer)
 {
@@ -4010,9 +4006,9 @@ void cell_renderer_height_override(GtkCellRenderer *renderer)
                }
 }
 
-static GdkColor *dupe_listview_color_shifted(GtkWidget *widget)
+static GdkRGBA *dupe_listview_color_shifted(GtkWidget *widget)
 {
-       static GdkColor color;
+       static GdkRGBA color;
        static GtkWidget *done = nullptr;
 
        if (done != widget)
@@ -4020,7 +4016,8 @@ static GdkColor *dupe_listview_color_shifted(GtkWidget *widget)
                GtkStyle *style;
 
                style = gtk_widget_get_style(widget);
-               memcpy(&color, &style->base[GTK_STATE_NORMAL], sizeof(color));
+               convert_gdkcolor_to_gdkrgba(&style->base[GTK_STATE_NORMAL], &color);
+
                shift_color(&color, -1, 0);
                done = widget;
                }
@@ -4028,7 +4025,7 @@ static GdkColor *dupe_listview_color_shifted(GtkWidget *widget)
        return &color;
 }
 
-static void dupe_listview_color_cb(GtkTreeViewColumn *UNUSED(tree_column), GtkCellRenderer *cell,
+static void dupe_listview_color_cb(GtkTreeViewColumn *, GtkCellRenderer *cell,
                                   GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
 {
        auto dw = static_cast<DupeWindow *>(data);
@@ -4036,7 +4033,7 @@ static void dupe_listview_color_cb(GtkTreeViewColumn *UNUSED(tree_column), GtkCe
 
        gtk_tree_model_get(tree_model, iter, DUPE_COLUMN_COLOR, &set, -1);
        g_object_set(G_OBJECT(cell),
-                    "cell-background-gdk", dupe_listview_color_shifted(dw->listview),
+                    "cell-background-rgba", dupe_listview_color_shifted(dw->listview),
                     "cell-background-set", set, NULL);
 }
 
@@ -4228,8 +4225,7 @@ static gboolean dupe_window_keypress_cb(GtkWidget *widget, GdkEventKey *event, g
                gtk_tree_model_get_iter(store, &iter, tpath);
                gtk_tree_model_get(store, &iter, DUPE_COLUMN_POINTER, &di, -1);
                }
-       g_list_foreach(slist, static_cast<GFunc>(tree_path_free_wrapper), nullptr);
-       g_list_free(slist);
+       g_list_free_full(slist, reinterpret_cast<GDestroyNotify>(gtk_tree_path_free));
 
        if (event->state & GDK_CONTROL_MASK)
                {
@@ -4312,6 +4308,21 @@ static gboolean dupe_window_keypress_cb(GtkWidget *widget, GdkEventKey *event, g
                                }
                        }
                }
+       else if (event->state & GDK_SHIFT_MASK)
+               {
+               stop_signal = TRUE;
+               switch (event->keyval)
+                       {
+                       case GDK_KEY_Delete:
+                       case GDK_KEY_KP_Delete:
+                               options->file_ops.safe_delete_enable = FALSE;
+                               file_util_delete_notify_done(nullptr, dupe_listview_get_selection(dw, dw->listview), dw->window, delete_finished_cb, dw);
+                               break;
+                       default:
+                               stop_signal = FALSE;
+                               break;
+                       }
+               }
        else
                {
                stop_signal = TRUE;
@@ -4389,7 +4400,7 @@ void dupe_window_clear(DupeWindow *dw)
        g_list_free(dw->dupes);
        dw->dupes = nullptr;
 
-       dupe_list_free(dw->list);
+       g_list_free_full(dw->list, reinterpret_cast<GDestroyNotify>(dupe_item_free));
        dw->list = nullptr;
        dw->set_count = 0;
 
@@ -4421,12 +4432,12 @@ void dupe_window_close(DupeWindow *dw)
        dupe_window_get_geometry(dw);
 
        dupe_window_list = g_list_remove(dupe_window_list, dw);
-       gtk_widget_destroy(dw->window);
+       gq_gtk_widget_destroy(dw->window);
 
        g_list_free(dw->dupes);
-       dupe_list_free(dw->list);
+       g_list_free_full(dw->list, reinterpret_cast<GDestroyNotify>(dupe_item_free));
 
-       dupe_list_free(dw->second_list);
+       g_list_free_full(dw->second_list, reinterpret_cast<GDestroyNotify>(dupe_item_free));
 
        file_data_unregister_notify_func(dupe_notify_cb, dw);
 
@@ -4435,7 +4446,7 @@ void dupe_window_close(DupeWindow *dw)
        g_free(dw);
 }
 
-static gint dupe_window_close_cb(GtkWidget *UNUSED(widget), gpointer data)
+static gint dupe_window_close_cb(GtkWidget *, gpointer data)
 {
        auto dw = static_cast<DupeWindow *>(data);
 
@@ -4444,7 +4455,7 @@ static gint dupe_window_close_cb(GtkWidget *UNUSED(widget), gpointer data)
        return TRUE;
 }
 
-static gint dupe_window_delete(GtkWidget *UNUSED(widget), GdkEvent *UNUSED(event), gpointer data)
+static gint dupe_window_delete(GtkWidget *, GdkEvent *, gpointer data)
 {
        auto dw = static_cast<DupeWindow *>(data);
        dupe_window_close(dw);
@@ -4452,12 +4463,12 @@ static gint dupe_window_delete(GtkWidget *UNUSED(widget), GdkEvent *UNUSED(event
        return TRUE;
 }
 
-static void dupe_help_cb(GtkAction *UNUSED(action), gpointer UNUSED(data))
+static void dupe_help_cb(GtkAction *, gpointer)
 {
        help_window_show("GuideImageSearchFindingDuplicates.html");
 }
 
-static gint default_sort_cb(GtkTreeModel *UNUSED(model), GtkTreeIter *UNUSED(a), GtkTreeIter *UNUSED(b), gpointer UNUSED(data))
+static gint default_sort_cb(GtkTreeModel *, GtkTreeIter *, GtkTreeIter *, gpointer)
 {
        return 0;
 }
@@ -4466,7 +4477,8 @@ static gint column_sort_cb(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b,
 {
        auto sortable = static_cast<GtkTreeSortable *>(data);
        gint ret = 0;
-       gchar *rank_str_a, *rank_str_b;
+       gchar *rank_str_a;
+       gchar *rank_str_b;
        gint rank_int_a;
        gint rank_int_b;
        gint group_a;
@@ -4551,7 +4563,7 @@ static gint column_sort_cb(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b,
        return ret;
 }
 
-static void column_clicked_cb(GtkWidget *UNUSED(widget),  gpointer data)
+static void column_clicked_cb(GtkWidget *,  gpointer data)
 {
        auto dw = static_cast<DupeWindow *>(data);
 
@@ -4599,7 +4611,7 @@ DupeWindow *dupe_window_new()
        if (options->duplicates_match == DUPE_MATCH_NAME_CI_CONTENT) dw->match_mask = DUPE_MATCH_NAME_CI_CONTENT;
        if (options->duplicates_match == DUPE_MATCH_ALL) dw->match_mask = DUPE_MATCH_ALL;
 
-       dw->window = window_new(GTK_WINDOW_TOPLEVEL, "dupe", nullptr, nullptr, _("Find duplicates"));
+       dw->window = window_new("dupe", nullptr, nullptr, _("Find duplicates"));
        DEBUG_NAME(dw->window);
 
        geometry.min_width = DEFAULT_MINIMAL_WINDOW_SIZE;
@@ -4612,7 +4624,7 @@ DupeWindow *dupe_window_new()
        if (lw && options->save_window_positions)
                {
                gtk_window_set_default_size(GTK_WINDOW(dw->window), lw->options.dupe_window.w, lw->options.dupe_window.h);
-               gtk_window_move(GTK_WINDOW(dw->window), lw->options.dupe_window.x, lw->options.dupe_window.y);
+               gq_gtk_window_move(GTK_WINDOW(dw->window), lw->options.dupe_window.x, lw->options.dupe_window.y);
                }
        else
                {
@@ -4628,17 +4640,19 @@ DupeWindow *dupe_window_new()
                         G_CALLBACK(dupe_window_keypress_cb), dw);
 
        vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
-       gtk_container_add(GTK_CONTAINER(dw->window), vbox);
+       gq_gtk_container_add(GTK_WIDGET(dw->window), vbox);
        gtk_widget_show(vbox);
 
-       dw->table = gtk_table_new(1, 3, FALSE);
-       gtk_box_pack_start(GTK_BOX(vbox), dw->table, TRUE, TRUE, 0);
+       dw->table = gtk_grid_new();
+       gq_gtk_box_pack_start(GTK_BOX(vbox), dw->table, TRUE, TRUE, 0);
+       gtk_grid_set_row_homogeneous(GTK_GRID(dw->table), TRUE);
+       gtk_grid_set_column_homogeneous(GTK_GRID(dw->table), TRUE);
        gtk_widget_show(dw->table);
 
-       scrolled = gtk_scrolled_window_new(nullptr, nullptr);
-       gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
+       scrolled = gq_gtk_scrolled_window_new(nullptr, nullptr);
+       gq_gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
        gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
-       gtk_table_attach_defaults(GTK_TABLE(dw->table), scrolled, 0, 2, 0, 1);
+       gtk_grid_attach(GTK_GRID(dw->table), scrolled, 0, 0, 2, 1);
        gtk_widget_show(scrolled);
 
        store = gtk_list_store_new(DUPE_COLUMN_COUNT, G_TYPE_POINTER, G_TYPE_STRING, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_INT, G_TYPE_INT);
@@ -4677,25 +4691,25 @@ DupeWindow *dupe_window_new()
        g_signal_connect(gtk_tree_view_get_column(GTK_TREE_VIEW(dw->listview), DUPE_COLUMN_DIMENSIONS - 1), "clicked", (GCallback)column_clicked_cb, dw);
        g_signal_connect(gtk_tree_view_get_column(GTK_TREE_VIEW(dw->listview), DUPE_COLUMN_PATH - 1), "clicked", (GCallback)column_clicked_cb, dw);
 
-       gtk_container_add(GTK_CONTAINER(scrolled), dw->listview);
+       gq_gtk_container_add(GTK_WIDGET(scrolled), dw->listview);
        gtk_widget_show(dw->listview);
 
        dw->second_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
-       gtk_table_attach_defaults(GTK_TABLE(dw->table), dw->second_vbox, 2, 3, 0, 1);
+       gtk_grid_attach(GTK_GRID(dw->table), dw->second_vbox, 2, 0, 3, 1);
        if (dw->second_set)
                {
-               gtk_table_set_col_spacings(GTK_TABLE(dw->table), PREF_PAD_GAP);
+               gtk_grid_set_column_spacing(GTK_GRID(dw->table), PREF_PAD_GAP);
                gtk_widget_show(dw->second_vbox);
                }
        else
                {
-               gtk_table_set_col_spacings(GTK_TABLE(dw->table), 0);
+               gtk_grid_set_column_spacing(GTK_GRID(dw->table), 0);
                }
 
-       scrolled = gtk_scrolled_window_new(nullptr, nullptr);
-       gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
+       scrolled = gq_gtk_scrolled_window_new(nullptr, nullptr);
+       gq_gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
        gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
-       gtk_box_pack_start(GTK_BOX(dw->second_vbox), scrolled, TRUE, TRUE, 0);
+       gq_gtk_box_pack_start(GTK_BOX(dw->second_vbox), scrolled, TRUE, TRUE, 0);
        gtk_widget_show(scrolled);
 
        store = gtk_list_store_new(2, G_TYPE_POINTER, G_TYPE_STRING);
@@ -4709,34 +4723,34 @@ DupeWindow *dupe_window_new()
 
        dupe_listview_add_column(dw, dw->second_listview, 1, _("Compare to:"), FALSE, FALSE);
 
-       gtk_container_add(GTK_CONTAINER(scrolled), dw->second_listview);
+       gq_gtk_container_add(GTK_WIDGET(scrolled), dw->second_listview);
        gtk_widget_show(dw->second_listview);
 
        dw->second_status_label = gtk_label_new("");
-       gtk_box_pack_start(GTK_BOX(dw->second_vbox), dw->second_status_label, FALSE, FALSE, 0);
+       gq_gtk_box_pack_start(GTK_BOX(dw->second_vbox), dw->second_status_label, FALSE, FALSE, 0);
        gtk_widget_show(dw->second_status_label);
 
        pref_line(dw->second_vbox, GTK_ORIENTATION_HORIZONTAL);
 
        status_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
-       gtk_box_pack_start(GTK_BOX(vbox), status_box, FALSE, FALSE, 0);
+       gq_gtk_box_pack_start(GTK_BOX(vbox), status_box, FALSE, FALSE, 0);
        gtk_widget_show(status_box);
 
        frame = gtk_frame_new(nullptr);
        DEBUG_NAME(frame);
-       gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
-       gtk_box_pack_start(GTK_BOX(status_box), frame, TRUE, TRUE, 0);
+       gq_gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
+       gq_gtk_box_pack_start(GTK_BOX(status_box), frame, TRUE, TRUE, 0);
        gtk_widget_show(frame);
 
        dw->status_label = gtk_label_new("");
-       gtk_container_add(GTK_CONTAINER(frame), dw->status_label);
+       gq_gtk_container_add(GTK_WIDGET(frame), dw->status_label);
        gtk_widget_show(dw->status_label);
 
        dw->extra_label = gtk_progress_bar_new();
        gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(dw->extra_label), 0.0);
        gtk_progress_bar_set_text(GTK_PROGRESS_BAR(dw->extra_label), "");
        gtk_progress_bar_set_show_text(GTK_PROGRESS_BAR(dw->extra_label), TRUE);
-       gtk_box_pack_start(GTK_BOX(status_box), dw->extra_label, FALSE, FALSE, PREF_PAD_SPACE);
+       gq_gtk_box_pack_start(GTK_BOX(status_box), dw->extra_label, FALSE, FALSE, PREF_PAD_SPACE);
        gtk_widget_show(dw->extra_label);
 
        controls_box = pref_box_new(vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0);
@@ -4748,73 +4762,73 @@ DupeWindow *dupe_window_new()
        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dw->button_thumbs), dw->show_thumbs);
        g_signal_connect(G_OBJECT(dw->button_thumbs), "toggled",
                         G_CALLBACK(dupe_window_show_thumb_cb), dw);
-       gtk_box_pack_start(GTK_BOX(controls_box), dw->button_thumbs, FALSE, FALSE, PREF_PAD_SPACE);
+       gq_gtk_box_pack_start(GTK_BOX(controls_box), dw->button_thumbs, FALSE, FALSE, PREF_PAD_SPACE);
        gtk_widget_show(dw->button_thumbs);
 
        label = gtk_label_new(_("Compare by:"));
-       gtk_box_pack_start(GTK_BOX(controls_box), label, FALSE, FALSE, PREF_PAD_SPACE);
+       gq_gtk_box_pack_start(GTK_BOX(controls_box), label, FALSE, FALSE, PREF_PAD_SPACE);
        gtk_widget_show(label);
 
        dupe_menu_setup(dw);
-       gtk_box_pack_start(GTK_BOX(controls_box), dw->combo, FALSE, FALSE, 0);
+       gq_gtk_box_pack_start(GTK_BOX(controls_box), dw->combo, FALSE, FALSE, 0);
        gtk_widget_show(dw->combo);
 
        label = gtk_label_new(_("Custom Threshold"));
-       gtk_box_pack_start(GTK_BOX(controls_box), label, FALSE, FALSE, PREF_PAD_SPACE);
+       gq_gtk_box_pack_start(GTK_BOX(controls_box), label, FALSE, FALSE, PREF_PAD_SPACE);
        gtk_widget_show(label);
        dw->custom_threshold = gtk_spin_button_new_with_range(1, 100, 1);
        gtk_widget_set_tooltip_text(GTK_WIDGET(dw->custom_threshold), "Custom similarity threshold\n(Use tab key to set value)");
        gtk_spin_button_set_value(GTK_SPIN_BUTTON(dw->custom_threshold), options->duplicates_similarity_threshold);
        g_signal_connect(G_OBJECT(dw->custom_threshold), "value_changed", G_CALLBACK(dupe_window_custom_threshold_cb), dw);
-       gtk_box_pack_start(GTK_BOX(controls_box), dw->custom_threshold, FALSE, FALSE, PREF_PAD_SPACE);
+       gq_gtk_box_pack_start(GTK_BOX(controls_box), dw->custom_threshold, FALSE, FALSE, PREF_PAD_SPACE);
        gtk_widget_show(dw->custom_threshold);
 
        button = gtk_check_button_new_with_label(_("Sort"));
-       gtk_widget_set_tooltip_text(GTK_WIDGET(button), "Sort by group totals");
+       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(controls_box), button, FALSE, FALSE, PREF_PAD_SPACE);
+       gq_gtk_box_pack_start(GTK_BOX(controls_box), button, FALSE, FALSE, PREF_PAD_SPACE);
        gtk_widget_show(button);
 
        dw->button_rotation_invariant = gtk_check_button_new_with_label(_("Ignore Orientation"));
-       gtk_widget_set_tooltip_text(GTK_WIDGET(dw->button_rotation_invariant), "Ignore image orientation");
+       gtk_widget_set_tooltip_text(GTK_WIDGET(dw->button_rotation_invariant), _("Ignore image orientation"));
        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dw->button_rotation_invariant), options->rot_invariant_sim);
        g_signal_connect(G_OBJECT(dw->button_rotation_invariant), "toggled",
                         G_CALLBACK(dupe_window_rotation_invariant_cb), dw);
-       gtk_box_pack_start(GTK_BOX(controls_box), dw->button_rotation_invariant, FALSE, FALSE, PREF_PAD_SPACE);
+       gq_gtk_box_pack_start(GTK_BOX(controls_box), dw->button_rotation_invariant, FALSE, FALSE, PREF_PAD_SPACE);
        gtk_widget_show(dw->button_rotation_invariant);
 
        button = gtk_check_button_new_with_label(_("Compare two file sets"));
        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), dw->second_set);
        g_signal_connect(G_OBJECT(button), "toggled",
                         G_CALLBACK(dupe_second_set_toggle_cb), dw);
-       gtk_box_pack_start(GTK_BOX(controls_box), button, FALSE, FALSE, PREF_PAD_SPACE);
+       gq_gtk_box_pack_start(GTK_BOX(controls_box), button, FALSE, FALSE, PREF_PAD_SPACE);
        gtk_widget_show(button);
 
        button_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
-       gtk_box_pack_start(GTK_BOX(vbox), button_box, FALSE, FALSE, 0);
+       gq_gtk_box_pack_start(GTK_BOX(vbox), button_box, FALSE, FALSE, 0);
        gtk_widget_show(button_box);
 
-       hbox = gtk_hbutton_box_new();
+       hbox = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL);
        gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
        gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_SPACE);
-       gtk_box_pack_end(GTK_BOX(button_box), hbox, FALSE, FALSE, 0);
+       gq_gtk_box_pack_end(GTK_BOX(button_box), hbox, FALSE, FALSE, 0);
        gtk_widget_show(hbox);
 
-       button = pref_button_new(nullptr, GTK_STOCK_HELP, nullptr, FALSE, G_CALLBACK(dupe_help_cb), nullptr);
+       button = pref_button_new(nullptr, GQ_ICON_HELP, _("Help"), G_CALLBACK(dupe_help_cb), nullptr);
        gtk_widget_set_tooltip_text(GTK_WIDGET(button), "F1");
-       gtk_container_add(GTK_CONTAINER(hbox), button);
+       gq_gtk_container_add(GTK_WIDGET(hbox), button);
        gtk_widget_set_can_default(button, TRUE);
        gtk_widget_show(button);
 
-       button = pref_button_new(nullptr, GTK_STOCK_STOP, nullptr, FALSE, G_CALLBACK(dupe_check_stop_cb), dw);
-       gtk_container_add(GTK_CONTAINER(hbox), button);
+       button = pref_button_new(nullptr, GQ_ICON_STOP, _("Stop"), G_CALLBACK(dupe_check_stop_cb), dw);
+       gq_gtk_container_add(GTK_WIDGET(hbox), button);
        gtk_widget_set_can_default(button, TRUE);
        gtk_widget_show(button);
 
-       button = pref_button_new(nullptr, GTK_STOCK_CLOSE, nullptr, FALSE, G_CALLBACK(dupe_window_close_cb), dw);
+       button = pref_button_new(nullptr, GQ_ICON_CLOSE, _("Close"), G_CALLBACK(dupe_window_close_cb), dw);
        gtk_widget_set_tooltip_text(GTK_WIDGET(button), "Ctrl-W");
-       gtk_container_add(GTK_CONTAINER(hbox), button);
+       gq_gtk_container_add(GTK_WIDGET(hbox), button);
        gtk_widget_set_can_default(button, TRUE);
        gtk_widget_grab_default(button);
        gtk_widget_show(button);
@@ -4862,12 +4876,12 @@ struct CDupeConfirmD {
        GList *list;
 };
 
-static void confirm_dir_list_cancel(GtkWidget *UNUSED(widget), gpointer UNUSED(data))
+static void confirm_dir_list_cancel(GtkWidget *, gpointer)
 {
        /* do nothing */
 }
 
-static void confirm_dir_list_add(GtkWidget *UNUSED(widget), gpointer data)
+static void confirm_dir_list_add(GtkWidget *, gpointer data)
 {
        auto d = static_cast<CDupeConfirmD *>(data);
        GList *work;
@@ -4894,19 +4908,19 @@ static void confirm_dir_list_add(GtkWidget *UNUSED(widget), gpointer data)
                }
 }
 
-static void confirm_dir_list_recurse(GtkWidget *UNUSED(widget), gpointer data)
+static void confirm_dir_list_recurse(GtkWidget *, gpointer data)
 {
        auto d = static_cast<CDupeConfirmD *>(data);
        dupe_window_add_files(d->dw, d->list, TRUE);
 }
 
-static void confirm_dir_list_skip(GtkWidget *UNUSED(widget), gpointer data)
+static void confirm_dir_list_skip(GtkWidget *, gpointer data)
 {
        auto d = static_cast<CDupeConfirmD *>(data);
        dupe_window_add_files(d->dw, d->list, FALSE);
 }
 
-static void confirm_dir_list_destroy(GtkWidget *UNUSED(widget), gpointer data)
+static void confirm_dir_list_destroy(GtkWidget *, gpointer data)
 {
        auto d = static_cast<CDupeConfirmD *>(data);
        filelist_free(d->list);
@@ -4926,13 +4940,13 @@ static GtkWidget *dupe_confirm_dir_list(DupeWindow *dw, GList *list)
        g_signal_connect(G_OBJECT(menu), "destroy",
                         G_CALLBACK(confirm_dir_list_destroy), d);
 
-       menu_item_add_stock(menu, _("Dropped list includes folders."), GTK_STOCK_DND_MULTIPLE, nullptr, nullptr);
+       menu_item_add_stock(menu, _("Dropped list includes folders."), GQ_ICON_DND, nullptr, nullptr);
        menu_item_add_divider(menu);
-       menu_item_add_stock(menu, _("_Add contents"), GTK_STOCK_OK, G_CALLBACK(confirm_dir_list_add), d);
-       menu_item_add_stock(menu, _("Add contents _recursive"), GTK_STOCK_ADD, G_CALLBACK(confirm_dir_list_recurse), d);
-       menu_item_add_stock(menu, _("_Skip folders"), GTK_STOCK_REMOVE, G_CALLBACK(confirm_dir_list_skip), d);
+       menu_item_add_icon(menu, _("_Add contents"), GQ_ICON_OK, G_CALLBACK(confirm_dir_list_add), d);
+       menu_item_add_icon(menu, _("Add contents _recursive"), GQ_ICON_ADD, G_CALLBACK(confirm_dir_list_recurse), d);
+       menu_item_add_icon(menu, _("_Skip folders"), GQ_ICON_REMOVE, G_CALLBACK(confirm_dir_list_skip), d);
        menu_item_add_divider(menu);
-       menu_item_add_stock(menu, _("Cancel"), GTK_STOCK_CANCEL, G_CALLBACK(confirm_dir_list_cancel), d);
+       menu_item_add_icon(menu, _("Cancel"), GQ_ICON_CANCEL, G_CALLBACK(confirm_dir_list_cancel), d);
 
        return menu;
 }
@@ -4955,9 +4969,9 @@ static GtkTargetEntry dupe_drop_types[] = {
 };
 static gint n_dupe_drop_types = 2;
 
-static void dupe_dnd_data_set(GtkWidget *widget, GdkDragContext *UNUSED(context),
+static void dupe_dnd_data_set(GtkWidget *widget, GdkDragContext *,
                              GtkSelectionData *selection_data, guint info,
-                             guint UNUSED(time), gpointer data)
+                             guint, gpointer data)
 {
        auto dw = static_cast<DupeWindow *>(data);
        GList *list;
@@ -4977,9 +4991,9 @@ static void dupe_dnd_data_set(GtkWidget *widget, GdkDragContext *UNUSED(context)
 }
 
 static void dupe_dnd_data_get(GtkWidget *widget, GdkDragContext *context,
-                             gint UNUSED(x), gint UNUSED(y),
+                             gint, gint,
                              GtkSelectionData *selection_data, guint info,
-                             guint UNUSED(time), gpointer data)
+                             guint, gpointer data)
 {
        auto dw = static_cast<DupeWindow *>(data);
        GtkWidget *source;
@@ -4988,7 +5002,7 @@ static void dupe_dnd_data_get(GtkWidget *widget, GdkDragContext *context,
 
        if (dw->add_files_queue_id > 0)
                {
-               warning_dialog(_("Find duplicates"), _("Please wait for the current file selection to be loaded."), GTK_STOCK_DIALOG_INFO, dw->window);
+               warning_dialog(_("Find duplicates"), _("Please wait for the current file selection to be loaded."), GQ_ICON_DIALOG_INFO, dw->window);
 
                return;
                }
@@ -5087,7 +5101,7 @@ static void dupe_dnd_begin(GtkWidget *widget, GdkDragContext *context, gpointer
                }
 }
 
-static void dupe_dnd_end(GtkWidget *UNUSED(widget), GdkDragContext *UNUSED(context), gpointer data)
+static void dupe_dnd_end(GtkWidget *, GdkDragContext *, gpointer data)
 {
        auto dw = static_cast<DupeWindow *>(data);
        dupe_dest_set(dw->listview, TRUE);
@@ -5167,7 +5181,7 @@ static void dupe_notify_cb(FileData *fd, NotifyType type, gpointer data)
  * 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 *UNUSED(dest_path), gpointer data)
+static void delete_finished_cb(gboolean success, const gchar *, gpointer data)
 {
        auto dw = static_cast<DupeWindow *>(data);
 
@@ -5203,7 +5217,7 @@ static void export_duplicates_close(ExportDupesData *edd)
        edd->dialog = nullptr;
 }
 
-static void export_duplicates_data_cancel_cb(FileDialog *UNUSED(fdlg), gpointer data)
+static void export_duplicates_data_cancel_cb(FileDialog *, gpointer data)
 {
        auto edd = static_cast<ExportDupesData *>(data);
 
@@ -5220,7 +5234,6 @@ static void export_duplicates_data_save_cb(FileDialog *fdlg, gpointer data)
        GFileOutputStream *gfstream;
        GFile *out_file;
        GString *output_string;
-       gchar *sep;
        gchar* rank;
        GList *work;
        GtkTreeSelection *selection;
@@ -5245,7 +5258,7 @@ static void export_duplicates_data_save_cb(FileDialog *fdlg, gpointer data)
                return;
                }
 
-       sep = g_strdup((edd->separator == EXPORT_CSV) ?  "," : "\t");
+       const gchar *sep = (edd->separator == EXPORT_CSV) ?  "," : "\t";
        output_string = g_string_new(g_strjoin(sep, _("Match"), _("Group"), _("Similarity"), _("Set"), _("Thumbnail"), _("Name"), _("Size"), _("Date"), _("Width"), _("Height"), _("Path\n"), NULL));
 
        selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(edd->dupewindow->listview));
@@ -5271,7 +5284,7 @@ static void export_duplicates_data_save_cb(FileDialog *fdlg, gpointer data)
                        match_count++;
                        }
                color_old = color_new;
-               output_string = g_string_append(output_string, g_strdup_printf("%d", match_count));
+               g_string_append_printf(output_string, "%d", match_count);
                output_string = g_string_append(output_string, sep);
 
                if ((dupe_match_find_parent(edd->dupewindow, di) == di))
@@ -5292,13 +5305,13 @@ static void export_duplicates_data_save_cb(FileDialog *fdlg, gpointer data)
                        }
                else
                        {
-                       output_string = g_string_append(output_string, g_strdup_printf("%s", rank_split[0]));
+                       output_string = g_string_append(output_string, rank_split[0]);
                        }
                output_string = g_string_append(output_string, sep);
                g_free(rank);
                g_strfreev(rank_split);
 
-               output_string = g_string_append(output_string, g_strdup_printf("%d", (di->second + 1)));
+               g_string_append_printf(output_string, "%d", di->second + 1);
                output_string = g_string_append(output_string, sep);
 
                thumb_cache = cache_find_location(CACHE_TYPE_THUMB, di->fd->path);
@@ -5318,13 +5331,13 @@ static void export_duplicates_data_save_cb(FileDialog *fdlg, gpointer data)
                output_string = g_string_append(output_string, sep);
                g_free(name);
 
-               output_string = g_string_append(output_string, g_strdup_printf("%" PRIu64, di->fd->size));
+               g_string_append_printf(output_string, "%" PRIu64, di->fd->size);
                output_string = g_string_append(output_string, sep);
                output_string = g_string_append(output_string, text_from_time(di->fd->date));
                output_string = g_string_append(output_string, sep);
-               output_string = g_string_append(output_string, g_strdup_printf("%d", (di->width ? di->width : 0)));
+               g_string_append_printf(output_string, "%d", di->width);
                output_string = g_string_append(output_string, sep);
-               output_string = g_string_append(output_string, g_strdup_printf("%d", (di->height ? di->height : 0)));
+               g_string_append_printf(output_string, "%d", di->height);
                output_string = g_string_append(output_string, sep);
                output_string = g_string_append(output_string, di->fd->path);
                output_string = g_string_append_c(output_string, '\n');
@@ -5332,9 +5345,8 @@ static void export_duplicates_data_save_cb(FileDialog *fdlg, gpointer data)
                work = work->next;
                }
 
-       g_output_stream_write(G_OUTPUT_STREAM(gfstream), output_string->str, strlen(output_string->str), nullptr, &error);
+       g_output_stream_write(G_OUTPUT_STREAM(gfstream), output_string->str, output_string->len, nullptr, &error);
 
-       g_free(sep);
        g_string_free(output_string, TRUE);
        g_object_unref(gfstream);
        g_object_unref(out_file);
@@ -5342,14 +5354,13 @@ static void export_duplicates_data_save_cb(FileDialog *fdlg, gpointer data)
        export_duplicates_close(edd);
 }
 
-static void pop_menu_export(GList *UNUSED(selection_list), gpointer dupe_window, gpointer data)
+static void pop_menu_export(GList *, gpointer dupe_window, gpointer data)
 {
        const gint index = GPOINTER_TO_INT(data);
        auto dw = static_cast<DupeWindow *>(dupe_window);
-       const gchar *title = "Export duplicates data";
+       const gchar *title = _("Export duplicates data");
        const gchar *default_path = "/tmp/";
        gchar *file_extension;
-       const gchar *stock_id;
        ExportDupesData *edd;
        const gchar *previous_path;
 
@@ -5370,10 +5381,8 @@ static void pop_menu_export(GList *UNUSED(selection_list), gpointer dupe_window,
                        return;
                }
 
-       stock_id = GTK_STOCK_SAVE;
-
        generic_dialog_add_message(GENERIC_DIALOG(edd->dialog), nullptr, title, nullptr, FALSE);
-       file_dialog_add_button(edd->dialog, stock_id, nullptr, export_duplicates_data_save_cb, TRUE);
+       file_dialog_add_button(edd->dialog, GQ_ICON_SAVE, _("Save"), export_duplicates_data_save_cb, TRUE);
 
        previous_path = history_list_find_last_path_by_key("export_duplicates");
 
@@ -5408,10 +5417,10 @@ static GtkWidget *submenu_add_export(GtkWidget *menu, GtkWidget **menu_item, GCa
        submenu = gtk_menu_new();
        g_object_set_data(G_OBJECT(submenu), "submenu_data", data);
 
-       menu_item_add_stock_sensitive(submenu, _("Export to csv"),
-                                       GTK_STOCK_INDEX, TRUE, G_CALLBACK(func), GINT_TO_POINTER(0));
-       menu_item_add_stock_sensitive(submenu, _("Export to tab-delimited"),
-                                       GTK_STOCK_INDEX, TRUE, G_CALLBACK(func), GINT_TO_POINTER(1));
+       menu_item_add_icon_sensitive(submenu, _("Export to csv"),
+                                       GQ_ICON_EXPORT, TRUE, G_CALLBACK(func), GINT_TO_POINTER(0));
+       menu_item_add_icon_sensitive(submenu, _("Export to tab-delimited"),
+                                       GQ_ICON_EXPORT, TRUE, G_CALLBACK(func), GINT_TO_POINTER(1));
 
        gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
        if (menu_item) *menu_item = item;