Simplify vflist_get_formatted() master
authorArkadiy Illarionov <qarkai@gmail.com>
Wed, 1 May 2024 12:21:57 +0000 (15:21 +0300)
committerColin Clark <colin.clark@cclark.uk>
Wed, 1 May 2024 13:21:40 +0000 (14:21 +0100)
Use GString for result.
Remove redundant with_stars parameter.

30 files changed:
meson.build
plugins/export-jpeg/geeqie-export-jpeg
plugins/image-crop/geeqie-image-crop
plugins/random-image/geeqie-random-image
scripts/untranslated-text.sh
src/collect-table.cc
src/compat.h
src/dupe.cc
src/exif-common.cc
src/filedata.cc
src/filedata.h
src/img-view.cc
src/layout-image.cc
src/layout-util.cc
src/main-defines.h
src/menu.cc
src/pixbuf-util.cc
src/pixbuf-util.h
src/preferences.cc
src/remote.cc
src/renderer-tiles.cc
src/search-and-run.cc
src/search.cc
src/toolbar.cc
src/trash.cc
src/ui-bookmark.cc
src/ui-menu.cc
src/ui-misc.cc
src/view-file/view-file-icon.cc
src/view-file/view-file-list.cc

index 9d0e118..49ea1ba 100644 (file)
@@ -771,6 +771,21 @@ else
     summary({'Temporary Comments' : ['Test runs:', false]}, section : 'Testing', bool_yn : true)
 endif
 
+# Untranslated text checks
+untranslated_text_sh = find_program('untranslated-text.sh', dirs : scriptsdir, required : true)
+if untranslated_text_sh.found()
+        foreach source_file : main_sources + pan_view_sources + view_file_sources
+               if fs.name(source_file).endswith('.cc')
+                       source_file_name = fs.name(source_file)
+                       test('Untranslated Text_ ' + source_file_name, untranslated_text_sh, args : [source_file], timeout : 200)
+               endif
+       endforeach
+
+       summary({'Untranslated Text' : ['Test runs:', true]}, section : 'Testing', bool_yn : true)
+else
+       summary({'Untranslated Text' : ['Test runs:', false]}, section : 'Testing', bool_yn : true)
+endif
+
 # Lua test
 option = get_option('lua')
 if not option.disabled()
index cf83ca5..628aee4 100755 (executable)
@@ -229,5 +229,5 @@ then
                fi
        fi
 
-       geeqie --remote view:"$tmpdir/"
+       geeqie --remote --view="$tmpdir/"
 fi
index 23711dd..33aa6cf 100755 (executable)
@@ -28,7 +28,7 @@ process_raw ()
 
                rm "$tmpdir/$src_filename"
 
-               geeqie --remote view:"$tmpdir/$filename-crop.$extension"
+               geeqie --remote --view="$tmpdir/$filename-crop.$extension"
                res=0
        else
                res=1
@@ -49,7 +49,7 @@ process_plain ()
        then
                zenity --error --title="$title" --text="Cannot process this file format" --width="$width" --window-icon="$window_icon"
        else
-               geeqie --remote view:"$tmpdir/$filename-crop.$extension"
+               geeqie --remote --view="$tmpdir/$filename-crop.$extension"
        fi
 }
 
index 8f221f2..e802c43 100755 (executable)
@@ -13,7 +13,7 @@ collection_list=$(geeqie --remote --get-collection-list)
 
 for collection_name in $collection_list
 do
-       collection_file_list=$(geeqie --remote --get-collection:"$collection_name")
+       collection_file_list=$(geeqie --remote --get-collection="$collection_name")
        for collection_file in $collection_file_list
                do
                list="${list:+${list}}\n${collection_file}"
@@ -21,7 +21,7 @@ do
 done
 
 # get list of images in current folder
-file_list=$(geeqie --remote --get-filelist:)
+file_list=$(geeqie --remote --get-filelist=)
 
 for file_name in $file_list
 do
@@ -61,4 +61,4 @@ then
        display_image=$(printf '%b' "$files_no_spaces" | sort --uniq | shuf -n 1)
 fi
 
-geeqie --remote file:"$display_image"
+geeqie --remote file="$display_image"
index a1587c7..ef6ef93 100755 (executable)
 #!/bin/sh
 
+#**********************************************************************
+# Copyright (C) 2024 - The Geeqie Team
+#
+# Author: Colin Clark
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#**********************************************************************
+
 ## @file
 ## @brief Locate strings not marked for translation
 ##
-## Checks all .c files under ./src
+## The check is not comprehensive - the exclusions make this
+## of limited value.
+##
+## @FIXME Strings starting with a space, or a lower-case alpha
+## or if there is more than one string per line, are not
+## checked for.
+##
+## The regex search is for a character sequence: \n
+## double quotes \n
+## upper-case alpha character \n
+## alpha character or space \n
+## printable character \n
+## previous character type repeated one or more times \n
+## double quotes
+##
+## The above sequence preceded by "_(" will not be a hit.
 ##
-## The check is not comprehensive - some errors are not detected
-## and there are some false hits.
+## $1 file to process
 ##
 
-for file in src/*.cc src/view-file/*.cc
+omit_text_array="
+ msg
+#define
+#include
+&lt
+@brief
+@param
+COPYRIGHT
+ColorSpace
+DEBUG
+Damien
+ERR
+EXIF
+Error
+Exif\.
+FIXME
+ImageLoaderType
+LUA_
+MonoSpace
+N_(
+NikonTag
+Pause
+PixbufRenderer
+PluginsMenu
+READ_
+Separator
+WRITE_
+Wrap
+\"Desktop\"
+\"Layout\"
+\"OK\"
+\"Xmp\.
+\.html
+\/\*
+\/\/
+\{\"
+_attribute
+action_group
+courier
+exif_get_item
+filter_add_if_missing
+font_name
+g_ascii_strcasecmp
+g_build_filename
+g_critical
+g_key_file_get_
+g_message
+g_object
+g_signal
+g_str_has_suffix
+g_strstr_len
+g_themed_icon_new
+g_warning
+getenv
+gtk_action_group_get_action
+gtk_container_child_get
+gtk_widget_add_accelerator
+layout_actions
+layout_toolbar_add
+luaL_
+lua_
+memcmp
+mouse_button_
+options->
+osd_template_insert
+pango_attr
+path_to_utf8
+primaries_name
+print_term
+printf
+return g_strdup
+runcmd
+setenv
+signal_
+signals_
+strcmp
+strncmp
+trc_name
+website-label
+write_char_option
+
+##cellrendericon.cc
+\"Background color as a GdkRGBA\"\,
+\"Background color\"\,
+\"Background set\"\,
+\"Draw focus indicator\"\,
+\"Fixed height\"\,
+\"Fixed width\"\,
+\"Focus\"\,
+\"Foreground color as a GdkRGBA\"\,
+\"Foreground color\"\,
+\"Foreground set\"\,
+\"GQvCellRendererIcon\"\,
+\"Height of icon excluding text\"\,
+\"Marks bit array\"\,
+\"Marks\"\,
+\"Number of marks\"\,
+\"Pixbuf Object\"\,
+\"Show marks\"\,
+\"Show text\"\,
+\"Text to render\"\,
+\"Text\"\,
+\"The pixbuf to render\"\,
+\"Toggled mark\"\,
+\"Whether the marks are displayed\"\,
+\"Whether the text is displayed\"\,
+\"Whether this tag affects the background color\"\,
+\"Whether this tag affects the foreground color\"\,
+\"Width of cell\"\,
+
+##pixbuf-renderer.cc
+\"Delay image update\"\,
+\"Display cache size MiB\"\,
+\"Expand image in autozoom.\"\,
+\"Fit window to image size\"\,
+\"Image actively loading\"\,
+\"Image rendering complete\"\,
+\"Limit size of image when autofitting\"\,
+\"Limit size of parent window\"\,
+\"New image scroll reset\"\,
+\"Number of tiles to retain in memory at any one time.\"\,
+\"Size increase limit of image when autofitting\"\,
+\"Size limit of image when autofitting\"\,
+\"Size limit of parent window\"\,
+\"Tile cache count\"\,
+\"Zoom maximum\"\,
+\"Zoom minimum\"\,
+\"Zoom quality\"\,
+
+##print.cc
+G_CALLBACK(print_set_font_cb)\, const_cast<char \*>(\"Image text font\"));
+G_CALLBACK(print_set_font_cb)\, const_cast<char \*>(\"Page text font\"));
+
+##remote.cc
+render_intent = g_strdup(\"Absolute Colorimetric\");
+render_intent = g_strdup(\"Absolute Colorimetric\");
+render_intent = g_strdup(\"Perceptual\");
+render_intent = g_strdup(\"Relative Colorimetric\");
+render_intent = g_strdup(\"Saturation\");
+"
+
+exclude_files_array="
+exif.cc
+format-canon.cc
+format-fuji.cc
+format-nikon.cc
+format-olympus.cc
+keymap-template.cc
+"
+
+filename_printed="no"
+
+omit="FILE_OK"
+while read -r omit_file
 do
-       for search_text in "label" "menu_item_add" "tooltip" "_button" "_text"
+       if [ -n "$omit_file" ]
+       then
+               if echo "$1" | grep --quiet "$omit_file"
+               then
+                       omit="omit"
+               fi
+       fi
+done << EOF
+$exclude_files_array
+EOF
+
+if [ "$omit" = "FILE_OK" ]
+then
+       while read -r infile_line
        do
-               cat -n "$file" | grep --extended-regexp --ignore-case "$search_text.*\(\"" | grep --invert-match "_(" | grep --invert-match "(\"\")" && printf '%s\n\n' "$file"
-       done
-done
+               if [ -n "$infile_line" ]
+               then
+                       omit="LINE_NOT_OK"
+                       while read -r omit_text
+                       do
+                               if [ -n "$omit_text" ]
+                               then
+                                       if echo "$infile_line" | grep --quiet "$omit_text"
+                                       then
+                                               omit="omit"
+                                       fi
+                               fi
+                       done << EOF
+$omit_text_array
+EOF
+                       if [ "$omit" = "LINE_NOT_OK" ]
+                       then
+                               if [ "$filename_printed" = "no" ]
+                               then
+                                       printf "\nfile: %s\n" "$1"
+                                       filename_printed="yes"
+                               fi
+
+                               no_tabs=$(echo "$infile_line" | tr -s '\t')
+                               printf "line: %s\n" "$no_tabs"
+                       fi
+               fi
+       done << EOF
+$(cat --number "$1" | grep --perl-regexp '(?<!_\()"[[:upper:]]([[:lower:]]|[[:space:]])[[:print:]]+"')
+EOF
+fi
+
+if [ "$filename_printed" = "yes" ]
+then
+       exit 1
+else
+       exit 0
+fi
index ee39fb9..41d2c1b 100644 (file)
@@ -2259,7 +2259,7 @@ static GtkWidget *collection_table_drop_menu(CollectTable *ct)
        g_signal_connect(G_OBJECT(menu), "destroy",
                         G_CALLBACK(collection_table_popup_destroy_cb), ct);
 
-       menu_item_add_stock(menu, _("Dropped list includes folders."), GQ_ICON_DND, nullptr, nullptr);
+       menu_item_add_icon(menu, _("Dropped list includes folders."), GQ_ICON_DIRECTORY, nullptr, nullptr);
        menu_item_add_divider(menu);
        menu_item_add_icon(menu, _("_Add contents"), GQ_ICON_OK,
                            G_CALLBACK(confirm_dir_list_add), ct);
index 1147133..477c1e4 100644 (file)
@@ -21,6 +21,7 @@
 #ifndef COMPAT_H
 #define COMPAT_H
 
+#include <glib.h>
 #include <gtk/gtk.h>
 
 #include <config.h>
@@ -44,8 +45,6 @@
        #define gq_gtk_window_move(window, x, y) ;
        #define gq_gtk_window_set_keep_above(window, setting) ;
        #define gq_gtk_window_set_position(window, position) ;
-
-       void gq_gtk_container_add(GtkWidget *container, GtkWidget *widget);
 #else
        #define gq_gtk_box_pack_end(box, child, expand, fill, padding) gtk_box_pack_end(box, child, expand, fill, padding)
        #define gq_gtk_box_pack_start(box, child, expand, fill, padding) gtk_box_pack_start(box, child, expand, fill, padding)
        #define gq_gtk_window_move(window, x, y) gtk_window_move(window, x, y)
        #define gq_gtk_window_set_keep_above(window, setting) gtk_window_set_keep_above(window, setting)
        #define gq_gtk_window_set_position(window, position) gtk_window_set_position(window, position)
-
-       void gq_gtk_container_add(GtkWidget *container, GtkWidget *widget);
 #endif
 
+void gq_gtk_container_add(GtkWidget *container, GtkWidget *widget);
+
+// Hide GtkAction deprecation warnings
+// @todo Remove after porting to GAction/GMenu
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+inline gboolean GQ_GTK_IS_RADIO_ACTION(GtkAction *action) { return GTK_IS_RADIO_ACTION(action); }
+inline gboolean GQ_GTK_IS_TOGGLE_ACTION(GtkAction *action) { return GTK_IS_TOGGLE_ACTION(action); }
+const auto gq_gtk_action_activate = gtk_action_activate;
+const auto gq_gtk_action_create_icon = gtk_action_create_icon;
+const auto gq_gtk_action_get_accel_path = gtk_action_get_accel_path;
+const auto gq_gtk_action_get_icon_name = gtk_action_get_icon_name;
+const auto gq_gtk_action_get_name = gtk_action_get_name;
+const auto gq_gtk_action_get_stock_id = gtk_action_get_stock_id;
+const auto gq_gtk_action_get_tooltip = gtk_action_get_tooltip;
+const auto gq_gtk_action_set_sensitive = gtk_action_set_sensitive;
+const auto gq_gtk_action_set_visible = gtk_action_set_visible;
+const auto gq_gtk_action_group_add_actions = gtk_action_group_add_actions;
+const auto gq_gtk_action_group_add_radio_actions = gtk_action_group_add_radio_actions;
+const auto gq_gtk_action_group_add_toggle_actions = gtk_action_group_add_toggle_actions;
+const auto gq_gtk_action_group_get_action = gtk_action_group_get_action;
+const auto gq_gtk_action_group_list_actions = gtk_action_group_list_actions;
+const auto gq_gtk_action_group_new = gtk_action_group_new;
+const auto gq_gtk_action_group_set_translate_func = gtk_action_group_set_translate_func;
+const auto gq_gtk_radio_action_get_current_value = gtk_radio_action_get_current_value;
+const auto gq_gtk_radio_action_set_current_value = gtk_radio_action_set_current_value;
+const auto gq_gtk_toggle_action_get_active = gtk_toggle_action_get_active;
+const auto gq_gtk_toggle_action_set_active = gtk_toggle_action_set_active;
+const auto gq_gtk_ui_manager_add_ui = gtk_ui_manager_add_ui;
+const auto gq_gtk_ui_manager_add_ui_from_resource = gtk_ui_manager_add_ui_from_resource;
+const auto gq_gtk_ui_manager_add_ui_from_string = gtk_ui_manager_add_ui_from_string;
+const auto gq_gtk_ui_manager_ensure_update = gtk_ui_manager_ensure_update;
+const auto gq_gtk_ui_manager_get_accel_group = gtk_ui_manager_get_accel_group;
+const auto gq_gtk_ui_manager_get_action_groups = gtk_ui_manager_get_action_groups;
+const auto gq_gtk_ui_manager_get_widget = gtk_ui_manager_get_widget;
+const auto gq_gtk_ui_manager_insert_action_group = gtk_ui_manager_insert_action_group;
+const auto gq_gtk_ui_manager_new = gtk_ui_manager_new;
+const auto gq_gtk_ui_manager_new_merge_id = gtk_ui_manager_new_merge_id;
+const auto gq_gtk_ui_manager_remove_action_group = gtk_ui_manager_remove_action_group;
+const auto gq_gtk_ui_manager_remove_ui = gtk_ui_manager_remove_ui;
+const auto gq_gtk_ui_manager_set_add_tearoffs = gtk_ui_manager_set_add_tearoffs;
+G_GNUC_END_IGNORE_DEPRECATIONS
+
 #endif /* COMPAT_H */
 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */
index 68e553f..b63e3a7 100644 (file)
@@ -4737,7 +4737,7 @@ DupeWindow *dupe_window_new()
        dw->controls_box = controls_box;
 
        dw->button_thumbs = gtk_check_button_new_with_label(_("Thumbnails"));
-       gtk_widget_set_tooltip_text(GTK_WIDGET(dw->button_thumbs), "Ctrl-T");
+       gtk_widget_set_tooltip_text(GTK_WIDGET(dw->button_thumbs), _("Ctrl-T"));
        dw->show_thumbs = options->duplicates_thumbnails;
        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dw->button_thumbs), dw->show_thumbs);
        g_signal_connect(G_OBJECT(dw->button_thumbs), "toggled",
@@ -4757,7 +4757,7 @@ DupeWindow *dupe_window_new()
        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_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);
        gq_gtk_box_pack_start(GTK_BOX(controls_box), dw->custom_threshold, FALSE, FALSE, PREF_PAD_SPACE);
@@ -4807,7 +4807,7 @@ DupeWindow *dupe_window_new()
        gtk_widget_show(button);
 
        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_widget_set_tooltip_text(GTK_WIDGET(button), _("Ctrl-W"));
        gq_gtk_container_add(GTK_WIDGET(hbox), button);
        gtk_widget_set_can_default(button, TRUE);
        gtk_widget_grab_default(button);
@@ -4920,7 +4920,7 @@ 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."), GQ_ICON_DND, nullptr, nullptr);
+       menu_item_add_icon(menu, _("Dropped list includes folders."), GQ_ICON_DIRECTORY, nullptr, nullptr);
        menu_item_add_divider(menu);
        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);
