Ref #332: include pdf-view
[geeqie.git] / src / preferences.c
1 /*
2  * Copyright (C) 2006 John Ellis
3  * Copyright (C) 2008 - 2016 The Geeqie Team
4  *
5  * Author: John Ellis
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21
22 #include "main.h"
23 #include "preferences.h"
24
25 #include "bar_exif.h"
26 #include "cache.h"
27 #include "cache_maint.h"
28 #include "editors.h"
29 #include "exif.h"
30 #include "filedata.h"
31 #include "filefilter.h"
32 #include "fullscreen.h"
33 #include "image.h"
34 #include "image-overlay.h"
35 #include "color-man.h"
36 #include "img-view.h"
37 #include "layout_config.h"
38 #include "layout_util.h"
39 #include "pixbuf_util.h"
40 #include "slideshow.h"
41 #include "toolbar.h"
42 #include "trash.h"
43 #include "utilops.h"
44 #include "ui_fileops.h"
45 #include "ui_misc.h"
46 #include "ui_tabcomp.h"
47 #include "ui_utildlg.h"
48 #include "window.h"
49 #include "zonedetect.h"
50
51 #include <math.h>
52
53 #ifdef HAVE_LCMS
54 #ifdef HAVE_LCMS2
55 #include <lcms2.h>
56 #else
57 #include <lcms.h>
58 #endif
59 #endif
60
61 #define EDITOR_NAME_MAX_LENGTH 32
62 #define EDITOR_COMMAND_MAX_LENGTH 1024
63
64 static void image_overlay_set_text_colours();
65
66 typedef struct _ThumbSize ThumbSize;
67 struct _ThumbSize
68 {
69         gint w;
70         gint h;
71 };
72
73 static ThumbSize thumb_size_list[] =
74 {
75         { 24, 24 },
76         { 32, 32 },
77         { 48, 48 },
78         { 64, 64 },
79         { 96, 72 },
80         { 96, 96 },
81         { 128, 96 },
82         { 128, 128 },
83         { 160, 120 },
84         { 160, 160 },
85         { 192, 144 },
86         { 192, 192 },
87         { 256, 192 },
88         { 256, 256 }
89 };
90
91 enum {
92         FE_ENABLE,
93         FE_EXTENSION,
94         FE_DESCRIPTION,
95         FE_CLASS,
96         FE_WRITABLE,
97         FE_ALLOW_SIDECAR
98 };
99
100 enum {
101         AE_ACTION,
102         AE_KEY,
103         AE_TOOLTIP,
104         AE_ACCEL
105 };
106
107 gchar *format_class_list[] = {
108         N_("Unknown"),
109         N_("Image"),
110         N_("RAW Image"),
111         N_("Metadata"),
112         N_("Video"),
113         N_("Collection"),
114         N_("Pdf")
115         };
116
117 /* config memory values */
118 static ConfOptions *c_options = NULL;
119
120
121 #ifdef DEBUG
122 static gint debug_c;
123 #endif
124
125 static GtkWidget *configwindow = NULL;
126 static GtkListStore *filter_store = NULL;
127 static GtkTreeStore *accel_store = NULL;
128
129 static GtkWidget *safe_delete_path_entry;
130
131 static GtkWidget *color_profile_input_file_entry[COLOR_PROFILE_INPUTS];
132 static GtkWidget *color_profile_input_name_entry[COLOR_PROFILE_INPUTS];
133 static GtkWidget *color_profile_screen_file_entry;
134
135 static GtkWidget *sidecar_ext_entry;
136 static GtkWidget *help_search_engine_entry;
137
138
139 #define CONFIG_WINDOW_DEF_WIDTH         700
140 #define CONFIG_WINDOW_DEF_HEIGHT        600
141
142 /*
143  *-----------------------------------------------------------------------------
144  * option widget callbacks (private)
145  *-----------------------------------------------------------------------------
146  */
147
148 static void zoom_increment_cb(GtkWidget *spin, gpointer data)
149 {
150         c_options->image.zoom_increment = (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) * 100.0 + 0.01);
151 }
152
153 static void slideshow_delay_hours_cb(GtkWidget *spin, gpointer data)
154 {
155         gint mins_secs_tenths, delay;
156
157         mins_secs_tenths = c_options->slideshow.delay %
158                                                 (3600 * SLIDESHOW_SUBSECOND_PRECISION);
159
160         delay = (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
161                                                                 (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
162                                                                 mins_secs_tenths);
163
164         c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
165                                                                                                         SLIDESHOW_SUBSECOND_PRECISION;
166 }
167
168 static void slideshow_delay_minutes_cb(GtkWidget *spin, gpointer data)
169 {
170         gint hours, secs_tenths, delay;
171
172         hours = c_options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
173         secs_tenths = c_options->slideshow.delay % (60 * SLIDESHOW_SUBSECOND_PRECISION);
174
175         delay = hours * (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
176                                         (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
177                                         (60 * SLIDESHOW_SUBSECOND_PRECISION) + secs_tenths);
178
179         c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
180                                                                                                         SLIDESHOW_SUBSECOND_PRECISION;
181 }
182
183 static void slideshow_delay_seconds_cb(GtkWidget *spin, gpointer data)
184 {
185         gint hours_mins, delay;
186
187         hours_mins = c_options->slideshow.delay / (60 * SLIDESHOW_SUBSECOND_PRECISION);
188
189         delay = (hours_mins * (60 * SLIDESHOW_SUBSECOND_PRECISION)) +
190                                                         (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
191                                                         (gdouble)(SLIDESHOW_SUBSECOND_PRECISION) + 0.01);
192
193         c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
194                                                                                                         SLIDESHOW_SUBSECOND_PRECISION;
195 }
196
197 /*
198  *-----------------------------------------------------------------------------
199  * sync progam to config window routine (private)
200  *-----------------------------------------------------------------------------
201  */
202
203 void config_entry_to_option(GtkWidget *entry, gchar **option, gchar *(*func)(const gchar *))
204 {
205         const gchar *buf;
206
207         g_free(*option);
208         *option = NULL;
209         buf = gtk_entry_get_text(GTK_ENTRY(entry));
210         if (buf && strlen(buf) > 0)
211                 {
212                 if (func)
213                         *option = func(buf);
214                 else
215                         *option = g_strdup(buf);
216                 }
217 }
218
219
220 static gboolean accel_apply_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
221 {
222         gchar *accel_path, *accel;
223
224         gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, AE_KEY, &accel, -1);
225
226         if (accel_path && accel_path[0])
227                 {
228                 GtkAccelKey key;
229                 gtk_accelerator_parse(accel, &key.accel_key, &key.accel_mods);
230                 gtk_accel_map_change_entry(accel_path, key.accel_key, key.accel_mods, TRUE);
231                 }
232
233         g_free(accel_path);
234         g_free(accel);
235
236         return FALSE;
237 }
238
239
240 static void config_window_apply(void)
241 {
242         gint i;
243         gboolean refresh = FALSE;
244
245         config_entry_to_option(safe_delete_path_entry, &options->file_ops.safe_delete_path, remove_trailing_slash);
246
247         if (options->file_filter.show_hidden_files != c_options->file_filter.show_hidden_files) refresh = TRUE;
248         if (options->file_filter.show_parent_directory != c_options->file_filter.show_parent_directory) refresh = TRUE;
249         if (options->file_filter.show_dot_directory != c_options->file_filter.show_dot_directory) refresh = TRUE;
250         if (options->file_sort.case_sensitive != c_options->file_sort.case_sensitive) refresh = TRUE;
251         if (options->file_sort.natural != c_options->file_sort.natural) refresh = TRUE;
252         if (options->file_filter.disable_file_extension_checks != c_options->file_filter.disable_file_extension_checks) refresh = TRUE;
253         if (options->file_filter.disable != c_options->file_filter.disable) refresh = TRUE;
254
255         options->file_ops.confirm_delete = c_options->file_ops.confirm_delete;
256         options->file_ops.enable_delete_key = c_options->file_ops.enable_delete_key;
257         options->file_ops.safe_delete_enable = c_options->file_ops.safe_delete_enable;
258         options->file_ops.safe_delete_folder_maxsize = c_options->file_ops.safe_delete_folder_maxsize;
259         options->tools_restore_state = c_options->tools_restore_state;
260         options->save_window_positions = c_options->save_window_positions;
261         options->use_saved_window_positions_for_new_windows = c_options->use_saved_window_positions_for_new_windows;
262         options->save_dialog_window_positions = c_options->save_dialog_window_positions;
263         options->show_window_ids = c_options->show_window_ids;
264         options->image.scroll_reset_method = c_options->image.scroll_reset_method;
265         options->image.zoom_2pass = c_options->image.zoom_2pass;
266         options->image.fit_window_to_image = c_options->image.fit_window_to_image;
267         options->image.limit_window_size = c_options->image.limit_window_size;
268         options->image.zoom_to_fit_allow_expand = c_options->image.zoom_to_fit_allow_expand;
269         options->image.max_window_size = c_options->image.max_window_size;
270         options->image.limit_autofit_size = c_options->image.limit_autofit_size;
271         options->image.max_autofit_size = c_options->image.max_autofit_size;
272         options->image.max_enlargement_size = c_options->image.max_enlargement_size;
273         options->image.use_clutter_renderer = c_options->image.use_clutter_renderer;
274         options->progressive_key_scrolling = c_options->progressive_key_scrolling;
275         options->keyboard_scroll_step = c_options->keyboard_scroll_step;
276
277         if (options->thumbnails.max_width != c_options->thumbnails.max_width
278             || options->thumbnails.max_height != c_options->thumbnails.max_height
279             || options->thumbnails.quality != c_options->thumbnails.quality)
280                 {
281                 thumb_format_changed = TRUE;
282                 refresh = TRUE;
283                 options->thumbnails.max_width = c_options->thumbnails.max_width;
284                 options->thumbnails.max_height = c_options->thumbnails.max_height;
285                 options->thumbnails.quality = c_options->thumbnails.quality;
286                 }
287         options->thumbnails.enable_caching = c_options->thumbnails.enable_caching;
288         options->thumbnails.cache_into_dirs = c_options->thumbnails.cache_into_dirs;
289         options->thumbnails.use_exif = c_options->thumbnails.use_exif;
290         options->thumbnails.use_ft_metadata = c_options->thumbnails.use_ft_metadata;
291 //      options->thumbnails.use_ft_metadata_small = c_options->thumbnails.use_ft_metadata_small;
292         options->thumbnails.spec_standard = c_options->thumbnails.spec_standard;
293         options->metadata.enable_metadata_dirs = c_options->metadata.enable_metadata_dirs;
294         options->file_filter.show_hidden_files = c_options->file_filter.show_hidden_files;
295         options->file_filter.show_parent_directory = c_options->file_filter.show_parent_directory;
296         options->file_filter.show_dot_directory = c_options->file_filter.show_dot_directory;
297         options->file_filter.disable_file_extension_checks = c_options->file_filter.disable_file_extension_checks;
298
299         options->file_sort.case_sensitive = c_options->file_sort.case_sensitive;
300         options->file_sort.natural = c_options->file_sort.natural;
301         options->file_filter.disable = c_options->file_filter.disable;
302
303         config_entry_to_option(sidecar_ext_entry, &options->sidecar.ext, NULL);
304         sidecar_ext_parse(options->sidecar.ext);
305
306         options->slideshow.random = c_options->slideshow.random;
307         options->slideshow.repeat = c_options->slideshow.repeat;
308         options->slideshow.delay = c_options->slideshow.delay;
309
310         options->mousewheel_scrolls = c_options->mousewheel_scrolls;
311         options->image_lm_click_nav = c_options->image_lm_click_nav;
312         options->image_l_click_video = c_options->image_l_click_video;
313         options->image_l_click_video_editor = c_options->image_l_click_video_editor;
314
315         options->file_ops.enable_in_place_rename = c_options->file_ops.enable_in_place_rename;
316
317         options->image.tile_cache_max = c_options->image.tile_cache_max;
318         options->image.image_cache_max = c_options->image.image_cache_max;
319
320         options->image.zoom_quality = c_options->image.zoom_quality;
321
322         options->image.zoom_increment = c_options->image.zoom_increment;
323
324         options->image.enable_read_ahead = c_options->image.enable_read_ahead;
325
326
327         if (options->image.use_custom_border_color != c_options->image.use_custom_border_color
328             || options->image.use_custom_border_color_in_fullscreen != c_options->image.use_custom_border_color_in_fullscreen
329             || !gdk_color_equal(&options->image.border_color, &c_options->image.border_color))
330                 {
331                 options->image.use_custom_border_color_in_fullscreen = c_options->image.use_custom_border_color_in_fullscreen;
332                 options->image.use_custom_border_color = c_options->image.use_custom_border_color;
333                 options->image.border_color = c_options->image.border_color;
334                 layout_colors_update();
335                 view_window_colors_update();
336                 }
337
338         options->image.alpha_color_1 = c_options->image.alpha_color_1;
339         options->image.alpha_color_2 = c_options->image.alpha_color_2;
340
341         options->fullscreen.screen = c_options->fullscreen.screen;
342         options->fullscreen.clean_flip = c_options->fullscreen.clean_flip;
343         options->fullscreen.disable_saver = c_options->fullscreen.disable_saver;
344         options->fullscreen.above = c_options->fullscreen.above;
345         if (c_options->image_overlay.template_string)
346                 set_image_overlay_template_string(&options->image_overlay.template_string,
347                                                   c_options->image_overlay.template_string);
348         if (c_options->image_overlay.font)
349                 set_image_overlay_font_string(&options->image_overlay.font,
350                                                   c_options->image_overlay.font);
351         options->image_overlay.text_red = c_options->image_overlay.text_red;
352         options->image_overlay.text_green = c_options->image_overlay.text_green;
353         options->image_overlay.text_blue = c_options->image_overlay.text_blue;
354         options->image_overlay.text_alpha = c_options->image_overlay.text_alpha;
355         options->image_overlay.background_red = c_options->image_overlay.background_red;
356         options->image_overlay.background_green = c_options->image_overlay.background_green;
357         options->image_overlay.background_blue = c_options->image_overlay.background_blue;
358         options->image_overlay.background_alpha = c_options->image_overlay.background_alpha;
359         options->update_on_time_change = c_options->update_on_time_change;
360         options->image.exif_proof_rotate_enable = c_options->image.exif_proof_rotate_enable;
361
362         options->duplicates_similarity_threshold = c_options->duplicates_similarity_threshold;
363         options->rot_invariant_sim = c_options->rot_invariant_sim;
364
365         options->tree_descend_subdirs = c_options->tree_descend_subdirs;
366
367         options->view_dir_list_single_click_enter = c_options->view_dir_list_single_click_enter;
368
369         options->open_recent_list_maxsize = c_options->open_recent_list_maxsize;
370         options->dnd_icon_size = c_options->dnd_icon_size;
371         options->clipboard_selection = c_options->clipboard_selection;
372
373         options->metadata.save_in_image_file = c_options->metadata.save_in_image_file;
374         options->metadata.save_legacy_IPTC = c_options->metadata.save_legacy_IPTC;
375         options->metadata.warn_on_write_problems = c_options->metadata.warn_on_write_problems;
376         options->metadata.save_legacy_format = c_options->metadata.save_legacy_format;
377         options->metadata.sync_grouped_files = c_options->metadata.sync_grouped_files;
378         options->metadata.confirm_write = c_options->metadata.confirm_write;
379         options->metadata.sidecar_extended_name = c_options->metadata.sidecar_extended_name;
380         options->metadata.confirm_timeout = c_options->metadata.confirm_timeout;
381         options->metadata.confirm_after_timeout = c_options->metadata.confirm_after_timeout;
382         options->metadata.confirm_on_image_change = c_options->metadata.confirm_on_image_change;
383         options->metadata.confirm_on_dir_change = c_options->metadata.confirm_on_dir_change;
384         options->metadata.keywords_case_sensitive = c_options->metadata.keywords_case_sensitive;
385         options->metadata.write_orientation = c_options->metadata.write_orientation;
386         options->stereo.mode = (c_options->stereo.mode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
387                                (c_options->stereo.tmp.mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
388                                (c_options->stereo.tmp.flip_right   ? PR_STEREO_FLIP_RIGHT : 0) |
389                                (c_options->stereo.tmp.mirror_left  ? PR_STEREO_MIRROR_LEFT : 0) |
390                                (c_options->stereo.tmp.flip_left    ? PR_STEREO_FLIP_LEFT : 0) |
391                                (c_options->stereo.tmp.swap         ? PR_STEREO_SWAP : 0) |
392                                (c_options->stereo.tmp.temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
393         options->stereo.fsmode = (c_options->stereo.fsmode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
394                                (c_options->stereo.tmp.fs_mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
395                                (c_options->stereo.tmp.fs_flip_right   ? PR_STEREO_FLIP_RIGHT : 0) |
396                                (c_options->stereo.tmp.fs_mirror_left  ? PR_STEREO_MIRROR_LEFT : 0) |
397                                (c_options->stereo.tmp.fs_flip_left    ? PR_STEREO_FLIP_LEFT : 0) |
398                                (c_options->stereo.tmp.fs_swap         ? PR_STEREO_SWAP : 0) |
399                                (c_options->stereo.tmp.fs_temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
400         options->stereo.enable_fsmode = c_options->stereo.enable_fsmode;
401         options->stereo.fixed_w = c_options->stereo.fixed_w;
402         options->stereo.fixed_h = c_options->stereo.fixed_h;
403         options->stereo.fixed_x1 = c_options->stereo.fixed_x1;
404         options->stereo.fixed_y1 = c_options->stereo.fixed_y1;
405         options->stereo.fixed_x2 = c_options->stereo.fixed_x2;
406         options->stereo.fixed_y2 = c_options->stereo.fixed_y2;
407
408         options->info_keywords.height = c_options->info_keywords.height;
409         options->info_title.height = c_options->info_title.height;
410         options->info_comment.height = c_options->info_comment.height;
411         options->info_rating.height = c_options->info_rating.height;
412
413         options->marks_save = c_options->marks_save;
414         options->with_rename = c_options->with_rename;
415         options->collections_on_top = c_options->collections_on_top;
416         config_entry_to_option(help_search_engine_entry, &options->help_search_engine, NULL);
417
418         options->read_metadata_in_idle = c_options->read_metadata_in_idle;
419
420         options->star_rating.star = c_options->star_rating.star;
421         options->star_rating.rejected = c_options->star_rating.rejected;
422 #ifdef DEBUG
423         set_debug_level(debug_c);
424 #endif
425
426 #ifdef HAVE_LCMS
427         for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
428                 {
429                 config_entry_to_option(color_profile_input_name_entry[i], &options->color_profile.input_name[i], NULL);
430                 config_entry_to_option(color_profile_input_file_entry[i], &options->color_profile.input_file[i], NULL);
431                 }
432         config_entry_to_option(color_profile_screen_file_entry, &options->color_profile.screen_file, NULL);
433         options->color_profile.use_x11_screen_profile = c_options->color_profile.use_x11_screen_profile;
434         if (options->color_profile.render_intent != c_options->color_profile.render_intent)
435                 {
436                 options->color_profile.render_intent = c_options->color_profile.render_intent;
437                 color_man_update();
438                 }
439 #endif
440
441         image_options_sync();
442
443         if (refresh)
444                 {
445                 filter_rebuild();
446                 layout_refresh(NULL);
447                 }
448
449         if (accel_store) gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_apply_cb, NULL);
450
451         toolbar_apply();
452 }
453
454 /*
455  *-----------------------------------------------------------------------------
456  * config window main button callbacks (private)
457  *-----------------------------------------------------------------------------
458  */
459
460 static void config_window_close_cb(GtkWidget *widget, gpointer data)
461 {
462         gtk_widget_destroy(configwindow);
463         configwindow = NULL;
464         filter_store = NULL;
465 }
466
467 static void config_window_help_cb(GtkWidget *widget, gpointer data)
468 {
469         GtkWidget *notebook = data;
470         gint i;
471
472         static gchar *html_section[] =
473         {
474         "GuideOptionsGeneral.html",
475         "GuideOptionsImage.html",
476         "GuideOptionsWindow.html",
477         "GuideOptionsKeyboard.html",
478         "GuideOptionsFiltering.html",
479         "GuideOptionsMetadata.html",
480         "GuideOptionsColor.html",
481         "GuideOptionsStereo.html",
482         "GuideOptionsBehavior.html",
483         "GuideOptionsToolbar.html"
484         };
485
486         i = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
487         help_window_show(html_section[i]);
488 }
489
490 static gboolean config_window_delete(GtkWidget *widget, GdkEventAny *event, gpointer data)
491 {
492         config_window_close_cb(NULL, NULL);
493         return TRUE;
494 }
495
496 static void config_window_ok_cb(GtkWidget *widget, gpointer data)
497 {
498         config_window_apply();
499         config_window_close_cb(NULL, NULL);
500 }
501
502 static void config_window_apply_cb(GtkWidget *widget, gpointer data)
503 {
504         LayoutWindow *lw;
505         lw = layout_window_list->data;
506
507         config_window_apply();
508         layout_util_sync(lw);
509 }
510
511 static void config_window_save_cb(GtkWidget *widget, gpointer data)
512 {
513         config_window_apply();
514         save_options(options);
515 }
516
517 /*
518  *-----------------------------------------------------------------------------
519  * config window setup (private)
520  *-----------------------------------------------------------------------------
521  */
522
523 static void quality_menu_cb(GtkWidget *combo, gpointer data)
524 {
525         gint *option = data;
526
527         switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
528                 {
529                 case 0:
530                 default:
531                         *option = GDK_INTERP_NEAREST;
532                         break;
533                 case 1:
534                         *option = GDK_INTERP_TILES;
535                         break;
536                 case 2:
537                         *option = GDK_INTERP_BILINEAR;
538                         break;
539                 case 3:
540                         *option = GDK_INTERP_HYPER;
541                         break;
542                 }
543 }
544
545 static void clipboard_selection_menu_cb(GtkWidget *combo, gpointer data)
546 {
547         gint *option = data;
548
549         switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
550                 {
551                 case 0:
552                 default:
553                         *option = PRIMARY;
554                         break;
555                 case 1:
556                         *option = CLIPBOARD;
557                         break;
558                 }
559 }
560
561 static void add_quality_menu(GtkWidget *table, gint column, gint row, const gchar *text,
562                              guint option, guint *option_c)
563 {
564         GtkWidget *combo;
565         gint current = 0;
566
567         *option_c = option;
568
569         pref_table_label(table, column, row, text, 0.0);
570
571         combo = gtk_combo_box_text_new();
572
573         gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Nearest (worst, but fastest)"));
574         if (option == GDK_INTERP_NEAREST) current = 0;
575         gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Tiles"));
576         if (option == GDK_INTERP_TILES) current = 1;
577         gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Bilinear"));
578         if (option == GDK_INTERP_BILINEAR) current = 2;
579         gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Hyper (best, but slowest)"));
580         if (option == GDK_INTERP_HYPER) current = 3;
581
582         gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
583
584         g_signal_connect(G_OBJECT(combo), "changed",
585                          G_CALLBACK(quality_menu_cb), option_c);
586
587         gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
588                          GTK_EXPAND | GTK_FILL, 0, 0, 0);
589         gtk_widget_show(combo);
590 }
591
592 static void add_clipboard_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
593                              gint option, gint *option_c)
594 {
595         GtkWidget *combo;
596         gint current = 0;
597
598         *option_c = option;
599
600         pref_table_label(table, column, row, text, 0.0);
601
602         combo = gtk_combo_box_text_new();
603
604         gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("PRIMARY"));
605         if (option == PRIMARY) current = 0;
606         gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("CLIPBOARD"));
607         if (option == CLIPBOARD) current = 1;
608
609         gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
610
611         g_signal_connect(G_OBJECT(combo), "changed",
612                          G_CALLBACK(clipboard_selection_menu_cb), option_c);
613
614         gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
615                          GTK_EXPAND | GTK_FILL, 0, 0, 0);
616         gtk_widget_show(combo);
617 }
618
619 static void thumb_size_menu_cb(GtkWidget *combo, gpointer data)
620 {
621         gint n;
622
623         n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
624         if (n < 0) return;
625
626         if ((guint) n < sizeof(thumb_size_list) / sizeof(ThumbSize))
627                 {
628                 c_options->thumbnails.max_width = thumb_size_list[n].w;
629                 c_options->thumbnails.max_height = thumb_size_list[n].h;
630                 }
631         else
632                 {
633                 c_options->thumbnails.max_width = options->thumbnails.max_width;
634                 c_options->thumbnails.max_height = options->thumbnails.max_height;
635                 }
636 }
637
638 static void add_thumb_size_menu(GtkWidget *table, gint column, gint row, gchar *text)
639 {
640         GtkWidget *combo;
641         gint current;
642         gint i;
643
644         c_options->thumbnails.max_width = options->thumbnails.max_width;
645         c_options->thumbnails.max_height = options->thumbnails.max_height;
646
647         pref_table_label(table, column, row, text, 0.0);
648
649         combo = gtk_combo_box_text_new();
650
651         current = -1;
652         for (i = 0; (guint) i < sizeof(thumb_size_list) / sizeof(ThumbSize); i++)
653                 {
654                 gint w, h;
655                 gchar *buf;
656
657                 w = thumb_size_list[i].w;
658                 h = thumb_size_list[i].h;
659
660                 buf = g_strdup_printf("%d x %d", w, h);
661                 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
662                 g_free(buf);
663
664                 if (w == options->thumbnails.max_width && h == options->thumbnails.max_height) current = i;
665                 }
666
667         if (current == -1)
668                 {
669                 gchar *buf;
670
671                 buf = g_strdup_printf("%s %d x %d", _("Custom"), options->thumbnails.max_width, options->thumbnails.max_height);
672                 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
673                 g_free(buf);
674
675                 current = i;
676                 }
677
678         gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
679         g_signal_connect(G_OBJECT(combo), "changed",
680                          G_CALLBACK(thumb_size_menu_cb), NULL);
681
682         gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
683                          GTK_EXPAND | GTK_FILL, 0, 0, 0);
684         gtk_widget_show(combo);
685 }
686
687 static void stereo_mode_menu_cb(GtkWidget *combo, gpointer data)
688 {
689         gint *option = data;
690
691         switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
692                 {
693                 case 0:
694                 default:
695                         *option = PR_STEREO_NONE;
696                         break;
697                 case 1:
698                         *option = PR_STEREO_ANAGLYPH_RC;
699                         break;
700                 case 2:
701                         *option = PR_STEREO_ANAGLYPH_GM;
702                         break;
703                 case 3:
704                         *option = PR_STEREO_ANAGLYPH_YB;
705                         break;
706                 case 4:
707                         *option = PR_STEREO_ANAGLYPH_GRAY_RC;
708                         break;
709                 case 5:
710                         *option = PR_STEREO_ANAGLYPH_GRAY_GM;
711                         break;
712                 case 6:
713                         *option = PR_STEREO_ANAGLYPH_GRAY_YB;
714                         break;
715                 case 7:
716                         *option = PR_STEREO_ANAGLYPH_DB_RC;
717                         break;
718                 case 8:
719                         *option = PR_STEREO_ANAGLYPH_DB_GM;
720                         break;
721                 case 9:
722                         *option = PR_STEREO_ANAGLYPH_DB_YB;
723                         break;
724                 case 10:
725                         *option = PR_STEREO_HORIZ;
726                         break;
727                 case 11:
728                         *option = PR_STEREO_HORIZ | PR_STEREO_HALF;
729                         break;
730                 case 12:
731                         *option = PR_STEREO_VERT;
732                         break;
733                 case 13:
734                         *option = PR_STEREO_VERT | PR_STEREO_HALF;
735                         break;
736                 case 14:
737                         *option = PR_STEREO_FIXED;
738                         break;
739                 }
740 }
741
742 static void add_stereo_mode_menu(GtkWidget *table, gint column, gint row, const gchar *text,
743                              gint option, gint *option_c, gboolean add_fixed)
744 {
745         GtkWidget *combo;
746         gint current = 0;
747
748         *option_c = option;
749
750         pref_table_label(table, column, row, text, 0.0);
751
752         combo = gtk_combo_box_text_new();
753
754         gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Single image"));
755
756         gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Red-Cyan"));
757         if (option & PR_STEREO_ANAGLYPH_RC) current = 1;
758         gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Green-Magenta"));
759         if (option & PR_STEREO_ANAGLYPH_GM) current = 2;
760         gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Yellow-Blue"));
761         if (option & PR_STEREO_ANAGLYPH_YB) current = 3;
762         gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Red-Cyan"));
763         if (option & PR_STEREO_ANAGLYPH_GRAY_RC) current = 4;
764         gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Green-Magenta"));
765         if (option & PR_STEREO_ANAGLYPH_GRAY_GM) current = 5;
766         gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Yellow-Blue"));
767         if (option & PR_STEREO_ANAGLYPH_GRAY_YB) current = 6;
768         gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Red-Cyan"));
769         if (option & PR_STEREO_ANAGLYPH_DB_RC) current = 7;
770         gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Green-Magenta"));
771         if (option & PR_STEREO_ANAGLYPH_DB_GM) current = 8;
772         gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Yellow-Blue"));
773         if (option & PR_STEREO_ANAGLYPH_DB_YB) current = 9;
774
775         gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side"));
776         gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side Half size"));
777         if (option & PR_STEREO_HORIZ)
778                 {
779                 current = 10;
780                 if (option & PR_STEREO_HALF) current = 11;
781                 }
782
783         gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom"));
784         gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom Half size"));
785         if (option & PR_STEREO_VERT)
786                 {
787                 current = 12;
788                 if (option & PR_STEREO_HALF) current = 13;
789                 }
790
791         if (add_fixed)
792                 {
793                 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Fixed position"));
794                 if (option & PR_STEREO_FIXED) current = 14;
795                 }
796
797         gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
798
799         g_signal_connect(G_OBJECT(combo), "changed",
800                          G_CALLBACK(stereo_mode_menu_cb), option_c);
801
802         gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
803                          GTK_EXPAND | GTK_FILL, 0, 0, 0);
804         gtk_widget_show(combo);
805 }
806
807 static void video_menu_cb(GtkWidget *combo, gpointer data)
808 {
809         gchar **option = data;
810
811         EditorDescription *ed = g_list_nth_data(editor_list_get(), gtk_combo_box_get_active(GTK_COMBO_BOX(combo)));
812         *option = ed->key;
813 }
814
815 static void video_menu_populate(gpointer data, gpointer user_data)
816 {
817         GtkWidget *combo = user_data;
818         EditorDescription *ed = data;
819
820         gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), ed->name);
821 }
822
823 static void add_video_menu(GtkWidget *table, gint column, gint row, const gchar *text,
824                              gchar *option, gchar **option_c)
825 {
826         GtkWidget *combo;
827         gint current;
828 /* use lists since they are sorted */
829         GList *eds = editor_list_get();
830
831         *option_c = option;
832
833         pref_table_label(table, column, row, text, 0.0);
834
835         combo = gtk_combo_box_text_new();
836         g_list_foreach(eds,video_menu_populate,(gpointer)combo);
837         current = option ? g_list_index(eds,g_hash_table_lookup(editors,option)): -1;
838
839         gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
840
841         g_signal_connect(G_OBJECT(combo), "changed",
842                          G_CALLBACK(video_menu_cb), option_c);
843
844         gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
845                          GTK_EXPAND | GTK_FILL, 0, 0, 0);
846         gtk_widget_show(combo);
847 }
848
849 static void filter_store_populate(void)
850 {
851         GList *work;
852
853         if (!filter_store) return;
854
855         gtk_list_store_clear(filter_store);
856
857         work = filter_get_list();
858         while (work)
859                 {
860                 FilterEntry *fe;
861                 GtkTreeIter iter;
862
863                 fe = work->data;
864                 work = work->next;
865
866                 gtk_list_store_append(filter_store, &iter);
867                 gtk_list_store_set(filter_store, &iter, 0, fe, -1);
868                 }
869 }
870
871 static void filter_store_ext_edit_cb(GtkCellRendererText *cell, gchar *path_str,
872                                      gchar *new_text, gpointer data)
873 {
874         GtkWidget *model = data;
875         FilterEntry *fe = data;
876         GtkTreePath *tpath;
877         GtkTreeIter iter;
878
879         if (!new_text || strlen(new_text) < 1) return;
880
881         tpath = gtk_tree_path_new_from_string(path_str);
882         gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
883         gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
884
885         g_free(fe->extensions);
886         fe->extensions = g_strdup(new_text);
887
888         gtk_tree_path_free(tpath);
889         filter_rebuild();
890 }
891
892 static void filter_store_class_edit_cb(GtkCellRendererText *cell, gchar *path_str,
893                                        gchar *new_text, gpointer data)
894 {
895         GtkWidget *model = data;
896         FilterEntry *fe = data;
897         GtkTreePath *tpath;
898         GtkTreeIter iter;
899         gint i;
900
901         if (!new_text || !new_text[0]) return;
902
903         tpath = gtk_tree_path_new_from_string(path_str);
904         gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
905         gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
906
907         for (i = 0; i < FILE_FORMAT_CLASSES; i++)
908                 {
909                 if (strcmp(new_text, _(format_class_list[i])) == 0)
910                         {
911                         fe->file_class = i;
912                         break;
913                         }
914                 }
915
916         gtk_tree_path_free(tpath);
917         filter_rebuild();
918 }
919
920 static void filter_store_desc_edit_cb(GtkCellRendererText *cell, gchar *path_str,
921                                       gchar *new_text, gpointer data)
922 {
923         GtkWidget *model = data;
924         FilterEntry *fe;
925         GtkTreePath *tpath;
926         GtkTreeIter iter;
927
928         if (!new_text || !new_text[0]) return;
929
930         tpath = gtk_tree_path_new_from_string(path_str);
931         gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
932         gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
933
934         g_free(fe->description);
935         fe->description = g_strdup(new_text);
936
937         gtk_tree_path_free(tpath);
938 }
939
940 static void filter_store_enable_cb(GtkCellRendererToggle *renderer,
941                                    gchar *path_str, gpointer data)
942 {
943         GtkWidget *model = data;
944         FilterEntry *fe;
945         GtkTreePath *tpath;
946         GtkTreeIter iter;
947
948         tpath = gtk_tree_path_new_from_string(path_str);
949         gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
950         gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
951
952         fe->enabled = !fe->enabled;
953
954         gtk_tree_path_free(tpath);
955         filter_rebuild();
956 }
957
958 static void filter_store_writable_cb(GtkCellRendererToggle *renderer,
959                                      gchar *path_str, gpointer data)
960 {
961         GtkWidget *model = data;
962         FilterEntry *fe;
963         GtkTreePath *tpath;
964         GtkTreeIter iter;
965
966         tpath = gtk_tree_path_new_from_string(path_str);
967         gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
968         gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
969
970         fe->writable = !fe->writable;
971         if (fe->writable) fe->allow_sidecar = FALSE;
972
973         gtk_tree_path_free(tpath);
974         filter_rebuild();
975 }
976
977 static void filter_store_sidecar_cb(GtkCellRendererToggle *renderer,
978                                     gchar *path_str, gpointer data)
979 {
980         GtkWidget *model = data;
981         FilterEntry *fe;
982         GtkTreePath *tpath;
983         GtkTreeIter iter;
984
985         tpath = gtk_tree_path_new_from_string(path_str);
986         gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
987         gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
988
989         fe->allow_sidecar = !fe->allow_sidecar;
990         if (fe->allow_sidecar) fe->writable = FALSE;
991
992         gtk_tree_path_free(tpath);
993         filter_rebuild();
994 }
995
996 static void filter_set_func(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
997                             GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
998 {
999         FilterEntry *fe;
1000
1001         gtk_tree_model_get(tree_model, iter, 0, &fe, -1);
1002
1003         switch (GPOINTER_TO_INT(data))
1004                 {
1005                 case FE_ENABLE:
1006                         g_object_set(GTK_CELL_RENDERER(cell),
1007                                      "active", fe->enabled, NULL);
1008                         break;
1009                 case FE_EXTENSION:
1010                         g_object_set(GTK_CELL_RENDERER(cell),
1011                                      "text", fe->extensions, NULL);
1012                         break;
1013                 case FE_DESCRIPTION:
1014                         g_object_set(GTK_CELL_RENDERER(cell),
1015                                      "text", fe->description, NULL);
1016                         break;
1017                 case FE_CLASS:
1018                         g_object_set(GTK_CELL_RENDERER(cell),
1019                                      "text", _(format_class_list[fe->file_class]), NULL);
1020                         break;
1021                 case FE_WRITABLE:
1022                         g_object_set(GTK_CELL_RENDERER(cell),
1023                                      "active", fe->writable, NULL);
1024                         break;
1025                 case FE_ALLOW_SIDECAR:
1026                         g_object_set(GTK_CELL_RENDERER(cell),
1027                                      "active", fe->allow_sidecar, NULL);
1028                         break;
1029                 }
1030 }
1031
1032 static gboolean filter_add_scroll(gpointer data)
1033 {
1034         GtkTreePath *path;
1035         GList *list_cells;
1036         GtkCellRenderer *cell;
1037         GtkTreeViewColumn *column;
1038         GList *list_columns;
1039         const gchar *title;
1040         guint i = 0;
1041         gint rows;
1042
1043         rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(filter_store), NULL);
1044         path = gtk_tree_path_new_from_indices(rows-1, -1);
1045
1046         list_columns = gtk_tree_view_get_columns(GTK_TREE_VIEW(data));
1047         do {
1048                 column = g_list_nth(list_columns,i)->data;
1049                 title = gtk_tree_view_column_get_title(GTK_TREE_VIEW_COLUMN(column));
1050                 i++;
1051                 } while (strcmp(title, "Filter") !=0 );
1052
1053         list_cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column));
1054         cell = g_list_last(list_cells)->data;
1055
1056         gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1057                                                                 path, column, FALSE, 0.0, 0.0 );
1058         gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(data),
1059                                                                 path, column, cell, TRUE);
1060
1061         gtk_tree_path_free(path);
1062         g_list_free(list_cells);
1063         g_list_free(list_columns);
1064
1065         return(FALSE);
1066 }
1067
1068 static void filter_add_cb(GtkWidget *widget, gpointer data)
1069 {
1070         filter_add_unique("description", ".new", FORMAT_CLASS_IMAGE, TRUE, FALSE, TRUE);
1071         filter_store_populate();
1072
1073         g_idle_add((GSourceFunc)filter_add_scroll, data);
1074 }
1075
1076 static void filter_remove_cb(GtkWidget *widget, gpointer data)
1077 {
1078         GtkWidget *filter_view = data;
1079         GtkTreeSelection *selection;
1080         GtkTreeIter iter;
1081         FilterEntry *fe;
1082
1083         if (!filter_store) return;
1084         selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1085         if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) return;
1086         gtk_tree_model_get(GTK_TREE_MODEL(filter_store), &iter, 0, &fe, -1);
1087         if (!fe) return;
1088
1089         filter_remove_entry(fe);
1090         filter_rebuild();
1091         filter_store_populate();
1092 }
1093
1094 static gboolean filter_default_ok_scroll(GtkTreeView *data)
1095 {
1096         GtkTreeIter iter;
1097         GtkTreePath *path;
1098         GtkTreeViewColumn *column;
1099
1100         gtk_tree_model_get_iter_first(GTK_TREE_MODEL(filter_store), &iter);
1101         path = gtk_tree_model_get_path(GTK_TREE_MODEL(filter_store), &iter);
1102         column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1103
1104         gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1105                                      path, column,
1106                                      FALSE, 0.0, 0.0);
1107
1108         gtk_tree_path_free(path);
1109
1110         return(FALSE);
1111 }
1112
1113 static void filter_default_ok_cb(GenericDialog *gd, gpointer data)
1114 {
1115         filter_reset();
1116         filter_add_defaults();
1117         filter_rebuild();
1118         filter_store_populate();
1119
1120         g_idle_add((GSourceFunc)filter_default_ok_scroll, gd->data);
1121 }
1122
1123 static void dummy_cancel_cb(GenericDialog *gd, gpointer data)
1124 {
1125         /* no op, only so cancel button appears */
1126 }
1127
1128 static void filter_default_cb(GtkWidget *widget, gpointer data)
1129 {
1130         GenericDialog *gd;
1131
1132         gd = generic_dialog_new(_("Reset filters"),
1133                                 "reset_filter", widget, TRUE,
1134                                 dummy_cancel_cb, data);
1135         generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset filters"),
1136                                    _("This will reset the file filters to the defaults.\nContinue?"), TRUE);
1137         generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, filter_default_ok_cb, TRUE);
1138         gtk_widget_show(gd->dialog);
1139 }
1140
1141 static void filter_disable_cb(GtkWidget *widget, gpointer data)
1142 {
1143         GtkWidget *frame = data;
1144
1145         gtk_widget_set_sensitive(frame,
1146                                  !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
1147 }
1148
1149 static void safe_delete_view_cb(GtkWidget *widget, gpointer data)
1150 {
1151         layout_set_path(NULL, gtk_entry_get_text(GTK_ENTRY(safe_delete_path_entry)));
1152 }
1153
1154 static void safe_delete_clear_ok_cb(GenericDialog *gd, gpointer data)
1155 {
1156         file_util_trash_clear();
1157 }
1158
1159 static void safe_delete_clear_cb(GtkWidget *widget, gpointer data)
1160 {
1161         GenericDialog *gd;
1162         GtkWidget *entry;
1163         gd = generic_dialog_new(_("Clear trash"),
1164                                 "clear_trash", widget, TRUE,
1165                                 dummy_cancel_cb, NULL);
1166         generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear trash"),
1167                                     _("This will remove the trash contents."), FALSE);
1168         generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, safe_delete_clear_ok_cb, TRUE);
1169         entry = gtk_entry_new();
1170         gtk_widget_set_can_focus(entry, FALSE);
1171         gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE);
1172         if (options->file_ops.safe_delete_path) gtk_entry_set_text(GTK_ENTRY(entry), options->file_ops.safe_delete_path);
1173         gtk_box_pack_start(GTK_BOX(gd->vbox), entry, FALSE, FALSE, 0);
1174         gtk_widget_show(entry);
1175         gtk_widget_show(gd->dialog);
1176 }
1177
1178 static void image_overlay_template_view_changed_cb(GtkWidget *widget, gpointer data)
1179 {
1180         GtkWidget *pTextView;
1181         GtkTextBuffer *pTextBuffer;
1182         GtkTextIter iStart;
1183         GtkTextIter iEnd;
1184
1185         pTextView = GTK_WIDGET(data);
1186
1187         pTextBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pTextView));
1188         gtk_text_buffer_get_start_iter(pTextBuffer, &iStart);
1189         gtk_text_buffer_get_end_iter(pTextBuffer, &iEnd);
1190
1191         set_image_overlay_template_string(&c_options->image_overlay.template_string,
1192                                           gtk_text_buffer_get_text(pTextBuffer, &iStart, &iEnd, TRUE));
1193 }
1194
1195 static void image_overlay_default_template_ok_cb(GenericDialog *gd, gpointer data)
1196 {
1197         GtkTextView *text_view = data;
1198         GtkTextBuffer *buffer;
1199
1200         set_default_image_overlay_template_string(&options->image_overlay.template_string);
1201         if (!configwindow) return;
1202
1203         buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
1204         gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1205 }
1206
1207 static void image_overlay_default_template_cb(GtkWidget *widget, gpointer data)
1208 {
1209         GenericDialog *gd;
1210
1211         gd = generic_dialog_new(_("Reset image overlay template string"),
1212                                 "reset_image_overlay_template_string", widget, TRUE,
1213                                 dummy_cancel_cb, data);
1214         generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset image overlay template string"),
1215                                    _("This will reset the image overlay template string to the default.\nContinue?"), TRUE);
1216         generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, image_overlay_default_template_ok_cb, TRUE);
1217         gtk_widget_show(gd->dialog);
1218 }
1219
1220 static void image_overlay_help_cb(GtkWidget *widget, gpointer data)
1221 {
1222         help_window_show("GuideOptionsWindow.html#OverlayScreenDisplay");
1223 }
1224
1225 static void image_overlay_set_font_cb(GtkWidget *widget, gpointer data)
1226 {
1227 #if GTK_CHECK_VERSION(3,4,0)
1228         GtkWidget *dialog;
1229         char *font;
1230         PangoFontDescription *font_desc;
1231
1232         dialog = gtk_font_chooser_dialog_new("Image Overlay Font", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1233         gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), options->image_overlay.font);
1234
1235         if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1236                 {
1237                 font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
1238                 font = pango_font_description_to_string(font_desc);
1239                 g_free(c_options->image_overlay.font);
1240                 c_options->image_overlay.font = g_strdup(font);
1241                 g_free(font);
1242                 }
1243
1244         gtk_widget_destroy(dialog);
1245 #else
1246         const char *font;
1247
1248         font = gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget));
1249         c_options->image_overlay.font = g_strdup(font);
1250 #endif
1251 }
1252
1253 static void image_overlay_set_text_colour_cb(GtkWidget *widget, gpointer data)
1254 {
1255         GtkWidget *dialog;
1256 #if GTK_CHECK_VERSION(3,4,0)
1257         GdkRGBA colour;
1258
1259         dialog = gtk_color_chooser_dialog_new("Image Overlay Text Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1260         colour.red = options->image_overlay.text_red;
1261         colour.green = options->image_overlay.text_green;
1262         colour.blue = options->image_overlay.text_blue;
1263         colour.alpha = options->image_overlay.text_alpha;
1264         gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1265         gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1266
1267         if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1268                 {
1269                 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1270                 c_options->image_overlay.text_red = colour.red*255;
1271                 c_options->image_overlay.text_green = colour.green*255;
1272                 c_options->image_overlay.text_blue = colour.blue*255;
1273                 c_options->image_overlay.text_alpha = colour.alpha*255;
1274                 }
1275         gtk_widget_destroy(dialog);
1276 #else
1277         GdkColor colour;
1278         GtkColorSelection *colorsel;
1279
1280         dialog = gtk_color_selection_dialog_new("Image Overlay Text Colour");
1281         gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1282         colour.red = options->image_overlay.text_red*257;
1283         colour.green = options->image_overlay.text_green*257;
1284         colour.blue = options->image_overlay.text_blue*257;
1285         colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1286         gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1287         gtk_color_selection_set_current_color(colorsel, &colour);
1288         gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.text_alpha*257);
1289
1290         if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1291                 {
1292                 gtk_color_selection_get_current_color(colorsel, &colour);
1293                 c_options->image_overlay.text_red = colour.red/257;
1294                 c_options->image_overlay.text_green = colour.green/257;
1295                 c_options->image_overlay.text_blue = colour.blue/257;
1296                 c_options->image_overlay.text_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1297                 }
1298         gtk_widget_destroy (dialog);
1299 #endif
1300 }
1301
1302
1303 static void image_overlay_set_background_colour_cb(GtkWidget *widget, gpointer data)
1304 {
1305         GtkWidget *dialog;
1306 #if GTK_CHECK_VERSION(3,4,0)
1307         GdkRGBA colour;
1308
1309         dialog = gtk_color_chooser_dialog_new("Image Overlay Background Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1310         colour.red = options->image_overlay.background_red;
1311         colour.green = options->image_overlay.background_green;
1312         colour.blue = options->image_overlay.background_blue;
1313         colour.alpha = options->image_overlay.background_alpha;
1314         gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1315         gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1316
1317         if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1318                 {
1319                 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1320                 c_options->image_overlay.background_red = colour.red*255;
1321                 c_options->image_overlay.background_green = colour.green*255;
1322                 c_options->image_overlay.background_blue = colour.blue*255;
1323                 c_options->image_overlay.background_alpha = colour.alpha*255;
1324                 }
1325         gtk_widget_destroy(dialog);
1326 #else
1327         GdkColor colour;
1328         GtkColorSelection *colorsel;
1329
1330         dialog = gtk_color_selection_dialog_new("Image Overlay Background Colour");
1331         gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1332         colour.red = options->image_overlay.background_red*257;
1333         colour.green = options->image_overlay.background_green*257;
1334         colour.blue = options->image_overlay.background_blue*257;
1335         colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1336         gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1337         gtk_color_selection_set_current_color(colorsel, &colour);
1338         gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.background_alpha*257);
1339
1340         if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1341                 {
1342                 gtk_color_selection_get_current_color(colorsel, &colour);
1343                 c_options->image_overlay.background_red = colour.red/257;
1344                 c_options->image_overlay.background_green = colour.green/257;
1345                 c_options->image_overlay.background_blue = colour.blue/257;
1346                 c_options->image_overlay.background_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1347                 }
1348         gtk_widget_destroy(dialog);
1349 #endif
1350 }
1351
1352 static void accel_store_populate(void)
1353 {
1354         LayoutWindow *lw;
1355         GList *groups, *actions;
1356         GtkAction *action;
1357         const gchar *accel_path;
1358         GtkAccelKey key;
1359         GtkTreeIter iter;
1360
1361         if (!accel_store || !layout_window_list || !layout_window_list->data) return;
1362
1363         gtk_tree_store_clear(accel_store);
1364         lw = layout_window_list->data; /* get the actions from the first window, it should not matter, they should be the same in all windows */
1365
1366         g_assert(lw && lw->ui_manager);
1367         groups = gtk_ui_manager_get_action_groups(lw->ui_manager);
1368         while (groups)
1369                 {
1370                 actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
1371                 while (actions)
1372                         {
1373                         action = GTK_ACTION(actions->data);
1374                         accel_path = gtk_action_get_accel_path(action);
1375                         if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
1376                                 {
1377                                 gchar *label, *label2, *tooltip, *accel;
1378                                 g_object_get(action,
1379                                              "tooltip", &tooltip,
1380                                              "label", &label,
1381                                              NULL);
1382
1383                                 if (pango_parse_markup(label, -1, '_', NULL, &label2, NULL, NULL) && label2)
1384                                         {
1385                                         g_free(label);
1386                                         label = label2;
1387                                         }
1388
1389                                 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1390
1391                                 if (tooltip)
1392                                         {
1393                                         gtk_tree_store_append(accel_store, &iter, NULL);
1394                                         gtk_tree_store_set(accel_store, &iter,
1395                                                            AE_ACTION, label,
1396                                                            AE_KEY, accel,
1397                                                            AE_TOOLTIP, tooltip ? tooltip : "",
1398                                                            AE_ACCEL, accel_path,
1399                                                            -1);
1400                                         }
1401
1402                                 g_free(accel);
1403                                 g_free(label);
1404                                 g_free(tooltip);
1405                                 }
1406                         actions = actions->next;
1407                         }
1408
1409                 groups = groups->next;
1410                 }
1411 }
1412
1413 static void accel_store_cleared_cb(GtkCellRendererAccel *accel, gchar *path_string, gpointer user_data)
1414 {
1415
1416 }
1417
1418 static gboolean accel_remove_key_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1419 {
1420         gchar *accel1 = data;
1421         gchar *accel2;
1422         GtkAccelKey key1;
1423         GtkAccelKey key2;
1424
1425         gtk_tree_model_get(model, iter, AE_KEY, &accel2, -1);
1426
1427         gtk_accelerator_parse(accel1, &key1.accel_key, &key1.accel_mods);
1428         gtk_accelerator_parse(accel2, &key2.accel_key, &key2.accel_mods);
1429
1430         if (key1.accel_key == key2.accel_key && key1.accel_mods == key2.accel_mods)
1431                 {
1432                 gtk_tree_store_set(accel_store, iter, AE_KEY, "",  -1);
1433                 DEBUG_1("accelerator key '%s' is already used, removing.", accel1);
1434                 }
1435
1436         g_free(accel2);
1437
1438         return FALSE;
1439 }
1440
1441
1442 static void accel_store_edited_cb(GtkCellRendererAccel *accel, gchar *path_string, guint accel_key, GdkModifierType accel_mods, guint hardware_keycode, gpointer user_data)
1443 {
1444         GtkTreeModel *model = (GtkTreeModel *)accel_store;
1445         GtkTreeIter iter;
1446         gchar *acc;
1447         gchar *accel_path;
1448         GtkAccelKey old_key, key;
1449         GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
1450
1451         gtk_tree_model_get_iter(model, &iter, path);
1452         gtk_tree_model_get(model, &iter, AE_ACCEL, &accel_path, -1);
1453
1454         /* test if the accelerator can be stored without conflicts*/
1455         gtk_accel_map_lookup_entry(accel_path, &old_key);
1456
1457         /* change the key and read it back (change may fail on keys hardcoded in gtk)*/
1458         gtk_accel_map_change_entry(accel_path, accel_key, accel_mods, TRUE);
1459         gtk_accel_map_lookup_entry(accel_path, &key);
1460
1461         /* restore the original for now, the key will be really changed when the changes are confirmed */
1462         gtk_accel_map_change_entry(accel_path, old_key.accel_key, old_key.accel_mods, TRUE);
1463
1464         acc = gtk_accelerator_name(key.accel_key, key.accel_mods);
1465         gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, acc);
1466
1467         gtk_tree_store_set(accel_store, &iter, AE_KEY, acc, -1);
1468         gtk_tree_path_free(path);
1469         g_free(acc);
1470 }
1471
1472 static gboolean accel_default_scroll(GtkTreeView *data)
1473 {
1474         GtkTreeIter iter;
1475         GtkTreePath *path;
1476         GtkTreeViewColumn *column;
1477
1478         gtk_tree_model_get_iter_first(GTK_TREE_MODEL(accel_store), &iter);
1479         path = gtk_tree_model_get_path(GTK_TREE_MODEL(accel_store), &iter);
1480         column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1481
1482         gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1483                                      path, column,
1484                                      FALSE, 0.0, 0.0);
1485
1486         gtk_tree_path_free(path);
1487
1488         return(FALSE);
1489 }
1490
1491 static void accel_default_cb(GtkWidget *widget, gpointer data)
1492 {
1493         accel_store_populate();
1494
1495         g_idle_add((GSourceFunc)accel_default_scroll, data);
1496 }
1497
1498 void accel_remove_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1499 {
1500         gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1501 }
1502
1503 void accel_reset_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1504 {
1505         GtkAccelKey key;
1506         gchar *accel_path, *accel;
1507
1508         gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, -1);
1509         gtk_accel_map_lookup_entry(accel_path, &key);
1510         accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1511
1512         gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, accel);
1513
1514         gtk_tree_store_set(accel_store, iter, AE_KEY, accel, -1);
1515         g_free(accel_path);
1516         g_free(accel);
1517 }
1518
1519 static void accel_reset_cb(GtkWidget *widget, gpointer data)
1520 {
1521         GtkTreeSelection *selection;
1522
1523         if (!accel_store) return;
1524         selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data));
1525         gtk_tree_selection_selected_foreach(selection, &accel_reset_selection, NULL);
1526 }
1527
1528
1529
1530 static GtkWidget *scrolled_notebook_page(GtkWidget *notebook, const gchar *title)
1531 {
1532         GtkWidget *label;
1533         GtkWidget *vbox;
1534         GtkWidget *scrolled;
1535         GtkWidget *viewport;
1536
1537         scrolled = gtk_scrolled_window_new(NULL, NULL);
1538         gtk_container_set_border_width(GTK_CONTAINER(scrolled), PREF_PAD_BORDER);
1539         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1540                                        GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1541         label = gtk_label_new(title);
1542         gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, label);
1543         gtk_widget_show(scrolled);
1544
1545         viewport = gtk_viewport_new(NULL, NULL);
1546         gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1547         gtk_container_add(GTK_CONTAINER(scrolled), viewport);
1548         gtk_widget_show(viewport);
1549
1550         vbox = gtk_vbox_new(FALSE, 0);
1551         gtk_container_add(GTK_CONTAINER(viewport), vbox);
1552         gtk_widget_show(vbox);
1553
1554         return vbox;
1555 }
1556
1557 static void cache_standard_cb(GtkWidget *widget, gpointer data)
1558 {
1559         if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1560                 {
1561                 c_options->thumbnails.spec_standard =TRUE;
1562                 c_options->thumbnails.cache_into_dirs = FALSE;
1563                 }
1564         else
1565                 {
1566                 c_options->thumbnails.spec_standard =FALSE;
1567                 }
1568 }
1569
1570 static void cache_geeqie_cb(GtkWidget *widget, gpointer data)
1571 {
1572         if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1573                 {
1574                 c_options->thumbnails.spec_standard =TRUE;
1575                 c_options->thumbnails.cache_into_dirs = FALSE;
1576                 }
1577         else
1578                 {
1579                 c_options->thumbnails.spec_standard =FALSE;
1580                 }
1581 }
1582
1583 static void cache_local_cb(GtkWidget *widget, gpointer data)
1584 {
1585         if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1586                 {
1587                 c_options->thumbnails.cache_into_dirs = TRUE;
1588                 c_options->thumbnails.spec_standard =FALSE;
1589                 }
1590         else
1591                 {
1592                 c_options->thumbnails.cache_into_dirs = FALSE;
1593                 }
1594 }
1595
1596 static void help_search_engine_entry_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1597                                                                         GdkEvent *event, gpointer userdata)
1598 {
1599         if (pos == GTK_ENTRY_ICON_PRIMARY)
1600                 {
1601                 gtk_entry_set_text(GTK_ENTRY(userdata), HELP_SEARCH_ENGINE);
1602                 }
1603         else
1604                 {
1605                 gtk_entry_set_text(GTK_ENTRY(userdata), "");
1606                 }
1607 }
1608
1609 static void star_rating_star_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1610                                                                         GdkEvent *event, gpointer userdata)
1611 {
1612         gchar *rating_symbol;
1613
1614         if (pos == GTK_ENTRY_ICON_PRIMARY)
1615                 {
1616                 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_STAR);
1617                 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1618                 g_free(rating_symbol);
1619                 }
1620         else
1621                 {
1622                 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1623                 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1624                 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1625                 }
1626 }
1627
1628 static void star_rating_rejected_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1629                                                                         GdkEvent *event, gpointer userdata)
1630 {
1631         gchar *rating_symbol;
1632
1633         if (pos == GTK_ENTRY_ICON_PRIMARY)
1634                 {
1635                 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_REJECTED);
1636                 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1637                 g_free(rating_symbol);
1638                 }
1639         else
1640                 {
1641                 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1642                 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1643                 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1644                 }
1645 }
1646
1647 static guint star_rating_symbol_test(GtkWidget *widget, gpointer data)
1648 {
1649         GtkContainer *hbox = data;
1650         GString *str = g_string_new(NULL);
1651         GtkEntry *hex_code_entry;
1652         gchar *hex_code_full;
1653         gchar **hex_code;
1654         GList *list;
1655         guint64 hex_value = 0;
1656
1657         list = gtk_container_get_children(hbox);
1658
1659         hex_code_entry = g_list_nth_data(list, 2);
1660         hex_code_full = g_strdup(gtk_entry_get_text(hex_code_entry));
1661
1662         hex_code = g_strsplit(hex_code_full, "+", 2);
1663         if (hex_code[0] && hex_code[1])
1664                 {
1665                 hex_value = strtoull(hex_code[1], NULL, 16);
1666                 }
1667         if (!hex_value || hex_value > 0x10FFFF)
1668                 {
1669                 hex_value = 0x003F; // Unicode 'Question Mark'
1670                 }
1671         str = g_string_append_unichar(str, (gunichar)hex_value);
1672         gtk_label_set_text(g_list_nth_data(list, 1), str->str);
1673
1674         g_strfreev(hex_code);
1675         g_string_free(str, TRUE);
1676         g_free(hex_code_full);
1677
1678         return hex_value;
1679 }
1680
1681 static void star_rating_star_test_cb(GtkWidget *widget, gpointer data)
1682 {
1683         guint64 star_symbol;
1684
1685         star_symbol = star_rating_symbol_test(widget, data);
1686         c_options->star_rating.star = star_symbol;
1687 }
1688
1689 static void star_rating_rejected_test_cb(GtkWidget *widget, gpointer data)
1690 {
1691         guint64 rejected_symbol;
1692
1693         rejected_symbol = star_rating_symbol_test(widget, data);
1694         c_options->star_rating.rejected = rejected_symbol;
1695 }
1696
1697 /* general options tab */
1698 static void config_tab_general(GtkWidget *notebook)
1699 {
1700         GtkWidget *vbox;
1701         GtkWidget *hbox;
1702         GtkWidget *group;
1703         GtkWidget *group_frame;
1704         GtkWidget *subgroup;
1705         GtkWidget *button;
1706         GtkWidget *ct_button;
1707         GtkWidget *table;
1708         GtkWidget *spin;
1709         gint hours, minutes, remainder;
1710         gdouble seconds;
1711         GtkWidget *star_rating_entry;
1712         GString *str;
1713         gchar *rating_symbol;
1714
1715         vbox = scrolled_notebook_page(notebook, _("General"));
1716
1717         group = pref_group_new(vbox, FALSE, _("Thumbnails"), GTK_ORIENTATION_VERTICAL);
1718
1719         table = pref_table_new(group, 2, 2, FALSE, FALSE);
1720         add_thumb_size_menu(table, 0, 0, _("Size:"));
1721         add_quality_menu(table, 0, 1, _("Quality:"), options->thumbnails.quality, &c_options->thumbnails.quality);
1722
1723         ct_button = pref_checkbox_new_int(group, _("Cache thumbnails"),
1724                                           options->thumbnails.enable_caching, &c_options->thumbnails.enable_caching);
1725
1726         subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1727         pref_checkbox_link_sensitivity(ct_button, subgroup);
1728
1729         group_frame = pref_frame_new(subgroup, TRUE, _("Use Geeqie thumbnail style and cache"),
1730                                                                                 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1731         button = pref_radiobutton_new(group_frame, NULL,  get_thumbnails_cache_dir(),
1732                                                         !options->thumbnails.spec_standard,
1733                                                         G_CALLBACK(cache_geeqie_cb), NULL);
1734
1735         group_frame = pref_frame_new(subgroup, TRUE,
1736                                                         _("Store thumbnails local to image folder (non-standard)"),
1737                                                         GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1738         pref_radiobutton_new(group_frame, button, "*/.thumbnails",
1739                                                         options->thumbnails.cache_into_dirs,
1740                                                         G_CALLBACK(cache_local_cb), NULL);
1741
1742         group_frame = pref_frame_new(subgroup, TRUE,
1743                                                         _("Use standard thumbnail style and cache, shared with other applications"),
1744                                                         GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1745         pref_radiobutton_new(group_frame, button, get_thumbnails_standard_cache_dir(),
1746                                                         options->thumbnails.spec_standard,
1747                                                         G_CALLBACK(cache_standard_cb), NULL);
1748
1749         pref_checkbox_new_int(group, _("Use EXIF thumbnails when available (EXIF thumbnails may be outdated)"),
1750                               options->thumbnails.use_exif, &c_options->thumbnails.use_exif);
1751
1752 #ifdef HAVE_FFMPEGTHUMBNAILER_METADATA
1753         pref_checkbox_new_int(group, _("Use embedded metadata in video files as thumbnails when available"),
1754                               options->thumbnails.use_ft_metadata, &c_options->thumbnails.use_ft_metadata);
1755
1756 //      pref_checkbox_new_int(group, _("Ignore embedded metadata if size is too small"),
1757 //                            options->thumbnails.use_ft_metadata_small, &c_options->thumbnails.use_ft_metadata_small);
1758 #endif
1759
1760         group = pref_group_new(vbox, FALSE, _("Star Rating"), GTK_ORIENTATION_VERTICAL);
1761
1762         c_options->star_rating.star = options->star_rating.star;
1763         c_options->star_rating.rejected = options->star_rating.rejected;
1764
1765         str = g_string_new(NULL);
1766         hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1767         pref_label_new(hbox, "Star character: ");
1768         str = g_string_append_unichar(str, options->star_rating.star);
1769         pref_label_new(hbox, g_strdup(str->str));
1770         rating_symbol = g_strdup_printf("U+%X", options->star_rating.star);
1771         star_rating_entry = gtk_entry_new();
1772         gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
1773         gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
1774         gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
1775         gtk_widget_show(star_rating_entry);
1776         button = pref_button_new(NULL, NULL, _("Set"), FALSE,
1777                                         G_CALLBACK(star_rating_star_test_cb), hbox);
1778         gtk_widget_set_tooltip_text(button, _("Display selected character"));
1779         gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1780         gtk_widget_show(button);
1781         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."));
1782         gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1783                                                 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
1784         gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1785                                                 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
1786         gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1787                                                 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
1788         gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1789                                                 GTK_ENTRY_ICON_PRIMARY, _("Default"));
1790         g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
1791                                                 G_CALLBACK(star_rating_star_icon_cb),
1792                                                 star_rating_entry);
1793
1794         g_string_free(str, TRUE);
1795         g_free(rating_symbol);
1796
1797         str = g_string_new(NULL);
1798         hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1799         pref_label_new(hbox, "Rejected character: ");
1800         str = g_string_append_unichar(str, options->star_rating.rejected);
1801         pref_label_new(hbox, g_strdup(str->str));
1802         rating_symbol = g_strdup_printf("U+%X", options->star_rating.rejected);
1803         star_rating_entry = gtk_entry_new();
1804         gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
1805         gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
1806         gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
1807         gtk_widget_show(star_rating_entry);
1808         button = pref_button_new(NULL, NULL, _("Set"), FALSE,
1809                                         G_CALLBACK(star_rating_rejected_test_cb), hbox);
1810         gtk_widget_set_tooltip_text(button, _("Display selected character"));
1811         gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1812         gtk_widget_show(button);
1813         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."));
1814         gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1815                                                 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
1816         gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1817                                                 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
1818         gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1819                                                 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
1820         gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1821                                                 GTK_ENTRY_ICON_PRIMARY, _("Default"));
1822         g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
1823                                                 G_CALLBACK(star_rating_rejected_icon_cb),
1824                                                 star_rating_entry);
1825
1826         g_string_free(str, TRUE);
1827         g_free(rating_symbol);
1828
1829         group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
1830
1831         c_options->slideshow.delay = options->slideshow.delay;
1832         hours = options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
1833         remainder = options->slideshow.delay % (3600 * SLIDESHOW_SUBSECOND_PRECISION);
1834         minutes = remainder / (60 * SLIDESHOW_SUBSECOND_PRECISION);
1835         seconds = (gdouble)(remainder % (60 * SLIDESHOW_SUBSECOND_PRECISION)) /
1836                                                                                         SLIDESHOW_SUBSECOND_PRECISION;
1837
1838         hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1839
1840         spin = pref_spin_new(hbox, _("Delay between image change hrs:mins:secs.dec"), NULL,
1841                                                                                 0, 23, 1.0, 0,
1842                                                                                 options->slideshow.delay ? hours : 0.0,
1843                                                                                 G_CALLBACK(slideshow_delay_hours_cb), NULL);
1844         gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1845         spin = pref_spin_new(hbox, ":" , NULL,
1846                                                                                 0, 59, 1.0, 0,
1847                                                                                 options->slideshow.delay ? minutes: 0.0,
1848                                                                                 G_CALLBACK(slideshow_delay_minutes_cb), NULL);
1849         gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1850         spin = pref_spin_new(hbox, ":", NULL,
1851                                                                                 SLIDESHOW_MIN_SECONDS, 59, 1.0, 1,
1852                                                                                 options->slideshow.delay ? seconds : 10.0,
1853                                                                                 G_CALLBACK(slideshow_delay_seconds_cb), NULL);
1854         gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1855
1856         pref_checkbox_new_int(group, _("Random"), options->slideshow.random, &c_options->slideshow.random);
1857         pref_checkbox_new_int(group, _("Repeat"), options->slideshow.repeat, &c_options->slideshow.repeat);
1858
1859         group = pref_group_new(vbox, FALSE, _("Image loading and caching"), GTK_ORIENTATION_VERTICAL);
1860
1861         pref_spin_new_int(group, _("Decoded image cache size (Mb):"), NULL,
1862                           0, 99999, 1, options->image.image_cache_max, &c_options->image.image_cache_max);
1863         pref_checkbox_new_int(group, _("Preload next image"),
1864                               options->image.enable_read_ahead, &c_options->image.enable_read_ahead);
1865
1866         pref_checkbox_new_int(group, _("Refresh on file change"),
1867                               options->update_on_time_change, &c_options->update_on_time_change);
1868
1869         group = pref_group_new(vbox, FALSE, _("Info sidebar heights"), GTK_ORIENTATION_VERTICAL);
1870         pref_label_new(group, _("NOTE! Geeqie must be restarted for changes to take effect"));
1871         hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1872         pref_spin_new_int(hbox, _("Keywords:"), NULL,
1873                                  1, 9999, 1,
1874                                  options->info_keywords.height, &c_options->info_keywords.height);
1875         pref_spin_new_int(hbox, _("Title:"), NULL,
1876                                  1, 9999, 1,
1877                                  options->info_title.height, &c_options->info_title.height);
1878         pref_spin_new_int(hbox, _("Comment:"), NULL,
1879                                  1, 9999, 1,
1880                                  options->info_comment.height, &c_options->info_comment.height);
1881         pref_spin_new_int(hbox, _("Rating:"), NULL,
1882                                  1, 9999, 1,
1883                                  options->info_rating.height, &c_options->info_rating.height);
1884
1885         group = pref_group_new(vbox, FALSE, _("On-line help search engine"), GTK_ORIENTATION_VERTICAL);
1886
1887         help_search_engine_entry = gtk_entry_new();
1888         gtk_entry_set_text(GTK_ENTRY(help_search_engine_entry), options->help_search_engine);
1889         gtk_box_pack_start(GTK_BOX(group), help_search_engine_entry, FALSE, FALSE, 0);
1890         gtk_widget_show(help_search_engine_entry);
1891
1892         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"));
1893
1894         gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
1895                                                 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
1896         gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
1897                                                 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
1898         gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
1899                                                 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
1900         gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
1901                                                 GTK_ENTRY_ICON_PRIMARY, _("Default"));
1902         g_signal_connect(GTK_ENTRY(help_search_engine_entry), "icon-press",
1903                                                 G_CALLBACK(help_search_engine_entry_icon_cb),
1904                                                 help_search_engine_entry);
1905 }
1906
1907 /* image tab */
1908 static void config_tab_image(GtkWidget *notebook)
1909 {
1910         GtkWidget *hbox;
1911         GtkWidget *vbox;
1912         GtkWidget *group;
1913         GtkWidget *ct_button;
1914         GtkWidget *enlargement_button;
1915         GtkWidget *table;
1916         GtkWidget *spin;
1917
1918         vbox = scrolled_notebook_page(notebook, _("Image"));
1919
1920         group = pref_group_new(vbox, FALSE, _("Zoom"), GTK_ORIENTATION_VERTICAL);
1921
1922         table = pref_table_new(group, 2, 1, FALSE, FALSE);
1923         add_quality_menu(table, 0, 0, _("Quality:"), options->image.zoom_quality, &c_options->image.zoom_quality);
1924
1925 #ifdef HAVE_CLUTTER
1926         pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library"),
1927                               options->image.use_clutter_renderer, &c_options->image.use_clutter_renderer);
1928 #endif
1929
1930         pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"),
1931                               options->image.zoom_2pass, &c_options->image.zoom_2pass);
1932
1933         c_options->image.zoom_increment = options->image.zoom_increment;
1934         spin = pref_spin_new(group, _("Zoom increment:"), NULL,
1935                              0.01, 4.0, 0.01, 2, (gdouble)options->image.zoom_increment / 100.0,
1936                              G_CALLBACK(zoom_increment_cb), NULL);
1937         gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1938
1939         group = pref_group_new(vbox, FALSE, _("Fit image to window"), GTK_ORIENTATION_VERTICAL);
1940
1941         hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1942         enlargement_button = pref_checkbox_new_int(hbox, _("Allow enlargement of image (max. size in %)"),
1943                               options->image.zoom_to_fit_allow_expand, &c_options->image.zoom_to_fit_allow_expand);
1944         spin = pref_spin_new_int(hbox, NULL, NULL,
1945                                  100, 999, 1,
1946                                  options->image.max_enlargement_size, &c_options->image.max_enlargement_size);
1947         pref_checkbox_link_sensitivity(enlargement_button, spin);
1948         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."));
1949
1950         hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1951         ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (% of actual window):"),
1952                                           options->image.limit_autofit_size, &c_options->image.limit_autofit_size);
1953         spin = pref_spin_new_int(hbox, NULL, NULL,
1954                                  10, 150, 1,
1955                                  options->image.max_autofit_size, &c_options->image.max_autofit_size);
1956         pref_checkbox_link_sensitivity(ct_button, spin);
1957         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."));
1958
1959         group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
1960
1961         pref_checkbox_new_int(group, _("Use custom border color in window mode"),
1962                               options->image.use_custom_border_color, &c_options->image.use_custom_border_color);
1963
1964         pref_checkbox_new_int(group, _("Use custom border color in fullscreen mode"),
1965                               options->image.use_custom_border_color_in_fullscreen, &c_options->image.use_custom_border_color_in_fullscreen);
1966
1967         pref_color_button_new(group, _("Border color"), &options->image.border_color,
1968                               G_CALLBACK(pref_color_button_set_cb), &c_options->image.border_color);
1969
1970         c_options->image.border_color = options->image.border_color;
1971
1972         pref_color_button_new(group, _("Alpha channel color 1"), &options->image.alpha_color_1,
1973                               G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_1);
1974
1975         pref_color_button_new(group, _("Alpha channel color 2"), &options->image.alpha_color_2,
1976                               G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_2);
1977
1978         c_options->image.alpha_color_1 = options->image.alpha_color_1;
1979         c_options->image.alpha_color_2 = options->image.alpha_color_2;
1980
1981         group = pref_group_new(vbox, FALSE, _("Convenience"), GTK_ORIENTATION_VERTICAL);
1982
1983         pref_checkbox_new_int(group, _("Auto rotate proofs using Exif information"),
1984                               options->image.exif_proof_rotate_enable, &c_options->image.exif_proof_rotate_enable);
1985 }
1986
1987 /* windows tab */
1988 static void config_tab_windows(GtkWidget *notebook)
1989 {
1990         GtkWidget *hbox;
1991         GtkWidget *vbox;
1992         GtkWidget *group;
1993         GtkWidget *button;
1994         GtkWidget *ct_button;
1995         GtkWidget *spin;
1996         GtkWidget *image_overlay_template_view;
1997         GtkWidget *scrolled;
1998         GtkTextBuffer *buffer;
1999
2000         vbox = scrolled_notebook_page(notebook, _("Windows"));
2001
2002         group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
2003
2004         ct_button = pref_checkbox_new_int(group, _("Remember window positions"),
2005                                           options->save_window_positions, &c_options->save_window_positions);
2006
2007         button = pref_checkbox_new_int(group, _("Use saved window positions also for new windows"),
2008                                        options->use_saved_window_positions_for_new_windows, &c_options->use_saved_window_positions_for_new_windows);
2009         pref_checkbox_link_sensitivity(ct_button, button);
2010
2011         pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
2012                               options->tools_restore_state, &c_options->tools_restore_state);
2013
2014         pref_checkbox_new_int(group, _("Remember dialog window positions"),
2015                               options->save_dialog_window_positions, &c_options->save_dialog_window_positions);
2016
2017         pref_checkbox_new_int(group, _("Show window IDs"),
2018                               options->show_window_ids, &c_options->show_window_ids);
2019
2020         group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
2021
2022         pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
2023                               options->image.fit_window_to_image, &c_options->image.fit_window_to_image);
2024
2025         hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2026         ct_button = pref_checkbox_new_int(hbox, _("Limit size when auto-sizing window (%):"),
2027                                           options->image.limit_window_size, &c_options->image.limit_window_size);
2028         spin = pref_spin_new_int(hbox, NULL, NULL,
2029                                  10, 150, 1,
2030                                  options->image.max_window_size, &c_options->image.max_window_size);
2031         pref_checkbox_link_sensitivity(ct_button, spin);
2032
2033         group = pref_group_new(vbox, FALSE, _("Full screen"), GTK_ORIENTATION_VERTICAL);
2034
2035         c_options->fullscreen.screen = options->fullscreen.screen;
2036         c_options->fullscreen.above = options->fullscreen.above;
2037         hbox = fullscreen_prefs_selection_new(_("Location:"), &c_options->fullscreen.screen, &c_options->fullscreen.above);
2038         gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2039         gtk_widget_show(hbox);
2040
2041         pref_checkbox_new_int(group, _("Smooth image flip"),
2042                               options->fullscreen.clean_flip, &c_options->fullscreen.clean_flip);
2043         pref_checkbox_new_int(group, _("Disable screen saver"),
2044                               options->fullscreen.disable_saver, &c_options->fullscreen.disable_saver);
2045
2046
2047         group = pref_group_new(vbox, FALSE, _("Overlay Screen Display"), GTK_ORIENTATION_VERTICAL);
2048
2049         pref_label_new(group, _("Image overlay template"));
2050
2051         scrolled = gtk_scrolled_window_new(NULL, NULL);
2052         gtk_widget_set_size_request(scrolled, 200, 150);
2053         gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2054         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
2055                                        GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2056         gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 5);
2057         gtk_widget_show(scrolled);
2058
2059         image_overlay_template_view = gtk_text_view_new();
2060
2061         gtk_widget_set_tooltip_markup(image_overlay_template_view,
2062         _("<i>%name%</i> results in the filename of the picture.\n"
2063           "Also available: <i>%collection%</i>, <i>%number%</i>, <i>%total%</i>, <i>%date%</i>,\n"
2064           "<i>%size%</i> (filesize), <i>%width%</i>, <i>%height%</i>, <i>%res%</i> (resolution),\n"
2065           "<i>%rating%</i>, <i>%keywords%</i>, <i>%comment%</i> (XMP), <i>%imagecomment%</i> (JPEG)\n"
2066           "To access exif data use the exif name, e. g. <i>%formatted.Camera%</i> is the formatted camera name,\n"
2067           "<i>%Exif.Photo.DateTimeOriginal%</i> the date of the original shot.\n"
2068           "<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"
2069           "If two or more variables are connected with the |-sign, it prints available variables with a separator.\n"
2070           "<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"
2071           "if there's no ISO information in the Exif data.\n"
2072           "If a line is empty, it is removed. This allows one to add lines that totally disappear when no data is available.\n"
2073         ));
2074         gtk_container_add(GTK_CONTAINER(scrolled), image_overlay_template_view);
2075         gtk_widget_show(image_overlay_template_view);
2076
2077         hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2078
2079 #if GTK_CHECK_VERSION(3,4,0)
2080         button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
2081                                  G_CALLBACK(image_overlay_set_font_cb), notebook);
2082 #else
2083         button = gtk_font_button_new();
2084         gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Image Overlay Font");
2085         gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->image_overlay.font);
2086         g_signal_connect(G_OBJECT(button), "font-set",
2087                                  G_CALLBACK(image_overlay_set_font_cb),NULL);
2088 #endif
2089         gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2090         gtk_widget_show(button);
2091
2092         button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Text"), FALSE,
2093                                  G_CALLBACK(image_overlay_set_text_colour_cb), NULL);
2094         gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2095         gtk_widget_show(button);
2096
2097         button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Background"), FALSE,
2098                                  G_CALLBACK(image_overlay_set_background_colour_cb), NULL);
2099         gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2100         gtk_widget_show(button);
2101         image_overlay_set_text_colours();
2102
2103         button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2104                                  G_CALLBACK(image_overlay_default_template_cb), image_overlay_template_view);
2105         gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2106         gtk_widget_show(button);
2107
2108         button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
2109                                  G_CALLBACK(image_overlay_help_cb), NULL);
2110         gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2111         gtk_widget_show(button);
2112
2113         buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_overlay_template_view));
2114         if (options->image_overlay.template_string) gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
2115         g_signal_connect(G_OBJECT(buffer), "changed",
2116                          G_CALLBACK(image_overlay_template_view_changed_cb), image_overlay_template_view);
2117
2118
2119 }
2120
2121 static GtkTreeModel *create_class_model(void)
2122 {
2123         GtkListStore *model;
2124         GtkTreeIter iter;
2125         gint i;
2126
2127         /* create list store */
2128         model = gtk_list_store_new(1, G_TYPE_STRING);
2129         for (i = 0; i < FILE_FORMAT_CLASSES; i++)
2130                 {
2131                 gtk_list_store_append(model, &iter);
2132                 gtk_list_store_set(model, &iter, 0, _(format_class_list[i]), -1);
2133                 }
2134         return GTK_TREE_MODEL (model);
2135 }
2136
2137
2138 /* filtering tab */
2139 static void config_tab_files(GtkWidget *notebook)
2140 {
2141         GtkWidget *hbox;
2142         GtkWidget *frame;
2143         GtkWidget *vbox;
2144         GtkWidget *group;
2145         GtkWidget *button;
2146         GtkWidget *ct_button;
2147         GtkWidget *scrolled;
2148         GtkWidget *filter_view;
2149         GtkCellRenderer *renderer;
2150         GtkTreeSelection *selection;
2151         GtkTreeViewColumn *column;
2152
2153         vbox = scrolled_notebook_page(notebook, _("Files"));
2154
2155         group = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2156
2157         pref_checkbox_new_int(group, _("Show hidden files or folders"),
2158                               options->file_filter.show_hidden_files, &c_options->file_filter.show_hidden_files);
2159         pref_checkbox_new_int(group, _("Show parent folder (..)"),
2160                               options->file_filter.show_parent_directory, &c_options->file_filter.show_parent_directory);
2161         pref_checkbox_new_int(group, _("Case sensitive sort"),
2162                               options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
2163         pref_checkbox_new_int(group, _("Natural sort order"),
2164                                           options->file_sort.natural, &c_options->file_sort.natural);
2165         pref_checkbox_new_int(group, _("Disable file extension checks"),
2166                               options->file_filter.disable_file_extension_checks, &c_options->file_filter.disable_file_extension_checks);
2167
2168         ct_button = pref_checkbox_new_int(group, _("Disable File Filtering"),
2169                                           options->file_filter.disable, &c_options->file_filter.disable);
2170
2171
2172         group = pref_group_new(vbox, FALSE, _("Grouping sidecar extensions"), GTK_ORIENTATION_VERTICAL);
2173
2174         sidecar_ext_entry = gtk_entry_new();
2175         gtk_entry_set_text(GTK_ENTRY(sidecar_ext_entry), options->sidecar.ext);
2176         gtk_box_pack_start(GTK_BOX(group), sidecar_ext_entry, FALSE, FALSE, 0);
2177         gtk_widget_show(sidecar_ext_entry);
2178
2179         group = pref_group_new(vbox, TRUE, _("File types"), GTK_ORIENTATION_VERTICAL);
2180
2181         frame = pref_group_parent(group);
2182         g_signal_connect(G_OBJECT(ct_button), "toggled",
2183                          G_CALLBACK(filter_disable_cb), frame);
2184         gtk_widget_set_sensitive(frame, !options->file_filter.disable);
2185
2186         scrolled = gtk_scrolled_window_new(NULL, NULL);
2187         gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2188         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2189         gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2190         gtk_widget_show(scrolled);
2191
2192         filter_store = gtk_list_store_new(1, G_TYPE_POINTER);
2193         filter_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(filter_store));
2194         g_object_unref(filter_store);
2195         selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
2196         gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
2197
2198         gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), FALSE);
2199
2200         column = gtk_tree_view_column_new();
2201         gtk_tree_view_column_set_title(column, _("Filter"));
2202         gtk_tree_view_column_set_resizable(column, TRUE);
2203
2204         renderer = gtk_cell_renderer_toggle_new();
2205         g_signal_connect(G_OBJECT(renderer), "toggled",
2206                          G_CALLBACK(filter_store_enable_cb), filter_store);
2207         gtk_tree_view_column_pack_start(column, renderer, FALSE);
2208         gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2209                                                 GINT_TO_POINTER(FE_ENABLE), NULL);
2210
2211         renderer = gtk_cell_renderer_text_new();
2212         g_signal_connect(G_OBJECT(renderer), "edited",
2213                          G_CALLBACK(filter_store_ext_edit_cb), filter_store);
2214         gtk_tree_view_column_pack_start(column, renderer, TRUE);
2215         g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2216         gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2217                                                 GINT_TO_POINTER(FE_EXTENSION), NULL);
2218         gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2219
2220         column = gtk_tree_view_column_new();
2221         gtk_tree_view_column_set_title(column, _("Description"));
2222         gtk_tree_view_column_set_resizable(column, TRUE);
2223         gtk_tree_view_column_set_fixed_width(column, 200);
2224         gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
2225
2226         renderer = gtk_cell_renderer_text_new();
2227         g_signal_connect(G_OBJECT(renderer), "edited",
2228                          G_CALLBACK(filter_store_desc_edit_cb), filter_store);
2229         g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2230         gtk_tree_view_column_pack_start(column, renderer, FALSE);
2231         gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2232                                                 GINT_TO_POINTER(FE_DESCRIPTION), NULL);
2233         gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2234
2235         column = gtk_tree_view_column_new();
2236         gtk_tree_view_column_set_title(column, _("Class"));
2237         gtk_tree_view_column_set_resizable(column, TRUE);
2238         renderer = gtk_cell_renderer_combo_new();
2239         g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE,
2240                                          "model", create_class_model(),
2241                                          "text-column", 0,
2242                                          "has-entry", FALSE,
2243                                          NULL);
2244
2245         g_signal_connect(G_OBJECT(renderer), "edited",
2246                          G_CALLBACK(filter_store_class_edit_cb), filter_store);
2247         gtk_tree_view_column_pack_start(column, renderer, TRUE);
2248         gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2249                                                 GINT_TO_POINTER(FE_CLASS), NULL);
2250         gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2251
2252         column = gtk_tree_view_column_new();
2253         gtk_tree_view_column_set_title(column, _("Writable"));
2254         gtk_tree_view_column_set_resizable(column, FALSE);
2255         renderer = gtk_cell_renderer_toggle_new();
2256         g_signal_connect(G_OBJECT(renderer), "toggled",
2257                          G_CALLBACK(filter_store_writable_cb), filter_store);
2258         gtk_tree_view_column_pack_start(column, renderer, FALSE);
2259         gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2260                                                 GINT_TO_POINTER(FE_WRITABLE), NULL);
2261         gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2262
2263         column = gtk_tree_view_column_new();
2264         gtk_tree_view_column_set_title(column, _("Sidecar is allowed"));
2265         gtk_tree_view_column_set_resizable(column, FALSE);
2266         renderer = gtk_cell_renderer_toggle_new();
2267         g_signal_connect(G_OBJECT(renderer), "toggled",
2268                          G_CALLBACK(filter_store_sidecar_cb), filter_store);
2269         gtk_tree_view_column_pack_start(column, renderer, FALSE);
2270         gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2271                                                 GINT_TO_POINTER(FE_ALLOW_SIDECAR), NULL);
2272         gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2273
2274
2275         filter_store_populate();
2276         gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
2277         gtk_widget_show(filter_view);
2278
2279         hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2280
2281         button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2282                                  G_CALLBACK(filter_default_cb), filter_view);
2283         gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2284         gtk_widget_show(button);
2285
2286         button = pref_button_new(NULL, GTK_STOCK_REMOVE, NULL, FALSE,
2287                                  G_CALLBACK(filter_remove_cb), filter_view);
2288         gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2289         gtk_widget_show(button);
2290
2291         button = pref_button_new(NULL, GTK_STOCK_ADD, NULL, FALSE,
2292                                  G_CALLBACK(filter_add_cb), filter_view);
2293         gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2294         gtk_widget_show(button);
2295 }
2296
2297 /* metadata tab */
2298 static void config_tab_metadata(GtkWidget *notebook)
2299 {
2300         GtkWidget *vbox;
2301         GtkWidget *hbox;
2302         GtkWidget *group;
2303         GtkWidget *ct_button;
2304         GtkWidget *label;
2305         gchar *text;
2306
2307         vbox = scrolled_notebook_page(notebook, _("Metadata"));
2308
2309
2310         group = pref_group_new(vbox, FALSE, _("Metadata writing process"), GTK_ORIENTATION_VERTICAL);
2311 #ifndef HAVE_EXIV2
2312         label = pref_label_new(group, _("Warning: Geeqie is built without Exiv2. Some options are disabled."));
2313 #endif
2314         label = pref_label_new(group, _("Metadata are written in the following order. The process ends after first success."));
2315         gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2316
2317         ct_button = pref_checkbox_new_int(group, _("1) Save metadata in image files, or sidecar files, according to the XMP standard"),
2318                               options->metadata.save_in_image_file, &c_options->metadata.save_in_image_file);
2319 #ifndef HAVE_EXIV2
2320         gtk_widget_set_sensitive(ct_button, FALSE);
2321 #endif
2322
2323         pref_checkbox_new_int(group, _("2) Save metadata in '.metadata' folder, local to image folder (non-standard)"),
2324                               options->metadata.enable_metadata_dirs, &c_options->metadata.enable_metadata_dirs);
2325
2326         text = g_strdup_printf(_("3) Save metadata in Geeqie private directory '%s'"), get_metadata_cache_dir());
2327         label = pref_label_new(group, text);
2328         gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2329         gtk_misc_set_padding(GTK_MISC(label), 22, 0);
2330         g_free(text);
2331
2332         group = pref_group_new(vbox, FALSE, _("Step 1: Write to image files"), GTK_ORIENTATION_VERTICAL);
2333 #ifndef HAVE_EXIV2
2334         gtk_widget_set_sensitive(group, FALSE);
2335 #endif
2336
2337         hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2338         pref_checkbox_link_sensitivity(ct_button, hbox);
2339
2340         pref_checkbox_new_int(hbox, _("Store metadata also in legacy IPTC tags (converted according to IPTC4XMP standard)"),
2341                               options->metadata.save_legacy_IPTC, &c_options->metadata.save_legacy_IPTC);
2342
2343         pref_checkbox_new_int(hbox, _("Warn if the image files are unwritable"),
2344                               options->metadata.warn_on_write_problems, &c_options->metadata.warn_on_write_problems);
2345
2346         pref_checkbox_new_int(hbox, _("Ask before writing to image files"),
2347                               options->metadata.confirm_write, &c_options->metadata.confirm_write);
2348
2349         pref_checkbox_new_int(hbox, _("Create sidecar files named image.ext.xmp (as opposed to image.xmp)"),
2350                               options->metadata.sidecar_extended_name, &c_options->metadata.sidecar_extended_name);
2351
2352         group = pref_group_new(vbox, FALSE, _("Step 2 and 3: write to Geeqie private files"), GTK_ORIENTATION_VERTICAL);
2353 #ifndef HAVE_EXIV2
2354         gtk_widget_set_sensitive(group, FALSE);
2355 #endif
2356
2357         pref_checkbox_new_int(group, _("Use GQview legacy metadata format (supports only keywords and comments) instead of XMP"),
2358                               options->metadata.save_legacy_format, &c_options->metadata.save_legacy_format);
2359
2360
2361         group = pref_group_new(vbox, FALSE, _("Miscellaneous"), GTK_ORIENTATION_VERTICAL);
2362         pref_checkbox_new_int(group, _("Write the same description tags (keywords, comment, etc.) to all grouped sidecars"),
2363                               options->metadata.sync_grouped_files, &c_options->metadata.sync_grouped_files);
2364
2365         pref_checkbox_new_int(group, _("Allow keywords to differ only in case"),
2366                               options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
2367
2368         ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"),
2369                               options->metadata.write_orientation, &c_options->metadata.write_orientation);
2370 #ifndef HAVE_EXIV2
2371         gtk_widget_set_sensitive(ct_button, FALSE);
2372 #endif
2373
2374         group = pref_group_new(vbox, FALSE, _("Auto-save options"), GTK_ORIENTATION_VERTICAL);
2375
2376         ct_button = pref_checkbox_new_int(group, _("Write metadata after timeout"),
2377                               options->metadata.confirm_after_timeout, &c_options->metadata.confirm_after_timeout);
2378
2379         hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2380         pref_checkbox_link_sensitivity(ct_button, hbox);
2381
2382         pref_spin_new_int(hbox, _("Timeout (seconds):"), NULL, 0, 900, 1,
2383                               options->metadata.confirm_timeout, &c_options->metadata.confirm_timeout);
2384
2385         pref_checkbox_new_int(group, _("Write metadata on image change"),
2386                               options->metadata.confirm_on_image_change, &c_options->metadata.confirm_on_image_change);
2387
2388         pref_checkbox_new_int(group, _("Write metadata on directory change"),
2389                               options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
2390
2391         group = pref_group_new(vbox, FALSE, _("Pre-load metadata"), GTK_ORIENTATION_VERTICAL);
2392
2393         ct_button = pref_checkbox_new_int(group, _("Read metadata in background"),
2394                                           options->read_metadata_in_idle, &c_options->read_metadata_in_idle);
2395         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");
2396 }
2397
2398 /* metadata tab */
2399 #ifdef HAVE_LCMS
2400 static void intent_menu_cb(GtkWidget *combo, gpointer data)
2401 {
2402         gint *option = data;
2403
2404         switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
2405                 {
2406                 case 0:
2407                 default:
2408                         *option = INTENT_PERCEPTUAL;
2409                         break;
2410                 case 1:
2411                         *option = INTENT_RELATIVE_COLORIMETRIC;
2412                         break;
2413                 case 2:
2414                         *option = INTENT_SATURATION;
2415                         break;
2416                 case 3:
2417                         *option = INTENT_ABSOLUTE_COLORIMETRIC;
2418                         break;
2419                 }
2420 }
2421
2422 static void add_intent_menu(GtkWidget *table, gint column, gint row, const gchar *text,
2423                              gint option, gint *option_c)
2424 {
2425         GtkWidget *combo;
2426         gint current = 0;
2427
2428         *option_c = option;
2429
2430         pref_table_label(table, column, row, text, 0.0);
2431
2432         combo = gtk_combo_box_text_new();
2433
2434         gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Perceptual"));
2435         if (option == INTENT_PERCEPTUAL) current = 0;
2436         gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Relative Colorimetric"));
2437         if (option == INTENT_RELATIVE_COLORIMETRIC) current = 1;
2438         gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Saturation"));
2439         if (option == INTENT_SATURATION) current = 2;
2440         gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Absolute Colorimetric"));
2441         if (option == INTENT_ABSOLUTE_COLORIMETRIC) current = 3;
2442
2443         gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
2444
2445         gtk_widget_set_tooltip_text(combo,"Refer to the lcms documentation for the defaults used when the selected Intent is not available");
2446
2447         g_signal_connect(G_OBJECT(combo), "changed",
2448                          G_CALLBACK(intent_menu_cb), option_c);
2449
2450         gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
2451                          GTK_EXPAND | GTK_FILL, 0, 0, 0);
2452         gtk_widget_show(combo);
2453 }
2454 #endif
2455
2456 static void config_tab_color(GtkWidget *notebook)
2457 {
2458         GtkWidget *label;
2459         GtkWidget *vbox;
2460         GtkWidget *group;
2461         GtkWidget *tabcomp;
2462         GtkWidget *table;
2463         gint i;
2464
2465         vbox = scrolled_notebook_page(notebook, _("Color management"));
2466
2467         group =  pref_group_new(vbox, FALSE, _("Input profiles"), GTK_ORIENTATION_VERTICAL);
2468 #ifndef HAVE_LCMS
2469         gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
2470 #endif
2471
2472         table = pref_table_new(group, 3, COLOR_PROFILE_INPUTS + 1, FALSE, FALSE);
2473         gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
2474
2475         label = pref_table_label(table, 0, 0, _("Type"), 0.0);
2476         pref_label_bold(label, TRUE, FALSE);
2477
2478         label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
2479         pref_label_bold(label, TRUE, FALSE);
2480
2481         label = pref_table_label(table, 2, 0, _("File"), 0.0);
2482         pref_label_bold(label, TRUE, FALSE);
2483
2484         for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
2485                 {
2486                 GtkWidget *entry;
2487                 gchar *buf;
2488
2489                 buf = g_strdup_printf(_("Input %d:"), i + COLOR_PROFILE_FILE);
2490                 pref_table_label(table, 0, i + 1, buf, 1.0);
2491                 g_free(buf);
2492
2493                 entry = gtk_entry_new();
2494                 gtk_entry_set_max_length(GTK_ENTRY(entry), EDITOR_NAME_MAX_LENGTH);
2495                 if (options->color_profile.input_name[i])
2496                         {
2497                         gtk_entry_set_text(GTK_ENTRY(entry), options->color_profile.input_name[i]);
2498                         }
2499                 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, i + 1, i + 2,
2500                                  GTK_FILL | GTK_EXPAND, 0, 0, 0);
2501                 gtk_widget_show(entry);
2502                 color_profile_input_name_entry[i] = entry;
2503
2504                 tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, ".icc", "ICC Files", NULL);
2505                 tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
2506                 gtk_widget_set_size_request(entry, 160, -1);
2507                 gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
2508                                  GTK_FILL | GTK_EXPAND, 0, 0, 0);
2509                 gtk_widget_show(tabcomp);
2510                 color_profile_input_file_entry[i] = entry;
2511                 }
2512
2513         group =  pref_group_new(vbox, FALSE, _("Screen profile"), GTK_ORIENTATION_VERTICAL);
2514 #ifndef HAVE_LCMS
2515         gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
2516 #endif
2517         pref_checkbox_new_int(group, _("Use system screen profile if available"),
2518                               options->color_profile.use_x11_screen_profile, &c_options->color_profile.use_x11_screen_profile);
2519
2520         table = pref_table_new(group, 2, 1, FALSE, FALSE);
2521
2522         pref_table_label(table, 0, 0, _("Screen:"), 1.0);
2523         tabcomp = tab_completion_new(&color_profile_screen_file_entry,
2524                                      options->color_profile.screen_file, NULL, ".icc", "ICC Files", NULL);
2525         tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
2526         gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
2527 #ifdef HAVE_LCMS
2528         add_intent_menu(table, 0, 1, _("Render Intent:"), options->color_profile.render_intent, &c_options->color_profile.render_intent);
2529 #endif
2530         gtk_table_attach(GTK_TABLE(table), tabcomp, 1, 2,
2531                          0, 1,
2532                          GTK_FILL | GTK_EXPAND, 0, 0, 0);
2533
2534         gtk_widget_show(tabcomp);
2535 }
2536
2537 /* advanced entry tab */
2538 static void config_tab_behavior(GtkWidget *notebook)
2539 {
2540         GtkWidget *hbox;
2541         GtkWidget *vbox;
2542         GtkWidget *group;
2543         GtkWidget *button;
2544         GtkWidget *tabcomp;
2545         GtkWidget *ct_button;
2546         GtkWidget *spin;
2547         GtkWidget *table;
2548         GtkWidget *marks;
2549         GtkWidget *with_rename;
2550         GtkWidget *collections_on_top;
2551
2552         vbox = scrolled_notebook_page(notebook, _("Behavior"));
2553
2554         group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
2555
2556         pref_checkbox_new_int(group, _("Confirm file delete"),
2557                               options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
2558         pref_checkbox_new_int(group, _("Enable Delete key"),
2559                               options->file_ops.enable_delete_key, &c_options->file_ops.enable_delete_key);
2560
2561         ct_button = pref_checkbox_new_int(group, _("Safe delete"),
2562                                           options->file_ops.safe_delete_enable, &c_options->file_ops.safe_delete_enable);
2563
2564         hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2565         pref_checkbox_link_sensitivity(ct_button, hbox);
2566
2567         pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
2568         pref_label_new(hbox, _("Folder:"));
2569
2570         tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL, NULL, NULL);
2571         tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
2572         gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
2573         gtk_widget_show(tabcomp);
2574
2575         hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2576         pref_checkbox_link_sensitivity(ct_button, hbox);
2577
2578         pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
2579         spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MB"),
2580                                  0, 2048, 1, options->file_ops.safe_delete_folder_maxsize, &c_options->file_ops.safe_delete_folder_maxsize);
2581         gtk_widget_set_tooltip_markup(spin, _("Set to 0 for unlimited size"));
2582         button = pref_button_new(NULL, NULL, _("View"), FALSE,
2583                                  G_CALLBACK(safe_delete_view_cb), NULL);
2584         gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2585         gtk_widget_show(button);
2586
2587         button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
2588                                  G_CALLBACK(safe_delete_clear_cb), NULL);
2589         gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2590         gtk_widget_show(button);
2591
2592
2593         group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
2594
2595         pref_checkbox_new_int(group, _("Descend folders in tree view"),
2596                               options->tree_descend_subdirs, &c_options->tree_descend_subdirs);
2597
2598         pref_checkbox_new_int(group, _("In place renaming"),
2599                               options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
2600
2601         pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
2602                               options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
2603
2604         marks = pref_checkbox_new_int(group, _("Save marks on exit"),
2605                                 options->marks_save, &c_options->marks_save);
2606         gtk_widget_set_tooltip_text(marks,"Note that marks linked to a keyword will be saved irrespective of this setting");
2607
2608         with_rename = pref_checkbox_new_int(group, _("Use \"With Rename\" as default for Copy/Move dialogs"),
2609                                 options->with_rename, &c_options->with_rename);
2610         gtk_widget_set_tooltip_text(with_rename,"Change the default button for Copy/Move dialogs");
2611
2612         collections_on_top = pref_checkbox_new_int(group, _("Open collections on top"),
2613                                 options->collections_on_top, &c_options->collections_on_top);
2614         gtk_widget_set_tooltip_text(collections_on_top,"Open collections window on top");
2615
2616         pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
2617                           1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
2618
2619         pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
2620                           16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
2621
2622         table = pref_table_new(group, 2, 1, FALSE, FALSE);
2623         add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
2624
2625         group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
2626
2627         pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
2628                               options->progressive_key_scrolling, &c_options->progressive_key_scrolling);
2629         pref_spin_new_int(group, _("Keyboard scrolling step multiplier:"), NULL,
2630                           1, 32, 1, options->keyboard_scroll_step, (int *)&c_options->keyboard_scroll_step);
2631         pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
2632                               options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
2633         pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
2634                               options->image_lm_click_nav, &c_options->image_lm_click_nav);
2635         pref_checkbox_new_int(group, _("Play video by left click on image"),
2636                               options->image_l_click_video, &c_options->image_l_click_video);
2637         table = pref_table_new(group, 2, 1, FALSE, FALSE);
2638         add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
2639
2640
2641 #ifdef DEBUG
2642         group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
2643
2644         pref_spin_new_int(group, _("Debug level:"), NULL,
2645                           DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
2646
2647         pref_checkbox_new_int(group, _("Timer data"),
2648                         options->log_window.timer_data, &c_options->log_window.timer_data);
2649
2650         pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
2651                           1, 99999, 1, options->log_window_lines, &options->log_window_lines);
2652 #endif
2653 }
2654
2655 /* accelerators tab */
2656 static void config_tab_accelerators(GtkWidget *notebook)
2657 {
2658         GtkWidget *hbox;
2659         GtkWidget *vbox;
2660         GtkWidget *group;
2661         GtkWidget *button;
2662         GtkWidget *scrolled;
2663         GtkWidget *accel_view;
2664         GtkCellRenderer *renderer;
2665         GtkTreeSelection *selection;
2666         GtkTreeViewColumn *column;
2667
2668         vbox = scrolled_notebook_page(notebook, _("Keyboard"));
2669
2670         group = pref_group_new(vbox, TRUE, _("Accelerators"), GTK_ORIENTATION_VERTICAL);
2671
2672         scrolled = gtk_scrolled_window_new(NULL, NULL);
2673         gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2674         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2675         gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2676         gtk_widget_show(scrolled);
2677
2678         accel_store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
2679
2680         accel_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(accel_store));
2681         g_object_unref(accel_store);
2682         selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(accel_view));
2683         gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
2684
2685         gtk_tree_view_set_enable_search(GTK_TREE_VIEW(accel_view), FALSE);
2686
2687         renderer = gtk_cell_renderer_text_new();
2688
2689         column = gtk_tree_view_column_new_with_attributes(_("Action"),
2690                                                           renderer,
2691                                                           "text", AE_ACTION,
2692                                                           NULL);
2693
2694         gtk_tree_view_column_set_sort_column_id(column, AE_ACTION);
2695         gtk_tree_view_column_set_resizable(column, TRUE);
2696         gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
2697
2698
2699         renderer = gtk_cell_renderer_accel_new();
2700         g_signal_connect(G_OBJECT(renderer), "accel-cleared",
2701                          G_CALLBACK(accel_store_cleared_cb), accel_store);
2702         g_signal_connect(G_OBJECT(renderer), "accel-edited",
2703                          G_CALLBACK(accel_store_edited_cb), accel_store);
2704
2705
2706         g_object_set (renderer,
2707                       "editable", TRUE,
2708                       "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
2709                       NULL);
2710
2711         column = gtk_tree_view_column_new_with_attributes(_("KEY"),
2712                                                           renderer,
2713                                                           "text", AE_KEY,
2714                                                           NULL);
2715
2716         gtk_tree_view_column_set_sort_column_id(column, AE_KEY);
2717         gtk_tree_view_column_set_resizable(column, TRUE);
2718         gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
2719
2720         renderer = gtk_cell_renderer_text_new();
2721
2722         column = gtk_tree_view_column_new_with_attributes(_("Tooltip"),
2723                                                           renderer,
2724                                                           "text", AE_TOOLTIP,
2725                                                           NULL);
2726
2727         gtk_tree_view_column_set_sort_column_id(column, AE_TOOLTIP);
2728         gtk_tree_view_column_set_resizable(column, TRUE);
2729         gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
2730
2731         renderer = gtk_cell_renderer_text_new();
2732
2733         column = gtk_tree_view_column_new_with_attributes("Accel",
2734                                                           renderer,
2735                                                           "text", AE_ACCEL,
2736                                                           NULL);
2737
2738         gtk_tree_view_column_set_sort_column_id(column, AE_ACCEL);
2739         gtk_tree_view_column_set_resizable(column, TRUE);
2740         gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
2741
2742         accel_store_populate();
2743         gtk_container_add(GTK_CONTAINER(scrolled), accel_view);
2744         gtk_widget_show(accel_view);
2745
2746         hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2747
2748         button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2749                                  G_CALLBACK(accel_default_cb), accel_view);
2750         gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2751         gtk_widget_show(button);
2752
2753         button = pref_button_new(NULL, NULL, _("Reset selected"), FALSE,
2754                                  G_CALLBACK(accel_reset_cb), accel_view);
2755         gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2756         gtk_widget_show(button);
2757 }
2758
2759 /* toolbar tab */
2760 static void config_tab_toolbar(GtkWidget *notebook)
2761 {
2762         GtkWidget *vbox;
2763         GtkWidget *toolbardata;
2764         LayoutWindow *lw;
2765
2766         lw = layout_window_list->data;
2767
2768         vbox = scrolled_notebook_page(notebook, _("Toolbar"));
2769
2770         toolbardata = toolbar_select_new(lw);
2771         gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
2772         gtk_widget_show(vbox);
2773 }
2774
2775 /* stereo tab */
2776 static void config_tab_stereo(GtkWidget *notebook)
2777 {
2778         GtkWidget *vbox;
2779         GtkWidget *group;
2780         GtkWidget *group2;
2781         GtkWidget *table;
2782         GtkWidget *box;
2783         GtkWidget *box2;
2784         GtkWidget *fs_button;
2785         vbox = scrolled_notebook_page(notebook, _("Stereo"));
2786
2787         group = pref_group_new(vbox, FALSE, _("Windowed stereo mode"), GTK_ORIENTATION_VERTICAL);
2788
2789         table = pref_table_new(group, 2, 1, FALSE, FALSE);
2790         add_stereo_mode_menu(table, 0, 0, _("Windowed stereo mode"), options->stereo.mode, &c_options->stereo.mode, FALSE);
2791
2792         table = pref_table_new(group, 2, 2, TRUE, FALSE);
2793         box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
2794         pref_checkbox_new_int(box, _("Mirror left image"),
2795                               options->stereo.mode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.mirror_left);
2796         box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
2797         pref_checkbox_new_int(box, _("Flip left image"),
2798                               options->stereo.mode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.flip_left);
2799         box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
2800         pref_checkbox_new_int(box, _("Mirror right image"),
2801                               options->stereo.mode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.mirror_right);
2802         box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
2803         pref_checkbox_new_int(box, _("Flip right image"),
2804                               options->stereo.mode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.flip_right);
2805         pref_checkbox_new_int(group, _("Swap left and right images"),
2806                               options->stereo.mode & PR_STEREO_SWAP, &c_options->stereo.tmp.swap);
2807         pref_checkbox_new_int(group, _("Disable stereo mode on single image source"),
2808                               options->stereo.mode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.temp_disable);
2809
2810         group = pref_group_new(vbox, FALSE, _("Fullscreen stereo mode"), GTK_ORIENTATION_VERTICAL);
2811         fs_button = pref_checkbox_new_int(group, _("Use different settings for fullscreen"),
2812                               options->stereo.enable_fsmode, &c_options->stereo.enable_fsmode);
2813         box2 = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2814         pref_checkbox_link_sensitivity(fs_button, box2);
2815         table = pref_table_new(box2, 2, 1, FALSE, FALSE);
2816         add_stereo_mode_menu(table, 0, 0, _("Fullscreen stereo mode"), options->stereo.fsmode, &c_options->stereo.fsmode, TRUE);
2817         table = pref_table_new(box2, 2, 2, TRUE, FALSE);
2818         box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
2819         pref_checkbox_new_int(box, _("Mirror left image"),
2820                               options->stereo.fsmode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.fs_mirror_left);
2821         box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
2822         pref_checkbox_new_int(box, _("Flip left image"),
2823                               options->stereo.fsmode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.fs_flip_left);
2824         box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
2825         pref_checkbox_new_int(box, _("Mirror right image"),
2826                               options->stereo.fsmode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.fs_mirror_right);
2827         box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
2828         pref_checkbox_new_int(box, _("Flip right image"),
2829                               options->stereo.fsmode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.fs_flip_right);
2830         pref_checkbox_new_int(box2, _("Swap left and right images"),
2831                               options->stereo.fsmode & PR_STEREO_SWAP, &c_options->stereo.tmp.fs_swap);
2832         pref_checkbox_new_int(box2, _("Disable stereo mode on single image source"),
2833                               options->stereo.fsmode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.fs_temp_disable);
2834
2835         group2 = pref_group_new(box2, FALSE, _("Fixed position"), GTK_ORIENTATION_VERTICAL);
2836         table = pref_table_new(group2, 5, 3, FALSE, FALSE);
2837         pref_table_spin_new_int(table, 0, 0, _("Width"), NULL,
2838                           1, 5000, 1, options->stereo.fixed_w, &c_options->stereo.fixed_w);
2839         pref_table_spin_new_int(table, 3, 0,  _("Height"), NULL,
2840                           1, 5000, 1, options->stereo.fixed_h, &c_options->stereo.fixed_h);
2841         pref_table_spin_new_int(table, 0, 1,  _("Left X"), NULL,
2842                           0, 5000, 1, options->stereo.fixed_x1, &c_options->stereo.fixed_x1);
2843         pref_table_spin_new_int(table, 3, 1,  _("Left Y"), NULL,
2844                           0, 5000, 1, options->stereo.fixed_y1, &c_options->stereo.fixed_y1);
2845         pref_table_spin_new_int(table, 0, 2,  _("Right X"), NULL,
2846                           0, 5000, 1, options->stereo.fixed_x2, &c_options->stereo.fixed_x2);
2847         pref_table_spin_new_int(table, 3, 2,  _("Right Y"), NULL,
2848                           0, 5000, 1, options->stereo.fixed_y2, &c_options->stereo.fixed_y2);
2849
2850 }
2851
2852 /* Main preferences window */
2853 static void config_window_create(void)
2854 {
2855         GtkWidget *win_vbox;
2856         GtkWidget *hbox;
2857         GtkWidget *notebook;
2858         GtkWidget *button;
2859         GtkWidget *ct_button;
2860
2861         if (!c_options) c_options = init_options(NULL);
2862
2863         configwindow = window_new(GTK_WINDOW_TOPLEVEL, "preferences", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Preferences"));
2864         gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
2865         g_signal_connect(G_OBJECT(configwindow), "delete_event",
2866                          G_CALLBACK(config_window_delete), NULL);
2867         gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
2868         gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
2869         gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
2870
2871         win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
2872         gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
2873         gtk_widget_show(win_vbox);
2874
2875         notebook = gtk_notebook_new();
2876         gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP);
2877         gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
2878
2879         config_tab_general(notebook);
2880         config_tab_image(notebook);
2881         config_tab_windows(notebook);
2882         config_tab_accelerators(notebook);
2883         config_tab_files(notebook);
2884         config_tab_metadata(notebook);
2885         config_tab_color(notebook);
2886         config_tab_stereo(notebook);
2887         config_tab_behavior(notebook);
2888         config_tab_toolbar(notebook);
2889
2890         hbox = gtk_hbutton_box_new();
2891         gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
2892         gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
2893         gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
2894         gtk_widget_show(hbox);
2895
2896         button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
2897                                  G_CALLBACK(config_window_help_cb), notebook);
2898         gtk_container_add(GTK_CONTAINER(hbox), button);
2899         gtk_widget_set_can_default(button, TRUE);
2900         gtk_widget_show(button);
2901
2902         button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
2903                                  G_CALLBACK(config_window_ok_cb), NULL);
2904         gtk_container_add(GTK_CONTAINER(hbox), button);
2905         gtk_widget_set_can_default(button, TRUE);
2906         gtk_widget_grab_default(button);
2907         gtk_widget_show(button);
2908
2909         ct_button = button;
2910
2911         button = pref_button_new(NULL, GTK_STOCK_SAVE, NULL, FALSE,
2912                                  G_CALLBACK(config_window_save_cb), NULL);
2913         gtk_container_add(GTK_CONTAINER(hbox), button);
2914         gtk_widget_set_can_default(button, TRUE);
2915         gtk_widget_show(button);
2916
2917         button = pref_button_new(NULL, GTK_STOCK_APPLY, NULL, FALSE,
2918                                  G_CALLBACK(config_window_apply_cb), NULL);
2919         gtk_container_add(GTK_CONTAINER(hbox), button);
2920         gtk_widget_set_can_default(button, TRUE);
2921         gtk_widget_show(button);
2922
2923         button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
2924                                  G_CALLBACK(config_window_close_cb), NULL);
2925         gtk_container_add(GTK_CONTAINER(hbox), button);
2926         gtk_widget_set_can_default(button, TRUE);
2927         gtk_widget_show(button);
2928
2929         if (!generic_dialog_get_alternative_button_order(configwindow))
2930                 {
2931                 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
2932                 }
2933
2934         gtk_widget_show(notebook);
2935
2936         gtk_widget_show(configwindow);
2937 }
2938
2939 /*
2940  *-----------------------------------------------------------------------------
2941  * config window show (public)
2942  *-----------------------------------------------------------------------------
2943  */
2944
2945 void show_config_window(void)
2946 {
2947         if (configwindow)
2948                 {
2949                 gtk_window_present(GTK_WINDOW(configwindow));
2950                 return;
2951                 }
2952
2953         config_window_create();
2954 }
2955
2956 /*
2957  *-----------------
2958  * about window
2959  *-----------------
2960  */
2961
2962 void show_about_window(LayoutWindow *lw)
2963 {
2964         GdkPixbuf *pixbuf_logo;
2965         GdkPixbuf *pixbuf_icon;
2966         gchar *authors[1000];
2967         gchar *comment;
2968         gint i_authors = 0;
2969         gchar *path;
2970         GString *copyright;
2971         gchar *zd_path;
2972         ZoneDetect *cd;
2973         FILE *fp = NULL;
2974 #define LINE_LENGTH 1000
2975         gchar line[LINE_LENGTH];
2976
2977         copyright = g_string_new(NULL);
2978         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");
2979
2980         zd_path = g_build_filename(GQ_BIN_DIR, TIMEZONE_DATABASE, NULL);
2981         cd = ZDOpenDatabase(zd_path);
2982         if (cd)
2983                 {
2984                 copyright = g_string_append(copyright, ZDGetNotice(cd));
2985                 }
2986         ZDCloseDatabase(cd);
2987         g_free(zd_path);
2988
2989         authors[0] = NULL;
2990         path = g_build_filename(GQ_HELPDIR, "AUTHORS", NULL);
2991         fp = fopen(path, "r");
2992         if (fp)
2993                 {
2994                 while(fgets(line, LINE_LENGTH, fp))
2995                         {
2996                         /* get rid of ending \n from fgets */
2997                         line[strlen(line) - 1] = '\0';
2998                         authors[i_authors] = g_strdup(line);
2999                         i_authors++;
3000                         }
3001                 authors[i_authors] = NULL;
3002                 fclose(fp);
3003                 }
3004         g_free(path);
3005
3006         comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
3007                                                 "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
3008
3009         pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
3010         pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
3011         gtk_show_about_dialog(GTK_WINDOW(lw->window),
3012                 "title", _("About Geeqie"),
3013                 "resizable", TRUE,
3014                 "program-name", GQ_APPNAME,
3015                 "version", VERSION,
3016                 "logo", pixbuf_logo,
3017                 "icon", pixbuf_icon,
3018                 "website", GQ_WEBSITE,
3019                 "website-label", "Website",
3020                 "comments", comment,
3021                 "authors", authors,
3022                 "translator-credits", _("translator-credits"),
3023                 "wrap-license", TRUE,
3024                 "license", copyright->str,
3025                 NULL);
3026
3027         g_string_free(copyright, TRUE);
3028
3029         gint n = 0;
3030         while(n < i_authors)
3031                 {
3032                 g_free(authors[n]);
3033                 n++;
3034                 }
3035         g_free(comment);
3036
3037         return;
3038 }
3039
3040 static void image_overlay_set_text_colours()
3041 {
3042         c_options->image_overlay.text_red = options->image_overlay.text_red;
3043         c_options->image_overlay.text_green = options->image_overlay.text_green;
3044         c_options->image_overlay.text_blue = options->image_overlay.text_blue;
3045         c_options->image_overlay.text_alpha = options->image_overlay.text_alpha;
3046         c_options->image_overlay.background_red = options->image_overlay.background_red;
3047         c_options->image_overlay.background_green = options->image_overlay.background_green;
3048         c_options->image_overlay.background_blue = options->image_overlay.background_blue;
3049         c_options->image_overlay.background_alpha = options->image_overlay.background_alpha;
3050 }
3051 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */