Addl fix #521: zoom increment is not multiplicative
[geeqie.git] / src / preferences.c
index 599620a..8c6804f 100644 (file)
 #include "layout_config.h"
 #include "layout_util.h"
 #include "metadata.h"
+#include "misc.h"
 #include "osd.h"
 #include "pixbuf_util.h"
+#include "rcfile.h"
 #include "slideshow.h"
 #include "toolbar.h"
 #include "trash.h"
@@ -117,7 +119,8 @@ gchar *format_class_list[] = {
        N_("Metadata"),
        N_("Video"),
        N_("Collection"),
-       N_("Document")
+       N_("Document"),
+       N_("Archive")
        };
 
 /* config memory values */
@@ -137,6 +140,8 @@ static GtkWidget *safe_delete_path_entry;
 static GtkWidget *color_profile_input_file_entry[COLOR_PROFILE_INPUTS];
 static GtkWidget *color_profile_input_name_entry[COLOR_PROFILE_INPUTS];
 static GtkWidget *color_profile_screen_file_entry;
+static GtkWidget *external_preview_select_entry;
+static GtkWidget *external_preview_extract_entry;
 
 static GtkWidget *sidecar_ext_entry;
 static GtkWidget *help_search_engine_entry;
@@ -202,7 +207,7 @@ static void slideshow_delay_seconds_cb(GtkWidget *spin, gpointer data)
 
 /*
  *-----------------------------------------------------------------------------
- * sync progam to config window routine (private)
+ * sync program to config window routine (private)
  *-----------------------------------------------------------------------------
  */
 