index 4dcdc4b..3c53802 100644 (file)
@@ -836,7 +836,7 @@ static gchar *exif_build_formatted_localtime(ExifData *exif)
 /**
  * @brief Gets timezone from GPS lat/long
  * @param[in] exif
- * @returns Timezone string in the form "Europe/London"
+ * @returns Timezone string in the form Europe/London
  *
  *
  */
index 3589331..9bc6613 100644 (file)
@@ -1921,6 +1921,34 @@ GList *file_data_filter_marks_list(GList *list, guint filter)
        return list;
 }
 
+gboolean file_data_mark_to_selection(FileData *fd, gint mark, MarkToSelectionMode mode, gboolean selected)
+{
+       gint n = mark - 1;
+       gboolean mark_val = file_data_get_mark(fd, n);
+
+       switch (mode)
+               {
+               case MTS_MODE_MINUS: return !mark_val && selected;
+               case MTS_MODE_SET: return mark_val;
+               case MTS_MODE_OR: return mark_val || selected;
+               case MTS_MODE_AND: return mark_val && selected;
+               }
+
+       return selected; // arbitrary value, we shouldn't get here
+}
+
+void file_data_selection_to_mark(FileData *fd, gint mark, SelectionToMarkMode mode)
+{
+       gint n = mark - 1;
+
+       switch (mode)
+               {
+               case STM_MODE_RESET: file_data_set_mark(fd, n, FALSE); break;
+               case STM_MODE_SET: file_data_set_mark(fd, n, TRUE); break;
+               case STM_MODE_TOGGLE: file_data_set_mark(fd, n, !file_data_get_mark(fd, n)); break;
+               }
+}
+
 gboolean file_data_filter_file_filter(FileData *fd, GRegex *filter)
 {
        return g_regex_match(filter, fd->name, static_cast<GRegexMatchFlags>(0), nullptr);
index d3af8ed..547a9fb 100644 (file)
@@ -210,6 +210,9 @@ void file_data_set_mark(FileData *fd, gint n, gboolean value);
 gboolean file_data_filter_marks(FileData *fd, guint filter);
 GList *file_data_filter_marks_list(GList *list, guint filter);
 
+gboolean file_data_mark_to_selection(FileData *fd, gint mark, MarkToSelectionMode mode, gboolean selected);
+void file_data_selection_to_mark(FileData *fd, gint mark, SelectionToMarkMode mode);
+
 gboolean file_data_filter_file_filter(FileData *fd, GRegex *filter);
 GList *file_data_filter_file_filter_list(GList *list, GRegex *filter);
 
index e78cbeb..d193c2e 100644 (file)
@@ -1606,7 +1606,7 @@ static GtkWidget *view_confirm_dir_list(ViewWindow *vw, GList *list)
        g_signal_connect(G_OBJECT(menu), "destroy",
                         G_CALLBACK(view_dir_list_destroy), d);
 
-       menu_item_add_stock(menu, _("Dropped list includes folders."), GQ_ICON_DND, nullptr, nullptr);
+       menu_item_add_icon(menu, _("Dropped list includes folders."), GQ_ICON_DIRECTORY, nullptr, nullptr);
        menu_item_add_divider(menu);
        menu_item_add_icon(menu, _("_Add contents"), GQ_ICON_OK, G_CALLBACK(view_dir_list_add), d);
        menu_item_add_icon(menu, _("Add contents _recursive"), GQ_ICON_ADD, G_CALLBACK(view_dir_list_recurse), d);
index 3b413bf..79a74df 100644 (file)
@@ -33,6 +33,7 @@
 
 #include "archives.h"
 #include "collect.h"
+#include "compat.h"
 #include "debug.h"
 #include "dnd.h"
 #include "editors.h"
@@ -504,8 +505,8 @@ void layout_image_animate_toggle(LayoutWindow *lw)
 
        lw->options.animate = !lw->options.animate;
 
-       action = gtk_action_group_get_action(lw->action_group, "Animate");
-       gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->options.animate);
+       action = gq_gtk_action_group_get_action(lw->action_group, "Animate");
+       gq_gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->options.animate);
 
        layout_image_animate_new_file(lw);
 }
