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