@@ -245,8 +250,10 @@ static gboolean accel_apply_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIt
 
 static void config_window_apply(void)
 {
-       gint i;
        gboolean refresh = FALSE;
+#ifdef HAVE_LCMS2
+       int i = 0;
+#endif
 
        config_entry_to_option(safe_delete_path_entry, &options->file_ops.safe_delete_path, remove_trailing_slash);
 
@@ -267,6 +274,7 @@ static void config_window_apply(void)
        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->save_window_workspace = c_options->save_window_workspace;
        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;
@@ -279,6 +287,7 @@ static void config_window_apply(void)
        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->image.tile_size = c_options->image.tile_size;
        options->progressive_key_scrolling = c_options->progressive_key_scrolling;
        options->keyboard_scroll_step = c_options->keyboard_scroll_step;
 
@@ -295,6 +304,7 @@ 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.use_color_management = c_options->thumbnails.use_color_management;
        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;
@@ -318,6 +328,7 @@ 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_archive = c_options->image_l_click_archive;
        options->image_l_click_video = c_options->image_l_click_video;
        options->image_l_click_video_editor = c_options->image_l_click_video_editor;
 
@@ -330,6 +341,8 @@ static void config_window_apply(void)
 
        options->image.zoom_increment = c_options->image.zoom_increment;
 
+       options->image.zoom_style = c_options->image.zoom_style;
+
        options->image.enable_read_ahead = c_options->image.enable_read_ahead;
 
 
@@ -374,6 +387,7 @@ static void config_window_apply(void)
        options->tree_descend_subdirs = c_options->tree_descend_subdirs;
 
        options->view_dir_list_single_click_enter = c_options->view_dir_list_single_click_enter;
+       options->circular_selection_lists = c_options->circular_selection_lists;
 
        options->open_recent_list_maxsize = c_options->open_recent_list_maxsize;
        options->dnd_icon_size = c_options->dnd_icon_size;
@@ -421,16 +435,25 @@ static void config_window_apply(void)
        options->info_rating.height = c_options->info_rating.height;
 
        options->show_predefined_keyword_tree = c_options->show_predefined_keyword_tree;
+       options->expand_menu_toolbar = c_options->expand_menu_toolbar;
 
        options->marks_save = c_options->marks_save;
        options->with_rename = c_options->with_rename;
        options->collections_on_top = c_options->collections_on_top;
+       options->hide_window_in_fullscreen = c_options->hide_window_in_fullscreen;
        config_entry_to_option(help_search_engine_entry, &options->help_search_engine, NULL);
 
+       options->external_preview.enable = c_options->external_preview.enable;
+       config_entry_to_option(external_preview_select_entry, &options->external_preview.select, NULL);
+       config_entry_to_option(external_preview_extract_entry, &options->external_preview.extract, 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;
+
+       options->threads.duplicates = c_options->threads.duplicates > 0 ? c_options->threads.duplicates : -1;
+
 #ifdef DEBUG
        set_debug_level(debug_c);
 #endif
@@ -453,6 +476,8 @@ static void config_window_apply(void)
        options->mouse_button_8 = c_options->mouse_button_8;
        options->mouse_button_9 = c_options->mouse_button_9;
 
+       options->override_disable_gpu = c_options->override_disable_gpu;
+
        config_tab_keywords_save();
 
        image_options_sync();
@@ -501,7 +526,8 @@ static void config_window_help_cb(GtkWidget *widget, gpointer data)
        "GuideOptionsStereo.html",
        "GuideOptionsBehavior.html",
        "GuideOptionsToolbar.html",
-       "GuideOptionsToolbar.html"
+       "GuideOptionsToolbar.html",
+       "GuideOptionsAdvanced.html"
        };
 
        i = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
@@ -517,8 +543,28 @@ static gboolean config_window_delete(GtkWidget *widget, GdkEventAny *event, gpoi
 static void config_window_ok_cb(GtkWidget *widget, gpointer data)
 {
        LayoutWindow *lw;
+       GtkNotebook *notebook = data;
+       GdkWindow *window;
+       gint x;
+       gint y;
+       gint w;
+       gint h;
+       gint page_number;
+
        lw = layout_window_list->data;
 
+       window = gtk_widget_get_window(widget);
+       gdk_window_get_root_origin(window, &x, &y);
+       w = gdk_window_get_width(window);
+       h = gdk_window_get_height(window);
+       page_number = gtk_notebook_get_current_page(notebook);
+
+       lw->options.preferences_window.x = x;
+       lw->options.preferences_window.y = y;
+       lw->options.preferences_window.w = w;
+       lw->options.preferences_window.h = h;
+       lw->options.preferences_window.page_number = page_number;
+
        config_window_apply();
        layout_util_sync(lw);
        save_options(options);
@@ -547,9 +593,6 @@ static void quality_menu_cb(GtkWidget *combo, gpointer data)
                case 2:
                        *option = GDK_INTERP_BILINEAR;
                        break;
-               case 3:
-                       *option = GDK_INTERP_HYPER;
-                       break;
                }
 }
 
@@ -578,12 +621,16 @@ static void clipboard_selection_menu_cb(GtkWidget *combo, gpointer data)
        switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
                {
                case 0:
-               default:
-                       *option = PRIMARY;
+                       *option = CLIPBOARD_PRIMARY;
                        break;
                case 1:
-                       *option = CLIPBOARD;
+                       *option = CLIPBOARD_CLIPBOARD;
+                       break;
+               case 2:
+                       *option = CLIPBOARD_BOTH;
                        break;
+               default:
+                       *option = CLIPBOARD_BOTH;
                }
 }
 
