Preferences tabs orientation
[geeqie.git] / src / preferences.c
index fce03ad..5376f08 100644 (file)
 #include "preferences.h"
 
 #include "bar_exif.h"
+#include "bar_keywords.h"
 #include "cache.h"
 #include "cache_maint.h"
+#include "dnd.h"
 #include "editors.h"
 #include "exif.h"
 #include "filedata.h"
 #include "img-view.h"
 #include "layout_config.h"
 #include "layout_util.h"
+#include "metadata.h"
+#include "osd.h"
 #include "pixbuf_util.h"
 #include "slideshow.h"
+#include "toolbar.h"
 #include "trash.h"
 #include "utilops.h"
 #include "ui_fileops.h"
 #include "ui_misc.h"
+#include "ui_spinner.h"
 #include "ui_tabcomp.h"
 #include "ui_utildlg.h"
 #include "window.h"
-
-#include <math.h>
+#include "zonedetect.h"
 
 #ifdef HAVE_LCMS
 #ifdef HAVE_LCMS2
@@ -61,6 +66,9 @@
 
 static void image_overlay_set_text_colours();
 
+GtkWidget *keyword_text;
+static void config_tab_keywords_save();
+
 typedef struct _ThumbSize ThumbSize;
 struct _ThumbSize
 {
@@ -102,11 +110,14 @@ enum {
        AE_ACCEL
 };
 
-static gchar *format_class_list[] = {
+gchar *format_class_list[] = {
        N_("Unknown"),
        N_("Image"),
        N_("RAW Image"),
-       N_("Metadata")
+       N_("Metadata"),
+       N_("Video"),
+       N_("Collection"),
+       N_("Pdf")
        };
 
 /* config memory values */
@@ -128,6 +139,7 @@ static GtkWidget *color_profile_input_name_entry[COLOR_PROFILE_INPUTS];
 static GtkWidget *color_profile_screen_file_entry;
 
 static GtkWidget *sidecar_ext_entry;
+static GtkWidget *help_search_engine_entry;
 
 
 #define CONFIG_WINDOW_DEF_WIDTH                700
@@ -139,27 +151,53 @@ static GtkWidget *sidecar_ext_entry;
  *-----------------------------------------------------------------------------
  */
 
-static void zoom_mode_cb(GtkWidget *widget, gpointer data)
+static void zoom_increment_cb(GtkWidget *spin, gpointer data)
 {
-       if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
-               c_options->image.zoom_mode = GPOINTER_TO_INT(data);
+       c_options->image.zoom_increment = (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) * 100.0 + 0.01);
 }
 
-static void scroll_reset_cb(GtkWidget *widget, gpointer data)
+static void slideshow_delay_hours_cb(GtkWidget *spin, gpointer data)
 {
-       if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
-               c_options->image.scroll_reset_method = GPOINTER_TO_INT(data);
+       gint mins_secs_tenths, delay;
+
+       mins_secs_tenths = c_options->slideshow.delay %
+                                               (3600 * SLIDESHOW_SUBSECOND_PRECISION);
+
+       delay = (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
+                                                               (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
+                                                               mins_secs_tenths);
+
+       c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
+                                                                                                       SLIDESHOW_SUBSECOND_PRECISION;
 }
 
-static void zoom_increment_cb(GtkWidget *spin, gpointer data)
+static void slideshow_delay_minutes_cb(GtkWidget *spin, gpointer data)
 {
-       c_options->image.zoom_increment = (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) * 100.0 + 0.01);
+       gint hours, secs_tenths, delay;
+
+       hours = c_options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
+       secs_tenths = c_options->slideshow.delay % (60 * SLIDESHOW_SUBSECOND_PRECISION);
+
+       delay = hours * (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
+                                       (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
+                                       (60 * SLIDESHOW_SUBSECOND_PRECISION) + secs_tenths);
+
+       c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
+                                                                                                       SLIDESHOW_SUBSECOND_PRECISION;
 }
 
-static void slideshow_delay_cb(GtkWidget *spin, gpointer data)
+static void slideshow_delay_seconds_cb(GtkWidget *spin, gpointer data)
 {
-       c_options->slideshow.delay = (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
-                                  (gdouble)SLIDESHOW_SUBSECOND_PRECISION + 0.01);
+       gint hours_mins, delay;
+
+       hours_mins = c_options->slideshow.delay / (60 * SLIDESHOW_SUBSECOND_PRECISION);
+
+       delay = (hours_mins * (60 * SLIDESHOW_SUBSECOND_PRECISION)) +
+                                                       (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
+                                                       (gdouble)(SLIDESHOW_SUBSECOND_PRECISION) + 0.01);
+
+       c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
+                                                                                                       SLIDESHOW_SUBSECOND_PRECISION;
 }
 
 /*
@@ -222,12 +260,14 @@ static void config_window_apply(void)
 
        options->file_ops.confirm_delete = c_options->file_ops.confirm_delete;
        options->file_ops.enable_delete_key = c_options->file_ops.enable_delete_key;
-       options->file_ops.safe_delete_enable = c_options->file_ops.safe_delete_enable;
+       options->file_ops.confirm_move_to_trash = c_options->file_ops.confirm_move_to_trash;
+       options->file_ops.use_system_trash = c_options->file_ops.use_system_trash;
        options->file_ops.safe_delete_folder_maxsize = c_options->file_ops.safe_delete_folder_maxsize;
        options->tools_restore_state = c_options->tools_restore_state;
        options->save_window_positions = c_options->save_window_positions;
        options->use_saved_window_positions_for_new_windows = c_options->use_saved_window_positions_for_new_windows;
-       options->image.zoom_mode = c_options->image.zoom_mode;
+       options->save_dialog_window_positions = c_options->save_dialog_window_positions;
+       options->show_window_ids = c_options->show_window_ids;
        options->image.scroll_reset_method = c_options->image.scroll_reset_method;
        options->image.zoom_2pass = c_options->image.zoom_2pass;
        options->image.fit_window_to_image = c_options->image.fit_window_to_image;
@@ -236,6 +276,7 @@ static void config_window_apply(void)
        options->image.max_window_size = c_options->image.max_window_size;
        options->image.limit_autofit_size = c_options->image.limit_autofit_size;
        options->image.max_autofit_size = c_options->image.max_autofit_size;
+       options->image.max_enlargement_size = c_options->image.max_enlargement_size;
        options->image.use_clutter_renderer = c_options->image.use_clutter_renderer;
        options->progressive_key_scrolling = c_options->progressive_key_scrolling;
        options->keyboard_scroll_step = c_options->keyboard_scroll_step;
@@ -253,6 +294,9 @@ static void config_window_apply(void)
        options->thumbnails.enable_caching = c_options->thumbnails.enable_caching;
        options->thumbnails.cache_into_dirs = c_options->thumbnails.cache_into_dirs;
        options->thumbnails.use_exif = c_options->thumbnails.use_exif;
+       options->thumbnails.collection_preview = c_options->thumbnails.collection_preview;
+       options->thumbnails.use_ft_metadata = c_options->thumbnails.use_ft_metadata;
+//     options->thumbnails.use_ft_metadata_small = c_options->thumbnails.use_ft_metadata_small;
        options->thumbnails.spec_standard = c_options->thumbnails.spec_standard;
        options->metadata.enable_metadata_dirs = c_options->metadata.enable_metadata_dirs;
        options->file_filter.show_hidden_files = c_options->file_filter.show_hidden_files;
@@ -273,6 +317,8 @@ static void config_window_apply(void)
 
        options->mousewheel_scrolls = c_options->mousewheel_scrolls;
        options->image_lm_click_nav = c_options->image_lm_click_nav;
+       options->image_l_click_video = c_options->image_l_click_video;
+       options->image_l_click_video_editor = c_options->image_l_click_video_editor;
 
        options->file_ops.enable_in_place_rename = c_options->file_ops.enable_in_place_rename;
 
@@ -297,6 +343,9 @@ static void config_window_apply(void)
                view_window_colors_update();
                }
 
+       options->image.alpha_color_1 = c_options->image.alpha_color_1;
+       options->image.alpha_color_2 = c_options->image.alpha_color_2;
+
        options->fullscreen.screen = c_options->fullscreen.screen;
        options->fullscreen.clean_flip = c_options->fullscreen.clean_flip;
        options->fullscreen.disable_saver = c_options->fullscreen.disable_saver;
@@ -327,6 +376,7 @@ static void config_window_apply(void)
 
        options->open_recent_list_maxsize = c_options->open_recent_list_maxsize;
        options->dnd_icon_size = c_options->dnd_icon_size;
+       options->clipboard_selection = c_options->clipboard_selection;
 
        options->metadata.save_in_image_file = c_options->metadata.save_in_image_file;
        options->metadata.save_legacy_IPTC = c_options->metadata.save_legacy_IPTC;
@@ -363,6 +413,22 @@ static void config_window_apply(void)
        options->stereo.fixed_x2 = c_options->stereo.fixed_x2;
        options->stereo.fixed_y2 = c_options->stereo.fixed_y2;
 
+       options->info_keywords.height = c_options->info_keywords.height;
+       options->info_title.height = c_options->info_title.height;
+       options->info_comment.height = c_options->info_comment.height;
+       options->info_rating.height = c_options->info_rating.height;
+
+       options->show_predefined_keyword_tree = c_options->show_predefined_keyword_tree;
+
+       options->marks_save = c_options->marks_save;
+       options->with_rename = c_options->with_rename;
+       options->collections_on_top = c_options->collections_on_top;
+       config_entry_to_option(help_search_engine_entry, &options->help_search_engine, NULL);
+
+       options->read_metadata_in_idle = c_options->read_metadata_in_idle;
+
+       options->star_rating.star = c_options->star_rating.star;
+       options->star_rating.rejected = c_options->star_rating.rejected;
 #ifdef DEBUG
        set_debug_level(debug_c);
 #endif
@@ -382,6 +448,8 @@ static void config_window_apply(void)
                }
 #endif
 
+       config_tab_keywords_save();
+
        image_options_sync();
 
        if (refresh)
@@ -391,6 +459,8 @@ static void config_window_apply(void)
                }
 
        if (accel_store) gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_apply_cb, NULL);
+
+       toolbar_apply();
 }
 
 /*
@@ -415,13 +485,16 @@ static void config_window_help_cb(GtkWidget *widget, gpointer data)
        {
        "GuideOptionsGeneral.html",
        "GuideOptionsImage.html",
+       "GuideOptionsOSD.html",
        "GuideOptionsWindow.html",
        "GuideOptionsKeyboard.html",
        "GuideOptionsFiltering.html",
        "GuideOptionsMetadata.html",
+       "GuideOptionsKeywords.html",
        "GuideOptionsColor.html",
-       "GuideOptionsSteroa.html",
-       "GuideOptionsBehavior.html"
+       "GuideOptionsStereo.html",
+       "GuideOptionsBehavior.html",
+       "GuideOptionsToolbar.html"
        };
 
        i = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
@@ -442,7 +515,11 @@ static void config_window_ok_cb(GtkWidget *widget, gpointer data)
 
 static void config_window_apply_cb(GtkWidget *widget, gpointer data)
 {
+       LayoutWindow *lw;
+       lw = layout_window_list->data;
+
        config_window_apply();
+       layout_util_sync(lw);
 }
 
 static void config_window_save_cb(GtkWidget *widget, gpointer data)
@@ -479,6 +556,22 @@ static void quality_menu_cb(GtkWidget *combo, gpointer data)
                }
 }
 
+static void clipboard_selection_menu_cb(GtkWidget *combo, gpointer data)
+{
+       gint *option = data;
+
+       switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
+               {
+               case 0:
+               default:
+                       *option = PRIMARY;
+                       break;
+               case 1:
+                       *option = CLIPBOARD;
+                       break;
+               }
+}
+
 static void add_quality_menu(GtkWidget *table, gint column, gint row, const gchar *text,
                             guint option, guint *option_c)
 {
@@ -510,6 +603,33 @@ static void add_quality_menu(GtkWidget *table, gint column, gint row, const gcha
        gtk_widget_show(combo);
 }
 
+static void add_clipboard_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
+                            gint option, gint *option_c)
+{
+       GtkWidget *combo;
+       gint current = 0;
+
+       *option_c = option;
+
+       pref_table_label(table, column, row, text, 0.0);
+
+       combo = gtk_combo_box_text_new();
+
+       gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("PRIMARY"));
+       if (option == PRIMARY) current = 0;
+       gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("CLIPBOARD"));
+       if (option == CLIPBOARD) current = 1;
+
+       gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
+
+       g_signal_connect(G_OBJECT(combo), "changed",
+                        G_CALLBACK(clipboard_selection_menu_cb), option_c);
+
+       gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
+                        GTK_EXPAND | GTK_FILL, 0, 0, 0);
+       gtk_widget_show(combo);
+}
+
 static void thumb_size_menu_cb(GtkWidget *combo, gpointer data)
 {
        gint n;
@@ -698,6 +818,48 @@ static void add_stereo_mode_menu(GtkWidget *table, gint column, gint row, const
        gtk_widget_show(combo);
 }
 
+static void video_menu_cb(GtkWidget *combo, gpointer data)
+{
+       gchar **option = data;
+
+       EditorDescription *ed = g_list_nth_data(editor_list_get(), gtk_combo_box_get_active(GTK_COMBO_BOX(combo)));
+       *option = ed->key;
+}
+
+static void video_menu_populate(gpointer data, gpointer user_data)
+{
+       GtkWidget *combo = user_data;
+       EditorDescription *ed = data;
+
+       gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), ed->name);
+}
+
+static void add_video_menu(GtkWidget *table, gint column, gint row, const gchar *text,
+                            gchar *option, gchar **option_c)
+{
+       GtkWidget *combo;
+       gint current;
+/* use lists since they are sorted */
+       GList *eds = editor_list_get();
+
+       *option_c = option;
+
+       pref_table_label(table, column, row, text, 0.0);
+
+       combo = gtk_combo_box_text_new();
+       g_list_foreach(eds,video_menu_populate,(gpointer)combo);
+       current = option ? g_list_index(eds,g_hash_table_lookup(editors,option)): -1;
+
+       gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
+
+       g_signal_connect(G_OBJECT(combo), "changed",
+                        G_CALLBACK(video_menu_cb), option_c);
+
+       gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
+                        GTK_EXPAND | GTK_FILL, 0, 0, 0);
+       gtk_widget_show(combo);
+}
+
 static void filter_store_populate(void)
 {
        GList *work;
@@ -985,7 +1147,7 @@ static void filter_default_cb(GtkWidget *widget, gpointer data)
                                "reset_filter", widget, TRUE,
                                dummy_cancel_cb, data);
        generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset filters"),