index c845c31..ec19abb 100644 (file)
@@ -561,16 +561,16 @@ static void layout_menu_alter_desaturate_cb(GtkToggleAction *action, gpointer da
 {
        auto lw = static_cast<LayoutWindow *>(data);
 
-       layout_image_set_desaturate(lw, gtk_toggle_action_get_active(action));
+       layout_image_set_desaturate(lw, gq_gtk_toggle_action_get_active(action));
 }
 
 static void layout_menu_alter_ignore_alpha_cb(GtkToggleAction *action, gpointer data)
 {
    auto lw = static_cast<LayoutWindow *>(data);
 
-       if (lw->options.ignore_alpha == gtk_toggle_action_get_active(action)) return;
+       if (lw->options.ignore_alpha == gq_gtk_toggle_action_get_active(action)) return;
 
-   layout_image_set_ignore_alpha(lw, gtk_toggle_action_get_active(action));
+   layout_image_set_ignore_alpha(lw, gq_gtk_toggle_action_get_active(action));
 }
 
 static void layout_menu_alter_none_cb(GtkAction *, gpointer data)
@@ -584,27 +584,27 @@ static void layout_menu_exif_rotate_cb(GtkToggleAction *action, gpointer data)
 {
        auto lw = static_cast<LayoutWindow *>(data);
 
-       options->image.exif_rotate_enable = gtk_toggle_action_get_active(action);
+       options->image.exif_rotate_enable = gq_gtk_toggle_action_get_active(action);
        layout_image_reset_orientation(lw);
 }
 
 static void layout_menu_select_rectangle_cb(GtkToggleAction *action, gpointer)
 {
-       options->draw_rectangle = gtk_toggle_action_get_active(action);
+       options->draw_rectangle = gq_gtk_toggle_action_get_active(action);
 }
 
 static void layout_menu_split_pane_sync_cb(GtkToggleAction *action, gpointer data)
 {
        auto lw = static_cast<LayoutWindow *>(data);
 
-       lw->options.split_pane_sync = gtk_toggle_action_get_active(action);
+       lw->options.split_pane_sync = gq_gtk_toggle_action_get_active(action);
 }
 
 static void layout_menu_select_overunderexposed_cb(GtkToggleAction *action, gpointer data)
 {
        auto lw = static_cast<LayoutWindow *>(data);
 
-       layout_image_set_overunderexposed(lw, gtk_toggle_action_get_active(action));
+       layout_image_set_overunderexposed(lw, gq_gtk_toggle_action_get_active(action));
 }
 
 static void layout_menu_write_rotate(GtkToggleAction *, gpointer data, gboolean keep_date)
@@ -918,7 +918,7 @@ static void layout_menu_split_cb(GtkRadioAction *action, GtkRadioAction *, gpoin
        ImageSplitMode mode;
 
        layout_exit_fullscreen(lw);
-       mode = static_cast<ImageSplitMode>(gtk_radio_action_get_current_value(action));
+       mode = static_cast<ImageSplitMode>(gq_gtk_radio_action_get_current_value(action));
        layout_split_change(lw, mode);
 }
 
@@ -927,7 +927,7 @@ static void layout_menu_thumb_cb(GtkToggleAction *action, gpointer data)
 {
        auto lw = static_cast<LayoutWindow *>(data);
 
-       layout_thumb_set(lw, gtk_toggle_action_get_active(action));
+       layout_thumb_set(lw, gq_gtk_toggle_action_get_active(action));
 }
 
 
@@ -936,7 +936,7 @@ static void layout_menu_list_cb(GtkRadioAction *action, GtkRadioAction *, gpoint
        auto lw = static_cast<LayoutWindow *>(data);
 
        layout_exit_fullscreen(lw);
-       layout_views_set(lw, lw->options.dir_view_type, static_cast<FileViewType>(gtk_radio_action_get_current_value(action)));
+       layout_views_set(lw, lw->options.dir_view_type, static_cast<FileViewType>(gq_gtk_radio_action_get_current_value(action)));
 }
 
 static void layout_menu_view_dir_as_cb(GtkToggleAction *action,  gpointer data)
@@ -945,7 +945,7 @@ static void layout_menu_view_dir_as_cb(GtkToggleAction *action,  gpointer data)
 
        layout_exit_fullscreen(lw);
 
-       if (gtk_toggle_action_get_active(action))
+       if (gq_gtk_toggle_action_get_active(action))
                {
                layout_views_set(lw, DIRVIEW_TREE, lw->options.file_view_type);
                }
@@ -1105,7 +1105,7 @@ static void layout_menu_overlay_cb(GtkToggleAction *action, gpointer data)
 {
        auto lw = static_cast<LayoutWindow *>(data);
 
-       if (gtk_toggle_action_get_active(action))
+       if (gq_gtk_toggle_action_get_active(action))
                {
                OsdShowFlags flags = image_osd_get(lw->image);
 
@@ -1114,10 +1114,10 @@ static void layout_menu_overlay_cb(GtkToggleAction *action, gpointer data)
                }
        else
                {
-               GtkToggleAction *histogram_action = GTK_TOGGLE_ACTION(gtk_action_group_get_action(lw->action_group, "ImageHistogram"));
+               GtkToggleAction *histogram_action = GTK_TOGGLE_ACTION(gq_gtk_action_group_get_action(lw->action_group, "ImageHistogram"));
 
                image_osd_set(lw->image, OSD_SHOW_NOTHING);
-               gtk_toggle_action_set_active(histogram_action, FALSE); /* this calls layout_menu_histogram_cb */
+               gq_gtk_toggle_action_set_active(histogram_action, FALSE); /* this calls layout_menu_histogram_cb */
                }
 }
 
@@ -1125,7 +1125,7 @@ static void layout_menu_histogram_cb(GtkToggleAction *action, gpointer data)
 {
        auto lw = static_cast<LayoutWindow *>(data);
 
-       if (gtk_toggle_action_get_active(action))
+       if (gq_gtk_toggle_action_get_active(action))
                {
                image_osd_set(lw->image, static_cast<OsdShowFlags>(OSD_SHOW_INFO | OSD_SHOW_STATUS | OSD_SHOW_HISTOGRAM));
                layout_util_sync_views(lw); /* show the overlay state, default channel and mode in the menu */
@@ -1142,13 +1142,13 @@ static void layout_menu_animate_cb(GtkToggleAction *action, gpointer data)
 {
        auto lw = static_cast<LayoutWindow *>(data);
 
-       if (lw->options.animate == gtk_toggle_action_get_active(action)) return;
+       if (lw->options.animate == gq_gtk_toggle_action_get_active(action)) return;
        layout_image_animate_toggle(lw);
 }
 
 static void layout_menu_rectangular_selection_cb(GtkToggleAction *action, gpointer)
 {
-       options->collections.rectangular_selection = gtk_toggle_action_get_active(action);
+       options->collections.rectangular_selection = gq_gtk_toggle_action_get_active(action);
 }
 
 static void layout_menu_histogram_toggle_channel_cb(GtkAction *, gpointer data)
@@ -1170,24 +1170,24 @@ static void layout_menu_histogram_toggle_mode_cb(GtkAction *, gpointer data)
 static void layout_menu_histogram_channel_cb(GtkRadioAction *action, GtkRadioAction *, gpointer data)
 {
        auto lw = static_cast<LayoutWindow *>(data);
-       gint channel = gtk_radio_action_get_current_value(action);
-       GtkToggleAction *histogram_action = GTK_TOGGLE_ACTION(gtk_action_group_get_action(lw->action_group, "ImageHistogram"));
+       gint channel = gq_gtk_radio_action_get_current_value(action);
+       GtkToggleAction *histogram_action = GTK_TOGGLE_ACTION(gq_gtk_action_group_get_action(lw->action_group, "ImageHistogram"));
 
        if (channel < 0 || channel >= HCHAN_COUNT) return;
 
-       gtk_toggle_action_set_active(histogram_action, TRUE); /* this calls layout_menu_histogram_cb */
+       gq_gtk_toggle_action_set_active(histogram_action, TRUE); /* this calls layout_menu_histogram_cb */
        image_osd_histogram_set_channel(lw->image, channel);
 }
 
 static void layout_menu_histogram_mode_cb(GtkRadioAction *action, GtkRadioAction *, gpointer data)
 {
        auto lw = static_cast<LayoutWindow *>(data);
-       gint mode = gtk_radio_action_get_current_value(action);
-       GtkToggleAction *histogram_action = GTK_TOGGLE_ACTION(gtk_action_group_get_action(lw->action_group, "ImageHistogram"));
+       gint mode = gq_gtk_radio_action_get_current_value(action);
+       GtkToggleAction *histogram_action = GTK_TOGGLE_ACTION(gq_gtk_action_group_get_action(lw->action_group, "ImageHistogram"));
 
        if (mode < 0 || mode > 1) return;
 
-       gtk_toggle_action_set_active(histogram_action, TRUE); /* this calls layout_menu_histogram_cb */
+       gq_gtk_toggle_action_set_active(histogram_action, TRUE); /* this calls layout_menu_histogram_cb */
        image_osd_histogram_set_mode(lw->image, mode);
 }
 
@@ -1219,7 +1219,7 @@ static void layout_menu_float_cb(GtkToggleAction *action, gpointer data)
 {
        auto lw = static_cast<LayoutWindow *>(data);
 
-       if (lw->options.tools_float == gtk_toggle_action_get_active(action)) return;
+       if (lw->options.tools_float == gq_gtk_toggle_action_get_active(action)) return;
 
        layout_exit_fullscreen(lw);
        layout_tools_float_toggle(lw);
@@ -1237,7 +1237,7 @@ static void layout_menu_selectable_toolbars_cb(GtkToggleAction *action, gpointer
 {
        auto lw = static_cast<LayoutWindow *>(data);
 
-       if (lw->options.selectable_toolbars_hidden == gtk_toggle_action_get_active(action)) return;
+       if (lw->options.selectable_toolbars_hidden == gq_gtk_toggle_action_get_active(action)) return;
 
        layout_exit_fullscreen(lw);
        layout_selectable_toolbars_toggle(lw);
@@ -1247,7 +1247,7 @@ static void layout_menu_info_pixel_cb(GtkToggleAction *action, gpointer data)
 {
        auto lw = static_cast<LayoutWindow *>(data);
 
-       if (lw->options.show_info_pixel == gtk_toggle_action_get_active(action)) return;
+       if (lw->options.show_info_pixel == gq_gtk_toggle_action_get_active(action)) return;
 
        layout_exit_fullscreen(lw);
        layout_info_pixel_set(lw, !lw->options.show_info_pixel);
@@ -1258,7 +1258,7 @@ static void layout_menu_bar_cb(GtkToggleAction *action, gpointer data)
 {
        auto lw = static_cast<LayoutWindow *>(data);
 
-       if (layout_bar_enabled(lw) == gtk_toggle_action_get_active(action)) return;
+       if (layout_bar_enabled(lw) == gq_gtk_toggle_action_get_active(action)) return;
 
        layout_exit_fullscreen(lw);
        layout_bar_toggle(lw);
@@ -1268,7 +1268,7 @@ static void layout_menu_bar_sort_cb(GtkToggleAction *action, gpointer data)
 {
        auto lw = static_cast<LayoutWindow *>(data);
 
-       if (layout_bar_sort_enabled(lw) == gtk_toggle_action_get_active(action)) return;
+       if (layout_bar_sort_enabled(lw) == gq_gtk_toggle_action_get_active(action)) return;
 
        layout_exit_fullscreen(lw);
        layout_bar_sort_toggle(lw);
@@ -1278,7 +1278,7 @@ static void layout_menu_hide_bars_cb(GtkToggleAction *action, gpointer data)
 {
        auto lw = static_cast<LayoutWindow *>(data);
 
-       if (lw->options.bars_state.hidden == gtk_toggle_action_get_active(action))
+       if (lw->options.bars_state.hidden == gq_gtk_toggle_action_get_active(action))
                {
                return;
                }
@@ -1289,7 +1289,7 @@ static void layout_menu_slideshow_cb(GtkToggleAction *action, gpointer data)
 {
        auto lw = static_cast<LayoutWindow *>(data);
 
-       if (layout_image_slideshow_active(lw) == gtk_toggle_action_get_active(action)) return;
+       if (layout_image_slideshow_active(lw) == gq_gtk_toggle_action_get_active(action)) return;
        layout_image_slideshow_toggle(lw);
 }
 
@@ -1323,8 +1323,8 @@ static void layout_menu_stereo_mode_next_cb(GtkAction *, gpointer data)
        /* 0->1, 1->2, 2->3, 3->1 - disable auto, then cycle */
        mode = mode % 3 + 1;
 
-       GtkAction *radio = gtk_action_group_get_action(lw->action_group, "StereoAuto");
-       gtk_radio_action_set_current_value(GTK_RADIO_ACTION(radio), mode);
+       GtkAction *radio = gq_gtk_action_group_get_action(lw->action_group, "StereoAuto");
+       gq_gtk_radio_action_set_current_value(GTK_RADIO_ACTION(radio), mode);
 
        /*
        this is called via fallback in layout_menu_stereo_mode_cb
@@ -1336,7 +1336,7 @@ static void layout_menu_stereo_mode_next_cb(GtkAction *, gpointer data)
 static void layout_menu_stereo_mode_cb(GtkRadioAction *action, GtkRadioAction *, gpointer data)
 {
        auto lw = static_cast<LayoutWindow *>(data);
-       gint mode = gtk_radio_action_get_current_value(action);
+       gint mode = gq_gtk_radio_action_get_current_value(action);
        layout_image_stereo_pixbuf_set(lw, mode);
 }
 
@@ -1593,14 +1593,14 @@ static void layout_menu_file_filter_cb(GtkToggleAction *action, gpointer data)
 {
        auto lw = static_cast<LayoutWindow *>(data);
 
-       layout_file_filter_set(lw, gtk_toggle_action_get_active(action));
+       layout_file_filter_set(lw, gq_gtk_toggle_action_get_active(action));
 }
 
 static void layout_menu_marks_cb(GtkToggleAction *action, gpointer data)
 {
        auto lw = static_cast<LayoutWindow *>(data);
 
-       layout_marks_set(lw, gtk_toggle_action_get_active(action));
+       layout_marks_set(lw, gq_gtk_toggle_action_get_active(action));
 }
 
 
@@ -1935,7 +1935,7 @@ static void layout_menu_up_cb(GtkAction *, gpointer data)
 static void layout_menu_edit_cb(GtkAction *action, gpointer data)
 {
        auto lw = static_cast<LayoutWindow *>(data);
-       const gchar *key = gtk_action_get_name(action);
+       const gchar *key = gq_gtk_action_get_name(action);
 
        if (!editor_window_flag_set(key))
                layout_exit_fullscreen(lw);
@@ -1979,9 +1979,9 @@ static void layout_color_menu_enable_cb(GtkToggleAction *action, gpointer data)
 {
        auto lw = static_cast<LayoutWindow *>(data);
 
-       if (layout_image_color_profile_get_use(lw) == gtk_toggle_action_get_active(action)) return;
+       if (layout_image_color_profile_get_use(lw) == gq_gtk_toggle_action_get_active(action)) return;
 
-       layout_image_color_profile_set_use(lw, gtk_toggle_action_get_active(action));
+       layout_image_color_profile_set_use(lw, gq_gtk_toggle_action_get_active(action));
        layout_util_sync_color(lw);
        layout_image_refresh(lw);
 }
@@ -1993,8 +1993,8 @@ static void layout_color_menu_use_image_cb(GtkToggleAction *action, gpointer dat
        gboolean use_image;
 
        if (!layout_image_color_profile_get(lw, &input, &use_image)) return;
-       if (use_image == gtk_toggle_action_get_active(action)) return;
-       layout_image_color_profile_set(lw, input, gtk_toggle_action_get_active(action));
+       if (use_image == gq_gtk_toggle_action_get_active(action)) return;
+       layout_image_color_profile_set(lw, input, gq_gtk_toggle_action_get_active(action));
        layout_util_sync_color(lw);
        layout_image_refresh(lw);
 }
@@ -2006,7 +2006,7 @@ static void layout_color_menu_input_cb(GtkRadioAction *action, GtkRadioAction *,
        gint input;
        gboolean use_image;
 
-       type = gtk_radio_action_get_current_value(action);
+       type = gq_gtk_radio_action_get_current_value(action);
        if (type < 0 || type >= COLOR_PROFILE_FILE + COLOR_PROFILE_INPUTS) return;
 
        if (!layout_image_color_profile_get(lw, &input, &use_image)) return;
@@ -2096,7 +2096,7 @@ static void layout_menu_collection_recent_update(LayoutWindow *lw)
                menu_item_add(menu, _("Empty"), nullptr, nullptr);
                }
 
-       recent = gtk_ui_manager_get_widget(lw->ui_manager, options->hamburger_menu ? "/MainMenu/OpenMenu/FileMenu/OpenRecent" : "/MainMenu/FileMenu/OpenRecent");
+       recent = gq_gtk_ui_manager_get_widget(lw->ui_manager, options->hamburger_menu ? "/MainMenu/OpenMenu/FileMenu/OpenRecent" : "/MainMenu/FileMenu/OpenRecent");
        gtk_menu_item_set_submenu(GTK_MENU_ITEM(recent), menu);
        gtk_widget_set_sensitive(recent, (n != 0));
 }
@@ -2152,7 +2152,7 @@ static void layout_menu_collection_open_update(LayoutWindow *lw)
                menu_item_add(menu, _("Empty"), nullptr, nullptr);
                }
 
-       recent = gtk_ui_manager_get_widget(lw->ui_manager, options->hamburger_menu ? "/MainMenu/OpenMenu/FileMenu/OpenCollection" : "/MainMenu/FileMenu/OpenCollection");
+       recent = gq_gtk_ui_manager_get_widget(lw->ui_manager, options->hamburger_menu ? "/MainMenu/OpenMenu/FileMenu/OpenCollection" : "/MainMenu/FileMenu/OpenCollection");
        gtk_menu_item_set_submenu(GTK_MENU_ITEM(recent), menu);
        gtk_widget_set_sensitive(recent, (n != 0));
 }
@@ -2312,7 +2312,7 @@ static void layout_menu_new_window_update(LayoutWindow *lw)
 
        list = layout_window_menu_list(list);
 
-       menu = gtk_ui_manager_get_widget(lw->ui_manager, options->hamburger_menu ? "/MainMenu/OpenMenu/WindowsMenu/NewWindow" : "/MainMenu/WindowsMenu/NewWindow");
+       menu = gq_gtk_ui_manager_get_widget(lw->ui_manager, options->hamburger_menu ? "/MainMenu/OpenMenu/WindowsMenu/NewWindow" : "/MainMenu/WindowsMenu/NewWindow");
        sub_menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(menu));
 
        children = gtk_container_get_children(GTK_CONTAINER(sub_menu));
@@ -2458,7 +2458,7 @@ static void layout_menu_windows_menu_cb(GtkWidget *, gpointer data)
        GList *iter;
        gint i;
 
-       menu = gtk_ui_manager_get_widget(lw->ui_manager, options->hamburger_menu ? "/MainMenu/OpenMenu/WindowsMenu/" : "/MainMenu/WindowsMenu/");
+       menu = gq_gtk_ui_manager_get_widget(lw->ui_manager, options->hamburger_menu ? "/MainMenu/OpenMenu/WindowsMenu/" : "/MainMenu/WindowsMenu/");
 
        sub_menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(menu));
 
@@ -2491,7 +2491,7 @@ static void layout_menu_view_menu_cb(GtkWidget *, gpointer data)
        gint i;
        FileData *fd;
 
-       menu = gtk_ui_manager_get_widget(lw->ui_manager, options->hamburger_menu ? "/MainMenu/OpenMenu/ViewMenu/" : "/MainMenu/ViewMenu/");
+       menu = gq_gtk_ui_manager_get_widget(lw->ui_manager, options->hamburger_menu ? "/MainMenu/OpenMenu/ViewMenu/" : "/MainMenu/ViewMenu/");
        sub_menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(menu));
 
        fd = layout_image_get_fd(lw);
@@ -2750,7 +2750,7 @@ static GtkActionEntry menu_entries[] = {
   { "Maintenance",           PIXBUF_INLINE_ICON_MAINTENANCE,    N_("_Cache maintenance..."),                            nullptr,               N_("Cache maintenance..."),                            CB(layout_menu_remove_thumb_cb) },
   { "Mirror",                GQ_ICON_FLIP_HORIZONTAL,           N_("_Mirror"),                                          "<shift>M",            N_("Image Mirror"),                                    CB(layout_menu_alter_mirror_cb) },
   { "Move",                  PIXBUF_INLINE_ICON_MOVE,           N_("_Move..."),                                         "<control>M",          N_("Move..."),                                         CB(layout_menu_move_cb) },
-  { "NewCollection",         GQ_ICON_COLLECTION,                N_("_New collection"),                                  "C",                   N_("New collection"),                                  CB(layout_menu_new_cb) },
+  { "NewCollection",         PIXBUF_INLINE_COLLECTION,          N_("_New collection"),                                  "C",                   N_("New collection"),                                  CB(layout_menu_new_cb) },
   { "NewFolder",             GQ_ICON_DIRECTORY,                 N_("N_ew folder..."),                                   "<control>F",          N_("New folder..."),                                   CB(layout_menu_dir_cb) },
   { "NewWindowDefault",      nullptr,                           N_("default"),                                          "<control>N",          N_("New window (default)"),                            CB(layout_menu_window_default_cb)  },
   { "NewWindowFromCurrent",  nullptr,                           N_("from current"),                                     nullptr,               N_("from current"),                                    CB(layout_menu_window_from_current_cb)  },
@@ -2936,8 +2936,8 @@ static void layout_actions_setup_mark(LayoutWindow *lw, gint mark, const gchar *
        else
                entry.tooltip = nullptr;
 
-       gtk_action_group_add_actions(lw->action_group, &entry, 1, lw);
-       action = gtk_action_group_get_action(lw->action_group, name);
+       gq_gtk_action_group_add_actions(lw->action_group, &entry, 1, lw);
+       action = gq_gtk_action_group_get_action(lw->action_group, name);
        g_object_set_data(G_OBJECT(action), "mark_num", GINT_TO_POINTER(mark > 0 ? mark : 10));
 }
 
@@ -3007,7 +3007,7 @@ static void layout_actions_setup_marks(LayoutWindow *lw)
        g_string_append(desc,   "</ui>" );
 
        error = nullptr;
-       if (!gtk_ui_manager_add_ui_from_string(lw->ui_manager, desc->str, -1, &error))
+       if (!gq_gtk_ui_manager_add_ui_from_string(lw->ui_manager, desc->str, -1, &error))
                {
                g_message("building menus failed: %s", error->message);
                g_error_free(error);
@@ -3110,16 +3110,16 @@ static void layout_actions_setup_editors(LayoutWindow *lw)
 
        if (lw->ui_editors_id)
                {
-               gtk_ui_manager_remove_ui(lw->ui_manager, lw->ui_editors_id);
+               gq_gtk_ui_manager_remove_ui(lw->ui_manager, lw->ui_editors_id);
                }
 
        if (lw->action_group_editors)
                {
-               gtk_ui_manager_remove_action_group(lw->ui_manager, lw->action_group_editors);
+               gq_gtk_ui_manager_remove_action_group(lw->ui_manager, lw->action_group_editors);
                g_object_unref(lw->action_group_editors);
                }
-       lw->action_group_editors = gtk_action_group_new("MenuActionsExternal");
-       gtk_ui_manager_insert_action_group(lw->ui_manager, lw->action_group_editors, 1);
+       lw->action_group_editors = gq_gtk_action_group_new("MenuActionsExternal");
+       gq_gtk_ui_manager_insert_action_group(lw->ui_manager, lw->action_group_editors, 1);
 
        /* lw->action_group_editors contains translated entries, no translate func is required */
        desc = g_string_new(
@@ -3150,7 +3150,7 @@ static void layout_actions_setup_editors(LayoutWindow *lw)
                        {
                        entry.stock_id = editor->key;
                        }
-               gtk_action_group_add_actions(lw->action_group_editors, &entry, 1, lw);
+               gq_gtk_action_group_add_actions(lw->action_group_editors, &entry, 1, lw);
 
                path = layout_actions_editor_menu_path(editor);
                layout_actions_editor_add(desc, path, old_path);
@@ -3173,7 +3173,7 @@ static void layout_actions_setup_editors(LayoutWindow *lw)
 
        error = nullptr;
 
-       lw->ui_editors_id = gtk_ui_manager_add_ui_from_string(lw->ui_manager, desc->str, -1, &error);
+       lw->ui_editors_id = gq_gtk_ui_manager_add_ui_from_string(lw->ui_manager, desc->str, -1, &error);
        if (!lw->ui_editors_id)
                {
                g_message("building menus failed: %s", error->message);
@@ -3203,44 +3203,44 @@ void layout_actions_setup(LayoutWindow *lw)
        DEBUG_1("%s layout_actions_setup: start", get_exec_time());
        if (lw->ui_manager) return;
 
-       lw->action_group = gtk_action_group_new("MenuActions");
-       gtk_action_group_set_translate_func(lw->action_group, menu_translate, nullptr, nullptr);
+       lw->action_group = gq_gtk_action_group_new("MenuActions");
+       gq_gtk_action_group_set_translate_func(lw->action_group, menu_translate, nullptr, nullptr);
 
-       gtk_action_group_add_actions(lw->action_group,
+       gq_gtk_action_group_add_actions(lw->action_group,
                                     menu_entries, G_N_ELEMENTS(menu_entries), lw);
-       gtk_action_group_add_toggle_actions(lw->action_group,
+       gq_gtk_action_group_add_toggle_actions(lw->action_group,
                                            menu_toggle_entries, G_N_ELEMENTS(menu_toggle_entries), lw);
-       gtk_action_group_add_radio_actions(lw->action_group,
+       gq_gtk_action_group_add_radio_actions(lw->action_group,
                                           menu_radio_entries, G_N_ELEMENTS(menu_radio_entries),
                                           0, G_CALLBACK(layout_menu_list_cb), lw);
-       gtk_action_group_add_radio_actions(lw->action_group,
+       gq_gtk_action_group_add_radio_actions(lw->action_group,
                                           menu_split_radio_entries, G_N_ELEMENTS(menu_split_radio_entries),
                                           0, G_CALLBACK(layout_menu_split_cb), lw);
-       gtk_action_group_add_toggle_actions(lw->action_group,
+       gq_gtk_action_group_add_toggle_actions(lw->action_group,
                                           menu_view_dir_toggle_entries, G_N_ELEMENTS(menu_view_dir_toggle_entries),
                                            lw);
-       gtk_action_group_add_radio_actions(lw->action_group,
+       gq_gtk_action_group_add_radio_actions(lw->action_group,
                                           menu_color_radio_entries, COLOR_PROFILE_FILE + COLOR_PROFILE_INPUTS,
                                           0, G_CALLBACK(layout_color_menu_input_cb), lw);
-       gtk_action_group_add_radio_actions(lw->action_group,
+       gq_gtk_action_group_add_radio_actions(lw->action_group,
                                           menu_histogram_channel, G_N_ELEMENTS(menu_histogram_channel),
                                           0, G_CALLBACK(layout_menu_histogram_channel_cb), lw);
-       gtk_action_group_add_radio_actions(lw->action_group,
+       gq_gtk_action_group_add_radio_actions(lw->action_group,
                                           menu_histogram_mode, G_N_ELEMENTS(menu_histogram_mode),
                                           0, G_CALLBACK(layout_menu_histogram_mode_cb), lw);
-       gtk_action_group_add_radio_actions(lw->action_group,
+       gq_gtk_action_group_add_radio_actions(lw->action_group,
                                           menu_stereo_mode_entries, G_N_ELEMENTS(menu_stereo_mode_entries),
                                           0, G_CALLBACK(layout_menu_stereo_mode_cb), lw);
 
 
-       lw->ui_manager = gtk_ui_manager_new();
-       gtk_ui_manager_set_add_tearoffs(lw->ui_manager, TRUE);
-       gtk_ui_manager_insert_action_group(lw->ui_manager, lw->action_group, 0);
+       lw->ui_manager = gq_gtk_ui_manager_new();
+       gq_gtk_ui_manager_set_add_tearoffs(lw->ui_manager, TRUE);
+       gq_gtk_ui_manager_insert_action_group(lw->ui_manager, lw->action_group, 0);
 
        DEBUG_1("%s layout_actions_setup: add menu", get_exec_time());
        error = nullptr;
 
-       if (!gtk_ui_manager_add_ui_from_resource(lw->ui_manager, options->hamburger_menu ? GQ_RESOURCE_PATH_UI "/menu-hamburger.ui" : GQ_RESOURCE_PATH_UI "/menu-classic.ui" , &error))
+       if (!gq_gtk_ui_manager_add_ui_from_resource(lw->ui_manager, options->hamburger_menu ? GQ_RESOURCE_PATH_UI "/menu-hamburger.ui" : GQ_RESOURCE_PATH_UI "/menu-classic.ui" , &error))
                {
                g_message("building menus failed: %s", error->message);
                g_error_free(error);
@@ -3337,14 +3337,14 @@ void layout_actions_add_window(LayoutWindow *lw, GtkWidget *window)
 
        if (!lw->ui_manager) return;
 
-       group = gtk_ui_manager_get_accel_group(lw->ui_manager);
+       group = gq_gtk_ui_manager_get_accel_group(lw->ui_manager);
        gtk_window_add_accel_group(GTK_WINDOW(window), group);
 }
 
 GtkWidget *layout_actions_menu_bar(LayoutWindow *lw)
 {
        if (lw->menu_bar) return lw->menu_bar;
-       lw->menu_bar = gtk_ui_manager_get_widget(lw->ui_manager, "/MainMenu");
+       lw->menu_bar = gq_gtk_ui_manager_get_widget(lw->ui_manager, "/MainMenu");
        g_object_ref(lw->menu_bar);
        return lw->menu_bar;
 }
@@ -3403,13 +3403,13 @@ void layout_toolbar_clear(LayoutWindow *lw, ToolbarType type)
 {
        if (lw->toolbar_merge_id[type])
                {
-               gtk_ui_manager_remove_ui(lw->ui_manager, lw->toolbar_merge_id[type]);
-               gtk_ui_manager_ensure_update(lw->ui_manager);
+               gq_gtk_ui_manager_remove_ui(lw->ui_manager, lw->toolbar_merge_id[type]);
+               gq_gtk_ui_manager_ensure_update(lw->ui_manager);
                }
        g_list_free_full(lw->toolbar_actions[type], g_free);
        lw->toolbar_actions[type] = nullptr;
 
-       lw->toolbar_merge_id[type] = gtk_ui_manager_new_merge_id(lw->ui_manager);
+       lw->toolbar_merge_id[type] = gq_gtk_ui_manager_new_merge_id(lw->ui_manager);
 
        if (lw->toolbar[type])
                {
@@ -3435,15 +3435,15 @@ void action_toggle_activate_cb(GtkAction* self, gpointer data)
 {
        auto button = static_cast<GtkToggleButton *>(data);
 
-       if (gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(self)) != gtk_toggle_button_get_active(button))
+       if (gq_gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(self)) != gtk_toggle_button_get_active(button))
                {
-               gtk_toggle_button_set_active(button, gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(self)));
+               gtk_toggle_button_set_active(button, gq_gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(self)));
                }
 }
 
 gboolean toolbar_button_press_event_cb(GtkWidget *, GdkEvent *, gpointer data)
 {
-       gtk_action_activate(GTK_ACTION(data));
+       gq_gtk_action_activate(GTK_ACTION(data));
 
        return TRUE;
 }
@@ -3482,10 +3482,10 @@ void layout_toolbar_add(LayoutWindow *lw, ToolbarType type, const gchar *action_
                   create a dummy action for now */
                if (!lw->action_group_editors)
                        {
-                       lw->action_group_editors = gtk_action_group_new("MenuActionsExternal");
-                       gtk_ui_manager_insert_action_group(lw->ui_manager, lw->action_group_editors, 1);
+                       lw->action_group_editors = gq_gtk_action_group_new("MenuActionsExternal");
+                       gq_gtk_ui_manager_insert_action_group(lw->ui_manager, lw->action_group_editors, 1);
                        }
-               if (!gtk_action_group_get_action(lw->action_group_editors, action_name))
+               if (!gq_gtk_action_group_get_action(lw->action_group_editors, action_name))
                        {
                        GtkActionEntry entry = { action_name,
                                                 GQ_ICON_MISSING_IMAGE,
@@ -3495,7 +3495,7 @@ void layout_toolbar_add(LayoutWindow *lw, ToolbarType type, const gchar *action_
                                                 nullptr
                                               };
                        DEBUG_1("Creating temporary action %s", action_name);
-                       gtk_action_group_add_actions(lw->action_group_editors, &entry, 1, lw);
+                       gq_gtk_action_group_add_actions(lw->action_group_editors, &entry, 1, lw);
                        }
                }
 
@@ -3505,27 +3505,23 @@ void layout_toolbar_add(LayoutWindow *lw, ToolbarType type, const gchar *action_
                }
        else
                {
-               action = gtk_action_group_get_action(lw->action_group, action_name);
+               action = gq_gtk_action_group_get_action(lw->action_group, action_name);
 
-               action_icon = gtk_action_create_icon(action, GTK_ICON_SIZE_SMALL_TOOLBAR);
-               tooltip_text = gtk_action_get_tooltip(action);
+               action_icon = gq_gtk_action_create_icon(action, GTK_ICON_SIZE_SMALL_TOOLBAR);
+               tooltip_text = gq_gtk_action_get_tooltip(action);
 
-               gtk_ui_manager_add_ui(lw->ui_manager, lw->toolbar_merge_id[type], path, action_name, action_name, GTK_UI_MANAGER_TOOLITEM, FALSE);
+               gq_gtk_ui_manager_add_ui(lw->ui_manager, lw->toolbar_merge_id[type], path, action_name, action_name, GTK_UI_MANAGER_TOOLITEM, FALSE);
 
-               if (GTK_IS_RADIO_ACTION(action) || GTK_IS_TOGGLE_ACTION(action))
+               if (GQ_GTK_IS_RADIO_ACTION(action) || GQ_GTK_IS_TOGGLE_ACTION(action))
                        {
                        button = gtk_toggle_button_new();
+                       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), gq_gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action)));
                        }
                else
                        {
                        button = gtk_button_new();
                        }
 
-               if (GTK_IS_TOGGLE_ACTION(action) || GTK_IS_RADIO_ACTION(action))
-                       {
-                       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action)));
-                       }
-
                if (action_icon)
                        {
                        gtk_button_set_image(GTK_BUTTON(button), action_icon);
@@ -3538,12 +3534,12 @@ void layout_toolbar_add(LayoutWindow *lw, ToolbarType type, const gchar *action_
                gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
                gtk_widget_set_tooltip_text(button, tooltip_text);
 
-               if (GTK_IS_RADIO_ACTION(action))
+               if (GQ_GTK_IS_RADIO_ACTION(action))
                        {
                        id = g_signal_connect(G_OBJECT(action), "changed", G_CALLBACK(action_radio_changed_cb), button);
                        g_object_set_data(G_OBJECT(button), "id", GUINT_TO_POINTER(id));
                        }
-               else if (GTK_IS_TOGGLE_ACTION(action))
+               else if (GQ_GTK_IS_TOGGLE_ACTION(action))
                        {
                        id = g_signal_connect(G_OBJECT(action), "activate", G_CALLBACK(action_toggle_activate_cb), button);
                        g_object_set_data(G_OBJECT(button), "id", GUINT_TO_POINTER(id));
@@ -3709,8 +3705,8 @@ void layout_util_status_update_write(LayoutWindow *lw)
 {
        GtkAction *action;
        gint n = metadata_queue_length();
-       action = gtk_action_group_get_action(lw->action_group, "SaveMetadata");
-       gtk_action_set_sensitive(action, n > 0);
+       action = gq_gtk_action_group_get_action(lw->action_group, "SaveMetadata");
+       gq_gtk_action_set_sensitive(action, n > 0);
        if (n > 0)
                {
                gchar *buf = g_strdup_printf(_("Number of files with unsaved metadata: %d"), n);
@@ -3761,9 +3757,9 @@ void layout_util_sync_color(LayoutWindow *lw)
 
        use_color = layout_image_color_profile_get_use(lw);
 
-       action = gtk_action_group_get_action(lw->action_group, "UseColorProfiles");
+       action = gq_gtk_action_group_get_action(lw->action_group, "UseColorProfiles");
 #if HAVE_LCMS
-       gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), use_color);
+       gq_gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), use_color);
        if (layout_image_color_profile_get_status(lw, &image_profile, &screen_profile))
                {
                gchar *buf;
@@ -3778,19 +3774,19 @@ void layout_util_sync_color(LayoutWindow *lw)
                g_object_set(G_OBJECT(action), "tooltip", _("Click to enable color management"), NULL);
                }
 #else
-       gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), FALSE);
-       gtk_action_set_sensitive(action, FALSE);
+       gq_gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), FALSE);
+       gq_gtk_action_set_sensitive(action, FALSE);
        g_object_set(G_OBJECT(action), "tooltip", _("Color profiles not supported"), NULL);
 #endif
 
-       action = gtk_action_group_get_action(lw->action_group, "UseImageProfile");
-       gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), use_image);
-       gtk_action_set_sensitive(action, use_color);
+       action = gq_gtk_action_group_get_action(lw->action_group, "UseImageProfile");
+       gq_gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), use_image);
+       gq_gtk_action_set_sensitive(action, use_color);
 
        for (i = 0; i < COLOR_PROFILE_FILE + COLOR_PROFILE_INPUTS; i++)
                {
                sprintf(action_name, "ColorProfile%d", i);
-               action = gtk_action_group_get_action(lw->action_group, action_name);
+               action = gq_gtk_action_group_get_action(lw->action_group, action_name);
 
                if (i >= COLOR_PROFILE_FILE)
                        {
@@ -3808,15 +3804,15 @@ void layout_util_sync_color(LayoutWindow *lw)
                        g_object_set(G_OBJECT(action), "label", buf, NULL);
                        g_free(buf);
 
-                       gtk_action_set_visible(action, file && file[0]);
+                       gq_gtk_action_set_visible(action, file && file[0]);
                        }
 
-               gtk_action_set_sensitive(action, !use_image);
-               gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), (i == input));
+               gq_gtk_action_set_sensitive(action, !use_image);
+               gq_gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), (i == input));
                }
 
-       action = gtk_action_group_get_action(lw->action_group, "Grayscale");
-       gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), layout_image_get_desaturate(lw));
+       action = gq_gtk_action_group_get_action(lw->action_group, "Grayscale");
+       gq_gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), layout_image_get_desaturate(lw));
 }
 
 void layout_util_sync_file_filter(LayoutWindow *lw)
