Sort headers using clang-tidy
[geeqie.git] / src / view-dir.cc
index 9419d22..43eb793 100644 (file)
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-#include "main.h"
 #include "view-dir.h"
 
+#include <config.h>
+
+#include "compat.h"
+#include "debug.h"
 #include "dnd.h"
 #include "dupe.h"
 #include "editors.h"
 #include "filedata.h"
+#include "intl.h"
 #include "layout-image.h"
-#include "layout-util.h"
+#include "layout.h"
+#include "main-defines.h"
 #include "menu.h"
 #include "ui-fileops.h"
-#include "ui-tree-edit.h"
 #include "ui-menu.h"
 #include "ui-misc.h"
-#include "utilops.h"
+#include "ui-tree-edit.h"
 #include "uri-utils.h"
+#include "utilops.h"
 #include "view-dir-list.h"
 #include "view-dir-tree.h"
 
-/* Folders icons to be used in tree or list directory view */
-static PixmapFolders *folder_icons_new(GtkWidget *widget)
+namespace
 {
-       auto pf = g_new0(PixmapFolders, 1);
-       GError *error = nullptr;
-       GdkPixbuf *icon;
-       gint scale;
-
-       GtkIconSize size = GTK_ICON_SIZE_MENU;
-
-/** @FIXME Emblems should be attached to icons via e.g.: \n
- * GIcon *.... \n
- * icon = g_themed_icon_new("folder"); \n
- * emblem_icon = g_themed_icon_new("emblem_symbolic_link"); \n
- * emblem = g_emblem_new(emblem_icon); \n
- * emblemed = g_emblemed_icon_new(icon, emblem); \n
- * gtk_icon_info_load_icon(icon_info, NULL) \n
+
+/** @FIXME Emblems should be attached to icons via e.g.:
+ * GIcon *....
+ * icon = g_themed_icon_new("folder");
+ * emblem_icon = g_themed_icon_new("emblem_symbolic_link");
+ * emblem = g_emblem_new(emblem_icon);
+ * emblemed = g_emblemed_icon_new(icon, emblem);
+ * gtk_icon_info_load_icon(icon_info, NULL)
  * But there does not seem to be a way to get GtkIconInfo from a GIcon
  */
-
-       /* Attempt to use stock gtk icons */
-       pf->close  = gtk_widget_render_icon(widget, GTK_STOCK_DIRECTORY, size, nullptr);
-       pf->open   = gtk_widget_render_icon(widget, GTK_STOCK_OPEN, size, nullptr);
-       pf->parent = gtk_widget_render_icon(widget, GTK_STOCK_GO_UP, size, nullptr);
-
-       if (gtk_icon_theme_has_icon(gtk_icon_theme_get_default(), "emblem-unreadable"))
-               {
-               icon = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(), "emblem-unreadable", size, GTK_ICON_LOOKUP_USE_BUILTIN, &error);
-               if (error)
-                       {
-                       log_printf("Error: %s\n", error->message);
-                       g_error_free(error);
-
-                       pf->deny = gdk_pixbuf_copy(gtk_widget_render_icon(widget, GTK_STOCK_STOP, size, nullptr));
-                       }
-               else
-                       {
-                       pf->deny = gdk_pixbuf_copy(gtk_widget_render_icon(widget, GTK_STOCK_DIRECTORY, size, nullptr));
-                       scale = gdk_pixbuf_get_width(icon) / 2;
-                       gdk_pixbuf_composite(icon, pf->deny, scale, scale, scale, scale, scale, scale, 0.5, 0.5, GDK_INTERP_HYPER, 255);
-
-                       }
-               g_object_unref(icon);
-               }
-       else
+GdkPixbuf *create_folder_icon_with_emblem(GtkIconTheme *icon_theme, const gchar *emblem, const gchar *fallback_icon, gint size)
+{
+       if (!gtk_icon_theme_has_icon(icon_theme, emblem))
                {
-               pf->deny = gdk_pixbuf_copy(gtk_widget_render_icon(widget, GTK_STOCK_STOP, size, nullptr));
+               return gq_gtk_icon_theme_load_icon_copy(icon_theme, fallback_icon, size, GTK_ICON_LOOKUP_USE_BUILTIN);
                }
 
-       if (gtk_icon_theme_has_icon(gtk_icon_theme_get_default(), "emblem-symbolic-link"))
+       GError *error = nullptr;
+       GdkPixbuf *icon = gtk_icon_theme_load_icon(icon_theme, emblem, size, GTK_ICON_LOOKUP_USE_BUILTIN, &error);
+       GdkPixbuf *pixbuf;
+       if (error)
                {
-               icon = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(), "emblem-symbolic-link", size, GTK_ICON_LOOKUP_USE_BUILTIN, &error);
-               if (error)
-                       {
-                       log_printf("Error: %s\n", error->message);
-                       g_error_free(error);
-
-                       pf->link = gdk_pixbuf_copy(gtk_widget_render_icon(widget, GTK_STOCK_REDO, size, nullptr));
-                       }
-               else
-                       {
-                       pf->link = gdk_pixbuf_copy(gtk_widget_render_icon(widget, GTK_STOCK_DIRECTORY, size, nullptr));
-                       scale = gdk_pixbuf_get_width(icon) / 2;
-                       gdk_pixbuf_composite(icon, pf->link, scale, scale, scale, scale, scale, scale, 0.5, 0.5, GDK_INTERP_HYPER, 255);
-                       }
-               g_object_unref(icon);
+               log_printf("Error: %s\n", error->message);
+               g_error_free(error);
+               pixbuf = gq_gtk_icon_theme_load_icon_copy(icon_theme, fallback_icon, size, GTK_ICON_LOOKUP_USE_BUILTIN);
                }
        else
                {
-               pf->link = gdk_pixbuf_copy(gtk_widget_render_icon(widget, GTK_STOCK_REDO, size, nullptr));
+               GdkPixbuf *directory_pixbuf = gtk_icon_theme_load_icon(icon_theme, GQ_ICON_DIRECTORY, size, GTK_ICON_LOOKUP_USE_BUILTIN, nullptr);
+               pixbuf = gdk_pixbuf_copy(directory_pixbuf);
+               g_object_unref(directory_pixbuf);
+               
+               gint scale = gdk_pixbuf_get_width(icon) / 2;
+               gdk_pixbuf_composite(icon, pixbuf, scale, scale, scale, scale, scale, scale, 0.5, 0.5, GDK_INTERP_HYPER, 255);
                }