-                                  _("This will reset the file filters to the defaults.\nContinue?"));
+                                  _("This will reset the file filters to the defaults.\nContinue?"), TRUE);
        generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, filter_default_ok_cb, TRUE);
        gtk_widget_show(gd->dialog);
 }
@@ -1016,7 +1178,7 @@ static void safe_delete_clear_cb(GtkWidget *widget, gpointer data)
                                "clear_trash", widget, TRUE,
                                dummy_cancel_cb, NULL);
        generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear trash"),
-                                   _("This will remove the trash contents."));
+                                   _("This will remove the trash contents."), FALSE);
        generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, safe_delete_clear_ok_cb, TRUE);
        entry = gtk_entry_new();
        gtk_widget_set_can_focus(entry, FALSE);
@@ -1064,14 +1226,14 @@ static void image_overlay_default_template_cb(GtkWidget *widget, gpointer data)
                                "reset_image_overlay_template_string", widget, TRUE,
                                dummy_cancel_cb, data);
        generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset image overlay template string"),
-                                  _("This will reset the image overlay template string to the default.\nContinue?"));
+                                  _("This will reset the image overlay template string to the default.\nContinue?"), TRUE);
        generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, image_overlay_default_template_ok_cb, TRUE);
        gtk_widget_show(gd->dialog);
 }
 
 static void image_overlay_help_cb(GtkWidget *widget, gpointer data)
 {
-       help_window_show("GuideOptionsWindow.html#OverlayScreenDisplay");
+       help_window_show("GuideOptionsOSD.html");
 }
 
 static void image_overlay_set_font_cb(GtkWidget *widget, gpointer data)
@@ -1406,16 +1568,151 @@ static GtkWidget *scrolled_notebook_page(GtkWidget *notebook, const gchar *title
        return vbox;
 }
 