@@ -3825,8 +3821,8 @@ void layout_util_sync_file_filter(LayoutWindow *lw)
 
        if (!lw->action_group) return;
 
-       action = gtk_action_group_get_action(lw->action_group, "ShowFileFilter");
-       gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->options.show_file_filter);
+       action = gq_gtk_action_group_get_action(lw->action_group, "ShowFileFilter");
+       gq_gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->options.show_file_filter);
 }
 
 void layout_util_sync_marks(LayoutWindow *lw)
@@ -3835,8 +3831,8 @@ void layout_util_sync_marks(LayoutWindow *lw)
 
        if (!lw->action_group) return;
 
-       action = gtk_action_group_get_action(lw->action_group, "ShowMarks");
-       gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->options.show_marks);
+       action = gq_gtk_action_group_get_action(lw->action_group, "ShowMarks");
+       gq_gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->options.show_marks);
 }
 
 static void layout_util_sync_views(LayoutWindow *lw)
@@ -3846,98 +3842,98 @@ static void layout_util_sync_views(LayoutWindow *lw)
 
        if (!lw->action_group) return;
 
-       action = gtk_action_group_get_action(lw->action_group, "FolderTree");
-       gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->options.dir_view_type);
+       action = gq_gtk_action_group_get_action(lw->action_group, "FolderTree");
+       gq_gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->options.dir_view_type);
 
-       action = gtk_action_group_get_action(lw->action_group, "SplitSingle");
-       gtk_radio_action_set_current_value(GTK_RADIO_ACTION(action), lw->split_mode);
+       action = gq_gtk_action_group_get_action(lw->action_group, "SplitSingle");
+       gq_gtk_radio_action_set_current_value(GTK_RADIO_ACTION(action), lw->split_mode);
 
-       action = gtk_action_group_get_action(lw->action_group, "SplitNextPane");
-       gtk_action_set_sensitive(action, !(lw->split_mode == SPLIT_NONE));
-       action = gtk_action_group_get_action(lw->action_group, "SplitPreviousPane");
-       gtk_action_set_sensitive(action, !(lw->split_mode == SPLIT_NONE));
-       action = gtk_action_group_get_action(lw->action_group, "SplitUpPane");
-       gtk_action_set_sensitive(action, !(lw->split_mode == SPLIT_NONE));
-       action = gtk_action_group_get_action(lw->action_group, "SplitDownPane");
-       gtk_action_set_sensitive(action, !(lw->split_mode == SPLIT_NONE));
+       action = gq_gtk_action_group_get_action(lw->action_group, "SplitNextPane");
+       gq_gtk_action_set_sensitive(action, !(lw->split_mode == SPLIT_NONE));
+       action = gq_gtk_action_group_get_action(lw->action_group, "SplitPreviousPane");
+       gq_gtk_action_set_sensitive(action, !(lw->split_mode == SPLIT_NONE));
+       action = gq_gtk_action_group_get_action(lw->action_group, "SplitUpPane");
+       gq_gtk_action_set_sensitive(action, !(lw->split_mode == SPLIT_NONE));
+       action = gq_gtk_action_group_get_action(lw->action_group, "SplitDownPane");
+       gq_gtk_action_set_sensitive(action, !(lw->split_mode == SPLIT_NONE));
 
-       action = gtk_action_group_get_action(lw->action_group, "SplitPaneSync");
-       gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->options.split_pane_sync);
+       action = gq_gtk_action_group_get_action(lw->action_group, "SplitPaneSync");
+       gq_gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->options.split_pane_sync);
 
-       action = gtk_action_group_get_action(lw->action_group, "ViewIcons");
-       gtk_radio_action_set_current_value(GTK_RADIO_ACTION(action), lw->options.file_view_type);
+       action = gq_gtk_action_group_get_action(lw->action_group, "ViewIcons");
+       gq_gtk_radio_action_set_current_value(GTK_RADIO_ACTION(action), lw->options.file_view_type);
 
-       action = gtk_action_group_get_action(lw->action_group, "FloatTools");
-       gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->options.tools_float);
+       action = gq_gtk_action_group_get_action(lw->action_group, "FloatTools");
+       gq_gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->options.tools_float);
 
-       action = gtk_action_group_get_action(lw->action_group, "SBar");
-       gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), layout_bar_enabled(lw));
+       action = gq_gtk_action_group_get_action(lw->action_group, "SBar");
+       gq_gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), layout_bar_enabled(lw));
 
-       action = gtk_action_group_get_action(lw->action_group, "SBarSort");
-       gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), layout_bar_sort_enabled(lw));
+       action = gq_gtk_action_group_get_action(lw->action_group, "SBarSort");
+       gq_gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), layout_bar_sort_enabled(lw));
 
-       action = gtk_action_group_get_action(lw->action_group, "HideSelectableToolbars");
-       gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->options.selectable_toolbars_hidden);
+       action = gq_gtk_action_group_get_action(lw->action_group, "HideSelectableToolbars");
+       gq_gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->options.selectable_toolbars_hidden);
 
-       action = gtk_action_group_get_action(lw->action_group, "ShowInfoPixel");
-       gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->options.show_info_pixel);
+       action = gq_gtk_action_group_get_action(lw->action_group, "ShowInfoPixel");
+       gq_gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->options.show_info_pixel);
 
-       action = gtk_action_group_get_action(lw->action_group, "SlideShow");
-       gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), layout_image_slideshow_active(lw));
+       action = gq_gtk_action_group_get_action(lw->action_group, "SlideShow");
+       gq_gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), layout_image_slideshow_active(lw));
 
-       action = gtk_action_group_get_action(lw->action_group, "IgnoreAlpha");
-       gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->options.ignore_alpha);
+       action = gq_gtk_action_group_get_action(lw->action_group, "IgnoreAlpha");
+       gq_gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->options.ignore_alpha);
 
-       action = gtk_action_group_get_action(lw->action_group, "Animate");
-       gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->options.animate);
+       action = gq_gtk_action_group_get_action(lw->action_group, "Animate");
+       gq_gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->options.animate);
 
-       action = gtk_action_group_get_action(lw->action_group, "ImageOverlay");
-       gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), osd_flags != OSD_SHOW_NOTHING);
+       action = gq_gtk_action_group_get_action(lw->action_group, "ImageOverlay");
+       gq_gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), osd_flags != OSD_SHOW_NOTHING);
 
-       action = gtk_action_group_get_action(lw->action_group, "ImageHistogram");
-       gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), osd_flags & OSD_SHOW_HISTOGRAM);
+       action = gq_gtk_action_group_get_action(lw->action_group, "ImageHistogram");
+       gq_gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), osd_flags & OSD_SHOW_HISTOGRAM);
 
-       action = gtk_action_group_get_action(lw->action_group, "ExifRotate");
-       gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), options->image.exif_rotate_enable);
+       action = gq_gtk_action_group_get_action(lw->action_group, "ExifRotate");
+       gq_gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), options->image.exif_rotate_enable);
 
-       action = gtk_action_group_get_action(lw->action_group, "OverUnderExposed");
-       gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), options->overunderexposed);
+       action = gq_gtk_action_group_get_action(lw->action_group, "OverUnderExposed");
+       gq_gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), options->overunderexposed);
 
-       action = gtk_action_group_get_action(lw->action_group, "DrawRectangle");
-       gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), options->draw_rectangle);
+       action = gq_gtk_action_group_get_action(lw->action_group, "DrawRectangle");
+       gq_gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), options->draw_rectangle);
 
-       action = gtk_action_group_get_action(lw->action_group, "RectangularSelection");
-       gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), options->collections.rectangular_selection);
+       action = gq_gtk_action_group_get_action(lw->action_group, "RectangularSelection");
+       gq_gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), options->collections.rectangular_selection);
 
-       action = gtk_action_group_get_action(lw->action_group, "ShowFileFilter");
-       gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->options.show_file_filter);
+       action = gq_gtk_action_group_get_action(lw->action_group, "ShowFileFilter");
+       gq_gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->options.show_file_filter);
 
-       action = gtk_action_group_get_action(lw->action_group, "HideBars");
-       gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), (lw->options.bars_state.hidden));
+       action = gq_gtk_action_group_get_action(lw->action_group, "HideBars");
+       gq_gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), (lw->options.bars_state.hidden));
 
        if (osd_flags & OSD_SHOW_HISTOGRAM)
                {
-               action = gtk_action_group_get_action(lw->action_group, "HistogramChanR");
-               gtk_radio_action_set_current_value(GTK_RADIO_ACTION(action), image_osd_histogram_get_channel(lw->image));
+               action = gq_gtk_action_group_get_action(lw->action_group, "HistogramChanR");
+               gq_gtk_radio_action_set_current_value(GTK_RADIO_ACTION(action), image_osd_histogram_get_channel(lw->image));
 
-               action = gtk_action_group_get_action(lw->action_group, "HistogramModeLin");
-               gtk_radio_action_set_current_value(GTK_RADIO_ACTION(action), image_osd_histogram_get_mode(lw->image));
+               action = gq_gtk_action_group_get_action(lw->action_group, "HistogramModeLin");
+               gq_gtk_radio_action_set_current_value(GTK_RADIO_ACTION(action), image_osd_histogram_get_mode(lw->image));
                }
 
-       action = gtk_action_group_get_action(lw->action_group, "ConnectZoomMenu");
-       gtk_action_set_sensitive(action, lw->split_mode != SPLIT_NONE);
+       action = gq_gtk_action_group_get_action(lw->action_group, "ConnectZoomMenu");
+       gq_gtk_action_set_sensitive(action, lw->split_mode != SPLIT_NONE);
 
        // @todo `which` is deprecated, use command -v
        gboolean is_write_rotation = !runcmd("which exiftran >/dev/null 2>&1")
                                  && !runcmd("which mogrify >/dev/null 2>&1")
                                  && !options->metadata.write_orientation;
-       action = gtk_action_group_get_action(lw->action_group, "WriteRotation");
-       gtk_action_set_sensitive(action, is_write_rotation);
-       action = gtk_action_group_get_action(lw->action_group, "WriteRotationKeepDate");
-       gtk_action_set_sensitive(action, is_write_rotation);
+       action = gq_gtk_action_group_get_action(lw->action_group, "WriteRotation");
+       gq_gtk_action_set_sensitive(action, is_write_rotation);
+       action = gq_gtk_action_group_get_action(lw->action_group, "WriteRotationKeepDate");
+       gq_gtk_action_set_sensitive(action, is_write_rotation);
 