@@ -603,10 +650,8 @@ static void add_quality_menu(GtkWidget *table, gint column, gint row, const gcha
        if (option == GDK_INTERP_NEAREST) current = 0;
        gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Tiles"));
        if (option == GDK_INTERP_TILES) current = 1;
-       gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Bilinear"));
+       gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Bilinear (best, but slowest)"));
        if (option == GDK_INTERP_BILINEAR) current = 2;
-       gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Hyper (best, but slowest)"));
-       if (option == GDK_INTERP_HYPER) current = 3;
 
        gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
 
@@ -656,10 +701,12 @@ static void add_clipboard_selection_menu(GtkWidget *table, gint column, gint row
 
        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_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Primary"));
+       if (option == CLIPBOARD_PRIMARY) current = 0;
+       gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Clipboard"));
+       if (option == CLIPBOARD_CLIPBOARD) current = 1;
+       gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Both"));
+       if (option == CLIPBOARD_BOTH) current = 2;
 
        gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
 
@@ -670,6 +717,47 @@ static void add_clipboard_selection_menu(GtkWidget *table, gint column, gint row
        gtk_widget_show(combo);
 }
 
+static void zoom_style_selection_menu_cb(GtkWidget *combo, gpointer data)
+{
+       gint *option = data;
+
+       switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
+               {
+               case 0:
+                       *option = ZOOM_GEOMETRIC;
+                       break;
+               case 1:
+                       *option = ZOOM_ARITHMETIC;
+                       break;
+               default:
+                       *option = ZOOM_GEOMETRIC;
+               }
+}
+
+static void add_zoom_style_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text, ZoomStyle option, ZoomStyle *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), _("Geometric"));
+       if (option == ZOOM_GEOMETRIC) current = 0;
+       gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Arithmetic"));
+       if (option == ZOOM_ARITHMETIC) current = 1;
+
+       gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
+
+       g_signal_connect(G_OBJECT(combo), "changed", G_CALLBACK(zoom_style_selection_menu_cb), option_c);
+
+       gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
+       gtk_widget_show(combo);
+}
+
 typedef struct _UseableMouseItems UseableMouseItems;
 struct _UseableMouseItems
 {
@@ -732,6 +820,7 @@ static const UseableMouseItems useable_mouse_items[] = {
        {"Zoom33",      N_("Zoom1:3"), GTK_STOCK_FILE},
        {"Zoom25",      N_("Zoom 1:4"), GTK_STOCK_FILE},
        {"ConnectZoomIn",       N_("Connected Zoom in"), GTK_STOCK_ZOOM_IN},
+       {"SplitPaneSync",       N_("Split Pane Sync"), PIXBUF_INLINE_SPLIT_PANE_SYNC},
        {"Grayscale",   N_("Grayscale"), PIXBUF_INLINE_ICON_GRAYSCALE},
        {"OverUnderExposed",    N_("Over Under Exposed"), PIXBUF_INLINE_ICON_EXPOSURE},
        {"HideTools",   N_("Hide file list"), PIXBUF_INLINE_ICON_HIDETOOLS},
@@ -743,7 +832,6 @@ static const UseableMouseItems useable_mouse_items[] = {
        {"ExifWin",     N_("Exif window"), PIXBUF_INLINE_ICON_EXIF},
        {"Thumbnails",  N_("Show thumbnails"), PIXBUF_INLINE_ICON_THUMB},
        {"ShowMarks",   N_("Show marks"), PIXBUF_INLINE_ICON_MARKS},
-       {"ImageGuidelines",     N_("Show guidelines"), PIXBUF_INLINE_ICON_GUIDELINES},
        {"DrawRectangle",       N_("Draw Rectangle"), PIXBUF_INLINE_ICON_DRAW_RECTANGLE},
        {"FloatTools",  N_("Float file list"), PIXBUF_INLINE_ICON_FLOAT},
        {"SBar",        N_("Info sidebar"), PIXBUF_INLINE_ICON_INFO},
@@ -1226,8 +1314,6 @@ static gboolean filter_add_scroll(gpointer data)
        GList *list_cells;
        GtkCellRenderer *cell;
        GtkTreeViewColumn *column;
-       const gchar *title;
-       guint i = 0;
        gint rows;
 
        rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(filter_store), NULL);
@@ -1916,7 +2002,7 @@ static void config_tab_general(GtkWidget *notebook)
        pref_spin_new_int(hbox, _("Width:"), NULL, 1, 512, 1, options->thumbnails.max_width, &c_options->thumbnails.max_width);
        pref_spin_new_int(hbox, _("Height:"), NULL, 1, 512, 1, options->thumbnails.max_height, &c_options->thumbnails.max_height);
 
-       ct_button = pref_checkbox_new_int(group, _("Cache thumbnails"),
+       ct_button = pref_checkbox_new_int(group, _("Cache thumbnails and sim. files"),
                                          options->thumbnails.enable_caching, &c_options->thumbnails.enable_caching);
 
        subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
@@ -1947,6 +2033,9 @@ static void config_tab_general(GtkWidget *notebook)
        pref_checkbox_new_int(group, _("Use EXIF thumbnails when available (EXIF thumbnails may be outdated)"),
                              options->thumbnails.use_exif, &c_options->thumbnails.use_exif);
 
+       pref_checkbox_new_int(group, _("Thumbnail color management"),
+                               options->thumbnails.use_color_management, &c_options->thumbnails.use_color_management);
+
        spin = pref_spin_new_int(group, _("Collection preview:"), NULL,
                                 1, 999, 1,
                                 options->thumbnails.collection_preview, &c_options->thumbnails.collection_preview);
@@ -1969,7 +2058,7 @@ static void config_tab_general(GtkWidget *notebook)
 
        str = g_string_new(NULL);
        hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
-       pref_label_new(hbox, "Star character: ");
+       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);
@@ -2001,7 +2090,7 @@ static void config_tab_general(GtkWidget *notebook)
 
        str = g_string_new(NULL);
        hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
-       pref_label_new(hbox, "Rejected character: ");
+       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);
@@ -2067,7 +2156,7 @@ 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,
+       pref_spin_new_int(group, _("Decoded image cache size (MiB):"), NULL,
                          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);
@@ -2075,30 +2164,14 @@ static void config_tab_general(GtkWidget *notebook)
        pref_checkbox_new_int(group, _("Refresh on file change"),
                              options->update_on_time_change, &c_options->update_on_time_change);
 
-       pref_spacer(group, PREF_PAD_GROUP);
-
-       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);
 
        pref_spacer(group, PREF_PAD_GROUP);
 