+static void cache_standard_cb(GtkWidget *widget, gpointer data)
+{
+       if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
+               {
+               c_options->thumbnails.spec_standard =TRUE;
+               c_options->thumbnails.cache_into_dirs = FALSE;
+               }
+}
+
+static void cache_geeqie_cb(GtkWidget *widget, gpointer data)
+{
+       if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
+               {
+               c_options->thumbnails.spec_standard =FALSE;
+               c_options->thumbnails.cache_into_dirs = FALSE;
+               }
+}
+
+static void cache_local_cb(GtkWidget *widget, gpointer data)
+{
+       if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
+               {
+               c_options->thumbnails.cache_into_dirs = TRUE;
+               c_options->thumbnails.spec_standard =FALSE;
+               }
+}
+
+static void help_search_engine_entry_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
+                                                                       GdkEvent *event, gpointer userdata)
+{
+       if (pos == GTK_ENTRY_ICON_PRIMARY)
+               {
+               gtk_entry_set_text(GTK_ENTRY(userdata), HELP_SEARCH_ENGINE);
+               }
+       else
+               {
+               gtk_entry_set_text(GTK_ENTRY(userdata), "");
+               }
+}
+
+static void star_rating_star_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
+                                                                       GdkEvent *event, gpointer userdata)
+{
+       gchar *rating_symbol;
+
+       if (pos == GTK_ENTRY_ICON_PRIMARY)
+               {
+               rating_symbol = g_strdup_printf("U+%X", STAR_RATING_STAR);
+               gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
+               g_free(rating_symbol);
+               }
+       else
+               {
+               gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
+               gtk_widget_grab_focus(GTK_WIDGET(userdata));
+               gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
+               }
+}
+
+static void star_rating_rejected_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
+                                                                       GdkEvent *event, gpointer userdata)
+{
+       gchar *rating_symbol;
+
+       if (pos == GTK_ENTRY_ICON_PRIMARY)
+               {
+               rating_symbol = g_strdup_printf("U+%X", STAR_RATING_REJECTED);
+               gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
+               g_free(rating_symbol);
+               }
+       else
+               {
+               gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
+               gtk_widget_grab_focus(GTK_WIDGET(userdata));
+               gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
+               }
+}
+
+static guint star_rating_symbol_test(GtkWidget *widget, gpointer data)
+{
+       GtkContainer *hbox = data;
+       GString *str = g_string_new(NULL);
+       GtkEntry *hex_code_entry;
+       gchar *hex_code_full;
+       gchar **hex_code;
+       GList *list;
+       guint64 hex_value = 0;
+
+       list = gtk_container_get_children(hbox);
+
+       hex_code_entry = g_list_nth_data(list, 2);
+       hex_code_full = g_strdup(gtk_entry_get_text(hex_code_entry));
+
+       hex_code = g_strsplit(hex_code_full, "+", 2);
+       if (hex_code[0] && hex_code[1])
+               {
+               hex_value = strtoull(hex_code[1], NULL, 16);
+               }
+       if (!hex_value || hex_value > 0x10FFFF)
+               {
+               hex_value = 0x003F; // Unicode 'Question Mark'
+               }
+       str = g_string_append_unichar(str, (gunichar)hex_value);
+       gtk_label_set_text(g_list_nth_data(list, 1), str->str);
+
+       g_strfreev(hex_code);
+       g_string_free(str, TRUE);
+       g_free(hex_code_full);
+
+       return hex_value;
+}
+
+static void star_rating_star_test_cb(GtkWidget *widget, gpointer data)
+{
+       guint64 star_symbol;
+
+       star_symbol = star_rating_symbol_test(widget, data);
+       c_options->star_rating.star = star_symbol;
+}
+
+static void star_rating_rejected_test_cb(GtkWidget *widget, gpointer data)
+{
+       guint64 rejected_symbol;
+
+       rejected_symbol = star_rating_symbol_test(widget, data);
+       c_options->star_rating.rejected = rejected_symbol;
+}
+
 /* general options tab */
 static void config_tab_general(GtkWidget *notebook)
 {
        GtkWidget *vbox;
+       GtkWidget *hbox;
        GtkWidget *group;
+       GtkWidget *group_frame;
        GtkWidget *subgroup;
        GtkWidget *button;
        GtkWidget *ct_button;
        GtkWidget *table;
        GtkWidget *spin;
+       gint hours, minutes, remainder;
+       gdouble seconds;
+       GtkWidget *star_rating_entry;
+       GString *str;
+       gchar *rating_symbol;
 
        vbox = scrolled_notebook_page(notebook, _("General"));
 
@@ -1431,25 +1728,138 @@ static void config_tab_general(GtkWidget *notebook)
        subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
        pref_checkbox_link_sensitivity(ct_button, subgroup);
 
-       button = pref_checkbox_new_int(subgroup, _("Use standard thumbnail cache, shared with other applications"),
-                                      options->thumbnails.spec_standard, &c_options->thumbnails.spec_standard);
-
-       subgroup = pref_box_new(subgroup, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
-       pref_checkbox_link_sensitivity_swap(button, subgroup);
-
-       pref_checkbox_new_int(subgroup, _("Store thumbnails in '.thumbnails' folder, local to image folder (non-standard)"),
-                             options->thumbnails.cache_into_dirs, &c_options->thumbnails.cache_into_dirs);
+       c_options->thumbnails.spec_standard = options->thumbnails.spec_standard;
+       c_options->thumbnails.cache_into_dirs = options->thumbnails.cache_into_dirs;
+       group_frame = pref_frame_new(subgroup, TRUE, _("Use Geeqie thumbnail style and cache"),
+                                                                               GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
+       button = pref_radiobutton_new(group_frame, NULL,  get_thumbnails_cache_dir(),
+                                                       !options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
+                                                       G_CALLBACK(cache_geeqie_cb), NULL);
+
+       group_frame = pref_frame_new(subgroup, TRUE,
+                                                       _("Store thumbnails local to image folder (non-standard)"),
+                                                       GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
+       pref_radiobutton_new(group_frame, button, "*/.thumbnails",
+                                                       !options->thumbnails.spec_standard && options->thumbnails.cache_into_dirs,
+                                                       G_CALLBACK(cache_local_cb), NULL);
+
+       group_frame = pref_frame_new(subgroup, TRUE,
+                                                       _("Use standard thumbnail style and cache, shared with other applications"),
+                                                       GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
+       pref_radiobutton_new(group_frame, button, get_thumbnails_standard_cache_dir(),
+                                                       options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
+                                                       G_CALLBACK(cache_standard_cb), NULL);
 
        pref_checkbox_new_int(group, _("Use EXIF thumbnails when available (EXIF thumbnails may be outdated)"),
                              options->thumbnails.use_exif, &c_options->thumbnails.use_exif);
 
+       spin = pref_spin_new_int(group, _("Collection preview:"), NULL,
+                                1, 999, 1,
+                                options->thumbnails.collection_preview, &c_options->thumbnails.collection_preview);
+       gtk_widget_set_tooltip_text(spin, _("The maximum number of thumbnails shown in a Collection preview montage"));
+
+#ifdef HAVE_FFMPEGTHUMBNAILER_METADATA
+       pref_checkbox_new_int(group, _("Use embedded metadata in video files as thumbnails when available"),
+                             options->thumbnails.use_ft_metadata, &c_options->thumbnails.use_ft_metadata);
+
+//     pref_checkbox_new_int(group, _("Ignore embedded metadata if size is too small"),
+//                           options->thumbnails.use_ft_metadata_small, &c_options->thumbnails.use_ft_metadata_small);
+#endif
+
+       group = pref_group_new(vbox, FALSE, _("Star Rating"), GTK_ORIENTATION_VERTICAL);
+
+       c_options->star_rating.star = options->star_rating.star;
+       c_options->star_rating.rejected = options->star_rating.rejected;
+
+       str = g_string_new(NULL);
+       hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
+       pref_label_new(hbox, "Star character: ");
+       str = g_string_append_unichar(str, options->star_rating.star);
+       pref_label_new(hbox, g_strdup(str->str));
+       rating_symbol = g_strdup_printf("U+%X", options->star_rating.star);
+       star_rating_entry = gtk_entry_new();
+       gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
+       gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
+       gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
+       gtk_widget_show(star_rating_entry);
+       button = pref_button_new(NULL, NULL, _("Set"), FALSE,
+                                       G_CALLBACK(star_rating_star_test_cb), hbox);
+       gtk_widget_set_tooltip_text(button, _("Display selected character"));
+       gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
+       gtk_widget_show(button);
+       gtk_widget_set_tooltip_text(star_rating_entry, _("Hexadecimal representation of a Unicode character. A list of all Unicode characters may be found on the Internet."));
+       gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
+                                               GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
+       gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
+                                               GTK_ENTRY_ICON_SECONDARY, _("Clear"));
+       gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
+                                               GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
+       gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
+                                               GTK_ENTRY_ICON_PRIMARY, _("Default"));
+       g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
+                                               G_CALLBACK(star_rating_star_icon_cb),
+                                               star_rating_entry);
+
+       g_string_free(str, TRUE);
+       g_free(rating_symbol);
+
+       str = g_string_new(NULL);
+       hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
+       pref_label_new(hbox, "Rejected character: ");
+       str = g_string_append_unichar(str, options->star_rating.rejected);
+       pref_label_new(hbox, g_strdup(str->str));
+       rating_symbol = g_strdup_printf("U+%X", options->star_rating.rejected);
+       star_rating_entry = gtk_entry_new();
+       gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
+       gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
+       gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
+       gtk_widget_show(star_rating_entry);
+       button = pref_button_new(NULL, NULL, _("Set"), FALSE,
+                                       G_CALLBACK(star_rating_rejected_test_cb), hbox);
+       gtk_widget_set_tooltip_text(button, _("Display selected character"));
+       gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
+       gtk_widget_show(button);
+       gtk_widget_set_tooltip_text(star_rating_entry, _("Hexadecimal representation of a Unicode character. A list of all Unicode characters may be found on the Internet."));
+       gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
+                                               GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
+       gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
+                                               GTK_ENTRY_ICON_SECONDARY, _("Clear"));
+       gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
+                                               GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
+       gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
+                                               GTK_ENTRY_ICON_PRIMARY, _("Default"));
+       g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
+                                               G_CALLBACK(star_rating_rejected_icon_cb),
+                                               star_rating_entry);
+
+       g_string_free(str, TRUE);
+       g_free(rating_symbol);
+
        group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
 
        c_options->slideshow.delay = options->slideshow.delay;