+       g_object_unref(icon);
+
+       return pixbuf;
+}
 
-       pf->read_only = gdk_pixbuf_copy(gtk_widget_render_icon(widget, GTK_STOCK_DIRECTORY, size, nullptr));
+/* Folders icons to be used in tree or list directory view */
+PixmapFolders *folder_icons_new()
+{
+       auto pf = g_new0(PixmapFolders, 1);
+       GtkIconTheme *icon_theme = gtk_icon_theme_get_default();
 
-       if (gtk_icon_theme_has_icon(gtk_icon_theme_get_default(), "emblem-readonly"))
+       gint size;
+       if (!gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &size, &size))
                {
-               icon = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(), "emblem-readonly", size, GTK_ICON_LOOKUP_USE_BUILTIN, &error);
-               if (error)
-                       {
-                       log_printf("Error: %s\n", error->message);
-                       g_error_free(error);
+               size = 16;
+               }
 
-                       pf->read_only = gdk_pixbuf_copy(gtk_widget_render_icon(widget, GTK_STOCK_DIRECTORY, size, nullptr));
-                       }
-               else
-                       {
-                       gint scale = gdk_pixbuf_get_width(icon) / 2;
-                       gdk_pixbuf_composite(icon, pf->read_only, scale, scale, scale, scale, scale, scale, 0.5, 0.5, GDK_INTERP_HYPER, 255);
+       pf->close  = gq_gtk_icon_theme_load_icon_copy(icon_theme, GQ_ICON_DIRECTORY, size, GTK_ICON_LOOKUP_USE_BUILTIN);
+       pf->open   = gq_gtk_icon_theme_load_icon_copy(icon_theme, GQ_ICON_OPEN, size, GTK_ICON_LOOKUP_USE_BUILTIN);
+       pf->parent = gq_gtk_icon_theme_load_icon_copy(icon_theme, GQ_ICON_GO_UP, size, GTK_ICON_LOOKUP_USE_BUILTIN);
 
-                       }
-               g_object_unref(icon);
-               }
+       pf->deny = create_folder_icon_with_emblem(icon_theme, GQ_ICON_UNREADABLE, GQ_ICON_STOP, size);
+       pf->link = create_folder_icon_with_emblem(icon_theme, GQ_ICON_LINK, GQ_ICON_REDO, size);
+       pf->read_only = create_folder_icon_with_emblem(icon_theme, GQ_ICON_READONLY, GQ_ICON_DIRECTORY, size);
 
        return pf;
 }
 
-static void folder_icons_free(PixmapFolders *pf)
+void folder_icons_free(PixmapFolders *pf)
 {
        if (!pf) return;
 
@@ -147,7 +121,7 @@ static void folder_icons_free(PixmapFolders *pf)
        g_free(pf);
 }
 