-       group = pref_group_new(vbox, FALSE, _("Show predefined keyword tree"), GTK_ORIENTATION_VERTICAL);
+       group = pref_group_new(vbox, FALSE, _("Expand menu and toolbar"), 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);
+       pref_checkbox_new_int(group, _("Expand menu and toolbar (NOTE! Geeqie must be restarted for change to take effect)"),
+                               options->expand_menu_toolbar, &c_options->expand_menu_toolbar);
+       gtk_widget_set_tooltip_text(group, _("Expand the menu and toolbar to the full width of the window"));
 
        pref_spacer(group, PREF_PAD_GROUP);
 
@@ -2176,6 +2249,10 @@ static void config_tab_image(GtkWidget *notebook)
        GtkWidget *enlargement_button;
        GtkWidget *table;
        GtkWidget *spin;
+       GtkWidget *two_pass;
+#ifdef HAVE_CLUTTER
+       GtkWidget *gpu_accel;
+#endif
 
        vbox = scrolled_notebook_page(notebook, _("Image"));
 
@@ -2183,14 +2260,26 @@ static void config_tab_image(GtkWidget *notebook)
 
        table = pref_table_new(group, 2, 1, FALSE, FALSE);
        add_quality_menu(table, 0, 0, _("Quality:"), options->image.zoom_quality, &c_options->image.zoom_quality);
+       if (options->image.use_clutter_renderer && !options->disable_gpu)
+               {
+               gtk_widget_set_sensitive(table, FALSE);
+               }
 
 #ifdef HAVE_CLUTTER
-       pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library"),
+       gpu_accel = pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library (Requires restart)"),
                              options->image.use_clutter_renderer, &c_options->image.use_clutter_renderer);
+       if (options->disable_gpu && !options->override_disable_gpu)
+               {
+               gtk_widget_set_sensitive(gpu_accel, FALSE);
+               }
 #endif
 
-       pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"),
+       two_pass = 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);
+       if (options->image.use_clutter_renderer && !options->disable_gpu)
+               {
+               gtk_widget_set_sensitive(two_pass, FALSE);
+               }
 
        c_options->image.zoom_increment = options->image.zoom_increment;
        spin = pref_spin_new(group, _("Zoom increment:"), NULL,
@@ -2198,6 +2287,10 @@ static void config_tab_image(GtkWidget *notebook)
                             G_CALLBACK(zoom_increment_cb), NULL);
        gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
 
+       c_options->image.zoom_style = options->image.zoom_style;
+       table = pref_table_new(group, 2, 1, FALSE, FALSE);
+       add_zoom_style_selection_menu(table, 0, 0, _("Zoom style:"), options->image.zoom_style, &c_options->image.zoom_style);
+
        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);
@@ -2218,6 +2311,15 @@ static void config_tab_image(GtkWidget *notebook)
        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."));
 