-       spin = pref_spin_new(group, _("Delay between image change:"), _("seconds"),
-                            SLIDESHOW_MIN_SECONDS, SLIDESHOW_MAX_SECONDS, 1.0, 1,
-                            options->slideshow.delay ? (gdouble)options->slideshow.delay / SLIDESHOW_SUBSECOND_PRECISION : 10.0,
-                            G_CALLBACK(slideshow_delay_cb), NULL);
+       hours = options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
+       remainder = options->slideshow.delay % (3600 * SLIDESHOW_SUBSECOND_PRECISION);
+       minutes = remainder / (60 * SLIDESHOW_SUBSECOND_PRECISION);
+       seconds = (gdouble)(remainder % (60 * SLIDESHOW_SUBSECOND_PRECISION)) /
+                                                                                       SLIDESHOW_SUBSECOND_PRECISION;
+
+       hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
+
+       spin = pref_spin_new(hbox, _("Delay between image change hrs:mins:secs.dec"), NULL,
+                                                                               0, 23, 1.0, 0,
+                                                                               options->slideshow.delay ? hours : 0.0,
+                                                                               G_CALLBACK(slideshow_delay_hours_cb), NULL);
+       gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
+       spin = pref_spin_new(hbox, ":" , NULL,
+                                                                               0, 59, 1.0, 0,
+                                                                               options->slideshow.delay ? minutes: 0.0,
+                                                                               G_CALLBACK(slideshow_delay_minutes_cb), NULL);
+       gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
+       spin = pref_spin_new(hbox, ":", NULL,
+                                                                               SLIDESHOW_MIN_SECONDS, 59, 1.0, 1,
+                                                                               options->slideshow.delay ? seconds : 10.0,
+                                                                               G_CALLBACK(slideshow_delay_seconds_cb), NULL);
        gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
 
        pref_checkbox_new_int(group, _("Random"), options->slideshow.random, &c_options->slideshow.random);
@@ -1458,12 +1868,54 @@ static void config_tab_general(GtkWidget *notebook)
        group = pref_group_new(vbox, FALSE, _("Image loading and caching"), GTK_ORIENTATION_VERTICAL);
 
        pref_spin_new_int(group, _("Decoded image cache size (Mb):"), NULL,
-                         0, 1024, 1, options->image.image_cache_max, &c_options->image.image_cache_max);
+                         0, 99999, 1, options->image.image_cache_max, &c_options->image.image_cache_max);
        pref_checkbox_new_int(group, _("Preload next image"),
                              options->image.enable_read_ahead, &c_options->image.enable_read_ahead);
 
        pref_checkbox_new_int(group, _("Refresh on file change"),
                              options->update_on_time_change, &c_options->update_on_time_change);
+
+       group = pref_group_new(vbox, FALSE, _("Info sidebar heights"), GTK_ORIENTATION_VERTICAL);
+       pref_label_new(group, _("NOTE! Geeqie must be restarted for changes to take effect"));
+       hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
+       pref_spin_new_int(hbox, _("Keywords:"), NULL,
+                                1, 9999, 1,
+                                options->info_keywords.height, &c_options->info_keywords.height);
+       pref_spin_new_int(hbox, _("Title:"), NULL,
+                                1, 9999, 1,
+                                options->info_title.height, &c_options->info_title.height);
+       pref_spin_new_int(hbox, _("Comment:"), NULL,
+                                1, 9999, 1,
+                                options->info_comment.height, &c_options->info_comment.height);
+       pref_spin_new_int(hbox, _("Rating:"), NULL,
+                                1, 9999, 1,
+                                options->info_rating.height, &c_options->info_rating.height);
+
+       group = pref_group_new(vbox, FALSE, _("Show predefined keyword tree"), GTK_ORIENTATION_VERTICAL);
+
+       pref_checkbox_new_int(group, _("Show predefined keyword tree (NOTE! Geeqie must be restarted for change to take effect)"),
+                               options->show_predefined_keyword_tree, &c_options->show_predefined_keyword_tree);
+
+       group = pref_group_new(vbox, FALSE, _("On-line help search engine"), GTK_ORIENTATION_VERTICAL);
+
+       help_search_engine_entry = gtk_entry_new();
+       gtk_entry_set_text(GTK_ENTRY(help_search_engine_entry), options->help_search_engine);
+       gtk_box_pack_start(GTK_BOX(group), help_search_engine_entry, FALSE, FALSE, 0);
+       gtk_widget_show(help_search_engine_entry);
+
+       gtk_widget_set_tooltip_text(help_search_engine_entry, _("The format varies between search engines, e.g the format may be:\nhttps://www.search_engine.com/search?q=site:geeqie.org/help\nhttps://www.search_engine.com/?q=site:geeqie.org/help"));
+
+       gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
+                                               GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
+       gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
+                                               GTK_ENTRY_ICON_SECONDARY, _("Clear"));
+       gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
+                                               GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
+       gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
+                                               GTK_ENTRY_ICON_PRIMARY, _("Default"));
+       g_signal_connect(GTK_ENTRY(help_search_engine_entry), "icon-press",
+                                               G_CALLBACK(help_search_engine_entry_icon_cb),
+                                               help_search_engine_entry);
 }
 
 /* image tab */
@@ -1471,10 +1923,9 @@ static void config_tab_image(GtkWidget *notebook)
 {
        GtkWidget *hbox;
        GtkWidget *vbox;
-       GtkWidget *vbox2;
        GtkWidget *group;
-       GtkWidget *button;
        GtkWidget *ct_button;
+       GtkWidget *enlargement_button;
        GtkWidget *table;
        GtkWidget *spin;
 
@@ -1493,49 +1944,31 @@ static void config_tab_image(GtkWidget *notebook)
        pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"),
                              options->image.zoom_2pass, &c_options->image.zoom_2pass);
 
