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