+       group = pref_group_new(vbox, FALSE, _("Tile size"), GTK_ORIENTATION_VERTICAL);
+       gtk_widget_set_sensitive(group, !options->image.use_clutter_renderer);
+
+       hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
+       spin = pref_spin_new_int(hbox, _("Pixels"), _("(Requires restart)"),
+                                128, 4096, 128,
+                                options->image.tile_size, &c_options->image.tile_size);
+       gtk_widget_set_tooltip_text(GTK_WIDGET(hbox), _("This value changes the size of the tiles large images are split into. Increasing the size of the tiles will reduce the tiling effect seen on image changes, but will also slightly increase the delay before the first part of a large image is seen."));
+
        group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
 
        pref_checkbox_new_int(group, _("Use custom border color in window mode"),
@@ -2247,11 +2349,63 @@ static void config_tab_image(GtkWidget *notebook)
 }
 
 /* windows tab */
+
+static void save_default_window_layout_cb(GtkWidget *widget, gpointer data)
+{
+       LayoutWindow *lw = NULL;
+       gchar *default_path;
+       gchar *tmp_id;
+
+       /* Get current lw */
+       layout_valid(&lw);
+
+       tmp_id = lw->options.id;
+       lw->options.id = g_strdup("lw_default");
+
+       default_path = g_build_filename(get_rc_dir(), DEFAULT_WINDOW_LAYOUT, NULL);
+       save_default_layout_options_to_file(default_path, options, lw);
+       g_free(lw->options.id);
+       lw->options.id = tmp_id;
+       g_free(default_path);
+}
+
+#if GTK_CHECK_VERSION(3,22,0)
+static gboolean popover_cb(gpointer data)
+{
+       GtkPopover *popover = data;
+
+       gtk_popover_popdown(popover);
+
+       return FALSE;
+}
+
+static void default_layout_changed_cb(GtkWidget *button, GtkPopover *popover)
+{
+       gtk_popover_popup(popover);
+
+       g_timeout_add(2000, popover_cb, popover);
+}
+
+static GtkWidget *create_popover(GtkWidget *parent, GtkWidget *child, GtkPositionType pos)
+{
+       GtkWidget *popover;
+
+       popover = gtk_popover_new(parent);
+       gtk_popover_set_position(GTK_POPOVER (popover), pos);
+       gtk_container_add (GTK_CONTAINER(popover), child);
+       gtk_container_set_border_width(GTK_CONTAINER (popover), 6);
+       gtk_widget_show (child);
+
+       return popover;
+}
+#endif
+
 static void config_tab_windows(GtkWidget *notebook)
 {
        GtkWidget *hbox;
        GtkWidget *vbox;
        GtkWidget *group;
+       GtkWidget *subgroup;
        GtkWidget *button;
        GtkWidget *ct_button;
        GtkWidget *spin;
@@ -2260,13 +2414,17 @@ static void config_tab_windows(GtkWidget *notebook)
 
        group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
 
-       ct_button = pref_checkbox_new_int(group, _("Remember window positions"),
+       ct_button = pref_checkbox_new_int(group, _("Remember session"),
                                          options->save_window_positions, &c_options->save_window_positions);
 
        button = pref_checkbox_new_int(group, _("Use saved window positions also for new windows"),
                                       options->use_saved_window_positions_for_new_windows, &c_options->use_saved_window_positions_for_new_windows);
        pref_checkbox_link_sensitivity(ct_button, button);
 
+       button = pref_checkbox_new_int(group, _("Remember window workspace"),
+                             options->save_window_workspace, &c_options->save_window_workspace);
+       pref_checkbox_link_sensitivity(ct_button, button);
+
        pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
                              options->tools_restore_state, &c_options->tools_restore_state);
 
@@ -2276,6 +2434,18 @@ static void config_tab_windows(GtkWidget *notebook)
        pref_checkbox_new_int(group, _("Show window IDs"),
                              options->show_window_ids, &c_options->show_window_ids);
 
+       subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
+       pref_label_new(subgroup, _("Use current layout for default: "));
+       button = pref_button_new(subgroup, NULL, _("Set"), FALSE, G_CALLBACK(save_default_window_layout_cb), NULL);
+
+#if GTK_CHECK_VERSION(3,22,0)
+       GtkWidget *popover;
+
+       popover = create_popover(button, gtk_label_new(_("Current window layout\nhas been set as default")), GTK_POS_TOP);
+       gtk_popover_set_modal(GTK_POPOVER (popover), FALSE);
+       g_signal_connect(button, "clicked", G_CALLBACK(default_layout_changed_cb), popover);
+#endif
+
        group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
 
        pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
@@ -2308,7 +2478,6 @@ static void config_tab_osd(GtkWidget *notebook)
 {
        GtkWidget *hbox;
        GtkWidget *vbox;
-       GtkWidget *vbox_buttons;
        GtkWidget *group;
        GtkWidget *button;
        GtkWidget *image_overlay_template_view;
@@ -2316,10 +2485,7 @@ static void config_tab_osd(GtkWidget *notebook)
        GtkWidget *scrolled_pre_formatted;
        GtkTextBuffer *buffer;
        GtkWidget *label;
-       GtkWidget *     subgroup;
-       gint i = 0;
-       gint rows = 0;
-       gint cols = 0;
+       GtkWidget *subgroup;
 
        vbox = scrolled_notebook_page(notebook, _("OSD"));
 
@@ -2635,7 +2801,12 @@ static void config_tab_metadata(GtkWidget *notebook)
        label = pref_label_new(group, _("Warning: Geeqie is built without Exiv2. Some options are disabled."));
 #endif
        label = pref_label_new(group, _("Metadata are written in the following order. The process ends after first success."));
+#if GTK_CHECK_VERSION(3,16,0)
+       gtk_label_set_xalign(GTK_LABEL(label), 0.0);
+       gtk_label_set_yalign(GTK_LABEL(label), 0.5);
+#else
        gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
+#endif
 
        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);
@@ -2648,7 +2819,12 @@ static void config_tab_metadata(GtkWidget *notebook)
 
        text = g_strdup_printf(_("3) Save metadata in Geeqie private directory '%s'"), get_metadata_cache_dir());
        label = pref_label_new(group, text);
+#if GTK_CHECK_VERSION(3,16,0)
+       gtk_label_set_xalign(GTK_LABEL(label), 0.0);
+       gtk_label_set_yalign(GTK_LABEL(label), 0.5);
+#else
        gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
+#endif
        gtk_misc_set_padding(GTK_MISC(label), 22, 0);
        g_free(text);
 
@@ -3239,6 +3415,9 @@ static void config_tab_behavior(GtkWidget *notebook)
        GtkWidget *marks;
        GtkWidget *with_rename;
        GtkWidget *collections_on_top;
+       GtkWidget *hide_window_in_fullscreen;
+       GtkWidget *checkbox;
+       GtkWidget *tmp;
 
        vbox = scrolled_notebook_page(notebook, _("Behavior"));
 
@@ -3269,7 +3448,7 @@ static void config_tab_behavior(GtkWidget *notebook)
        pref_checkbox_link_sensitivity(ct_button, hbox);
 
        pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
-       spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MB"),
+       spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MiB"),
                                 0, 2048, 1, options->file_ops.safe_delete_folder_maxsize, &c_options->file_ops.safe_delete_folder_maxsize);
        gtk_widget_set_tooltip_markup(spin, _("Set to 0 for unlimited size"));
        button = pref_button_new(NULL, NULL, _("View"), FALSE,
@@ -3302,6 +3481,10 @@ 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);
 