-       pref_checkbox_new_int(group, _("Allow enlargement of image for zoom to fit"),
+       c_options->image.zoom_increment = options->image.zoom_increment;
+       spin = pref_spin_new(group, _("Zoom increment:"), NULL,
+                            0.01, 4.0, 0.01, 2, (gdouble)options->image.zoom_increment / 100.0,
+                            G_CALLBACK(zoom_increment_cb), NULL);
+       gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
+
+       group = pref_group_new(vbox, FALSE, _("Fit image to window"), GTK_ORIENTATION_VERTICAL);
+
+       hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
+       enlargement_button = pref_checkbox_new_int(hbox, _("Allow enlargement of image (max. size in %)"),
                              options->image.zoom_to_fit_allow_expand, &c_options->image.zoom_to_fit_allow_expand);
+       spin = pref_spin_new_int(hbox, NULL, NULL,
+                                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."));
 
        hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
-       ct_button = pref_checkbox_new_int(hbox, _("Limit image size when autofitting (%):"),
+       ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (% of actual window):"),
                                          options->image.limit_autofit_size, &c_options->image.limit_autofit_size);
        spin = pref_spin_new_int(hbox, NULL, NULL,
                                 10, 150, 1,
                                 options->image.max_autofit_size, &c_options->image.max_autofit_size);
        pref_checkbox_link_sensitivity(ct_button, spin);
-
-       c_options->image.zoom_increment = options->image.zoom_increment;
-       spin = pref_spin_new(group, _("Zoom increment:"), NULL,
-                            0.01, 4.0, 0.01, 2, (gdouble)options->image.zoom_increment / 100.0,
-                            G_CALLBACK(zoom_increment_cb), NULL);
-       gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
-
-       group = pref_group_new(vbox, FALSE, _("When new image is selected:"), GTK_ORIENTATION_HORIZONTAL);
-
-       vbox2 = pref_box_new(group, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
-       c_options->image.zoom_mode = options->image.zoom_mode;
-       button = pref_radiobutton_new(vbox2, NULL, _("Zoom to original size"),
-                                     (options->image.zoom_mode == ZOOM_RESET_ORIGINAL),
-                                     G_CALLBACK(zoom_mode_cb), GINT_TO_POINTER(ZOOM_RESET_ORIGINAL));
-       button = pref_radiobutton_new(vbox2, button, _("Fit image to window"),
-                                     (options->image.zoom_mode == ZOOM_RESET_FIT_WINDOW),
-                                     G_CALLBACK(zoom_mode_cb), GINT_TO_POINTER(ZOOM_RESET_FIT_WINDOW));
-       button = pref_radiobutton_new(vbox2, button, _("Leave Zoom at previous setting"),
-                                     (options->image.zoom_mode == ZOOM_RESET_NONE),
-                                     G_CALLBACK(zoom_mode_cb), GINT_TO_POINTER(ZOOM_RESET_NONE));
-
-       vbox2 = pref_box_new(group, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
-       c_options->image.scroll_reset_method = options->image.scroll_reset_method;
-       button = pref_radiobutton_new(vbox2, NULL, _("Scroll to top left corner"),
-                                     (options->image.scroll_reset_method == SCROLL_RESET_TOPLEFT),
-                                     G_CALLBACK(scroll_reset_cb), GINT_TO_POINTER(SCROLL_RESET_TOPLEFT));
-       button = pref_radiobutton_new(vbox2, button, _("Scroll to image center"),
-                                     (options->image.scroll_reset_method == SCROLL_RESET_CENTER),
-                                     G_CALLBACK(scroll_reset_cb), GINT_TO_POINTER(SCROLL_RESET_CENTER));
-       button = pref_radiobutton_new(vbox2, button, _("Keep the region from previous image"),
-                                     (options->image.scroll_reset_method == SCROLL_RESET_NOCHANGE),
-                                     G_CALLBACK(scroll_reset_cb), GINT_TO_POINTER(SCROLL_RESET_NOCHANGE));
-
+       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, _("Appearance"), GTK_ORIENTATION_VERTICAL);
 
@@ -1548,6 +1981,17 @@ static void config_tab_image(GtkWidget *notebook)
        pref_color_button_new(group, _("Border color"), &options->image.border_color,
                              G_CALLBACK(pref_color_button_set_cb), &c_options->image.border_color);
 
+       c_options->image.border_color = options->image.border_color;
+
+       pref_color_button_new(group, _("Alpha channel color 1"), &options->image.alpha_color_1,
+                             G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_1);
+
+       pref_color_button_new(group, _("Alpha channel color 2"), &options->image.alpha_color_2,
+                             G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_2);
+
+       c_options->image.alpha_color_1 = options->image.alpha_color_1;
+       c_options->image.alpha_color_2 = options->image.alpha_color_2;
+
        group = pref_group_new(vbox, FALSE, _("Convenience"), GTK_ORIENTATION_VERTICAL);
 
        pref_checkbox_new_int(group, _("Auto rotate proofs using Exif information"),
@@ -1563,9 +2007,6 @@ static void config_tab_windows(GtkWidget *notebook)
        GtkWidget *button;
        GtkWidget *ct_button;
        GtkWidget *spin;
-       GtkWidget *image_overlay_template_view;
-       GtkWidget *scrolled;
-       GtkTextBuffer *buffer;
 
        vbox = scrolled_notebook_page(notebook, _("Windows"));
 
@@ -1581,6 +2022,12 @@ static void config_tab_windows(GtkWidget *notebook)
        pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
                              options->tools_restore_state, &c_options->tools_restore_state);
 
+       pref_checkbox_new_int(group, _("Remember dialog window positions"),
+                             options->save_dialog_window_positions, &c_options->save_dialog_window_positions);
+
+       pref_checkbox_new_int(group, _("Show window IDs"),
+                             options->show_window_ids, &c_options->show_window_ids);
+
        group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
 
        pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
@@ -1606,34 +2053,55 @@ static void config_tab_windows(GtkWidget *notebook)
                              options->fullscreen.clean_flip, &c_options->fullscreen.clean_flip);
        pref_checkbox_new_int(group, _("Disable screen saver"),
                              options->fullscreen.disable_saver, &c_options->fullscreen.disable_saver);
+}
+
+#define PRE_FORMATTED_COLUMNS 5
+static void config_tab_osd(GtkWidget *notebook)
+{
+       GtkWidget *hbox;
+       GtkWidget *vbox;
+       GtkWidget *vbox_buttons;
+       GtkWidget *group;
+       GtkWidget *button;
+       GtkWidget *image_overlay_template_view;
+       GtkWidget *scrolled;
+       GtkWidget *scrolled_pre_formatted;
+       GtkTextBuffer *buffer;
+       GtkWidget *label;
+       GtkWidget *     subgroup;
+       gint i = 0;
+       gint rows = 0;
+       gint cols = 0;
 
+       vbox = scrolled_notebook_page(notebook, _("OSD"));
+
+       image_overlay_template_view = gtk_text_view_new();
 
        group = pref_group_new(vbox, FALSE, _("Overlay Screen Display"), GTK_ORIENTATION_VERTICAL);
 
+       subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
+
+       scrolled_pre_formatted = osd_new(PRE_FORMATTED_COLUMNS, image_overlay_template_view);
+       gtk_widget_set_size_request(scrolled_pre_formatted, 200, 150);
+       gtk_box_pack_start(GTK_BOX(subgroup), scrolled_pre_formatted, FALSE, FALSE, 0);
+       gtk_widget_show(scrolled_pre_formatted);
+       gtk_widget_show(subgroup);
+
+       pref_line(group, PREF_PAD_GAP);
+
        pref_label_new(group, _("Image overlay template"));
 
        scrolled = gtk_scrolled_window_new(NULL, NULL);
        gtk_widget_set_size_request(scrolled, 200, 150);
        gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
        gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
-                                      GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+                                                                       GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
        gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 5);
        gtk_widget_show(scrolled);
 
-       image_overlay_template_view = gtk_text_view_new();
-
        gtk_widget_set_tooltip_markup(image_overlay_template_view,
-       _("<i>%name%</i> results in the filename of the picture.\n"
-         "Also available: <i>%collection%</i>, <i>%number%</i>, <i>%total%</i>, <i>%date%</i>,\n"
-         "<i>%size%</i> (filesize), <i>%width%</i>, <i>%height%</i>, <i>%res%</i> (resolution)\n"
-         "To access exif data use the exif name, e. g. <i>%formatted.Camera%</i> is the formatted camera name,\n"
-         "<i>%Exif.Photo.DateTimeOriginal%</i> the date of the original shot.\n"
-         "<i>%formatted.Camera:20</i> notation will truncate the displayed data to 20 characters and will add 3 dots at the end to denote the truncation.\n"
-         "If two or more variables are connected with the |-sign, it prints available variables with a separator.\n"
-         "<i>%formatted.ShutterSpeed%</i>|<i>%formatted.ISOSpeedRating%</i>|<i>%formatted.FocalLength%</i> could show \"1/20s - 400 - 80 mm\" or \"1/200 - 80 mm\",\n"
-         "if there's no ISO information in the Exif data.\n"
-         "If a line is empty, it is removed. This allows one to add lines that totally disappear when no data is available.\n"
-       ));
+                                       _("Extensive formatting options are shown in the Help file"));
+
        gtk_container_add(GTK_CONTAINER(scrolled), image_overlay_template_view);
        gtk_widget_show(image_overlay_template_view);
 
@@ -1678,7 +2146,51 @@ static void config_tab_windows(GtkWidget *notebook)
        g_signal_connect(G_OBJECT(buffer), "changed",
                         G_CALLBACK(image_overlay_template_view_changed_cb), image_overlay_template_view);
 
+       pref_line(group, PREF_PAD_GAP);
+
+       group = pref_group_new(vbox, FALSE, _("Exif, XMP or IPTC tags"), GTK_ORIENTATION_VERTICAL);
+       hbox = gtk_hbox_new(FALSE, 0);
+       gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
+       gtk_widget_show(hbox);
+       label = gtk_label_new(_("%Exif.Image.Orientation%"));
+       gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
+       gtk_widget_show(label);
+       pref_spacer(group,TRUE);
+
+       group = pref_group_new(vbox, FALSE, _("Field separators"), GTK_ORIENTATION_VERTICAL);
+       hbox = gtk_hbox_new(FALSE, 0);
+       gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
+       gtk_widget_show(hbox);
+       label = gtk_label_new(_("Separator shown only if both fields are non-null:\n%formatted.ShutterSpeed%|%formatted.ISOSpeedRating%"));
+       gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
+       gtk_widget_show(label);
+       pref_spacer(group,TRUE);
+
+       group = pref_group_new(vbox, FALSE, _("Field maximum length"), GTK_ORIENTATION_VERTICAL);
+       hbox = gtk_hbox_new(FALSE, 0);
+       gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
+       gtk_widget_show(hbox);
+       label = gtk_label_new(_("%path:39%"));
+       gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
+       gtk_widget_show(label);
+       pref_spacer(group,TRUE);
 