-
+}
 
 static void vd_notify_cb(FileData *fd, NotifyType type, gpointer data);
 
@@ -161,7 +135,7 @@ static void vd_destroy_cb(GtkWidget *widget, gpointer data)
                {
                g_signal_handlers_disconnect_matched(G_OBJECT(vd->popup), G_SIGNAL_MATCH_DATA,
                                                     0, 0, nullptr, nullptr, vd);
-               gtk_widget_destroy(vd->popup);
+               g_object_unref(vd->popup);
                }
 
        switch (vd->type)
@@ -183,13 +157,13 @@ ViewDir *vd_new(LayoutWindow *lw)
 {
        auto vd = g_new0(ViewDir, 1);
 
-       vd->widget = gtk_scrolled_window_new(nullptr, nullptr);
-       gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(vd->widget), GTK_SHADOW_IN);
+       vd->widget = gq_gtk_scrolled_window_new(nullptr, nullptr);
+       gq_gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(vd->widget), GTK_SHADOW_IN);
        gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(vd->widget),
                                       GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
 
        vd->layout = lw;
-       vd->pf = folder_icons_new(vd->widget);
+       vd->pf = folder_icons_new();
 
        switch (lw->options.dir_view_type)
                {
@@ -229,10 +203,13 @@ void vd_set_select_func(ViewDir *vd,
        vd->select_data = data;
 }
 
-//void vd_set_layout(ViewDir *vd, LayoutWindow *layout)
-//{
-       //vd->layout = layout;
-//}
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-function"
+void vd_set_layout_unused(ViewDir *vd, LayoutWindow *layout)
+{
+       vd->layout = layout;
+}
+#pragma GCC diagnostic pop
 
 gboolean vd_set_fd(ViewDir *vd, FileData *dir_fd)
 {
@@ -260,18 +237,21 @@ void vd_refresh(ViewDir *vd)
        }
 }
 
-//const gchar *vd_row_get_path(ViewDir *vd, gint row)
-//{
-       //const gchar *ret = NULL;
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-function"
+const gchar *vd_row_get_path_unused(ViewDir *vd, gint row)
+{
+       const gchar *ret = nullptr;
 
-       //switch (vd->type)
-       //{
-       //case DIRVIEW_LIST: ret = vdlist_row_get_path(vd, row); break;
-       //case DIRVIEW_TREE: ret = vdtree_row_get_path(vd, row); break;
-       //}
+       switch (vd->type)
+       {
+       case DIRVIEW_LIST: ret = vdlist_row_get_path(vd, row); break;
+       case DIRVIEW_TREE: ret = vdtree_row_get_path(vd, row); break;
+       }
 
-       //return ret;
-//}
+       return ret;
+}
+#pragma GCC diagnostic pop
 
 /* the calling stack is this:
    vd_select_row -> select_func -> layout_set_fd -> vd_set_fd
@@ -339,7 +319,7 @@ static void vd_rename_finished_cb(gboolean success, const gchar *new_path, gpoin
                }
 }
 
-static gboolean vd_rename_cb(TreeEditData *td, const gchar *UNUSED(old_name), const gchar *new_name, gpointer data)
+static gboolean vd_rename_cb(TreeEditData *td, const gchar *, const gchar *new_name, gpointer data)
 {
        auto vd = static_cast<ViewDir *>(data);
        FileData *fd;
@@ -395,7 +375,7 @@ void vd_color_set(ViewDir *vd, FileData *fd, gint color_set)
        }
 }
 
-void vd_popup_destroy_cb(GtkWidget *UNUSED(widget), gpointer data)
+void vd_popup_destroy_cb(GtkWidget *, gpointer data)
 {
        auto vd = static_cast<ViewDir *>(data);
 
@@ -415,7 +395,7 @@ void vd_popup_destroy_cb(GtkWidget *UNUSED(widget), gpointer data)
  *-----------------------------------------------------------------------------
  */
 
-static void vd_drop_menu_copy_cb(GtkWidget *UNUSED(widget), gpointer data)
+static void vd_drop_menu_copy_cb(GtkWidget *, gpointer data)
 {
        auto vd = static_cast<ViewDir *>(data);
        const gchar *path;
@@ -430,7 +410,7 @@ static void vd_drop_menu_copy_cb(GtkWidget *UNUSED(widget), gpointer data)
        file_util_copy_simple(list, path, vd->widget);
 }
 