-       action = gtk_action_group_get_action(lw->action_group, "StereoAuto");
-       gtk_radio_action_set_current_value(GTK_RADIO_ACTION(action), layout_image_stereo_pixbuf_get(lw));
+       action = gq_gtk_action_group_get_action(lw->action_group, "StereoAuto");
+       gq_gtk_radio_action_set_current_value(GTK_RADIO_ACTION(action), layout_image_stereo_pixbuf_get(lw));
 
        layout_util_sync_marks(lw);
        layout_util_sync_color(lw);
@@ -3950,8 +3946,8 @@ void layout_util_sync_thumb(LayoutWindow *lw)
 
        if (!lw->action_group) return;
 
-       action = gtk_action_group_get_action(lw->action_group, "Thumbnails");
-       gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->options.show_thumbnails);
+       action = gq_gtk_action_group_get_action(lw->action_group, "Thumbnails");
+       gq_gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->options.show_thumbnails);
        g_object_set(action, "sensitive", (lw->options.file_view_type == FILEVIEW_LIST), NULL);
 }
 
index b9f0f5b..6c53660 100644 (file)
 #define GQ_ICON_COLOR_MANAGEMENT "preferences-color" // breeze has nicer "color-management" icon, missing in others
 
 // not done... plus many more
-#define GQ_ICON_COLLECTION GTK_STOCK_INDEX
-#define GQ_ICON_DND GTK_STOCK_DND_MULTIPLE
 // PIXBUF_INLINE_ICON_ZOOMFILLHOR
 // PIXBUF_INLINE_ICON_ZOOMFILLVERT
 