+       group = pref_group_new(vbox, FALSE, _("Pre- and post- text"), GTK_ORIENTATION_VERTICAL);
+       hbox = gtk_hbox_new(FALSE, 0);
+       gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
+       gtk_widget_show(hbox);
+       label = gtk_label_new(_("Text shown only if the field is non-null:\n%formatted.Aperture:F no. * setting%\n %formatted.Aperture:10:F no. * setting%"));
+       gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
+       gtk_widget_show(label);
+       pref_spacer(group,TRUE);
+
+       group = pref_group_new(vbox, FALSE, _("Pango markup"), GTK_ORIENTATION_VERTICAL);
+       hbox = gtk_hbox_new(FALSE, 0);
+       gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
+       gtk_widget_show(hbox);
+       label = gtk_label_new(_("<b>bold</b>\n<u>underline</u>\n<i>italic</i>\n<s>strikethrough</s>"));
+       gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
+       gtk_widget_show(label);
 }
 
 static GtkTreeModel *create_class_model(void)
@@ -1877,7 +2389,7 @@ static void config_tab_metadata(GtkWidget *notebook)
        label = pref_label_new(group, _("Metadata are written in the following order. The process ends after first success."));
        gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
 
-       ct_button = pref_checkbox_new_int(group, _("1) Save metadata in image files, resp. sidecar files, according to the XMP standard"),
+       ct_button = pref_checkbox_new_int(group, _("1) Save metadata in image files, or sidecar files, according to the XMP standard"),
                              options->metadata.save_in_image_file, &c_options->metadata.save_in_image_file);
 #ifndef HAVE_EXIV2
        gtk_widget_set_sensitive(ct_button, FALSE);
@@ -1950,6 +2462,355 @@ static void config_tab_metadata(GtkWidget *notebook)
 
        pref_checkbox_new_int(group, _("Write metadata on directory change"),
                              options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
+
+       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");
+}
+
+/* keywords tab */
+
+typedef struct _KeywordFindData KeywordFindData;
+struct _KeywordFindData
+{
+       GenericDialog *gd;
+
+       GList *list;
+       GList *list_dir;
+
+       GtkWidget *button_close;
+       GtkWidget *button_stop;
+       GtkWidget *button_start;
+       GtkWidget *progress;
+       GtkWidget *spinner;
+
+       GtkWidget *group;
+       GtkWidget *entry;
+
+       gboolean recurse;
+
+       guint idle_id; /* event source id */
+};
+
+#define KEYWORD_DIALOG_WIDTH 400
+
+static void keywords_find_folder(KeywordFindData *kfd, FileData *dir_fd)
+{
+       GList *list_d = NULL;
+       GList *list_f = NULL;
+
+       if (kfd->recurse)
+               {
+               filelist_read(dir_fd, &list_f, &list_d);
+               }
+       else
+               {
+               filelist_read(dir_fd, &list_f, NULL);
+               }
+
+       list_f = filelist_filter(list_f, FALSE);
+       list_d = filelist_filter(list_d, TRUE);
+
+       kfd->list = g_list_concat(list_f, kfd->list);
+       kfd->list_dir = g_list_concat(list_d, kfd->list_dir);
+}
+
+static void keywords_find_reset(KeywordFindData *kfd)
+{
+       filelist_free(kfd->list);
+       kfd->list = NULL;
+
+       filelist_free(kfd->list_dir);
+       kfd->list_dir = NULL;
+}
+
+static void keywords_find_close_cb(GenericDialog *fd, gpointer data)
+{
+       KeywordFindData *kfd = data;
+
+       if (!gtk_widget_get_sensitive(kfd->button_close)) return;
+
+       keywords_find_reset(kfd);
+       generic_dialog_close(kfd->gd);
+       g_free(kfd);
+}
+
+static void keywords_find_finish(KeywordFindData *kfd)
+{
+       keywords_find_reset(kfd);
+
+       gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("done"));
+       spinner_set_interval(kfd->spinner, -1);
+
+       gtk_widget_set_sensitive(kfd->group, TRUE);
+       gtk_widget_set_sensitive(kfd->button_start, TRUE);
+       gtk_widget_set_sensitive(kfd->button_stop, FALSE);
+       gtk_widget_set_sensitive(kfd->button_close, TRUE);
+}
+
+static void keywords_find_stop_cb(GenericDialog *fd, gpointer data)
+{
+       KeywordFindData *kfd = data;
+
+       g_idle_remove_by_data(kfd);
+
+       keywords_find_finish(kfd);
+}
+
+static gboolean keywords_find_file(gpointer data)
+{
+       KeywordFindData *kfd = data;
+       GtkTextIter iter;
+       GtkTextBuffer *buffer;
+       gchar *tmp;
+       GList *keywords;
+
+       if (kfd->list)
+               {
+               FileData *fd;
+
+               fd = kfd->list->data;
+               kfd->list = g_list_remove(kfd->list, fd);
+
+               keywords = metadata_read_list(fd, KEYWORD_KEY, METADATA_PLAIN);
+               buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
+
+               while (keywords)
+                       {
+                       gtk_text_buffer_get_end_iter(buffer, &iter);
+                       tmp = g_strconcat(keywords->data, "\n", NULL);
+                       gtk_text_buffer_insert(buffer, &iter, tmp, -1);
+                       g_free(tmp);
+                       keywords = keywords->next;
+                       }
+
+               gtk_entry_set_text(GTK_ENTRY(kfd->progress), fd->path);
+               file_data_unref(fd);
+               string_list_free(keywords);
+
+               return (TRUE);
+               }
+       else if (kfd->list_dir)
+               {
+               FileData *fd;
+
+               fd = kfd->list_dir->data;
+               kfd->list_dir = g_list_remove(kfd->list_dir, fd);
+
+               keywords_find_folder(kfd, fd);
+
+               file_data_unref(fd);
+
+               return TRUE;
+               }
+
+       keywords_find_finish(kfd);
+
+       return FALSE;
+}
+
+static void keywords_find_start_cb(GenericDialog *fd, gpointer data)
+{
+       KeywordFindData *kfd = data;
+       gchar *path;
+
+       if (kfd->list || !gtk_widget_get_sensitive(kfd->button_start)) return;
+
+       path = remove_trailing_slash((gtk_entry_get_text(GTK_ENTRY(kfd->entry))));
+       parse_out_relatives(path);
+
+       if (!isdir(path))
+               {
+               warning_dialog(_("Invalid folder"),
+                               _("The specified folder can not be found."),
+                               GTK_STOCK_DIALOG_WARNING, kfd->gd->dialog);
+               }
+       else
+               {
+               FileData *dir_fd;
+
+               gtk_widget_set_sensitive(kfd->group, FALSE);
+               gtk_widget_set_sensitive(kfd->button_start, FALSE);
+               gtk_widget_set_sensitive(kfd->button_stop, TRUE);
+               gtk_widget_set_sensitive(kfd->button_close, FALSE);
+               spinner_set_interval(kfd->spinner, SPINNER_SPEED);
+
+               dir_fd = file_data_new_dir(path);
+               keywords_find_folder(kfd, dir_fd);
+               file_data_unref(dir_fd);
+               kfd->idle_id = g_idle_add(keywords_find_file, kfd);
+               }
+
+       g_free(path);
+}
+
+static void keywords_find_dialog(GtkWidget *widget, const gchar *path)
+{
+       KeywordFindData *kfd;
+       GtkWidget *hbox;
+       GtkWidget *label;
+
+       kfd = g_new0(KeywordFindData, 1);
+
+       kfd->gd = generic_dialog_new(_("Search for keywords"),
+                                                                       "search_for_keywords",
+                                                                       widget, FALSE,
+                                                                       NULL, kfd);
+       gtk_window_set_default_size(GTK_WINDOW(kfd->gd->dialog), KEYWORD_DIALOG_WIDTH, -1);
+       kfd->gd->cancel_cb = keywords_find_close_cb;
+       kfd->button_close = generic_dialog_add_button(kfd->gd, GTK_STOCK_CLOSE, NULL,
+                                                    keywords_find_close_cb, FALSE);
+       kfd->button_start = generic_dialog_add_button(kfd->gd, GTK_STOCK_OK, _("S_tart"),
+                                                    keywords_find_start_cb, FALSE);
+       kfd->button_stop = generic_dialog_add_button(kfd->gd, GTK_STOCK_STOP, NULL,
+                                                   keywords_find_stop_cb, FALSE);
+       gtk_widget_set_sensitive(kfd->button_stop, FALSE);
+
+       generic_dialog_add_message(kfd->gd, NULL, _("Search for keywords"), NULL, FALSE);
+
+       hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0);
+       pref_spacer(hbox, PREF_PAD_INDENT);
+       kfd->group = pref_box_new(hbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
+
+       hbox = pref_box_new(kfd->group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
+       pref_label_new(hbox, _("Folder:"));
+
+       label = tab_completion_new(&kfd->entry, path, NULL, NULL, NULL, NULL);
+       tab_completion_add_select_button(kfd->entry,_("Select folder") , TRUE);
+       gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
+       gtk_widget_show(label);
+
+       pref_checkbox_new_int(kfd->group, _("Include subfolders"), FALSE, &kfd->recurse);
+
+       pref_line(kfd->gd->vbox, PREF_PAD_SPACE);
+       hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
+
+       kfd->progress = gtk_entry_new();
+       gtk_widget_set_can_focus(kfd->progress, FALSE);
+       gtk_editable_set_editable(GTK_EDITABLE(kfd->progress), FALSE);
+       gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("click start to begin"));
+       gtk_box_pack_start(GTK_BOX(hbox), kfd->progress, TRUE, TRUE, 0);
+       gtk_widget_show(kfd->progress);
+
+       kfd->spinner = spinner_new(NULL, -1);
+       gtk_box_pack_start(GTK_BOX(hbox), kfd->spinner, FALSE, FALSE, 0);
+       gtk_widget_show(kfd->spinner);
+
+       kfd->list = NULL;
+
+       gtk_widget_show(kfd->gd->dialog);
+}
+
+static void keywords_find_cb(GtkWidget *widget, gpointer data)
+{
+       const gchar *path = layout_get_path(NULL);
+
+       if (!path || !*path) path = homedir();
+       keywords_find_dialog(widget, path);
+}
+
+static void config_tab_keywords_save()
+{
+       GtkTextIter start, end;
+       GtkTextBuffer *buffer;
+       GList *kw_list = NULL;
+       GList *work;
+       gchar *buffer_text;
+       gchar *kw_split;
+       gboolean found;
+
+       buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
+       gtk_text_buffer_get_bounds(buffer, &start, &end);
+
+       buffer_text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
+
+       kw_split = strtok(buffer_text, "\n");
+       while (kw_split != NULL)
+               {
+               work = kw_list;
+               found = FALSE;
+               while (work)
+                       {
+                       if (g_strcmp0(work->data, kw_split) == 0)
+                               {
+                               found = TRUE;
+                               break;
+                               }
+                       work = work->next;
+                       }
+               if (!found)
+                       {
+                       kw_list = g_list_append(kw_list, g_strdup(kw_split));
+                       }
+               kw_split = strtok(NULL, "\n");
+               }
+
+       keyword_list_set(kw_list);
+
+       string_list_free(kw_list);
+       g_free(buffer_text);
+}
+
+static void config_tab_keywords(GtkWidget *notebook)
+{
+       GtkWidget *hbox;
+       GtkWidget *vbox;
+       GtkWidget *group;
+       GtkWidget *button;
+       GtkWidget *scrolled;
+       GtkTextIter iter;
+       GtkTextBuffer *buffer;
+       gchar *tmp;
+
+       vbox = scrolled_notebook_page(notebook, _("Keywords"));
+
+       group = pref_group_new(vbox, TRUE, _("Edit keywords autocompletion list"), GTK_ORIENTATION_VERTICAL);
+
+       hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
+
+       button = pref_button_new(hbox, GTK_STOCK_EXECUTE, _("Search"), FALSE,
+                                  G_CALLBACK(keywords_find_cb), keyword_text);
+       gtk_widget_set_tooltip_text(button, "Search for existing keywords");
+
+
+       keyword_text = gtk_text_view_new();
+       gtk_widget_set_size_request(keyword_text, 20, 20);
+       scrolled = gtk_scrolled_window_new(NULL, NULL);
+       gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
+       gtk_widget_show(scrolled);
+
+       gtk_container_add(GTK_CONTAINER(scrolled), keyword_text);
+       gtk_widget_show(keyword_text);
+
+       gtk_text_view_set_editable(GTK_TEXT_VIEW(keyword_text), TRUE);
+
+       buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
+       gtk_text_buffer_create_tag(buffer, "monospace",
+                               "family", "monospace", NULL);
+
+       gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(keyword_text), GTK_WRAP_WORD);
+       gtk_text_buffer_get_start_iter(buffer, &iter);
+       gtk_text_buffer_create_mark(buffer, "end", &iter, FALSE);
+       gchar *path;
+
+       path = g_build_filename(get_rc_dir(), "keywords", NULL);
+
+       GList *kwl = keyword_list_get();
+       kwl = g_list_first(kwl);
+       while (kwl)
+       {
+               gtk_text_buffer_get_end_iter (buffer, &iter);
+           tmp = g_strconcat(kwl->data, "\n", NULL);
+               gtk_text_buffer_insert(buffer, &iter, tmp, -1);
+               kwl = kwl->next;
+               g_free(tmp);
+       }
+
+       gtk_text_buffer_set_modified(buffer, FALSE);
+
+       g_free(path);
 }
 
 /* metadata tab */