-static void vd_drop_menu_move_cb(GtkWidget *UNUSED(widget), gpointer data)
+static void vd_drop_menu_move_cb(GtkWidget *, gpointer data)
 {
        auto vd = static_cast<ViewDir *>(data);
        const gchar *path;
@@ -480,7 +460,7 @@ GtkWidget *vd_drop_menu(ViewDir *vd, gint active)
        g_signal_connect(G_OBJECT(menu), "destroy",
                         G_CALLBACK(vd_popup_destroy_cb), vd);
 
-       menu_item_add_stock_sensitive(menu, _("_Copy"), GTK_STOCK_COPY, active,
+       menu_item_add_icon_sensitive(menu, _("_Copy"), GQ_ICON_COPY, active,
                                      G_CALLBACK(vd_drop_menu_copy_cb), vd);
        menu_item_add_sensitive(menu, _("_Move"), active, G_CALLBACK(vd_drop_menu_move_cb), vd);
 
@@ -500,7 +480,7 @@ GtkWidget *vd_drop_menu(ViewDir *vd, gint active)
        g_list_free(editors_list);
 
        menu_item_add_divider(menu);
-       menu_item_add_stock(menu, _("Cancel"), GTK_STOCK_CANCEL, nullptr, vd);
+       menu_item_add_icon(menu, _("Cancel"), GQ_ICON_CANCEL, nullptr, vd);
 
        return menu;
 }
@@ -511,7 +491,7 @@ GtkWidget *vd_drop_menu(ViewDir *vd, gint active)
  *-----------------------------------------------------------------------------
  */
 
-static void vd_pop_menu_up_cb(GtkWidget *UNUSED(widget), gpointer data)
+static void vd_pop_menu_up_cb(GtkWidget *, gpointer data)
 {
        auto vd = static_cast<ViewDir *>(data);
        gchar *path;
@@ -529,7 +509,7 @@ static void vd_pop_menu_up_cb(GtkWidget *UNUSED(widget), gpointer data)
        g_free(path);
 }
 
-static void vd_pop_menu_slide_cb(GtkWidget *UNUSED(widget), gpointer data)
+static void vd_pop_menu_slide_cb(GtkWidget *, gpointer data)
 {
        auto vd = static_cast<ViewDir *>(data);
 
@@ -542,7 +522,7 @@ static void vd_pop_menu_slide_cb(GtkWidget *UNUSED(widget), gpointer data)
        layout_image_slideshow_start(vd->layout);
 }
 
-static void vd_pop_menu_slide_rec_cb(GtkWidget *UNUSED(widget), gpointer data)
+static void vd_pop_menu_slide_rec_cb(GtkWidget *, gpointer data)
 {
        auto vd = static_cast<ViewDir *>(data);
        GList *list;
@@ -550,7 +530,7 @@ static void vd_pop_menu_slide_rec_cb(GtkWidget *UNUSED(widget), gpointer data)
        if (!vd->layout) return;
        if (!vd->click_fd) return;
 
-       list = filelist_recursive_full(vd->click_fd, vd->layout->sort_method, vd->layout->sort_ascend);
+       list = filelist_recursive_full(vd->click_fd, vd->layout->options.file_view_list_sort.method, vd->layout->options.file_view_list_sort.ascend, vd->layout->options.file_view_list_sort.case_sensitive);
 
        layout_image_slideshow_stop(vd->layout);
        layout_image_slideshow_start_from_list(vd->layout, list);
@@ -579,19 +559,19 @@ static void vd_pop_menu_dupe(ViewDir *vd, gint recursive)
        filelist_free(list);
 }
 
-static void vd_pop_menu_dupe_cb(GtkWidget *UNUSED(widget), gpointer data)
+static void vd_pop_menu_dupe_cb(GtkWidget *, gpointer data)
 {
        auto vd = static_cast<ViewDir *>(data);
        vd_pop_menu_dupe(vd, FALSE);
 }
 
-static void vd_pop_menu_dupe_rec_cb(GtkWidget *UNUSED(widget), gpointer data)
+static void vd_pop_menu_dupe_rec_cb(GtkWidget *, gpointer data)
 {
        auto vd = static_cast<ViewDir *>(data);
        vd_pop_menu_dupe(vd, TRUE);
 }
 
-static void vd_pop_menu_delete_cb(GtkWidget *UNUSED(widget), gpointer data)
+static void vd_pop_menu_delete_cb(GtkWidget *, gpointer data)
 {
        auto vd = static_cast<ViewDir *>(data);
 
@@ -599,7 +579,7 @@ static void vd_pop_menu_delete_cb(GtkWidget *UNUSED(widget), gpointer data)
        file_util_delete_dir(vd->click_fd, vd->widget);
 }
 
-static void vd_pop_menu_copy_path_cb(GtkWidget *UNUSED(widget), gpointer data)
+static void vd_pop_menu_copy_path_cb(GtkWidget *, gpointer data)
 {
        auto vd = static_cast<ViewDir *>(data);
 
@@ -608,7 +588,7 @@ static void vd_pop_menu_copy_path_cb(GtkWidget *UNUSED(widget), gpointer data)
        file_util_copy_path_to_clipboard(vd->click_fd, TRUE);
 }
 
-static void vd_pop_menu_copy_path_unquoted_cb(GtkWidget *UNUSED(widget), gpointer data)
+static void vd_pop_menu_copy_path_unquoted_cb(GtkWidget *, gpointer data)
 {
        auto vd = static_cast<ViewDir *>(data);
 
@@ -621,18 +601,18 @@ static void vd_pop_submenu_dir_view_as_cb(GtkWidget *widget, gpointer data)
 {
        auto vd = static_cast<ViewDir *>(data);
 
-       auto  new_type = static_cast<DirViewType>(GPOINTER_TO_INT((g_object_get_data(G_OBJECT(widget), "menu_item_radio_data"))));
+       auto new_type = static_cast<DirViewType>(GPOINTER_TO_INT((g_object_get_data(G_OBJECT(widget), "menu_item_radio_data"))));
        layout_views_set(vd->layout, new_type, vd->layout->options.file_view_type);
 }
 
-static void vd_pop_menu_refresh_cb(GtkWidget *UNUSED(widget), gpointer data)
+static void vd_pop_menu_refresh_cb(GtkWidget *, gpointer data)
 {
        auto vd = static_cast<ViewDir *>(data);
 
        if (vd->layout) layout_refresh(vd->layout);
 }
 
-static void vd_toggle_show_hidden_files_cb(GtkWidget *UNUSED(widget), gpointer data)
+static void vd_toggle_show_hidden_files_cb(GtkWidget *, gpointer data)
 {
        auto vd = static_cast<ViewDir *>(data);
 
@@ -675,7 +655,7 @@ static void vd_pop_menu_new_folder_cb(gboolean success, const gchar *new_path, g
        gtk_tree_path_free(tpath);
 }
 
-static void vd_pop_menu_new_cb(GtkWidget *UNUSED(widget), gpointer data)
+static void vd_pop_menu_new_cb(GtkWidget *, gpointer data)
 {
        auto vd = static_cast<ViewDir *>(data);
        FileData *dir_fd = nullptr;
@@ -696,10 +676,10 @@ static void vd_pop_menu_new_cb(GtkWidget *UNUSED(widget), gpointer data)
                        break;
                }
 
-       file_util_create_dir(dir_fd, vd->layout->window, vd_pop_menu_new_folder_cb, vd);
+       file_util_create_dir(dir_fd->path, vd->layout->window, vd_pop_menu_new_folder_cb, vd);
 }
 
-static void vd_pop_menu_rename_cb(GtkWidget *UNUSED(widget), gpointer data)
+static void vd_pop_menu_rename_cb(GtkWidget *, gpointer data)
 {
        auto vd = static_cast<ViewDir *>(data);
 
@@ -716,7 +696,22 @@ static void vd_pop_menu_sort_ascend_cb(GtkWidget *widget, gpointer data)
        if (!vd->layout) return;
 
        ascend = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget));
-       layout_views_set_sort(vd->layout, vd->layout->options.dir_view_list_sort.method, ascend);
+       layout_views_set_sort_dir(vd->layout, vd->layout->options.dir_view_list_sort.method, ascend, vd->layout->options.dir_view_list_sort.case_sensitive);
+
+       if (vd->layout) layout_refresh(vd->layout);
+}
+
+static void vd_pop_menu_sort_case_cb(GtkWidget *widget, gpointer data)
+{
+       auto vd = static_cast<ViewDir *>(data);
+       gboolean case_sensitive;
+
+       if (!vd) return;
+
+       if (!vd->layout) return;
+
+       case_sensitive = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget));
+       layout_views_set_sort_dir(vd->layout, vd->layout->options.dir_view_list_sort.method, vd->layout->options.dir_view_list_sort.ascend, case_sensitive);
 
        if (vd->layout) layout_refresh(vd->layout);
 }