index 085e69d..5d9ac01 100644 (file)
@@ -459,8 +459,8 @@ GtkWidget *submenu_add_collections(GtkWidget *menu, GtkWidget **menu_item,
        submenu = gtk_menu_new();
        g_object_set_data(G_OBJECT(submenu), "submenu_data", data);
 
-       menu_item_add_stock_sensitive(submenu, _("New collection"),
-                                       GQ_ICON_COLLECTION, TRUE, G_CALLBACK(func), GINT_TO_POINTER(-1));
+       menu_item_add_icon_sensitive(submenu, _("New collection"),
+                                    PIXBUF_INLINE_COLLECTION, TRUE, G_CALLBACK(func), GINT_TO_POINTER(-1));
        menu_item_add_divider(submenu);
 
        collect_manager_list(&collection_list,nullptr,nullptr);
index 0d87b7f..3e2a257 100644 (file)
@@ -398,18 +398,24 @@ gboolean util_clip_region(gint x, gint y, gint w, gint h,
                          gint clip_x, gint clip_y, gint clip_w, gint clip_h,
                          gint *rx, gint *ry, gint *rw, gint *rh)
 {
-       if (clip_x + clip_w <= x ||
-           clip_x >= x + w ||
-           clip_y + clip_h <= y ||
-           clip_y >= y + h)
+       // Ensures that clip region and main region have some overlap (they aren't
+       // completely disjoint).
+       if (clip_x + clip_w <= x ||  /* assert(x < clip_right) && */
+           clip_x >= x + w ||       /* assert(clip_x < right) && */
+           clip_y + clip_h <= y ||  /* assert(y < clip_bottom && */
+           clip_y >= y + h)         /* assert(bottom < clip_y) */
                {
                return FALSE;
                }
 
+       // We choose the right-most x coordinate.
        *rx = MAX(x, clip_x);
+       // And the narrowest width.
        *rw = MIN((x + w), (clip_x + clip_w)) - *rx;
 
+       // We choose the bottom-most y coordinate.
        *ry = MAX(y, clip_y);
+       // And the shortest height.
        *rh = MIN((y + h), (clip_y + clip_h)) - *ry;
 
        return TRUE;
@@ -743,6 +749,8 @@ void pixbuf_draw_rect_fill(GdkPixbuf *pb,
                        pp[0] = (r * a + pp[0] * (256-a)) >> 8;
                        pp[1] = (g * a + pp[1] * (256-a)) >> 8;
                        pp[2] = (b * a + pp[2] * (256-a)) >> 8;
+                        // TODO(xsdg): Should we do anything about a potential
+                        // existing alpha value here?
                        pp += p_step;
                        }
                }
@@ -809,15 +817,22 @@ void pixbuf_set_rect_fill(GdkPixbuf *pb,
 void pixbuf_set_rect(GdkPixbuf *pb,
                     gint x, gint y, gint w, gint h,
                     gint r, gint g, gint b, gint a,
-                    gint left, gint right, gint top, gint bottom)
+                    gint left_width, gint right_width, gint top_width, gint bottom_width)
 {
-       pixbuf_set_rect_fill(pb, x + left, y, w - left - right, top,
+       // TODO(xsdg): This function has multiple off-by-one errors.  Would be
+       // much easier to read (and implement correctly) with temporaries to
+       // translate from (x, y, w, h) coordinates to (x1, y1, x2, y2).
+       pixbuf_set_rect_fill(pb,
+                            x + left_width, y, w - left_width - right_width, top_width,
                             r, g, b ,a);
-       pixbuf_set_rect_fill(pb, x + w - right, y, right, h,
+       pixbuf_set_rect_fill(pb,
+                            x + w - right_width, y, right_width, h,
                             r, g, b ,a);
-       pixbuf_set_rect_fill(pb, x + left, y + h - bottom, w - left - right, bottom,
+       pixbuf_set_rect_fill(pb,
+                            x + left_width, y + h - bottom_width, w - left_width - right_width, bottom_width,
                             r, g, b ,a);
-       pixbuf_set_rect_fill(pb, x, y, left, h,
+       pixbuf_set_rect_fill(pb,
+                            x, y, left_width, h,
                             r, g, b ,a);
 }
 
@@ -1052,13 +1067,17 @@ void pixbuf_draw_triangle(GdkPixbuf *pb,
        pw = gdk_pixbuf_get_width(pb);
        ph = gdk_pixbuf_get_height(pb);
 
+       // Intersects the clip region with the pixbuf. r{x,y,w,h} is that
+       // intersecting region.
        if (!util_clip_region(0, 0, pw, ph,
                              clip_x, clip_y, clip_w, clip_h,
                              &rx, &ry, &rw, &rh)) return;
 
+       // Determine the bounding box for the triangle.
        util_clip_triangle(x1, y1, x2, y2, x3, y3,
                           tx, ty, tw, th);
 
+       // And now clip the triangle bounding box to the pixbuf clipping region.
        if (!util_clip_region(rx, ry, rw, rh,
                              tx, ty, tw, th,
                              &fx1, &fy1, &fw, &fh)) return;
@@ -1071,6 +1090,7 @@ void pixbuf_draw_triangle(GdkPixbuf *pb,
 
        p_step = (has_alpha) ? 4 : 3;
 
+       // Ensure that points are ordered by increasing y coordinate.
        if (y1 > y2)
                {
                std::swap(x1, x2);
@@ -1087,6 +1107,8 @@ void pixbuf_draw_triangle(GdkPixbuf *pb,
                std::swap(y1, y2);
                }
 
+       // TODO(xsdg): Drop these explicit casts.  Int will always promote to
+       // double without issue.
        slope1 = static_cast<gdouble>(y2 - y1);
        if (slope1) slope1 = static_cast<gdouble>(x2 - x1) / slope1;
        slope1_x = x1;
@@ -1140,6 +1162,17 @@ void pixbuf_draw_triangle(GdkPixbuf *pb,
  *-----------------------------------------------------------------------------
  */
 
+/**
+ * @brief Clips the specified line segment to the specified clipping region.
+ * @param[in] clip_x,clip_y Coordinates of the top-left corner of the clipping region.
+ * @param[in] clip_w,clip_h Extent of the clipping region.
+ * @param[in] x1,y1 Coordinates of the first point of the line segment.
+ * @param[in] x2,y2 Coordinates of the second point of the line segment.
+ * @param[out] rx1,ry1 Computed coordinates of the first point of the clipped line segment.
+ * @param[out] rx2,ry2 Computed coordinates of the second point of the clipped line segment.
+ * @retval FALSE The line segment lies outside of the clipping region.
+ * @retval TRUE The clip operation was performed, and the output params were set.
+ */
 static gboolean util_clip_line(gdouble clip_x, gdouble clip_y, gdouble clip_w, gdouble clip_h,
                               gdouble x1, gdouble y1, gdouble x2, gdouble y2,
                               gdouble *rx1, gdouble *ry1, gdouble *rx2, gdouble *ry2)
@@ -1147,6 +1180,7 @@ static gboolean util_clip_line(gdouble clip_x, gdouble clip_y, gdouble clip_w, g
        gboolean flip = FALSE;
        gdouble d;
 
+       // Normalize: Line endpoint 1 must be farther left.
        if (x1 > x2)
                {
                std::swap(x1, x2);
@@ -1154,8 +1188,13 @@ static gboolean util_clip_line(gdouble clip_x, gdouble clip_y, gdouble clip_w, g
                flip = TRUE;
                }
 
+       // Ensure the line horizontally overlaps with the clip region.
        if (x2 < clip_x || x1 > clip_x + clip_w) return FALSE;
 
+       // Ensure the line vertically overlaps with the clip region.
+       // Note that a line can both horizontally and vertically overlap with
+       // clipping region, while still being outside of the clipping region.  That
+       // case is detected further below.
        if (y1 < y2)
                {
                if (y2 < clip_y || y1 > clip_y + clip_h) return FALSE;
@@ -1166,16 +1205,21 @@ static gboolean util_clip_line(gdouble clip_x, gdouble clip_y, gdouble clip_w, g
                }
 
        d = x2 - x1;
+       // TODO(xsdg): Either use ints here, or define a reasonable epsilon to do the
+       // right thing if -epsilon < d < 0.  We already guaranteed above that x2 >= x1.
        if (d > 0.0)
                {
                gdouble slope;
 
                slope = (y2 - y1) / d;
+               // If needed, project (x1, y1) to be horizontally within the clip
+               // region, while maintaining the line's slope and y-offset.
                if (x1 < clip_x)
                        {
                        y1 = y1 + slope * (clip_x - x1);
                        x1 = clip_x;
                        }
+               // Likewise with (x2, y2).
                if (x2 > clip_x + clip_w)
                        {
                        y2 = y2 + slope * (clip_x + clip_w - x2);
@@ -1183,6 +1227,8 @@ static gboolean util_clip_line(gdouble clip_x, gdouble clip_y, gdouble clip_w, g
                        }
                }
 
+       // Check that any horizontal projections didn't cause the line segment to
+       // no longer vertically overlap with the clip region.
        if (y1 < y2)
                {
                if (y2 < clip_y || y1 > clip_y + clip_h) return FALSE;
@@ -1191,6 +1237,7 @@ static gboolean util_clip_line(gdouble clip_x, gdouble clip_y, gdouble clip_w, g
                {
                if (y1 < clip_y || y2 > clip_y + clip_h) return FALSE;
 
+               // Re-normalize: line endpoint 1 must be farther up.
                std::swap(x1, x2);
                std::swap(y1, y2);
                flip = !flip;
@@ -1202,11 +1249,14 @@ static gboolean util_clip_line(gdouble clip_x, gdouble clip_y, gdouble clip_w, g
                gdouble slope;
 
                slope = (x2 - x1) / d;
+               // If needed, project (x1, y1) to be vertically within the clip
+               // region, while maintaining the line's slope and x-offset.
                if (y1 < clip_y)
                        {
                        x1 = x1 + slope * (clip_y - y1);
                        y1 = clip_y;
                        }
+               // Likewise with (x2, y2).
                if (y2 > clip_y + clip_h)
                        {
                        x2 = x2 + slope * (clip_y + clip_h - y2);
@@ -1214,6 +1264,8 @@ static gboolean util_clip_line(gdouble clip_x, gdouble clip_y, gdouble clip_w, g
                        }
                }
 
+       // Set the output params, accounting for any flips that might have
+       // happened during normalization.
        if (flip)
                {
                *rx1 = x2;
@@ -1267,9 +1319,13 @@ void pixbuf_draw_line(GdkPixbuf *pb,
        pw = gdk_pixbuf_get_width(pb);
        ph = gdk_pixbuf_get_height(pb);
 
+       // Intersects the clip region with the pixbuf. r{x,y,w,h} is that
+       // intersecting region.
        if (!util_clip_region(0, 0, pw, ph,
                              clip_x, clip_y, clip_w, clip_h,
                              &rx, &ry, &rw, &rh)) return;
+       // TODO(xsdg): These explicit casts are unnecessary and harm readability.
+       // Clips the specified line segment to the intersecting region from above.
        if (!util_clip_line(static_cast<gdouble>(rx), static_cast<gdouble>(ry), static_cast<gdouble>(rw), static_cast<gdouble>(rh),
                            static_cast<gdouble>(x1), static_cast<gdouble>(y1), static_cast<gdouble>(x2), static_cast<gdouble>(y2),
                            &rx1, &ry1, &rx2, &ry2)) return;
@@ -1285,6 +1341,10 @@ void pixbuf_draw_line(GdkPixbuf *pb,
 
        p_step = (has_alpha) ? 4 : 3;
 
+       // We draw the clipped line segment along the longer axis first, and
+       // allow the shorter axis to follow.  This is because our raster line segment
+       // will contain max(rx2-rx1, ry2-ry1) pixels, and the pixels along the
+       // shorter axis may not advance for each cycle (the line is not anti-aliased).
        if (fabs(rx2 - rx1) > fabs(ry2 - ry1))
                {
                if (rx1 > rx2)
@@ -1345,6 +1405,27 @@ void pixbuf_draw_line(GdkPixbuf *pb,
  *-----------------------------------------------------------------------------
  */
 
+/**
+ * @brief Composites a horizontal or vertical linear gradient into the rectangular
+ *        region defined by corners `(x1, y1)` and `(x2, y2)`.  Note that the
+ *        current implementation breaks if the max distance between `s` and
+ *        `x1/x2/y1/y2` is greater than `border`.
+ * @param p_pix The pixel buffer to paint into.
+ * @param prs The pixel row stride (how many pixels per row of the buffer).
+ * @param has_alpha TRUE if the p_pix representation is rgba.  FALSE if just rgb.
+ * @param s The "center" of the gradient, along the axis defined by `vertical`.
+ *          Note that if the center is not along an edge, the gradient will be
+ *          symmetric about the center.
+ * @param vertical When `TRUE`, the gradient color will vary vertically.  When `FALSE`,
+ *                 horizontally.
+ * @param border The maximum extent of the gradient, in pixels.
+ * @param x1,y1 Coordinates of the first corner of the region.
+ * @param x2,y2 Coordinates of the second corner of the region.
+ * @param r,g,b Base color of the gradient.
+ * @param a The peak alpha value when compositing the gradient.  The alpha varies
+ *          from this value down to 0 (fully transparent).  Note that any alpha
+ *          value associated with the original pixel is unmodified.
+ */
 static void pixbuf_draw_fade_linear(guchar *p_pix, gint prs, gboolean has_alpha,
                                    gint s, gboolean vertical, gint border,
                                    gint x1, gint y1, gint x2, gint y2,
@@ -1372,11 +1453,30 @@ static void pixbuf_draw_fade_linear(guchar *p_pix, gint prs, gboolean has_alpha,
                }
 }
 
+/**
+ * @brief Composites a radial gradient into the rectangular region defined by
+ *        corners `(x1, y1)` and `(x2, y2)`.
+ * @param p_pix The pixel buffer to paint into.
+ * @param prs The pixel row stride (how many pixels per row of the buffer).
+ * @param has_alpha TRUE if the p_pix representation is rgba.  FALSE if just rgb.
+ * @param sx,sy The coordinates of the center of the gradient.
+ * @param border The max radius, in pixels, of the gradient.  Pixels farther away
+ *               from the center than this will be unaffected.
+ * @param x1,y1 Coordinates of the first corner of the region.
+ * @param x2,y2 Coordinates of the second corner of the region.
+ * @param r,g,b Base color of the gradient.
+ * @param a The peak alpha value when compositing the gradient.  The alpha varies
+ *          from this value down to 0 (fully transparent).  Note that any alpha
+ *          value associated with the original pixel is unmodified.
+ */
 static void pixbuf_draw_fade_radius(guchar *p_pix, gint prs, gboolean has_alpha,
                                    gint sx, gint sy, gint border,
                                    gint x1, gint y1, gint x2, gint y2,
                                    guint8, guint8 g, guint8 b, guint8 a)
 {
+       // TODO(xsdg): r (red) was shadowed by r (radius), and was removed from
+       // the params list by an automated cleanup.  Fix this and distinguish the
+       // red param from the radius temporary variable.
        guchar *pp;
        gint p_step;
        gint i;
@@ -1425,6 +1525,8 @@ void pixbuf_draw_shadow(GdkPixbuf *pb,
        pw = gdk_pixbuf_get_width(pb);
        ph = gdk_pixbuf_get_height(pb);
 
+       // Intersects the clip region with the pixbuf. r{x,y,w,h} is that
+       // intersecting region.
        if (!util_clip_region(0, 0, pw, ph,
                              clip_x, clip_y, clip_w, clip_h,
                              &rx, &ry, &rw, &rh)) return;
@@ -1433,6 +1535,9 @@ void pixbuf_draw_shadow(GdkPixbuf *pb,
        prs = gdk_pixbuf_get_rowstride(pb);
        p_pix = gdk_pixbuf_get_pixels(pb);
 
+       // Composites the specified color into the rectangle specified by x, y, w, h,
+       // as contracted by `border` pixels, with a composition fraction that's defined
+       // by the supplied `a` parameter.
        if (util_clip_region(x + border, y + border, w - border * 2, h - border * 2,
                             rx, ry, rw, rh,
                             &fx, &fy, &fw, &fh))
@@ -1442,6 +1547,7 @@ void pixbuf_draw_shadow(GdkPixbuf *pb,
 
        if (border < 1) return;
 
+       // Draws linear gradients along each of the 4 edges.
        if (util_clip_region(x, y + border, border, h - border * 2,
                             rx, ry, rw, rh,
                             &fx, &fy, &fw, &fh))
@@ -1478,6 +1584,7 @@ void pixbuf_draw_shadow(GdkPixbuf *pb,
                                        fx, fy, fx + fw, fy + fh,
                                        r, g, b, a);
                }
+       // Draws radial gradients at each of the 4 corners.
        if (util_clip_region(x, y, border, border,
                             rx, ry, rw, rh,
                             &fx, &fy, &fw, &fh))
@@ -1567,7 +1674,8 @@ void pixbuf_desaturate_rect(GdkPixbuf *pb,
 
 /*
  *-----------------------------------------------------------------------------
- * pixbuf highlight under/over exposure *-----------------------------------------------------------------------------
+ * pixbuf highlight under/over exposure
+ *-----------------------------------------------------------------------------
  */
 void pixbuf_highlight_overunderexposed(GdkPixbuf *pb, gint x, gint y, gint w, gint h)
 {
@@ -1616,7 +1724,7 @@ void pixbuf_highlight_overunderexposed(GdkPixbuf *pb, gint x, gint y, gint w, gi
  *-----------------------------------------------------------------------------
 */
 void pixbuf_ignore_alpha_rect(GdkPixbuf *pb,
-                 gint x, gint y, gint w, gint h)
+                             gint x, gint y, gint w, gint h)
 {
    gboolean has_alpha;
    gint pw;
index 8f8f419..87ff6ad 100644 (file)
@@ -82,19 +82,55 @@ GdkPixbuf *pixbuf_copy_rotate_90(GdkPixbuf *src, gboolean counter_clockwise);
 GdkPixbuf *pixbuf_copy_mirror(GdkPixbuf *src, gboolean mirror, gboolean flip);
 GdkPixbuf* pixbuf_apply_orientation(GdkPixbuf *pixbuf, gint orientation);
 
+/**
+ * @brief Composites the fill color with the existing contents of the pixbuf,
+ *        within the specified region, with a proportion set by the alpha (`a`)
+ *        parameter.
+ * @param pb The `GdkPixbuf` to paint into.
+ * @param x,y Coordinates of the top-left corner of the first region.
+ * @param w,h Extent of the first region.
+ * @param r,g,b Fill color.
+ * @param a The alpha to use for compositing. a=255 is solid (fully the new
+ *          color).  a=0 is tranparent (fully the original contents).
+ */
 void pixbuf_draw_rect_fill(GdkPixbuf *pb,
                           gint x, gint y, gint w, gint h,
                           gint r, gint g, gint b, gint a);
 
+/**
+ * @brief Fills the specified region of the pixbuf with the specified color.
+ * @param pb The `GdkPixbuf` to paint into.
+ * @param x,y Coordinates of the top-left corner of the first region.
+ * @param w,h Extent of the first region.
+ * @param r,g,b,a Fill color and alpha.
+ */
 void pixbuf_set_rect_fill(GdkPixbuf *pb,
                          gint x, gint y, gint w, gint h,
                          gint r, gint g, gint b, gint a);
 
+/**
+ * @brief Draws a rectangular stroke of the specified stroke width and color
+ *        around the specified region of the pixbuf.
+ * @param pb The `GdkPixbuf` to paint into.
+ * @param x,y Coordinates of the top-left corner of the region.
+ * @param w,h Extent of the region.
+ * @param r,g,b,a Line color and alpha.
+ * @param left_width Stroke width of the left edge of the rectangle.
+ * @param right_width Stroke width of the right edge of the rectangle.
+ * @param top_width Stroke width of the top edge of the rectangle.
+ * @param bottom_width Stroke width of the bottom edge of the rectangle.
+ */
 void pixbuf_set_rect(GdkPixbuf *pb,
                     gint x, gint y, gint w, gint h,
                     gint r, gint g, gint b, gint a,
-                    gint left, gint right, gint top, gint bottom);
+                    gint left_width, gint right_width, gint top_width, gint bottom_width);
 
+/**
+ * @brief Sets the specified pixel of the pixbuf to the specified color.
+ * @param pb The `GdkPixbuf` to paint into.
+ * @param x,y Coordinates of the pixel to set.
+ * @param r,g,b,a Color and alpha.
+ */
 void pixbuf_pixel_set(GdkPixbuf *pb, gint x, gint y, gint r, gint g, gint b, gint a);
 
 
@@ -103,33 +139,112 @@ void pixbuf_draw_layout(GdkPixbuf *pixbuf, PangoLayout *layout, GtkWidget *widge
                        guint8 r, guint8 g, guint8 b, guint8 a);
 
 
+/**
+ * @brief Draws a filled triangle of the specified color into the pixbuf, constrained
+ *        to the specified clip region.
+ * @param pb The `GdkPixbuf` to paint into.
+ * @param x1,y1 Coordinates of the first corner of the triangle.
+ * @param x2,y2 Coordinates of the second corner of the triangle.
+ * @param x3,y3 Coordinates of the third corner of the triangle.
+ * @param clip_x,clip_y Coordinates of the top-left corner of the clipping region.
+ * @param clip_w,clip_h Extent of the clipping region.
+ * @param r,g,b,a Color and alpha.
+ */
 void pixbuf_draw_triangle(GdkPixbuf *pb,
                          gint clip_x, gint clip_y, gint clip_w, gint clip_h,
                          gint x1, gint y1, gint x2, gint y2, gint x3, gint y3,
                          guint8 r, guint8 g, guint8 b, guint8 a);
 
+/**
+ * @brief Draws the sub-segment of the specified line segment that lies within the
+ *        clip region into the pixbuf.
+ * @param pb The `GdkPixbuf` to paint into.
+ * @param clip_x,clip_y Coordinates of the top-left corner of the clipping region.
+ * @param clip_w,clip_h Extent of the clipping region.
+ * @param x1,y1 Coordinates of the first point of the line segment.
+ * @param x2,y2 Coordinates of the second point of the line segment.
+ * @param r,g,b,a Color and alpha.
+ */
 void pixbuf_draw_line(GdkPixbuf *pb,
                      gint clip_x, gint clip_y, gint clip_w, gint clip_h,
                      gint x1, gint y1, gint x2, gint y2,
                      guint8 r, guint8 g, guint8 b, guint8 a);
 
+/**
+ * @brief Composites a "shaded" region of the specified color and with the
+ *        specified size and border gradient width into the clip region of the
+ *        specified pixbuf.
+ * @param pb The `GdkPixbuf` to paint into.
+ * @param clip_x,clip_y Coordinates of the top-left corner of the clipping region.
+ * @param clip_w,clip_h Extent of the clipping region.
+ * @param x,y Coordinates of the top-left corner of the shaded region.
+ * @param w,h Extent of the shaded region.
+ * @param border The thickness, in pixels, of the gradient border around the
+ *        fully-shaded region.
+ * @param r,g,b Shadow base color.
+ * @param a The max shadow composition fraction.  Note that any alpha value of the
+ *          original pixel will remain untouched.
+ */
 void pixbuf_draw_shadow(GdkPixbuf *pb,
                        gint clip_x, gint clip_y, gint clip_w, gint clip_h,
                        gint x, gint y, gint w, gint h, gint border,
                        guint8 r, guint8 g, guint8 b, guint8 a);
 
+/**
+ * @brief Sets the r, g, and b values for each pixel within the specified region
+ *        of the pixbuf the average of the original values for that pixel.
+ * @param pb The `GdkPixbuf` to paint into.
+ * @param x,y Coordinates of the top-left corner of the region.
+ * @param w,h Extent of the region.
+ */
 void pixbuf_desaturate_rect(GdkPixbuf *pb,
                            gint x, gint y, gint w, gint h);
+/**
+ * @brief Sets each full-black `(0, 0, 0)` or full-white `(255, 255, 255)` pixel in the
+ *        specified pixbuf region to full-red `(255, 0, 0)`.  Does not change alpha.
+ * @param pb The `GdkPixbuf` to paint into.
+ * @param x,y Coordinates of the top-left corner of the first region.
+ * @param w,h Extent of the first region.
+ */
 void pixbuf_highlight_overunderexposed(GdkPixbuf *pb,
-                           gint x, gint y, gint w, gint h);
+                                      gint x, gint y, gint w, gint h);
+/**
+ * @brief Sets the alpha channel to 255 (fully opaque) for every pixel in the specified
+ *        pixbuf region.
+ * @param pb The `GdkPixbuf` to paint into.
+ * @param x,y Coordinates of the top-left corner of the first region.
+ * @param w,h Extent of the first region.
+ */
 void pixbuf_ignore_alpha_rect(GdkPixbuf *pb,
-                 gint x, gint y, gint w, gint h);
+                             gint x, gint y, gint w, gint h);
 
 /* clipping utils */
 
+// TODO(xsdg): Rename this function to util_intersect_regions.
+/**
+ * @brief Performs an intersection of the two specified regions.
+ * @param[in] x,y Coordinates of the top-left corner of the first region.
+ * @param[in] w,h Extent of the first region.
+ * @param[in] clip_x,clip_y Coordinates of the top-left corner of the second region.
+ * @param[in] clip_w,clip_h Extent of the second region.
+ * @param[out] rx,ry Computed coordinates of the top-left corner of the intersection.
+ * @param[out] rw,rh Computed extent of the intersection.
+ * @retval FALSE The specified regions are non-overlapping.
+ * @retval TRUE The intersection operation was performed, and the output params were set.
+ */
 gboolean util_clip_region(gint x, gint y, gint w, gint h,
                          gint clip_x, gint clip_y, gint clip_w, gint clip_h,
                          gint *rx, gint *ry, gint *rw, gint *rh);
+
+// TODO(xsdg): Rename this function to util_triangle_bounding_box.
+/**
+ * @brief Computes the bounding box for the specified triangle.
+ * @param[in] x1,y1 Coordinates of the first corner of the triangle.
+ * @param[in] x2,y2 Coordinates of the second corner of the triangle.
+ * @param[in] x3,y3 Coordinates of the third corner of the triangle.
+ * @param[out] rx,ry Computed coordinates of the top-left corner of the bounding box.
+ * @param[out] rw,rh Computed extent of the bounding box.
+ */
 void util_clip_triangle(gint x1, gint y1, gint x2, gint y2, gint x3, gint y3,
                         gint &rx, gint &ry, gint &rw, gint &rh);
 
index f0ae2de..287cb1d 100644 (file)
@@ -1654,14 +1654,14 @@ static void accel_store_populate()
        lw = static_cast<LayoutWindow *>(layout_window_list->data); /* get the actions from the first window, it should not matter, they should be the same in all windows */
 
        g_assert(lw && lw->ui_manager);
-       groups = gtk_ui_manager_get_action_groups(lw->ui_manager);
+       groups = gq_gtk_ui_manager_get_action_groups(lw->ui_manager);
        while (groups)
                {
-               actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
+               actions = gq_gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
                while (actions)
                        {
                        action = GTK_ACTION(actions->data);
-                       accel_path = gtk_action_get_accel_path(action);
+                       accel_path = gq_gtk_action_get_accel_path(action);
                        if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
                                {
                                gchar *label;
@@ -1680,7 +1680,7 @@ static void accel_store_populate()
                                        }
 
                                accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
-                               icon_name = gtk_action_get_icon_name(action);
+                               icon_name = gq_gtk_action_get_icon_name(action);
 
                                if (tooltip)
                                        {
@@ -2351,7 +2351,7 @@ static void config_tab_image(GtkWidget *notebook)
                                 100, 999, 1,
                                 options->image.max_enlargement_size, &c_options->image.max_enlargement_size);
        pref_checkbox_link_sensitivity(enlargement_button, spin);
-       gtk_widget_set_tooltip_text(GTK_WIDGET(hbox), _("Enable this to allow Geeqie to increase the image size for images that are smaller than the current view area when the zoom is set to \"Fit image to window\". This value sets the maximum expansion permitted in percent i.e. 100% is full-size."));
+       gtk_widget_set_tooltip_text(GTK_WIDGET(hbox), _("Enable this to allow Geeqie to increase the image size for images that are smaller than the current view area when the zoom is set to 'Fit image to window'. This value sets the maximum expansion permitted in percent i.e. 100% is full-size."));
 
        hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
        ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (%% of actual window):"),
@@ -2360,7 +2360,7 @@ static void config_tab_image(GtkWidget *notebook)
                                 10, 150, 1,
                                 options->image.max_autofit_size, &c_options->image.max_autofit_size);
        pref_checkbox_link_sensitivity(ct_button, spin);
-       gtk_widget_set_tooltip_text(GTK_WIDGET(hbox), _("This value will set the virtual size of the window when \"Fit image to window\" is set. Instead of using the actual size of the window, the specified percentage of the window will be used. It allows one to keep a border around the image (values lower than 100%) or to auto zoom the image (values greater than 100%). It affects fullscreen mode too."));
+       gtk_widget_set_tooltip_text(GTK_WIDGET(hbox), _("This value will set the virtual size of the window when 'Fit image to window' is set. Instead of using the actual size of the window, the specified percentage of the window will be used. It allows one to keep a border around the image (values lower than 100%) or to auto zoom the image (values greater than 100%). It affects fullscreen mode too."));
 
        group = pref_group_new(vbox, FALSE, _("Tile size"), GTK_ORIENTATION_VERTICAL);
 
@@ -2478,7 +2478,7 @@ static void config_tab_windows(GtkWidget *notebook)
 
        widget = pref_checkbox_new_int(group, _("Hide window decorations"),
                              options->hide_window_decorations, &c_options->hide_window_decorations);
-       gtk_widget_set_tooltip_text(widget, "Remove borders and title bar from windows. A restart of Geeqie is required for this feature to take effect on the main layout window");
+       gtk_widget_set_tooltip_text(widget, _("Remove borders and title bar from windows. A restart of Geeqie is required for this feature to take effect on the main layout window"));
 
        pref_checkbox_new_int(group, _("Show window IDs"),
                              options->show_window_ids, &c_options->show_window_ids);
@@ -2993,7 +2993,7 @@ static void config_tab_metadata(GtkWidget *notebook)
        gtk_widget_set_tooltip_text(tmp_widget, _("See the Help file for a list of the tags used"));
 
        tmp_widget = pref_checkbox_new_int(group, _("Permit Keywords to be case-sensitive"), options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
-       gtk_widget_set_tooltip_text(tmp_widget, _("When selected, \"Place\" and \"place\" are two different keywords"));
+       gtk_widget_set_tooltip_text(tmp_widget, _("When selected, 'Place' and 'place' are two different keywords"));
 
        ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"), options->metadata.write_orientation, &c_options->metadata.write_orientation);
        gtk_widget_set_tooltip_text(ct_button, _("If checked, the results of orientation commands (Rotate, Mirror and Flip) issued on an image will be written to metadata\nNote: If this option is not checked, the results of orientation commands will be lost when Geeqie closes"));
@@ -3031,7 +3031,7 @@ static void config_tab_metadata(GtkWidget *notebook)
        group = pref_group_new(vbox, FALSE, _("Pre-load metadata"), GTK_ORIENTATION_VERTICAL);
 
        ct_button = pref_checkbox_new_int(group, _("Read metadata in background"), options->read_metadata_in_idle, &c_options->read_metadata_in_idle);
-       gtk_widget_set_tooltip_text(ct_button,"On folder change, read DateTimeOriginal, DateTimeDigitized and Star Rating in the idle loop.\nIf this is not selected, initial loading of the folder will be faster but sorting on these items will be slower");
+       gtk_widget_set_tooltip_text(ct_button,_("On folder change, read DateTimeOriginal, DateTimeDigitized and Star Rating in the idle loop.\nIf this is not selected, initial loading of the folder will be faster but sorting on these items will be slower"));
 }
 
 /* keywords tab */
@@ -3640,9 +3640,9 @@ static void config_tab_behavior(GtkWidget *notebook)
                                options->marks_save, &c_options->marks_save);
        gtk_widget_set_tooltip_text(marks,_("Note that marks linked to a keyword will be saved irrespective of this setting"));
 
-       with_rename = pref_checkbox_new_int(group, _("Use \"With Rename\" as default for Copy/Move dialogs"),
+       with_rename = pref_checkbox_new_int(group, _("Use 'With Rename' as default for Copy/Move dialogs"),
                                options->with_rename, &c_options->with_rename);
-       gtk_widget_set_tooltip_text(with_rename,"Change the default button for Copy/Move dialogs");
+       gtk_widget_set_tooltip_text(with_rename,_("Change the default button for Copy/Move dialogs"));
 
        collections_on_top = pref_checkbox_new_int(group, _("Permit duplicates in Collections"),
                                options->collections_duplicates, &c_options->collections_duplicates);
@@ -3654,11 +3654,11 @@ static void config_tab_behavior(GtkWidget *notebook)
 
        hide_window_in_fullscreen = pref_checkbox_new_int(group, _("Hide window in fullscreen"),
                                options->hide_window_in_fullscreen, &c_options->hide_window_in_fullscreen);
-       gtk_widget_set_tooltip_text(hide_window_in_fullscreen,"When alt-tabbing, prevent Geeqie window showing twice");
+       gtk_widget_set_tooltip_text(hide_window_in_fullscreen, _("When alt-tabbing, prevent Geeqie window showing twice"));
 
        hide_osd_in_fullscreen = pref_checkbox_new_int(group, _("Hide OSD in fullscreen"),
                                options->hide_osd_in_fullscreen, &c_options->hide_osd_in_fullscreen);
-       gtk_widget_set_tooltip_text(hide_osd_in_fullscreen,"Hide Overlay Screen Display in fullscreen mode");
+       gtk_widget_set_tooltip_text(hide_osd_in_fullscreen, _("Hide Overlay Screen Display in fullscreen mode"));
 
        pref_spin_new_int(group, _("Recent folder list maximum size"), nullptr,
                          1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
index b071094..573b69c 100644 (file)
@@ -1597,10 +1597,10 @@ static void gr_action(const gchar *text, GIOChannel *, gpointer)
                }
        else
                {
-               action = gtk_action_group_get_action(lw_id->action_group, text);
+               action = gq_gtk_action_group_get_action(lw_id->action_group, text);
                if (action)
                        {
-                       gtk_action_activate(action);
+                       gq_gtk_action_activate(action);
                        }
                else
                        {
index 654fbbd..cea35fc 100644 (file)
@@ -1130,128 +1130,132 @@ static void rt_tile_apply_orientation(RendererTiles *rt, gint orientation, GdkPi
                }
 }
 
+/**
+ * @brief Renders the contents of the specified region of the specified ImageTile, using
+ *        SourceTiles that the RendererTiles knows how to create/access.
+ * @param rt The RendererTiles object.
+ * @param it The ImageTile to render.
+ * @param x,y,w,h The sub-region of the ImageTile to render.
+ * @retval TRUE We rendered something that needs to be drawn.
+ * @retval FALSE We didn't render anything that needs to be drawn.
+ */
 static gboolean rt_source_tile_render(RendererTiles *rt, ImageTile *it,
                                      gint x, gint y, gint w, gint h,
-                                     gboolean, gboolean fast)
+                                     gboolean, gboolean)
 {
        PixbufRenderer *pr = rt->pr;
-       GList *list;
-       GList *work;
        gboolean draw = FALSE;
 
-       if (pr->zoom == 1.0 || pr->scale == 1.0)
-               {
-               list = pr_source_tile_compute_region(pr, it->x + x, it->y + y, w, h, TRUE);
-               work = list;
-               while (work)
-                       {
-                       SourceTile *st;
-                       gint rx;
-                       gint ry;
-                       gint rw;
-                       gint rh;
-
-                       st = static_cast<SourceTile *>(work->data);
-                       work = work->next;
-
-                       if (pr_clip_region(st->x, st->y, pr->source_tile_width, pr->source_tile_height,
-                                          it->x + x, it->y + y, w, h,
-                                          &rx, &ry, &rw, &rh))
-                               {
-                               cairo_t *cr;
-                               cr = cairo_create(it->surface);
-                               cairo_rectangle (cr, rx - it->x, ry - it->y, rw, rh);
+       if (pr->image_width == 0 || pr->image_height == 0) return FALSE;
 
-                               if (st->blank)
-                                       {
-                                       cairo_set_source_rgb(cr, 0, 0, 0);
-                                       cairo_fill (cr);
-                                       }
-                               else /* (pr->zoom == 1.0 || pr->scale == 1.0) */
-                                       {
-                                       rt_hidpi_aware_draw(rt, cr, st->pixbuf, -it->x + st->x, -it->y + st->y);
-                                       }
-                               cairo_destroy (cr);
-                               }
-                       }
-               }
-       else
-               {
-               gdouble scale_x;
-               gdouble scale_y;
-               gint sx;
-               gint sy;
-               gint sw;
-               gint sh;
+       // This is the scale due to zooming.  So if the user is zoomed in 2x (we're
+       // rendering twice as large), these numbers will be 2.  Note that these values
+       // can definitely be fractional (becomes important below).
+       const gdouble scale_x = static_cast<gdouble>(pr->width) / pr->image_width;
+       const gdouble scale_y = static_cast<gdouble>(pr->height) / pr->image_height;
 
-               if (pr->image_width == 0 || pr->image_height == 0) return FALSE;
-               scale_x = static_cast<gdouble>(pr->width) / pr->image_width;
-               scale_y = static_cast<gdouble>(pr->height) / pr->image_height;
+       // And these are the unscaled coordinates where our tile data should originate from.
+       const gint sx = static_cast<gdouble>(it->x + x) / scale_x;
+       const gint sy = static_cast<gdouble>(it->y + y) / scale_y;
+       const gint sw = static_cast<gdouble>(w) / scale_x;
+       const gint sh = static_cast<gdouble>(h) / scale_y;
 
-               sx = static_cast<gdouble>(it->x + x) / scale_x;
-               sy = static_cast<gdouble>(it->y + y) / scale_y;
-               sw = static_cast<gdouble>(w) / scale_x;
-               sh = static_cast<gdouble>(h) / scale_y;
-
-               if (pr->width < PR_MIN_SCALE_SIZE || pr->height < PR_MIN_SCALE_SIZE) fast = TRUE;
+       /* HACK: The pixbuf scalers get kinda buggy(crash) with extremely
+        * small sizes for anything but GDK_INTERP_NEAREST
+        */
+       const gboolean force_nearest = pr->width < PR_MIN_SCALE_SIZE || pr->height < PR_MIN_SCALE_SIZE;
 
 #if 0
-               /* draws red over draw region, to check for leaks (regions not filled) */
-               pixbuf_set_rect_fill(it->pixbuf, x, y, w, h, 255, 0, 0, 255);
+       // Draws red over draw region, to check for leaks (regions not filled)
+       pixbuf_set_rect_fill(it->pixbuf, x, y, rt->hidpi_scale * w, rt->hidpi_scale * h, 255, 0, 0, 255);
 #endif
 
-               list = pr_source_tile_compute_region(pr, sx, sy, sw, sh, TRUE);
-               work = list;
-               while (work)
+       // Since the RendererTiles ImageTiles and PixbufRenderer SourceTiles are different
+       // sizes and may not exactly overlap, we now determine which SourceTiles are needed
+       // to cover the ImageTile that we're being asked to render.
+       //
+       // This will render the relevant SourceTiles if needed, or pull from the cache if
+       // they've already been generated.
+       GList *list = pr_source_tile_compute_region(pr, sx, sy, sw, sh, TRUE);
+       GList *work = list;
+       while (work)
+               {
+               const auto st = static_cast<SourceTile *>(work->data);
+               work = work->next;
+
+               // The scaled (output) coordinates that are covered by this SourceTile.
+               // To avoid aliasing line artifacts due to under-drawing, we expand the
+               // render area to the nearest whole pixel.
+               const gint stx = floor(st->x * scale_x);
+               const gint sty = floor(st->y * scale_y);
+               const gint stw = ceil((st->x + pr->source_tile_width) * scale_x) - stx;
+               const gint sth = ceil((st->y + pr->source_tile_height) * scale_y) - sty;
+
+               // We find the overlapping region (r{x,y,w,h}) between the ImageTile (output)
+               // region and the region that's covered by this SourceTile (input).
+               gint rx, ry, rw, rh;  // NOLINT(readability-isolate-declaration)
+               if (pr_clip_region(stx, sty, stw, sth,
+                                  it->x + x, it->y + y, w, h,
+                                  &rx, &ry, &rw, &rh))
                        {
-                       SourceTile *st;
-                       gint rx;
-                       gint ry;
-                       gint rw;
-                       gint rh;
-                       gint stx;
-                       gint sty;
-                       gint stw;
-                       gint sth;
-
-                       st = static_cast<SourceTile *>(work->data);
-                       work = work->next;
-
-                       stx = floor(static_cast<gdouble>(st->x) * scale_x);
-                       sty = floor(static_cast<gdouble>(st->y) * scale_y);
-                       stw = ceil(static_cast<gdouble>(st->x + pr->source_tile_width) * scale_x) - stx;
-                       sth = ceil(static_cast<gdouble>(st->y + pr->source_tile_height) * scale_y) - sty;
-
-                       if (pr_clip_region(stx, sty, stw, sth,
-                                          it->x + x, it->y + y, w, h,
-                                          &rx, &ry, &rw, &rh))
-                               {
 
-                               if (st->blank)
-                                       {
-                                       cairo_t *cr;
-                                       cr = cairo_create(it->surface);
-                                       cairo_rectangle (cr, rx - st->x, ry - st->y, rw, rh);
-                                       cairo_set_source_rgb(cr, 0, 0, 0);
-                                       cairo_fill (cr);
-                                       cairo_destroy (cr);
-                                       }
-                               else
-                                       {
-                                       gdouble offset_x;
-                                       gdouble offset_y;
-
-                                       /* may need to use unfloored stx,sty values here */
-                                       offset_x = static_cast<gdouble>(stx - it->x);
-                                       offset_y = static_cast<gdouble>(sty - it->y);
-
-                                       gdk_pixbuf_scale(st->pixbuf, it->pixbuf, rx - it->x, ry - it->y, rw, rh,
-                                                static_cast<gdouble>(0.0) + offset_x,
-                                                static_cast<gdouble>(0.0) + offset_y,
-                                                scale_x, scale_y,
-                                                (fast) ? GDK_INTERP_NEAREST : pr->zoom_quality);
-                                       draw = TRUE;
-                                       }
+                       if (st->blank)
+                               {
+                               // If this SourceTile has no contents, we just paint a black rect
+                               // of the appropriate size.
+                               cairo_t *cr = cairo_create(it->surface);
+                               cairo_rectangle (cr, rx - st->x, ry - st->y, rt->hidpi_scale * rw, rt->hidpi_scale * rh);
+                               cairo_set_source_rgb(cr, 0, 0, 0);
+                               cairo_fill (cr);
+                               cairo_destroy (cr);
+                               // TODO(xsdg): We almost certainly need to set draw = TRUE in this branch.
+                               // This may explain the smearing that we sometimes get when panning the view while drawing.
+                               }
+                       else
+                               {
+                               // Note that the ImageTile it contains its own solitary pixbuf, it->pixbuf.
+                               // This means that the region covered by this function (possibly split across
+                               // multiple SourceTiles) has origin (0, 0).  Additionally, the width and height
+                               // of that pixbuf will reflect the value of GDK_SCALE (which is stored by the
+                               // RendererTiles rt).  The following is an invariant:
+                               // it->pixbuf->width  = rt->hidpi_scale * it->width
+                               // it->pixbuf->height = rt->hidpi_scale * it->height
+                               //
+                               // So for hidpi rendering, we need to multiply the scale factor from the zoom by
+                               // the additional scale factor for hidpi.  This combined scale factor is then
+                               // applied to the offset (explained below), width, and height.
+
+                               // (May need to use unfloored stx,sty values here)
+                               const gdouble offset_x = rt->hidpi_scale * static_cast<gdouble>(stx - it->x);
+                               const gdouble offset_y = rt->hidpi_scale * static_cast<gdouble>(sty - it->y);
+
+                               // TODO(xsdg): Just draw instead of usign scale-draw for the case where
+                               // (pr->zoom == 1.0 || pr->scale == 1.0)
+
+                               // The order of operations in this function is scale, offset, clip, copy.
+                               // So we start with the data from st->pixbuf.  First we scale that data by
+                               // the scale factors.  Then we offset that intermediate image by the offsets.
+                               // Next, we clip that offsetted image to the (x,y,w,h) region specified.  And
+                               // lastly, we copy the resulting region into the _region with the same
+                               // coordinates_ in it->pixbuf.
+                               //
+                               // At this point, recall that we may need to render into ImageTile from multiple
+                               // SourceTiles.  The region specified by r{x,y,w,h} accounts for this, and thus,
+                               // those are the coordinates _within the current SourceTile_ that need to be
+                               // rendered into the ImageTile.
+                               //
+                               // The offsets translate the region from wherever it may be in the actual image
+                               // to the ImageTile pixbuf coordinate system.  Because ImageTile and SourceTile
+                               // coordinates are not necessarily aligned, an offset will be negative if this
+                               // SourceTile starts left of or above the ImageTile, positive if it starts in
+                               // the middle of the ImageTile, or zero if the left or top edges are aligned.
+                               gdk_pixbuf_scale(
+                                       st->pixbuf, it->pixbuf,
+                                       rx - it->x, ry - it->y, rt->hidpi_scale * rw, rt->hidpi_scale * rh,
+                                       offset_x, offset_y,
+                                       rt->hidpi_scale * scale_x, rt->hidpi_scale * scale_y,
+                                       (force_nearest) ? GDK_INTERP_NEAREST : pr->zoom_quality);
+                               draw = TRUE;
                                }
                        }
                }
index c23da61..b6b8202 100644 (file)
@@ -104,14 +104,14 @@ static void command_store_populate(SarData* sar)
 
        gtk_tree_sortable_set_sort_column_id(sortable, SAR_LABEL, GTK_SORT_ASCENDING);
 
-       groups = gtk_ui_manager_get_action_groups(sar->lw->ui_manager);
+       groups = gq_gtk_ui_manager_get_action_groups(sar->lw->ui_manager);
        while (groups)
                {
-               actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
+               actions = gq_gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
                while (actions)
                        {
                        action = GTK_ACTION(actions->data);
-                       accel_path = gtk_action_get_accel_path(action);
+                       accel_path = gq_gtk_action_get_accel_path(action);
                        if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
                                {
                                g_object_get(action, "tooltip", &tooltip, "label", &label, NULL);
@@ -199,7 +199,7 @@ static gboolean entry_box_activate_cb(GtkWidget *, gpointer data)
 
        if (sar->action)
                {
-               gtk_action_activate(sar->action);
+               gq_gtk_action_activate(sar->action);
                }
 
        search_and_run_destroy(sar);
@@ -236,7 +236,7 @@ static gboolean match_selected_cb(GtkEntryCompletion *, GtkTreeModel *model, Gtk
 
        if (sar->action)
                {
-               gtk_action_activate(sar->action);
+               gq_gtk_action_activate(sar->action);
                }
 
        g_idle_add(static_cast<GSourceFunc>(search_and_run_destroy), sar);
index 79625e6..7ef6da2 100644 (file)
@@ -2736,9 +2736,7 @@ static void search_start_cb(GtkWidget *, gpointer data)
                                                sd->search_lat < -90 || sd->search_lat > 90 ||
                                                sd->search_lon < -180 || sd->search_lon > 180)
                                {
-                               file_util_warning_dialog(_(
-                                               "Entry does not contain a valid lat/long value"),
-                                                       entry_text, GQ_ICON_DIALOG_WARNING, sd->window);
+                               file_util_warning_dialog(_("Entry does not contain a valid lat/long value"), entry_text, GQ_ICON_DIALOG_WARNING, sd->window);
                                return;
                                }
                        g_free(entry_text);
@@ -3449,7 +3447,7 @@ void search_new(FileData *dir_fd, FileData *example_file)
        pref_checkbox_new_int(hbox, _("Match case"),
                              sd->search_name_match_case, &sd->search_name_match_case);
        pref_checkbox_new_int(hbox, _("Symbolic link"), sd->search_name_symbolic_link, &sd->search_name_symbolic_link);
-       gtk_widget_set_tooltip_text(GTK_WIDGET(combo), "When set to \"contains\" or \"path contains\", this field uses Perl Compatible Regular Expressions.\ne.g. use \n.*\\.jpg\n and not \n*.jpg\n\nSee the Help file.");
+       gtk_widget_set_tooltip_text(GTK_WIDGET(combo), _("When set to 'contains' or 'path contains', this field uses Perl Compatible Regular Expressions.\ne.g. use \n.*\\.jpg\n and not \n*.jpg\n\nSee the Help file."));
 
        /* Search for file size */
        hbox = menu_choice(sd->box_search, &sd->check_size, &sd->menu_size,
@@ -3558,7 +3556,7 @@ void search_new(FileData *dir_fd, FileData *example_file)
        gtk_widget_show(sd->entry_comment);
        pref_checkbox_new_int(hbox, _("Match case"),
                              sd->search_comment_match_case, &sd->search_comment_match_case);
-       gtk_widget_set_tooltip_text(GTK_WIDGET(sd->entry_comment), "This field uses Perl Compatible Regular Expressions.\ne.g. use \nabc.*ghk\n and not \nabc*ghk\n\nSee the Help file.");
+       gtk_widget_set_tooltip_text(GTK_WIDGET(sd->entry_comment), _("This field uses Perl Compatible Regular Expressions.\ne.g. use \nabc.*ghk\n and not \nabc*ghk\n\nSee the Help file."));
 
        /* Search for image rating */
        hbox = menu_choice(sd->box_search, &sd->check_rating, &sd->menu_rating,
@@ -3720,7 +3718,7 @@ void search_new(FileData *dir_fd, FileData *example_file)
 
        sd->button_thumbs = pref_checkbox_new(hbox, _("Thumbnails"), FALSE,
                                              G_CALLBACK(search_thumb_toggle_cb), sd);
-       gtk_widget_set_tooltip_text(GTK_WIDGET(sd->button_thumbs), "Ctrl-T");
+       gtk_widget_set_tooltip_text(GTK_WIDGET(sd->button_thumbs), _("Ctrl-T"));
 
        frame = gtk_frame_new(nullptr);
        DEBUG_NAME(frame);
@@ -3752,15 +3750,15 @@ void search_new(FileData *dir_fd, FileData *example_file)
        pref_spacer(hbox, PREF_PAD_BUTTON_GAP);
        sd->button_start = pref_button_new(hbox, GQ_ICON_FIND, _("Find"),
                                           G_CALLBACK(search_start_cb), sd);
-       gtk_widget_set_tooltip_text(GTK_WIDGET(sd->button_start), "Ctrl-Return");
+       gtk_widget_set_tooltip_text(GTK_WIDGET(sd->button_start), _("Ctrl-Return"));
        pref_spacer(hbox, PREF_PAD_BUTTON_GAP);
        sd->button_stop = pref_button_new(hbox, GQ_ICON_STOP, _("Stop"),
                                          G_CALLBACK(search_start_cb), sd);
-       gtk_widget_set_tooltip_text(GTK_WIDGET(sd->button_stop), "Ctrl-Return");
+       gtk_widget_set_tooltip_text(GTK_WIDGET(sd->button_stop), _("Ctrl-Return"));
        gtk_widget_set_sensitive(sd->button_stop, FALSE);
        pref_spacer(hbox, PREF_PAD_BUTTON_GAP);
        sd->button_close = pref_button_new(hbox, GQ_ICON_CLOSE, _("Close"), G_CALLBACK(search_window_close_cb), sd);
-       gtk_widget_set_tooltip_text(GTK_WIDGET(sd->button_close), "Ctrl-W");
+       gtk_widget_set_tooltip_text(GTK_WIDGET(sd->button_close), _("Ctrl-W"));
        gtk_widget_set_sensitive(sd->button_close, TRUE);
 
        search_result_thumb_enable(sd, TRUE);
index 417cf84..7fe2d0d 100644 (file)
@@ -59,7 +59,6 @@ struct ToolbarButtonData
        GtkWidget *image;
 
        const gchar *name; /* GtkActionEntry terminology */
-       const gchar *stock_id;
 };
 
 static ToolbarData *toolbarlist[2];
@@ -190,7 +189,6 @@ static void toolbar_item_free(ToolbarButtonData *tbbd)
        if (!tbbd) return;
 
        g_free(const_cast<gchar *>(tbbd->name));
-       g_free(const_cast<gchar *>(tbbd->stock_id));
        g_free(const_cast<ToolbarButtonData *>(tbbd));
 }
 
@@ -223,7 +221,6 @@ static void toolbarlist_add_button(const gchar *name, const gchar *label,
 
        toolbar_entry->button_label = gtk_label_new(label);
        toolbar_entry->name = g_strdup(name);
-       toolbar_entry->stock_id = g_strdup(stock_id);
 
 #if HAVE_GTK4
        gesture = gtk_gesture_click_new();
@@ -234,11 +231,11 @@ static void toolbarlist_add_button(const gchar *name, const gchar *label,
        gtk_gesture_single_set_button(GTK_GESTURE_SINGLE(gesture), MOUSE_BUTTON_RIGHT);
        g_signal_connect(gesture, "released", G_CALLBACK(toolbar_press_cb), toolbar_entry);
 
-       if (toolbar_entry->stock_id)
+       if (stock_id)
                {
                GdkPixbuf *pixbuf;
                gchar *iconl;
-               iconl = path_from_utf8(toolbar_entry->stock_id);
+               iconl = path_from_utf8(stock_id);
                pixbuf = gdk_pixbuf_new_from_file(iconl, nullptr);
                g_free(iconl);
                if (pixbuf)
@@ -259,8 +256,7 @@ static void toolbarlist_add_button(const gchar *name, const gchar *label,
                        }
                else
                        {
-                       toolbar_entry->image = gtk_image_new_from_stock(toolbar_entry->stock_id,
-                                                                                                               GTK_ICON_SIZE_BUTTON);
+                       toolbar_entry->image = gtk_image_new_from_stock(stock_id, GTK_ICON_SIZE_BUTTON);
                        }
                }
        else
index 7daa656..44d5cb0 100644 (file)
@@ -202,7 +202,7 @@ gboolean file_util_safe_unlink(const gchar *path)
 
                if (!g_file_trash(tmp, FALSE, &error) )
                        {
-                       message = g_strconcat("See the Help file for a possible workaround.\n\n", error->message, NULL);
+                       message = g_strconcat(_("See the Help file for a possible workaround.\n\n"), error->message, NULL);
                        gd = warning_dialog(_("Move to trash failed\n\n"), message, GQ_ICON_DIALOG_ERROR, nullptr);
                        generic_dialog_add_button(gd, GQ_ICON_HELP, _("Help"), move_to_trash_failed_cb, FALSE);
 
index 69a8f49..293c8fc 100644 (file)
@@ -770,7 +770,7 @@ static void bookmark_dnd_get_data(GtkWidget *, GdkDragContext *,
 
                        if (strstr(real_path, get_collections_dir()) && isfile(path))
                                {
-                               buf = bookmark_string(filename_from_path(path), path, "gq-icon-collection");
+                               buf = bookmark_string(filename_from_path(path), path, PIXBUF_INLINE_COLLECTION);
                                }
                        else if (isfile(path))
                                {
@@ -916,7 +916,7 @@ void bookmark_list_add(GtkWidget *list, const gchar *name, const gchar *path)
 
        if (strstr(real_path, get_collections_dir()) && isfile(path))
                {
-               buf.reset(bookmark_string(name, path, "gq-icon-collection"));
+               buf.reset(bookmark_string(name, path, PIXBUF_INLINE_COLLECTION));
                }
        else
                {
index 2fd315e..9c04a0a 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <pango/pango.h>
 
+#include "compat.h"
 #include "layout.h"
 
 /*
@@ -89,8 +90,8 @@ static gint actions_sort_cb(gconstpointer a, gconstpointer b)
        const gchar *accel_path_b;
        GtkAccelKey key_b;
 
-       accel_path_a = gtk_action_get_accel_path(GTK_ACTION(a));
-       accel_path_b = gtk_action_get_accel_path(GTK_ACTION(b));
+       accel_path_a = gq_gtk_action_get_accel_path(GTK_ACTION(a));
+       accel_path_b = gq_gtk_action_get_accel_path(GTK_ACTION(b));
 
        if (accel_path_a && gtk_accel_map_lookup_entry(accel_path_a, &key_a) && accel_path_b && gtk_accel_map_lookup_entry(accel_path_b, &key_b))
                {
@@ -130,17 +131,17 @@ static void menu_item_add_main_window_accelerator(GtkWidget *menu, GtkAccelGroup
        lw = static_cast<LayoutWindow *>(layout_window_list->data); /* get the actions from the first window, it should not matter, they should be the same in all windows */
 
        g_assert(lw && lw->ui_manager);
-       groups = gtk_ui_manager_get_action_groups(lw->ui_manager);
+       groups = gq_gtk_ui_manager_get_action_groups(lw->ui_manager);
 
        while (groups)
                {
-               actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
+               actions = gq_gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
                actions = g_list_sort(actions, actions_sort_cb);
 
                while (actions)
                        {
                        action = GTK_ACTION(actions->data);
-                       accel_path = gtk_action_get_accel_path(action);
+                       accel_path = gq_gtk_action_get_accel_path(action);
                        if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
                                {
                                g_object_get(action, "label", &action_label, NULL);
index 47aff9e..71d023d 100644 (file)
@@ -1504,14 +1504,14 @@ GList* get_action_items()
                return nullptr;
                }
 
-       groups = gtk_ui_manager_get_action_groups(lw->ui_manager);
+       groups = gq_gtk_ui_manager_get_action_groups(lw->ui_manager);
        while (groups)
                {
-               actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
+               actions = gq_gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
                while (actions)
                        {
                        action = GTK_ACTION(actions->data);
-                       accel_path = gtk_action_get_accel_path(action);
+                       accel_path = gq_gtk_action_get_accel_path(action);
 
                        if (accel_path && gtk_accel_map_lookup_entry(accel_path, nullptr))
                                {
@@ -1544,7 +1544,7 @@ GList* get_action_items()
                                                }
 
                                        action_item->name = action_name;
-                                       action_item->icon_name = g_strdup(gtk_action_get_stock_id(action));
+                                       action_item->icon_name = g_strdup(gq_gtk_action_get_stock_id(action));
 
                                        list_duplicates = g_list_prepend(list_duplicates, action_item);
                                        }
@@ -1609,10 +1609,10 @@ gboolean defined_mouse_buttons(GtkWidget *, GdkEventButton *event, gpointer data
                                        }
                                else
                                        {
-                                       action = gtk_action_group_get_action(lw->action_group, options->mouse_button_8);
+                                       action = gq_gtk_action_group_get_action(lw->action_group, options->mouse_button_8);
                                        if (action)
                                                {
-                                               gtk_action_activate(action);
+                                               gq_gtk_action_activate(action);
                                                }
                                        ret = TRUE;
                                        }
@@ -1627,11 +1627,11 @@ gboolean defined_mouse_buttons(GtkWidget *, GdkEventButton *event, gpointer data
                                        }
                                else
                                        {
-                                       action = gtk_action_group_get_action(lw->action_group, options->mouse_button_9);
+                                       action = gq_gtk_action_group_get_action(lw->action_group, options->mouse_button_9);
                                        ret = TRUE;
                                        if (action)
                                                {
-                                               gtk_action_activate(action);
+                                               gq_gtk_action_activate(action);
                                                }
                                        ret = TRUE;
                                        }
index 1eedd5f..9bb913d 100644 (file)
@@ -832,65 +832,33 @@ void vficon_select_list(ViewFile *vf, GList *list)
 
 void vficon_mark_to_selection(ViewFile *vf, gint mark, MarkToSelectionMode mode)
 {
-       GList *work;
-       gint n = mark - 1;
-
        g_assert(mark >= 1 && mark <= FILEDATA_MARKS_SIZE);
 
-       work = vf->list;
-       while (work)
+       for (GList *work = vf->list; work; work = work->next)
                {
                auto fd = static_cast<FileData *>(work->data);
-               gboolean mark_val;
                gboolean selected;
 
                g_assert(fd->magick == FD_MAGICK);
 
-               mark_val = file_data_get_mark(fd, n);
-               selected = fd->selected & SELECTION_SELECTED;
-
-               switch (mode)
-                       {
-                       case MTS_MODE_SET: selected = mark_val;
-                               break;
-                       case MTS_MODE_OR: selected = mark_val || selected;
-                               break;
-                       case MTS_MODE_AND: selected = mark_val && selected;
-                               break;
-                       case MTS_MODE_MINUS: selected = !mark_val && selected;
-                               break;
-                       }
+               selected = file_data_mark_to_selection(fd, mark, mode, fd->selected & SELECTION_SELECTED);
 
                vficon_select_util(vf, fd, selected);
-
-               work = work->next;
                }
 }
 
 void vficon_selection_to_mark(ViewFile *vf, gint mark, SelectionToMarkMode mode)
 {
        GList *slist;
-       GList *work;
-       gint n = mark -1;
 
        g_assert(mark >= 1 && mark <= FILEDATA_MARKS_SIZE);
 
        slist = vficon_selection_get_list(vf);
-       work = slist;
-       while (work)
+       for (GList *work = slist; work; work = work->next)
                {
                auto fd = static_cast<FileData *>(work->data);
 
-               switch (mode)
-                       {
-                       case STM_MODE_SET: file_data_set_mark(fd, n, 1);
-                               break;
-                       case STM_MODE_RESET: file_data_set_mark(fd, n, 0);
-                               break;
-                       case STM_MODE_TOGGLE: file_data_set_mark(fd, n, !file_data_get_mark(fd, n));
-                               break;
-                       }
-               work = work->next;
+               file_data_selection_to_mark(fd, mark, mode);
                }
        filelist_free(slist);
 }
index 32c2f13..e0e53e1 100644 (file)
@@ -710,28 +710,24 @@ static void vflist_collapse_cb(GtkTreeView *, GtkTreeIter *iter, GtkTreePath *,
  *-----------------------------------------------------------------------------
  */
 
-
-static gchar* vflist_get_formatted(ViewFile *vf, const gchar *name, const gchar *sidecars, const gchar *size, const gchar *time, gboolean expanded, gboolean with_stars, const gchar *star_rating)
- {
+static gchar* vflist_get_formatted(ViewFile *vf, const gchar *name, const gchar *sidecars, const gchar *size, const gchar *time, gboolean expanded, const gchar *star_rating)
+{
        gboolean multiline = vflist_is_multiline(vf);
-       gchar *text;
+       GString *text = g_string_new(nullptr);
+
+       g_string_printf(text, "%s %s", name, expanded ? "" : sidecars);
 
        if (multiline)
                {
-               if (with_stars)
-                       {
-                                       text = g_strdup_printf("%s %s\n%s\n%s\n%s", name, expanded ? "" : sidecars, size, time, star_rating);
-                       }
-               else
+               g_string_append_printf(text, "\n%s\n%s", size, time);
+
+               if (star_rating)
                        {
-                       text = g_strdup_printf("%s %s\n%s\n%s", name, expanded ? "" : sidecars, size, time);
+                       g_string_append_printf(text, "\n%s", star_rating);
                        }
                }
-       else
-               {
-               text = g_strdup_printf("%s %s", name, expanded ? "" : sidecars);
-               }
-       return text;
+
+       return g_string_free(text, FALSE);
 }
 
 static void vflist_set_expanded(ViewFile *vf, GtkTreeIter *iter, gboolean expanded)
@@ -754,8 +750,8 @@ static void vflist_set_expanded(ViewFile *vf, GtkTreeIter *iter, gboolean expand
                                        FILE_COLUMN_STAR_RATING, &star_rating,
                                        -1);
 
-       formatted = vflist_get_formatted(vf, name, sidecars, size, time, expanded, FALSE, nullptr);
-       formatted_with_stars = vflist_get_formatted(vf, name, sidecars, size, time, expanded, TRUE, star_rating);
+       formatted = vflist_get_formatted(vf, name, sidecars, size, time, expanded, nullptr);
+       formatted_with_stars = vflist_get_formatted(vf, name, sidecars, size, time, expanded, star_rating);
 
        gtk_tree_store_set(store, iter, FILE_COLUMN_FORMATTED, formatted,
                                        FILE_COLUMN_EXPANDED, expanded,
@@ -804,8 +800,8 @@ static void vflist_setup_iter(ViewFile *vf, GtkTreeStore *store, GtkTreeIter *it
        name = g_strdup_printf("%s%s%s", link, fd->name, disabled_grouping);
        size = text_from_size(fd->size);
 
-       formatted = vflist_get_formatted(vf, name, sidecars, size, time, expanded, FALSE, nullptr);
-       formatted_with_stars = vflist_get_formatted(vf, name, sidecars, size, time, expanded, TRUE, star_rating);
+       formatted = vflist_get_formatted(vf, name, sidecars, size, time, expanded, nullptr);
+       formatted_with_stars = vflist_get_formatted(vf, name, sidecars, size, time, expanded, star_rating);
 
        gtk_tree_store_set(store, iter, FILE_COLUMN_POINTER, fd,
                                        FILE_COLUMN_VERSION, fd->version,
@@ -1158,7 +1154,7 @@ void vflist_set_star_fd(ViewFile *vf, FileData *fd)
                                        FILE_COLUMN_EXPANDED, &expanded,
                                        -1);
 
-       formatted_with_stars = vflist_get_formatted(vf, name, sidecars, size, time, expanded, TRUE, star_rating);
+       formatted_with_stars = vflist_get_formatted(vf, name, sidecars, size, time, expanded, star_rating);
 
        gtk_tree_store_set(store, &iter, FILE_COLUMN_FORMATTED_WITH_STARS, formatted_with_stars,
                                        FILE_COLUMN_EXPANDED, expanded,
@@ -1596,7 +1592,6 @@ void vflist_mark_to_selection(ViewFile *vf, gint mark, MarkToSelectionMode mode)
        GtkTreeIter iter;
        GtkTreeSelection *selection;
        gboolean valid;
-       gint n = mark - 1;
 
        g_assert(mark >= 1 && mark <= FILEDATA_MARKS_SIZE);
 
@@ -1607,24 +1602,10 @@ void vflist_mark_to_selection(ViewFile *vf, gint mark, MarkToSelectionMode mode)
        while (valid)
                {
                FileData *fd;
-               gboolean mark_val;
                gboolean selected;
                gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, FILE_COLUMN_POINTER, &fd, -1);
 
-               mark_val = file_data_get_mark(fd, n);
-               selected = gtk_tree_selection_iter_is_selected(selection, &iter);
-
-               switch (mode)
-                       {
-                       case MTS_MODE_SET: selected = mark_val;
-                               break;
-                       case MTS_MODE_OR: selected = mark_val || selected;
-                               break;
-                       case MTS_MODE_AND: selected = mark_val && selected;
-                               break;
-                       case MTS_MODE_MINUS: selected = !mark_val && selected;
-                               break;
-                       }
+               selected = file_data_mark_to_selection(fd, mark, mode, gtk_tree_selection_iter_is_selected(selection, &iter));
 
                if (selected)
                        gtk_tree_selection_select_iter(selection, &iter);
@@ -1640,15 +1621,12 @@ void vflist_selection_to_mark(ViewFile *vf, gint mark, SelectionToMarkMode mode)
        GtkTreeModel *store;
        GtkTreeSelection *selection;
        GList *slist;
-       GList *work;
-       gint n = mark - 1;
 
        g_assert(mark >= 1 && mark <= FILEDATA_MARKS_SIZE);
 
        selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
        slist = gtk_tree_selection_get_selected_rows(selection, &store);
-       work = slist;
-       while (work)
+       for (GList *work = slist; work; work = work->next)
                {
                auto tpath = static_cast<GtkTreePath *>(work->data);
                FileData *fd;
@@ -1661,15 +1639,7 @@ void vflist_selection_to_mark(ViewFile *vf, gint mark, SelectionToMarkMode mode)
                   complete re-read of the directory - try to do only minimal update instead */
                file_data_unregister_notify_func(vf_notify_cb, vf); /* we don't need the notification */
 
-               switch (mode)
-                       {
-                       case STM_MODE_SET: file_data_set_mark(fd, n, 1);
-                               break;
-                       case STM_MODE_RESET: file_data_set_mark(fd, n, 0);
-                               break;
-                       case STM_MODE_TOGGLE: file_data_set_mark(fd, n, !file_data_get_mark(fd, n));
-                               break;
-                       }
+               file_data_selection_to_mark(fd, mark, mode);
 
                if (!file_data_filter_marks(fd, vf_marks_get_filter(vf))) /* file no longer matches the filter -> remove it */
                        {
@@ -1683,10 +1653,7 @@ void vflist_selection_to_mark(ViewFile *vf, gint mark, SelectionToMarkMode mode)
                        vflist_setup_iter_recursive(vf, GTK_TREE_STORE(store), &iter, fd->sidecar_files, nullptr, FALSE);
                        }
 
-
                file_data_register_notify_func(vf_notify_cb, vf, NOTIFY_PRIORITY_MEDIUM);
-
-               work = work->next;
                }
        g_list_free_full(slist, reinterpret_cast<GDestroyNotify>(gtk_tree_path_free));
 }