+       tmp = pref_checkbox_new_int(group, _("Circular selection lists"),
+                             options->circular_selection_lists, &c_options->circular_selection_lists);
+       gtk_widget_set_tooltip_text(tmp, _("Traverse selection lists in a circular manner"));
+
        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");
@@ -3314,6 +3497,10 @@ static void config_tab_behavior(GtkWidget *notebook)
                                options->collections_on_top, &c_options->collections_on_top);
        gtk_widget_set_tooltip_text(collections_on_top,"Open collections window on top");
 
+       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");
+
        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);
 
@@ -3338,6 +3525,8 @@ 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, _("Open archive by left click on image"),
+                             options->image_l_click_archive, &c_options->image_l_click_archive);
        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);
@@ -3349,6 +3538,14 @@ static void config_tab_behavior(GtkWidget *notebook)
        table = pref_table_new(group, 2, 1, FALSE, FALSE);
        add_mouse_selection_menu(table, 0, 0, _("Mouse button Forward:"), options->mouse_button_9, &c_options->mouse_button_9);
 
+       pref_spacer(group, PREF_PAD_GROUP);
+
+       group = pref_group_new(vbox, FALSE, _("GPU"), GTK_ORIENTATION_VERTICAL);
+
+       checkbox = pref_checkbox_new_int(group, _("Override disable GPU"),
+                               options->override_disable_gpu, &c_options->override_disable_gpu);
+       gtk_widget_set_tooltip_text(checkbox, "Contact the developers for usage");
+
 #ifdef DEBUG
        pref_spacer(group, PREF_PAD_GROUP);
 