@@ -2058,7 +2919,7 @@ static void config_tab_color(GtkWidget *notebook)
                gtk_widget_show(entry);
                color_profile_input_name_entry[i] = entry;
 
-               tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, NULL);
+               tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, ".icc", "ICC Files", NULL);
                tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
                gtk_widget_set_size_request(entry, 160, -1);
                gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
@@ -2078,7 +2939,7 @@ static void config_tab_color(GtkWidget *notebook)
 
        pref_table_label(table, 0, 0, _("Screen:"), 1.0);
        tabcomp = tab_completion_new(&color_profile_screen_file_entry,
-                                    options->color_profile.screen_file, NULL, NULL);
+                                    options->color_profile.screen_file, NULL, ".icc", "ICC Files", NULL);
        tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
        gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
 #ifdef HAVE_LCMS
@@ -2092,6 +2953,22 @@ static void config_tab_color(GtkWidget *notebook)
 }
 
 /* advanced entry tab */
+static void use_geeqie_trash_cb(GtkWidget *widget, gpointer data)
+{
+       if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
+               {
+               c_options->file_ops.use_system_trash = FALSE;
+               }
+}
+
+static void use_system_trash_cb(GtkWidget *widget, gpointer data)
+{
+       if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
+               {
+               c_options->file_ops.use_system_trash = TRUE;
+               }
+}
+
 static void config_tab_behavior(GtkWidget *notebook)
 {
        GtkWidget *hbox;
@@ -2101,18 +2978,24 @@ static void config_tab_behavior(GtkWidget *notebook)
        GtkWidget *tabcomp;
        GtkWidget *ct_button;
        GtkWidget *spin;
+       GtkWidget *table;
+       GtkWidget *marks;
+       GtkWidget *with_rename;
+       GtkWidget *collections_on_top;
 
        vbox = scrolled_notebook_page(notebook, _("Behavior"));
 
        group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
 
-       pref_checkbox_new_int(group, _("Confirm file delete"),
+       pref_checkbox_new_int(group, _("Confirm permanent file delete"),
                              options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
+       pref_checkbox_new_int(group, _("Confirm move file to Trash"),
+                             options->file_ops.confirm_move_to_trash, &c_options->file_ops.confirm_move_to_trash);
        pref_checkbox_new_int(group, _("Enable Delete key"),
                              options->file_ops.enable_delete_key, &c_options->file_ops.enable_delete_key);
 
-       ct_button = pref_checkbox_new_int(group, _("Safe delete"),
-                                         options->file_ops.safe_delete_enable, &c_options->file_ops.safe_delete_enable);
+       ct_button = pref_radiobutton_new(group, NULL, _("Use Geeqie trash location"),
+                                       !options->file_ops.use_system_trash, G_CALLBACK(use_geeqie_trash_cb),NULL);
 
        hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
        pref_checkbox_link_sensitivity(ct_button, hbox);
@@ -2120,7 +3003,7 @@ static void config_tab_behavior(GtkWidget *notebook)
        pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
        pref_label_new(hbox, _("Folder:"));
 
-       tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL);
+       tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL, NULL, NULL);
        tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
        gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
        gtk_widget_show(tabcomp);
@@ -2140,8 +3023,12 @@ static void config_tab_behavior(GtkWidget *notebook)
        button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
                                 G_CALLBACK(safe_delete_clear_cb), NULL);
        gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
+       pref_radiobutton_new(group, ct_button, _("Use system Trash bin"),
+                                       options->file_ops.use_system_trash, G_CALLBACK(use_system_trash_cb), NULL);
        gtk_widget_show(button);
 
+       pref_spacer(group, PREF_PAD_GROUP);
+
 
        group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
 
@@ -2154,12 +3041,29 @@ static void config_tab_behavior(GtkWidget *notebook)
        pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
                              options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
 