@@ -733,9 +728,9 @@ static void vd_pop_menu_sort_cb(GtkWidget *widget, gpointer data)
 
        type = static_cast<SortType>GPOINTER_TO_INT(data);
 
-       if (type == SORT_NAME || type == SORT_TIME)
+       if (type == SORT_NAME || type == SORT_NUMBER || type == SORT_TIME)
                {
-               layout_views_set_sort(vd->layout, type, vd->layout->options.dir_view_list_sort.ascend);
+               layout_views_set_sort_dir(vd->layout, type, vd->layout->options.dir_view_list_sort.ascend, vd->layout->options.dir_view_list_sort.case_sensitive);
 
                if (vd->layout) layout_refresh(vd->layout);
                }
@@ -783,7 +778,7 @@ GtkWidget *vd_pop_menu(ViewDir *vd, FileData *fd)
        g_signal_connect(G_OBJECT(menu), "destroy",
                         G_CALLBACK(vd_popup_destroy_cb), vd);
 
-       menu_item_add_stock_sensitive(menu, _("_Up to parent"), GTK_STOCK_GO_UP,
+       menu_item_add_icon_sensitive(menu, _("_Up to parent"), GQ_ICON_GO_UP,
                                      (vd->dir_fd && strcmp(vd->dir_fd->path, G_DIR_SEPARATOR_S) != 0),
                                      G_CALLBACK(vd_pop_menu_up_cb), vd);
 
@@ -794,9 +789,9 @@ GtkWidget *vd_pop_menu(ViewDir *vd, FileData *fd)
                                G_CALLBACK(vd_pop_menu_slide_rec_cb), vd);
 
        menu_item_add_divider(menu);