@@ -3501,6 +3698,107 @@ static void config_tab_toolbar_status(GtkWidget *notebook)
        gtk_widget_show(vbox);
 }
 
+/* advanced tab */
+static gint extension_sort_cb(gconstpointer a, gconstpointer b)
+{
+       return g_strcmp0((gchar *)a, (gchar *)b);
+}
+
+static void config_tab_advanced(GtkWidget *notebook)
+{
+       GtkWidget *vbox;
+       GtkWidget *group;
+       GSList *formats_list;
+       GList *extensions_list = NULL;
+       gchar **extensions;
+       GtkWidget *tabcomp;
+       GdkPixbufFormat *fm;
+       gint i;
+       GString *types_string = g_string_new(NULL);
+       GtkWidget *types_string_label;
+       GtkWidget *threads_string_label;
+       GtkWidget *dupes_threads_spin;
+
+       vbox = scrolled_notebook_page(notebook, _("Advanced"));
+       group = pref_group_new(vbox, FALSE, _("External preview extraction"), GTK_ORIENTATION_VERTICAL);
+
+       pref_checkbox_new_int(group, _("Use external preview extraction -  Requires restart"), options->external_preview.enable, &c_options->external_preview.enable);
+
+       pref_spacer(group, PREF_PAD_GROUP);
+
+       formats_list = gdk_pixbuf_get_formats();
+
+       while (formats_list)
+               {
+               fm = formats_list->data;
+               extensions = gdk_pixbuf_format_get_extensions(fm);
+
+               i = 0;
+               while (extensions[i])
+                       {
+                       extensions_list = g_list_insert_sorted(extensions_list, g_strdup(extensions[i]), extension_sort_cb);
+                       i++;
+                       }
+
+               g_strfreev(extensions);
+               formats_list = formats_list->next;
+               }
+
+       while (extensions_list)
+               {
+               if (types_string->len == 0)
+                       {
+                       types_string = g_string_append(types_string, extensions_list->data);
+                       }
+               else
+                       {
+                       types_string = g_string_append(types_string, ", ");
+                       types_string = g_string_append(types_string, extensions_list->data);
+                       }
+
+               extensions_list = extensions_list->next;
+               }
+
+       types_string = g_string_prepend(types_string, _("Usable file types:\n"));
+       types_string_label = pref_label_new(group, types_string->str);
+       gtk_label_set_line_wrap(GTK_LABEL(types_string_label), TRUE);
+
+       pref_spacer(group, PREF_PAD_GROUP);
+
+       group = pref_group_new(vbox, FALSE, _("File identification tool"), GTK_ORIENTATION_VERTICAL);
+       external_preview_select_entry = gtk_entry_new();
+       tabcomp = tab_completion_new(&external_preview_select_entry, options->external_preview.select, NULL, NULL, NULL, NULL);
+       tab_completion_add_select_button(external_preview_select_entry, _("Select file identification tool"), FALSE);
+       gtk_box_pack_start(GTK_BOX(group), tabcomp, TRUE, TRUE, 0);
+       gtk_widget_show(tabcomp);
+
+       group = pref_group_new(vbox, FALSE, _("Preview extraction tool"), GTK_ORIENTATION_VERTICAL);
+       external_preview_extract_entry = gtk_entry_new();
+       tabcomp = tab_completion_new(&external_preview_extract_entry, options->external_preview.extract, NULL, NULL, NULL, NULL);
+       tab_completion_add_select_button(external_preview_extract_entry, _("Select preview extraction tool"), FALSE);
+       gtk_box_pack_start(GTK_BOX(group), tabcomp, TRUE, TRUE, 0);
+       gtk_widget_show(tabcomp);
+
+       gtk_widget_show(vbox);
+
+       g_slist_free(formats_list);
+       string_list_free(extensions_list);
+       g_string_free(types_string, TRUE);
+
+       pref_spacer(group, PREF_PAD_GROUP);
+
+       pref_line(vbox, PREF_PAD_SPACE);
+       group = pref_group_new(vbox, FALSE, _("Thread pool limits"), GTK_ORIENTATION_VERTICAL);
+
+       threads_string_label = pref_label_new(group, "This option limits the number of threads (or cpu cores)\nthat Geeqie will use when running duplicate checks. The default value is 0, which means all available cores will be used.");
+       gtk_label_set_line_wrap(GTK_LABEL(threads_string_label), TRUE);
+
+       pref_spacer(vbox, PREF_PAD_GROUP);
+
+       dupes_threads_spin = pref_spin_new_int(vbox, _("Duplicate check:"), _("max. threads"), 0, get_cpu_cores(), 1, options->threads.duplicates, &c_options->threads.duplicates);
+       gtk_widget_set_tooltip_markup(dupes_threads_spin, _("Set to 0 for unlimited"));
+}
+
 /* stereo tab */
 static void config_tab_stereo(GtkWidget *notebook)
 {
@@ -3579,7 +3877,7 @@ static void config_tab_stereo(GtkWidget *notebook)
 }
 
 /* Main preferences window */