+       marks = pref_checkbox_new_int(group, _("Save marks on exit"),
+                               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"),
+                               options->with_rename, &c_options->with_rename);
+       gtk_widget_set_tooltip_text(with_rename,"Change the default button for Copy/Move dialogs");
+
+       collections_on_top = pref_checkbox_new_int(group, _("Open collections on top"),
+                               options->collections_on_top, &c_options->collections_on_top);
+       gtk_widget_set_tooltip_text(collections_on_top,"Open collections window on top");
+
        pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
                          1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
 
        pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
                          16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
 
+       table = pref_table_new(group, 2, 1, FALSE, FALSE);
+       add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
+
+       pref_spacer(group, PREF_PAD_GROUP);
+
        group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
 
        pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
@@ -2170,12 +3074,25 @@ static void config_tab_behavior(GtkWidget *notebook)
                              options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
        pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
                              options->image_lm_click_nav, &c_options->image_lm_click_nav);
+       pref_checkbox_new_int(group, _("Play video by left click on image"),
+                             options->image_l_click_video, &c_options->image_l_click_video);
+       table = pref_table_new(group, 2, 1, FALSE, FALSE);
+       add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
+
 
 #ifdef DEBUG
+       pref_spacer(group, PREF_PAD_GROUP);
+
        group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
 
        pref_spin_new_int(group, _("Debug level:"), NULL,
                          DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
+
+       pref_checkbox_new_int(group, _("Timer data"),
+                       options->log_window.timer_data, &c_options->log_window.timer_data);
+
+       pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
+                         1, 99999, 1, options->log_window_lines, &options->log_window_lines);
 #endif
 }
 
@@ -2283,6 +3200,22 @@ static void config_tab_accelerators(GtkWidget *notebook)
        gtk_widget_show(button);
 }
 
+/* toolbar tab */
+static void config_tab_toolbar(GtkWidget *notebook)
+{
+       GtkWidget *vbox;
+       GtkWidget *toolbardata;
+       LayoutWindow *lw;
+
+       lw = layout_window_list->data;
+
+       vbox = scrolled_notebook_page(notebook, _("Toolbar"));
+
+       toolbardata = toolbar_select_new(lw);
+       gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
+       gtk_widget_show(vbox);
+}
+
 /* stereo tab */
 static void config_tab_stereo(GtkWidget *notebook)
 {
@@ -2384,18 +3317,22 @@ static void config_window_create(void)
        gtk_widget_show(win_vbox);
 
        notebook = gtk_notebook_new();
-       gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP);
+       gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_LEFT);
+       gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE);
        gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
 
        config_tab_general(notebook);
        config_tab_image(notebook);
+       config_tab_osd(notebook);
        config_tab_windows(notebook);
        config_tab_accelerators(notebook);
        config_tab_files(notebook);
        config_tab_metadata(notebook);
+       config_tab_keywords(notebook);
        config_tab_color(notebook);
        config_tab_stereo(notebook);
        config_tab_behavior(notebook);
+       config_tab_toolbar(notebook);
 
        hbox = gtk_hbutton_box_new();
        gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
@@ -2469,95 +3406,82 @@ void show_config_window(void)
  *-----------------
  */
 
-static GtkWidget *about = NULL;
-
-static gboolean about_delete_cb(GtkWidget *widget, GdkEventAny *event, gpointer data)
-{
-       gtk_widget_destroy(about);
-       about = NULL;
-
-       return TRUE;
-}
-
-static void about_window_close(GtkWidget *widget, gpointer data)
-{
-       if (!about) return;
-
-       gtk_widget_destroy(about);
-       about = NULL;
-}
-
-static void about_credits_cb(GtkWidget *widget, gpointer data)
-{
-       help_window_show("credits");
-}
-
-void show_about_window(void)
-{
-       GtkWidget *vbox;
-       GtkWidget *hbox;
-       GtkWidget *label;
-       GtkWidget *button;
-       GdkPixbuf *pixbuf;
-
-       gchar *buf;
-
-       if (about)
+void show_about_window(LayoutWindow *lw)
+{
+       GdkPixbuf *pixbuf_logo;
+       GdkPixbuf *pixbuf_icon;
+       gchar *authors[1000];
+       gchar *comment;
+       gint i_authors = 0;
+       gchar *path;
+       GString *copyright;
+       gchar *zd_path;
+       ZoneDetect *cd;
+       FILE *fp = NULL;
+#define LINE_LENGTH 1000
+       gchar line[LINE_LENGTH];
+
+       copyright = g_string_new(NULL);
+       copyright = g_string_append(copyright, "This program comes with absolutely no warranty.\nGNU General Public License, version 2 or later.\nSee https://www.gnu.org/licenses/old-licenses/gpl-2.0.html\n\n");
+
+       zd_path = g_build_filename(GQ_BIN_DIR, TIMEZONE_DATABASE, NULL);
+       cd = ZDOpenDatabase(zd_path);
+       if (cd)
                {
-               gtk_window_present(GTK_WINDOW(about));
-               return;
+               copyright = g_string_append(copyright, ZDGetNotice(cd));
                }
+       ZDCloseDatabase(cd);
+       g_free(zd_path);
 
-       about = window_new(GTK_WINDOW_TOPLEVEL, "about", NULL, NULL, _("About"));
-       gtk_window_set_type_hint(GTK_WINDOW(about), GDK_WINDOW_TYPE_HINT_DIALOG);
-       g_signal_connect(G_OBJECT(about), "delete_event",
-                        G_CALLBACK(about_delete_cb), NULL);
-
-       gtk_container_set_border_width(GTK_CONTAINER(about), PREF_PAD_BORDER);
-
-       vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
-       gtk_container_add(GTK_CONTAINER(about), vbox);
-       gtk_widget_show(vbox);
-
-       pixbuf = pixbuf_inline(PIXBUF_INLINE_LOGO);
-       button = gtk_image_new_from_pixbuf(pixbuf);
-       g_object_unref(pixbuf);
-       gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 0);
-       gtk_widget_show(button);
-
-       buf = g_strdup_printf(_("%s %s\n\nCopyright (c) 2006 John Ellis\nCopyright (c) %s The Geeqie Team\nwebsite: %s\nemail: %s\n\nReleased under the GNU General Public License"),
-                             GQ_APPNAME,
-                             VERSION,
-                             "2008 - 2016",
-                             GQ_WEBSITE,
-                             GQ_EMAIL_ADDRESS);
-       label = gtk_label_new(buf);
-       g_free(buf);
-
-       gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER);
-       gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
-       gtk_widget_show(label);
-
-       hbox = gtk_hbutton_box_new();
-       gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
-       gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
-       gtk_box_pack_end(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
-       gtk_widget_show(hbox);
-
-       button = pref_button_new(NULL, NULL, _("Credits..."), FALSE,
-                                G_CALLBACK(about_credits_cb), NULL);
-       gtk_container_add(GTK_CONTAINER(hbox), button);
-       gtk_widget_set_can_default(button, TRUE);
-       gtk_widget_show(button);
-
-       button = pref_button_new(NULL, GTK_STOCK_CLOSE, NULL, FALSE,
-                                G_CALLBACK(about_window_close), NULL);
-       gtk_container_add(GTK_CONTAINER(hbox), button);
-       gtk_widget_set_can_default(button, TRUE);
-       gtk_widget_grab_default(button);
-       gtk_widget_show(button);
+       authors[0] = NULL;
+       path = g_build_filename(GQ_HELPDIR, "AUTHORS", NULL);
+       fp = fopen(path, "r");
+       if (fp)
+               {
+               while(fgets(line, LINE_LENGTH, fp))
+                       {
+                       /* get rid of ending \n from fgets */
+                       line[strlen(line) - 1] = '\0';
+                       authors[i_authors] = g_strdup(line);
+                       i_authors++;
+                       }
+               authors[i_authors] = NULL;
+               fclose(fp);
+               }
+       g_free(path);
+
+       comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
+                                               "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
+
+       pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
+       pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
+       gtk_show_about_dialog(GTK_WINDOW(lw->window),
+               "title", _("About Geeqie"),
+               "resizable", TRUE,
+               "program-name", GQ_APPNAME,
+               "version", VERSION,
+               "logo", pixbuf_logo,
+               "icon", pixbuf_icon,
+               "website", GQ_WEBSITE,
+               "website-label", "Website",
+               "comments", comment,
+               "authors", authors,
+               "translator-credits", _("translator-credits"),
+               "wrap-license", TRUE,
+               "license", copyright->str,
+               NULL);
+
+       g_string_free(copyright, TRUE);
+
+       gint n = 0;
+       while(n < i_authors)
+               {
+               g_free(authors[n]);
+               n++;
+               }
+       g_free(comment);
 
-       gtk_widget_show(about);
+       return;
 }
 
 static void image_overlay_set_text_colours()