-       menu_item_add_stock_sensitive(menu, _("Find _duplicates..."), GTK_STOCK_FIND, active,
+       menu_item_add_icon_sensitive(menu, _("Find _duplicates..."), GQ_ICON_FIND, active,
                                      G_CALLBACK(vd_pop_menu_dupe_cb), vd);
-       menu_item_add_stock_sensitive(menu, _("Find duplicates recursive..."), GTK_STOCK_FIND, active,
+       menu_item_add_icon_sensitive(menu, _("Find duplicates recursive..."), GQ_ICON_FIND, active,
                                      G_CALLBACK(vd_pop_menu_dupe_rec_cb), vd);
 
        menu_item_add_divider(menu);
@@ -813,7 +808,7 @@ GtkWidget *vd_pop_menu(ViewDir *vd, FileData *fd)
        menu_item_add(menu, _("_Copy path unquoted"),
                      G_CALLBACK(vd_pop_menu_copy_path_unquoted_cb), vd);
 
-       menu_item_add_stock_sensitive(menu, _("_Delete..."), GTK_STOCK_DELETE, rename_delete_active,
+       menu_item_add_icon_sensitive(menu, _("_Delete..."), GQ_ICON_DELETE, rename_delete_active,
                                      G_CALLBACK(vd_pop_menu_delete_cb), vd);
        menu_item_add_divider(menu);
 
@@ -828,6 +823,14 @@ GtkWidget *vd_pop_menu(ViewDir *vd, FileData *fd)
                {
                submenu = submenu_add_dir_sort(nullptr, G_CALLBACK(vd_pop_menu_sort_cb), vd, FALSE, FALSE, TRUE, vd->layout->options.dir_view_list_sort.method);
                menu_item_add_check(submenu, _("Ascending"), vd->layout->options.dir_view_list_sort.ascend, G_CALLBACK(vd_pop_menu_sort_ascend_cb), (vd));
+               menu_item_add_check(submenu, _("Case"), vd->layout->options.dir_view_list_sort.case_sensitive, G_CALLBACK(vd_pop_menu_sort_case_cb), (vd));
+               item = menu_item_add(menu, _("_Sort"), nullptr, nullptr);
+               gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
+               }
+
+       if (vd->type == DIRVIEW_TREE)
+               {
+               submenu = submenu_add_dir_sort(nullptr, G_CALLBACK(vd_pop_menu_sort_cb), vd, FALSE, FALSE, TRUE, vd->layout->options.dir_view_list_sort.method);
                item = menu_item_add(menu, _("_Sort"), nullptr, nullptr);
                gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
                }
@@ -837,7 +840,7 @@ GtkWidget *vd_pop_menu(ViewDir *vd, FileData *fd)
        menu_item_add_check(menu, _("Show _hidden files"), options->file_filter.show_hidden_files,
                            G_CALLBACK(vd_toggle_show_hidden_files_cb), vd);
 
-       menu_item_add_stock(menu, _("Re_fresh"), GTK_STOCK_REFRESH,
+       menu_item_add_icon(menu, _("Re_fresh"), GQ_ICON_REFRESH,
                            G_CALLBACK(vd_pop_menu_refresh_cb), vd);
 
        return menu;
@@ -845,7 +848,7 @@ GtkWidget *vd_pop_menu(ViewDir *vd, FileData *fd)
 
 void vd_new_folder(ViewDir *vd, FileData *dir_fd)
 {
-       file_util_create_dir(dir_fd, vd->layout->window, vd_pop_menu_new_folder_cb, vd);
+       file_util_create_dir(dir_fd->path, vd->layout->window, vd_pop_menu_new_folder_cb, vd);
 }
 
 /*
@@ -874,9 +877,9 @@ static void vd_dest_set(ViewDir *vd, gint enable)
                }
 }
 
-static void vd_dnd_get(GtkWidget *UNUSED(widget), GdkDragContext *UNUSED(context),
+static void vd_dnd_get(GtkWidget *, GdkDragContext *,
                           GtkSelectionData *selection_data, guint info,
-                          guint UNUSED(time), gpointer data)
+                          guint, gpointer data)
 {
        auto vd = static_cast<ViewDir *>(data);
        GList *list;
@@ -894,7 +897,7 @@ static void vd_dnd_get(GtkWidget *UNUSED(widget), GdkDragContext *UNUSED(context
                }
 }
 
-static void vd_dnd_begin(GtkWidget *UNUSED(widget), GdkDragContext *UNUSED(context), gpointer data)
+static void vd_dnd_begin(GtkWidget *, GdkDragContext *, gpointer data)
 {
        auto vd = static_cast<ViewDir *>(data);
 
@@ -902,7 +905,7 @@ static void vd_dnd_begin(GtkWidget *UNUSED(widget), GdkDragContext *UNUSED(conte
        vd_dest_set(vd, FALSE);
 }
 
-static void vd_dnd_end(GtkWidget *UNUSED(widget), GdkDragContext *context, gpointer data)
+static void vd_dnd_end(GtkWidget *, GdkDragContext *context, gpointer data)
 {
        auto vd = static_cast<ViewDir *>(data);
 
@@ -915,10 +918,10 @@ static void vd_dnd_end(GtkWidget *UNUSED(widget), GdkDragContext *context, gpoin
        vd_dest_set(vd, TRUE);
 }
 
-static void vd_dnd_drop_receive(GtkWidget *widget,
-                               GdkDragContext *UNUSED(context), gint x, gint y,
+static void vd_dnd_drop_receive(GtkWidget *widget, GdkDragContext *,
+                               gint x, gint y,
                                GtkSelectionData *selection_data, guint info,
-                               guint UNUSED(time), gpointer data)
+                               guint, gpointer data)
 {
        auto vd = static_cast<ViewDir *>(data);
        GtkTreePath *tpath;
@@ -1044,8 +1047,10 @@ static gboolean vd_auto_scroll_idle_cb(gpointer data)
        if (vd->drop_fd)
                {
                GdkWindow *window;
-               gint x, y;
-               gint w, h;
+               gint x;
+               gint y;
+               gint w;
+               gint h;
 
                window = gtk_widget_get_window(vd->view);
                seat = gdk_display_get_default_seat(gdk_window_get_display(window));
@@ -1064,7 +1069,7 @@ static gboolean vd_auto_scroll_idle_cb(gpointer data)
        return G_SOURCE_REMOVE;
 }
 
-static gboolean vd_auto_scroll_notify_cb(GtkWidget *UNUSED(widget), gint UNUSED(x), gint UNUSED(y), gpointer data)
+static gboolean vd_auto_scroll_notify_cb(GtkWidget *, gint, gint, gpointer data)
 {
        auto vd = static_cast<ViewDir *>(data);
 
@@ -1075,8 +1080,7 @@ static gboolean vd_auto_scroll_notify_cb(GtkWidget *UNUSED(widget), gint UNUSED(
        return TRUE;
 }
 
-static gboolean vd_dnd_drop_motion(GtkWidget *UNUSED(widget), GdkDragContext *context,
-                                  gint x, gint y, guint time, gpointer data)
+static gboolean vd_dnd_drop_motion(GtkWidget *, GdkDragContext *context, gint x, gint y, guint time, gpointer data)
 {
        auto vd = static_cast<ViewDir *>(data);
 
@@ -1088,23 +1092,21 @@ static gboolean vd_dnd_drop_motion(GtkWidget *UNUSED(widget), GdkDragContext *co
                gdk_drag_status(context, GDK_ACTION_DEFAULT, time);
                return TRUE;
                }
-       else
-               {
-               gdk_drag_status(context, gdk_drag_context_get_suggested_action(context), time);
-               }
+
+       gdk_drag_status(context, gdk_drag_context_get_suggested_action(context), time);
 
        vd_dnd_drop_update(vd, x, y);
 
        if (vd->drop_fd)
                {
-               GtkAdjustment *adj = gtk_tree_view_get_vadjustment(GTK_TREE_VIEW(vd->view));
+               GtkAdjustment *adj = gtk_scrollable_get_vadjustment(GTK_SCROLLABLE(vd->view));
                widget_auto_scroll_start(vd->view, adj, -1, -1, vd_auto_scroll_notify_cb, vd);
                }
 
        return FALSE;
 }
 
-static void vd_dnd_drop_leave(GtkWidget *UNUSED(widget), GdkDragContext *UNUSED(context), guint UNUSED(time), gpointer data)
+static void vd_dnd_drop_leave(GtkWidget *, GdkDragContext *, guint, gpointer data)
 {
        auto vd = static_cast<ViewDir *>(data);
 
@@ -1142,24 +1144,28 @@ void vd_dnd_init(ViewDir *vd)
  *----------------------------------------------------------------------------
  */
 
-//void vd_menu_position_cb(GtkMenu *menu, gint *x, gint *y, gboolean *UNUSED(push_in), gpointer data)
-//{
-       //ViewDir *vd = static_cast<//ViewDir *>(data);
-       //GtkTreeModel *store;
-       //GtkTreeIter iter;
-       //GtkTreePath *tpath;
-       //gint cw, ch;
-
-       //if (!vd_find_row(vd, vd->click_fd, &iter)) return;
-       //store = gtk_tree_view_get_model(GTK_TREE_VIEW(vd->view));
-       //tpath = gtk_tree_model_get_path(store, &iter);
-       //tree_view_get_cell_clamped(GTK_TREE_VIEW(vd->view), tpath, 0, TRUE, x, y, &cw, &ch);
-       //gtk_tree_path_free(tpath);
-       //*y += ch;
-       //popup_menu_position_clamp(menu, x, y, 0);
-//}
-
-void vd_activate_cb(GtkTreeView *tview, GtkTreePath *tpath, GtkTreeViewColumn *UNUSED(column), gpointer data)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-function"
+void vd_menu_position_cb_unused(GtkMenu *menu, gint *x, gint *y, gboolean *, gpointer data)
+{
+       auto *vd = static_cast<ViewDir *>(data);
+       GtkTreeModel *store;
+       GtkTreeIter iter;
+       GtkTreePath *tpath;
+       gint cw;
+       gint ch;
+
+       if (!vd_find_row(vd, vd->click_fd, &iter)) return;
+       store = gtk_tree_view_get_model(GTK_TREE_VIEW(vd->view));
+       tpath = gtk_tree_model_get_path(store, &iter);
+       tree_view_get_cell_clamped(GTK_TREE_VIEW(vd->view), tpath, 0, TRUE, x, y, &cw, &ch);
+       gtk_tree_path_free(tpath);
+       *y += ch;
+       popup_menu_position_clamp(menu, x, y, 0);
+}
+#pragma GCC diagnostic pop
+
+void vd_activate_cb(GtkTreeView *tview, GtkTreePath *tpath, GtkTreeViewColumn *, gpointer data)
 {
        auto vd = static_cast<ViewDir *>(data);
        FileData *fd = vd_get_fd_from_tree_path(vd, tview, tpath);
@@ -1167,33 +1173,40 @@ void vd_activate_cb(GtkTreeView *tview, GtkTreePath *tpath, GtkTreeViewColumn *U
        vd_select_row(vd, fd);
 }
 
-static GdkColor *vd_color_shifted(GtkWidget *widget)
+static GdkRGBA *vd_color_shifted(GtkWidget *widget)
 {
-       static GdkColor color;
+       static GdkRGBA color;
+       static GdkRGBA color_style;
        static GtkWidget *done = nullptr;
 
+#ifdef HAVE_GTK4
+/* @FIXME GTK4 no background color */
+#else
        if (done != widget)
                {
-               GtkStyle *style;
+               GtkStyleContext *style_context;
+
+               style_context = gtk_widget_get_style_context(widget);
+               gtk_style_context_get_background_color(style_context, GTK_STATE_FLAG_NORMAL, &color_style);
+
+               memcpy(&color, &color_style, sizeof(color_style));
 
-               style = gtk_widget_get_style(widget);
-               memcpy(&color, &style->base[GTK_STATE_NORMAL], sizeof(color));
                shift_color(&color, -1, 0);
                done = widget;
                }
+#endif
 
        return &color;
 }
 
-void vd_color_cb(GtkTreeViewColumn *UNUSED(tree_column), GtkCellRenderer *cell,
-                GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
+void vd_color_cb(GtkTreeViewColumn *, GtkCellRenderer *cell, GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
 {
        auto vd = static_cast<ViewDir *>(data);
        gboolean set;
 
        gtk_tree_model_get(tree_model, iter, DIR_COLUMN_COLOR, &set, -1);
        g_object_set(G_OBJECT(cell),
-                    "cell-background-gdk", vd_color_shifted(vd->view),
+                    "cell-background-rgba", vd_color_shifted(vd->view),
                     "cell-background-set", set, NULL);
 }