-static void config_window_create(void)
+static void config_window_create(LayoutWindow *lw)
 {
        GtkWidget *win_vbox;
        GtkWidget *hbox;
@@ -3594,7 +3892,15 @@ static void config_window_create(void)
        gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
        g_signal_connect(G_OBJECT(configwindow), "delete_event",
                         G_CALLBACK(config_window_delete), NULL);
-       gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
+       if (options->save_dialog_window_positions)
+               {
+               gtk_window_resize(GTK_WINDOW(configwindow), lw->options.preferences_window.w, lw->options.preferences_window.h);
+               gtk_window_move(GTK_WINDOW(configwindow), lw->options.preferences_window.x, lw->options.preferences_window.y);
+               }
+       else
+               {
+               gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
+               }
        gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
        gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
 
@@ -3620,6 +3926,9 @@ static void config_window_create(void)
        config_tab_behavior(notebook);
        config_tab_toolbar_main(notebook);
        config_tab_toolbar_status(notebook);
+       config_tab_advanced(notebook);
+
+       gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), lw->options.preferences_window.page_number);
 
        hbox = gtk_hbutton_box_new();
        gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
@@ -3634,7 +3943,7 @@ static void config_window_create(void)
        gtk_widget_show(button);
 
        button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
-                                G_CALLBACK(config_window_ok_cb), NULL);
+                                G_CALLBACK(config_window_ok_cb), notebook);
        gtk_container_add(GTK_CONTAINER(hbox), button);
        gtk_widget_set_can_default(button, TRUE);
        gtk_widget_grab_default(button);
@@ -3664,7 +3973,7 @@ static void config_window_create(void)
  *-----------------------------------------------------------------------------
  */
 
-void show_config_window(void)
+void show_config_window(LayoutWindow *lw)
 {
        if (configwindow)
                {
@@ -3672,7 +3981,7 @@ void show_config_window(void)
                return;
                }
 
-       config_window_create();
+       config_window_create(lw);
 }
 
 /*
@@ -3717,7 +4026,7 @@ void show_about_window(LayoutWindow *lw)
        g_free(basename);
 
        authors[0] = NULL;
-       path = g_build_filename(GQ_HELPDIR, "AUTHORS", NULL);
+       path = g_build_filename(gq_helpdir, "AUTHORS", NULL);
        fp = fopen(path, "r");
        if (fp)
                {
@@ -3828,7 +4137,6 @@ static void timezone_progress_cb(goffset current_num_bytes, goffset total_num_by
 static void timezone_cancel_button_cb(GenericDialog *gd, gpointer data)
 {
        TZData *tz = data;
-       GError *error = NULL;
 
        g_cancellable_cancel(tz->cancellable);
 }