2 * Copyright (C) 2006 John Ellis
3 * Copyright (C) 2008 - 2016 The Geeqie Team
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.
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.
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.
23 #include "preferences.h"
27 #include "cache_maint.h"
31 #include "filefilter.h"
32 #include "fullscreen.h"
34 #include "image-overlay.h"
35 #include "color-man.h"
37 #include "layout_config.h"
38 #include "layout_util.h"
39 #include "pixbuf_util.h"
40 #include "slideshow.h"
44 #include "ui_fileops.h"
46 #include "ui_tabcomp.h"
47 #include "ui_utildlg.h"
49 #include "zonedetect.h"
61 #define EDITOR_NAME_MAX_LENGTH 32
62 #define EDITOR_COMMAND_MAX_LENGTH 1024
64 static void image_overlay_set_text_colours();
66 typedef struct _ThumbSize ThumbSize;
73 static ThumbSize thumb_size_list[] =
107 gchar *format_class_list[] = {
115 /* config memory values */
116 static ConfOptions *c_options = NULL;
123 static GtkWidget *configwindow = NULL;
124 static GtkListStore *filter_store = NULL;
125 static GtkTreeStore *accel_store = NULL;
127 static GtkWidget *safe_delete_path_entry;
129 static GtkWidget *color_profile_input_file_entry[COLOR_PROFILE_INPUTS];
130 static GtkWidget *color_profile_input_name_entry[COLOR_PROFILE_INPUTS];
131 static GtkWidget *color_profile_screen_file_entry;
133 static GtkWidget *sidecar_ext_entry;
134 static GtkWidget *help_search_engine_entry;
137 #define CONFIG_WINDOW_DEF_WIDTH 700
138 #define CONFIG_WINDOW_DEF_HEIGHT 600
141 *-----------------------------------------------------------------------------
142 * option widget callbacks (private)
143 *-----------------------------------------------------------------------------
146 static void zoom_increment_cb(GtkWidget *spin, gpointer data)
148 c_options->image.zoom_increment = (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) * 100.0 + 0.01);
151 static void slideshow_delay_hours_cb(GtkWidget *spin, gpointer data)
153 gint mins_secs_tenths, delay;
155 mins_secs_tenths = c_options->slideshow.delay %
156 (3600 * SLIDESHOW_SUBSECOND_PRECISION);
158 delay = (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
159 (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
162 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
163 SLIDESHOW_SUBSECOND_PRECISION;
166 static void slideshow_delay_minutes_cb(GtkWidget *spin, gpointer data)
168 gint hours, secs_tenths, delay;
170 hours = c_options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
171 secs_tenths = c_options->slideshow.delay % (60 * SLIDESHOW_SUBSECOND_PRECISION);
173 delay = hours * (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
174 (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
175 (60 * SLIDESHOW_SUBSECOND_PRECISION) + secs_tenths);
177 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
178 SLIDESHOW_SUBSECOND_PRECISION;
181 static void slideshow_delay_seconds_cb(GtkWidget *spin, gpointer data)
183 gint hours_mins, delay;
185 hours_mins = c_options->slideshow.delay / (60 * SLIDESHOW_SUBSECOND_PRECISION);
187 delay = (hours_mins * (60 * SLIDESHOW_SUBSECOND_PRECISION)) +
188 (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
189 (gdouble)(SLIDESHOW_SUBSECOND_PRECISION) + 0.01);
191 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
192 SLIDESHOW_SUBSECOND_PRECISION;
196 *-----------------------------------------------------------------------------
197 * sync progam to config window routine (private)
198 *-----------------------------------------------------------------------------
201 void config_entry_to_option(GtkWidget *entry, gchar **option, gchar *(*func)(const gchar *))
207 buf = gtk_entry_get_text(GTK_ENTRY(entry));
208 if (buf && strlen(buf) > 0)
213 *option = g_strdup(buf);
218 static gboolean accel_apply_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
220 gchar *accel_path, *accel;
222 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, AE_KEY, &accel, -1);
224 if (accel_path && accel_path[0])
227 gtk_accelerator_parse(accel, &key.accel_key, &key.accel_mods);
228 gtk_accel_map_change_entry(accel_path, key.accel_key, key.accel_mods, TRUE);
238 static void config_window_apply(void)
241 gboolean refresh = FALSE;
243 config_entry_to_option(safe_delete_path_entry, &options->file_ops.safe_delete_path, remove_trailing_slash);
245 if (options->file_filter.show_hidden_files != c_options->file_filter.show_hidden_files) refresh = TRUE;
246 if (options->file_filter.show_parent_directory != c_options->file_filter.show_parent_directory) refresh = TRUE;
247 if (options->file_filter.show_dot_directory != c_options->file_filter.show_dot_directory) refresh = TRUE;
248 if (options->file_sort.case_sensitive != c_options->file_sort.case_sensitive) refresh = TRUE;
249 if (options->file_sort.natural != c_options->file_sort.natural) refresh = TRUE;
250 if (options->file_filter.disable_file_extension_checks != c_options->file_filter.disable_file_extension_checks) refresh = TRUE;
251 if (options->file_filter.disable != c_options->file_filter.disable) refresh = TRUE;
253 options->file_ops.confirm_delete = c_options->file_ops.confirm_delete;
254 options->file_ops.enable_delete_key = c_options->file_ops.enable_delete_key;
255 options->file_ops.safe_delete_enable = c_options->file_ops.safe_delete_enable;
256 options->file_ops.safe_delete_folder_maxsize = c_options->file_ops.safe_delete_folder_maxsize;
257 options->tools_restore_state = c_options->tools_restore_state;
258 options->save_window_positions = c_options->save_window_positions;
259 options->use_saved_window_positions_for_new_windows = c_options->use_saved_window_positions_for_new_windows;
260 options->save_dialog_window_positions = c_options->save_dialog_window_positions;
261 options->show_window_ids = c_options->show_window_ids;
262 options->image.scroll_reset_method = c_options->image.scroll_reset_method;
263 options->image.zoom_2pass = c_options->image.zoom_2pass;
264 options->image.fit_window_to_image = c_options->image.fit_window_to_image;
265 options->image.limit_window_size = c_options->image.limit_window_size;
266 options->image.zoom_to_fit_allow_expand = c_options->image.zoom_to_fit_allow_expand;
267 options->image.max_window_size = c_options->image.max_window_size;
268 options->image.limit_autofit_size = c_options->image.limit_autofit_size;
269 options->image.max_autofit_size = c_options->image.max_autofit_size;
270 options->image.max_enlargement_size = c_options->image.max_enlargement_size;
271 options->image.use_clutter_renderer = c_options->image.use_clutter_renderer;
272 options->progressive_key_scrolling = c_options->progressive_key_scrolling;
273 options->keyboard_scroll_step = c_options->keyboard_scroll_step;
275 if (options->thumbnails.max_width != c_options->thumbnails.max_width
276 || options->thumbnails.max_height != c_options->thumbnails.max_height
277 || options->thumbnails.quality != c_options->thumbnails.quality)
279 thumb_format_changed = TRUE;
281 options->thumbnails.max_width = c_options->thumbnails.max_width;
282 options->thumbnails.max_height = c_options->thumbnails.max_height;
283 options->thumbnails.quality = c_options->thumbnails.quality;
285 options->thumbnails.enable_caching = c_options->thumbnails.enable_caching;
286 options->thumbnails.cache_into_dirs = c_options->thumbnails.cache_into_dirs;
287 options->thumbnails.use_exif = c_options->thumbnails.use_exif;
288 options->thumbnails.use_ft_metadata = c_options->thumbnails.use_ft_metadata;
289 // options->thumbnails.use_ft_metadata_small = c_options->thumbnails.use_ft_metadata_small;
290 options->thumbnails.spec_standard = c_options->thumbnails.spec_standard;
291 options->metadata.enable_metadata_dirs = c_options->metadata.enable_metadata_dirs;
292 options->file_filter.show_hidden_files = c_options->file_filter.show_hidden_files;
293 options->file_filter.show_parent_directory = c_options->file_filter.show_parent_directory;
294 options->file_filter.show_dot_directory = c_options->file_filter.show_dot_directory;
295 options->file_filter.disable_file_extension_checks = c_options->file_filter.disable_file_extension_checks;
297 options->file_sort.case_sensitive = c_options->file_sort.case_sensitive;
298 options->file_sort.natural = c_options->file_sort.natural;
299 options->file_filter.disable = c_options->file_filter.disable;
301 config_entry_to_option(sidecar_ext_entry, &options->sidecar.ext, NULL);
302 sidecar_ext_parse(options->sidecar.ext);
304 options->slideshow.random = c_options->slideshow.random;
305 options->slideshow.repeat = c_options->slideshow.repeat;
306 options->slideshow.delay = c_options->slideshow.delay;
308 options->mousewheel_scrolls = c_options->mousewheel_scrolls;
309 options->image_lm_click_nav = c_options->image_lm_click_nav;
310 options->image_l_click_video = c_options->image_l_click_video;
311 options->image_l_click_video_editor = c_options->image_l_click_video_editor;
313 options->file_ops.enable_in_place_rename = c_options->file_ops.enable_in_place_rename;
315 options->image.tile_cache_max = c_options->image.tile_cache_max;
316 options->image.image_cache_max = c_options->image.image_cache_max;
318 options->image.zoom_quality = c_options->image.zoom_quality;
320 options->image.zoom_increment = c_options->image.zoom_increment;
322 options->image.enable_read_ahead = c_options->image.enable_read_ahead;
325 if (options->image.use_custom_border_color != c_options->image.use_custom_border_color
326 || options->image.use_custom_border_color_in_fullscreen != c_options->image.use_custom_border_color_in_fullscreen
327 || !gdk_color_equal(&options->image.border_color, &c_options->image.border_color))
329 options->image.use_custom_border_color_in_fullscreen = c_options->image.use_custom_border_color_in_fullscreen;
330 options->image.use_custom_border_color = c_options->image.use_custom_border_color;
331 options->image.border_color = c_options->image.border_color;
332 layout_colors_update();
333 view_window_colors_update();
336 options->image.alpha_color_1 = c_options->image.alpha_color_1;
337 options->image.alpha_color_2 = c_options->image.alpha_color_2;
339 options->fullscreen.screen = c_options->fullscreen.screen;
340 options->fullscreen.clean_flip = c_options->fullscreen.clean_flip;
341 options->fullscreen.disable_saver = c_options->fullscreen.disable_saver;
342 options->fullscreen.above = c_options->fullscreen.above;
343 if (c_options->image_overlay.template_string)
344 set_image_overlay_template_string(&options->image_overlay.template_string,
345 c_options->image_overlay.template_string);
346 if (c_options->image_overlay.font)
347 set_image_overlay_font_string(&options->image_overlay.font,
348 c_options->image_overlay.font);
349 options->image_overlay.text_red = c_options->image_overlay.text_red;
350 options->image_overlay.text_green = c_options->image_overlay.text_green;
351 options->image_overlay.text_blue = c_options->image_overlay.text_blue;
352 options->image_overlay.text_alpha = c_options->image_overlay.text_alpha;
353 options->image_overlay.background_red = c_options->image_overlay.background_red;
354 options->image_overlay.background_green = c_options->image_overlay.background_green;
355 options->image_overlay.background_blue = c_options->image_overlay.background_blue;
356 options->image_overlay.background_alpha = c_options->image_overlay.background_alpha;
357 options->update_on_time_change = c_options->update_on_time_change;
358 options->image.exif_proof_rotate_enable = c_options->image.exif_proof_rotate_enable;
360 options->duplicates_similarity_threshold = c_options->duplicates_similarity_threshold;
361 options->rot_invariant_sim = c_options->rot_invariant_sim;
363 options->tree_descend_subdirs = c_options->tree_descend_subdirs;
365 options->view_dir_list_single_click_enter = c_options->view_dir_list_single_click_enter;
367 options->open_recent_list_maxsize = c_options->open_recent_list_maxsize;
368 options->dnd_icon_size = c_options->dnd_icon_size;
369 options->clipboard_selection = c_options->clipboard_selection;
371 options->metadata.save_in_image_file = c_options->metadata.save_in_image_file;
372 options->metadata.save_legacy_IPTC = c_options->metadata.save_legacy_IPTC;
373 options->metadata.warn_on_write_problems = c_options->metadata.warn_on_write_problems;
374 options->metadata.save_legacy_format = c_options->metadata.save_legacy_format;
375 options->metadata.sync_grouped_files = c_options->metadata.sync_grouped_files;
376 options->metadata.confirm_write = c_options->metadata.confirm_write;
377 options->metadata.sidecar_extended_name = c_options->metadata.sidecar_extended_name;
378 options->metadata.confirm_timeout = c_options->metadata.confirm_timeout;
379 options->metadata.confirm_after_timeout = c_options->metadata.confirm_after_timeout;
380 options->metadata.confirm_on_image_change = c_options->metadata.confirm_on_image_change;
381 options->metadata.confirm_on_dir_change = c_options->metadata.confirm_on_dir_change;
382 options->metadata.keywords_case_sensitive = c_options->metadata.keywords_case_sensitive;
383 options->metadata.write_orientation = c_options->metadata.write_orientation;
384 options->stereo.mode = (c_options->stereo.mode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
385 (c_options->stereo.tmp.mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
386 (c_options->stereo.tmp.flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
387 (c_options->stereo.tmp.mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
388 (c_options->stereo.tmp.flip_left ? PR_STEREO_FLIP_LEFT : 0) |
389 (c_options->stereo.tmp.swap ? PR_STEREO_SWAP : 0) |
390 (c_options->stereo.tmp.temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
391 options->stereo.fsmode = (c_options->stereo.fsmode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
392 (c_options->stereo.tmp.fs_mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
393 (c_options->stereo.tmp.fs_flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
394 (c_options->stereo.tmp.fs_mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
395 (c_options->stereo.tmp.fs_flip_left ? PR_STEREO_FLIP_LEFT : 0) |
396 (c_options->stereo.tmp.fs_swap ? PR_STEREO_SWAP : 0) |
397 (c_options->stereo.tmp.fs_temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
398 options->stereo.enable_fsmode = c_options->stereo.enable_fsmode;
399 options->stereo.fixed_w = c_options->stereo.fixed_w;
400 options->stereo.fixed_h = c_options->stereo.fixed_h;
401 options->stereo.fixed_x1 = c_options->stereo.fixed_x1;
402 options->stereo.fixed_y1 = c_options->stereo.fixed_y1;
403 options->stereo.fixed_x2 = c_options->stereo.fixed_x2;
404 options->stereo.fixed_y2 = c_options->stereo.fixed_y2;
406 options->info_keywords.height = c_options->info_keywords.height;
407 options->info_title.height = c_options->info_title.height;
408 options->info_comment.height = c_options->info_comment.height;
409 options->info_rating.height = c_options->info_rating.height;
411 options->marks_save = c_options->marks_save;
412 options->with_rename = c_options->with_rename;
413 config_entry_to_option(help_search_engine_entry, &options->help_search_engine, NULL);
416 set_debug_level(debug_c);
420 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
422 config_entry_to_option(color_profile_input_name_entry[i], &options->color_profile.input_name[i], NULL);
423 config_entry_to_option(color_profile_input_file_entry[i], &options->color_profile.input_file[i], NULL);
425 config_entry_to_option(color_profile_screen_file_entry, &options->color_profile.screen_file, NULL);
426 options->color_profile.use_x11_screen_profile = c_options->color_profile.use_x11_screen_profile;
427 if (options->color_profile.render_intent != c_options->color_profile.render_intent)
429 options->color_profile.render_intent = c_options->color_profile.render_intent;
434 image_options_sync();
439 layout_refresh(NULL);
442 if (accel_store) gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_apply_cb, NULL);
448 *-----------------------------------------------------------------------------
449 * config window main button callbacks (private)
450 *-----------------------------------------------------------------------------
453 static void config_window_close_cb(GtkWidget *widget, gpointer data)
455 gtk_widget_destroy(configwindow);
460 static void config_window_help_cb(GtkWidget *widget, gpointer data)
462 GtkWidget *notebook = data;
465 static gchar *html_section[] =
467 "GuideOptionsGeneral.html",
468 "GuideOptionsImage.html",
469 "GuideOptionsWindow.html",
470 "GuideOptionsKeyboard.html",
471 "GuideOptionsFiltering.html",
472 "GuideOptionsMetadata.html",
473 "GuideOptionsColor.html",
474 "GuideOptionsStereo.html",
475 "GuideOptionsBehavior.html",
476 "GuideOptionsToolbar.html"
479 i = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
480 help_window_show(html_section[i]);
483 static gboolean config_window_delete(GtkWidget *widget, GdkEventAny *event, gpointer data)
485 config_window_close_cb(NULL, NULL);
489 static void config_window_ok_cb(GtkWidget *widget, gpointer data)
491 config_window_apply();
492 config_window_close_cb(NULL, NULL);
495 static void config_window_apply_cb(GtkWidget *widget, gpointer data)
498 lw = layout_window_list->data;
500 config_window_apply();
501 layout_util_sync(lw);
504 static void config_window_save_cb(GtkWidget *widget, gpointer data)
506 config_window_apply();
507 save_options(options);
511 *-----------------------------------------------------------------------------
512 * config window setup (private)
513 *-----------------------------------------------------------------------------
516 static void quality_menu_cb(GtkWidget *combo, gpointer data)
520 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
524 *option = GDK_INTERP_NEAREST;
527 *option = GDK_INTERP_TILES;
530 *option = GDK_INTERP_BILINEAR;
533 *option = GDK_INTERP_HYPER;
538 static void clipboard_selection_menu_cb(GtkWidget *combo, gpointer data)
542 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
554 static void add_quality_menu(GtkWidget *table, gint column, gint row, const gchar *text,
555 guint option, guint *option_c)
562 pref_table_label(table, column, row, text, 0.0);
564 combo = gtk_combo_box_text_new();
566 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Nearest (worst, but fastest)"));
567 if (option == GDK_INTERP_NEAREST) current = 0;
568 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Tiles"));
569 if (option == GDK_INTERP_TILES) current = 1;
570 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Bilinear"));
571 if (option == GDK_INTERP_BILINEAR) current = 2;
572 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Hyper (best, but slowest)"));
573 if (option == GDK_INTERP_HYPER) current = 3;
575 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
577 g_signal_connect(G_OBJECT(combo), "changed",
578 G_CALLBACK(quality_menu_cb), option_c);
580 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
581 GTK_EXPAND | GTK_FILL, 0, 0, 0);
582 gtk_widget_show(combo);
585 static void add_clipboard_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
586 gint option, gint *option_c)
593 pref_table_label(table, column, row, text, 0.0);
595 combo = gtk_combo_box_text_new();
597 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("PRIMARY"));
598 if (option == PRIMARY) current = 0;
599 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("CLIPBOARD"));
600 if (option == CLIPBOARD) current = 1;
602 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
604 g_signal_connect(G_OBJECT(combo), "changed",
605 G_CALLBACK(clipboard_selection_menu_cb), option_c);
607 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
608 GTK_EXPAND | GTK_FILL, 0, 0, 0);
609 gtk_widget_show(combo);
612 static void thumb_size_menu_cb(GtkWidget *combo, gpointer data)
616 n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
619 if ((guint) n < sizeof(thumb_size_list) / sizeof(ThumbSize))
621 c_options->thumbnails.max_width = thumb_size_list[n].w;
622 c_options->thumbnails.max_height = thumb_size_list[n].h;
626 c_options->thumbnails.max_width = options->thumbnails.max_width;
627 c_options->thumbnails.max_height = options->thumbnails.max_height;
631 static void add_thumb_size_menu(GtkWidget *table, gint column, gint row, gchar *text)
637 c_options->thumbnails.max_width = options->thumbnails.max_width;
638 c_options->thumbnails.max_height = options->thumbnails.max_height;
640 pref_table_label(table, column, row, text, 0.0);
642 combo = gtk_combo_box_text_new();
645 for (i = 0; (guint) i < sizeof(thumb_size_list) / sizeof(ThumbSize); i++)
650 w = thumb_size_list[i].w;
651 h = thumb_size_list[i].h;
653 buf = g_strdup_printf("%d x %d", w, h);
654 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
657 if (w == options->thumbnails.max_width && h == options->thumbnails.max_height) current = i;
664 buf = g_strdup_printf("%s %d x %d", _("Custom"), options->thumbnails.max_width, options->thumbnails.max_height);
665 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
671 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
672 g_signal_connect(G_OBJECT(combo), "changed",
673 G_CALLBACK(thumb_size_menu_cb), NULL);
675 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
676 GTK_EXPAND | GTK_FILL, 0, 0, 0);
677 gtk_widget_show(combo);
680 static void stereo_mode_menu_cb(GtkWidget *combo, gpointer data)
684 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
688 *option = PR_STEREO_NONE;
691 *option = PR_STEREO_ANAGLYPH_RC;
694 *option = PR_STEREO_ANAGLYPH_GM;
697 *option = PR_STEREO_ANAGLYPH_YB;
700 *option = PR_STEREO_ANAGLYPH_GRAY_RC;
703 *option = PR_STEREO_ANAGLYPH_GRAY_GM;
706 *option = PR_STEREO_ANAGLYPH_GRAY_YB;
709 *option = PR_STEREO_ANAGLYPH_DB_RC;
712 *option = PR_STEREO_ANAGLYPH_DB_GM;
715 *option = PR_STEREO_ANAGLYPH_DB_YB;
718 *option = PR_STEREO_HORIZ;
721 *option = PR_STEREO_HORIZ | PR_STEREO_HALF;
724 *option = PR_STEREO_VERT;
727 *option = PR_STEREO_VERT | PR_STEREO_HALF;
730 *option = PR_STEREO_FIXED;
735 static void add_stereo_mode_menu(GtkWidget *table, gint column, gint row, const gchar *text,
736 gint option, gint *option_c, gboolean add_fixed)
743 pref_table_label(table, column, row, text, 0.0);
745 combo = gtk_combo_box_text_new();
747 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Single image"));
749 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Red-Cyan"));
750 if (option & PR_STEREO_ANAGLYPH_RC) current = 1;
751 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Green-Magenta"));
752 if (option & PR_STEREO_ANAGLYPH_GM) current = 2;
753 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Yellow-Blue"));
754 if (option & PR_STEREO_ANAGLYPH_YB) current = 3;
755 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Red-Cyan"));
756 if (option & PR_STEREO_ANAGLYPH_GRAY_RC) current = 4;
757 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Green-Magenta"));
758 if (option & PR_STEREO_ANAGLYPH_GRAY_GM) current = 5;
759 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Yellow-Blue"));
760 if (option & PR_STEREO_ANAGLYPH_GRAY_YB) current = 6;
761 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Red-Cyan"));
762 if (option & PR_STEREO_ANAGLYPH_DB_RC) current = 7;
763 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Green-Magenta"));
764 if (option & PR_STEREO_ANAGLYPH_DB_GM) current = 8;
765 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Yellow-Blue"));
766 if (option & PR_STEREO_ANAGLYPH_DB_YB) current = 9;
768 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side"));
769 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side Half size"));
770 if (option & PR_STEREO_HORIZ)
773 if (option & PR_STEREO_HALF) current = 11;
776 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom"));
777 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom Half size"));
778 if (option & PR_STEREO_VERT)
781 if (option & PR_STEREO_HALF) current = 13;
786 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Fixed position"));
787 if (option & PR_STEREO_FIXED) current = 14;
790 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
792 g_signal_connect(G_OBJECT(combo), "changed",
793 G_CALLBACK(stereo_mode_menu_cb), option_c);
795 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
796 GTK_EXPAND | GTK_FILL, 0, 0, 0);
797 gtk_widget_show(combo);
800 static void video_menu_cb(GtkWidget *combo, gpointer data)
802 gchar **option = data;
804 EditorDescription *ed = g_list_nth_data(editor_list_get(), gtk_combo_box_get_active(GTK_COMBO_BOX(combo)));
808 static void video_menu_populate(gpointer data, gpointer user_data)
810 GtkWidget *combo = user_data;
811 EditorDescription *ed = data;
813 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), ed->name);
816 static void add_video_menu(GtkWidget *table, gint column, gint row, const gchar *text,
817 gchar *option, gchar **option_c)
821 /* use lists since they are sorted */
822 GList *eds = editor_list_get();
826 pref_table_label(table, column, row, text, 0.0);
828 combo = gtk_combo_box_text_new();
829 g_list_foreach(eds,video_menu_populate,(gpointer)combo);
830 current = option ? g_list_index(eds,g_hash_table_lookup(editors,option)): -1;
832 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
834 g_signal_connect(G_OBJECT(combo), "changed",
835 G_CALLBACK(video_menu_cb), option_c);
837 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
838 GTK_EXPAND | GTK_FILL, 0, 0, 0);
839 gtk_widget_show(combo);
842 static void filter_store_populate(void)
846 if (!filter_store) return;
848 gtk_list_store_clear(filter_store);
850 work = filter_get_list();
859 gtk_list_store_append(filter_store, &iter);
860 gtk_list_store_set(filter_store, &iter, 0, fe, -1);
864 static void filter_store_ext_edit_cb(GtkCellRendererText *cell, gchar *path_str,
865 gchar *new_text, gpointer data)
867 GtkWidget *model = data;
868 FilterEntry *fe = data;
872 if (!new_text || strlen(new_text) < 1) return;
874 tpath = gtk_tree_path_new_from_string(path_str);
875 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
876 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
878 g_free(fe->extensions);
879 fe->extensions = g_strdup(new_text);
881 gtk_tree_path_free(tpath);
885 static void filter_store_class_edit_cb(GtkCellRendererText *cell, gchar *path_str,
886 gchar *new_text, gpointer data)
888 GtkWidget *model = data;
889 FilterEntry *fe = data;
894 if (!new_text || !new_text[0]) return;
896 tpath = gtk_tree_path_new_from_string(path_str);
897 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
898 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
900 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
902 if (strcmp(new_text, _(format_class_list[i])) == 0)
909 gtk_tree_path_free(tpath);
913 static void filter_store_desc_edit_cb(GtkCellRendererText *cell, gchar *path_str,
914 gchar *new_text, gpointer data)
916 GtkWidget *model = data;
921 if (!new_text || !new_text[0]) return;
923 tpath = gtk_tree_path_new_from_string(path_str);
924 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
925 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
927 g_free(fe->description);
928 fe->description = g_strdup(new_text);
930 gtk_tree_path_free(tpath);
933 static void filter_store_enable_cb(GtkCellRendererToggle *renderer,
934 gchar *path_str, gpointer data)
936 GtkWidget *model = data;
941 tpath = gtk_tree_path_new_from_string(path_str);
942 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
943 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
945 fe->enabled = !fe->enabled;
947 gtk_tree_path_free(tpath);
951 static void filter_store_writable_cb(GtkCellRendererToggle *renderer,
952 gchar *path_str, gpointer data)
954 GtkWidget *model = data;
959 tpath = gtk_tree_path_new_from_string(path_str);
960 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
961 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
963 fe->writable = !fe->writable;
964 if (fe->writable) fe->allow_sidecar = FALSE;
966 gtk_tree_path_free(tpath);
970 static void filter_store_sidecar_cb(GtkCellRendererToggle *renderer,
971 gchar *path_str, gpointer data)
973 GtkWidget *model = data;
978 tpath = gtk_tree_path_new_from_string(path_str);
979 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
980 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
982 fe->allow_sidecar = !fe->allow_sidecar;
983 if (fe->allow_sidecar) fe->writable = FALSE;
985 gtk_tree_path_free(tpath);
989 static void filter_set_func(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
990 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
994 gtk_tree_model_get(tree_model, iter, 0, &fe, -1);
996 switch (GPOINTER_TO_INT(data))
999 g_object_set(GTK_CELL_RENDERER(cell),
1000 "active", fe->enabled, NULL);
1003 g_object_set(GTK_CELL_RENDERER(cell),
1004 "text", fe->extensions, NULL);
1006 case FE_DESCRIPTION:
1007 g_object_set(GTK_CELL_RENDERER(cell),
1008 "text", fe->description, NULL);
1011 g_object_set(GTK_CELL_RENDERER(cell),
1012 "text", _(format_class_list[fe->file_class]), NULL);
1015 g_object_set(GTK_CELL_RENDERER(cell),
1016 "active", fe->writable, NULL);
1018 case FE_ALLOW_SIDECAR:
1019 g_object_set(GTK_CELL_RENDERER(cell),
1020 "active", fe->allow_sidecar, NULL);
1025 static gboolean filter_add_scroll(gpointer data)
1029 GtkCellRenderer *cell;
1030 GtkTreeViewColumn *column;
1031 GList *list_columns;
1036 rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(filter_store), NULL);
1037 path = gtk_tree_path_new_from_indices(rows-1, -1);
1039 list_columns = gtk_tree_view_get_columns(GTK_TREE_VIEW(data));
1041 column = g_list_nth(list_columns,i)->data;
1042 title = gtk_tree_view_column_get_title(GTK_TREE_VIEW_COLUMN(column));
1044 } while (strcmp(title, "Filter") !=0 );
1046 list_cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column));
1047 cell = g_list_last(list_cells)->data;
1049 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1050 path, column, FALSE, 0.0, 0.0 );
1051 gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(data),
1052 path, column, cell, TRUE);
1054 gtk_tree_path_free(path);
1055 g_list_free(list_cells);
1056 g_list_free(list_columns);
1061 static void filter_add_cb(GtkWidget *widget, gpointer data)
1063 filter_add_unique("description", ".new", FORMAT_CLASS_IMAGE, TRUE, FALSE, TRUE);
1064 filter_store_populate();
1066 g_idle_add((GSourceFunc)filter_add_scroll, data);
1069 static void filter_remove_cb(GtkWidget *widget, gpointer data)
1071 GtkWidget *filter_view = data;
1072 GtkTreeSelection *selection;
1076 if (!filter_store) return;
1077 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1078 if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) return;
1079 gtk_tree_model_get(GTK_TREE_MODEL(filter_store), &iter, 0, &fe, -1);
1082 filter_remove_entry(fe);
1084 filter_store_populate();
1087 static gboolean filter_default_ok_scroll(GtkTreeView *data)
1091 GtkTreeViewColumn *column;
1093 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(filter_store), &iter);
1094 path = gtk_tree_model_get_path(GTK_TREE_MODEL(filter_store), &iter);
1095 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1097 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1101 gtk_tree_path_free(path);
1106 static void filter_default_ok_cb(GenericDialog *gd, gpointer data)
1109 filter_add_defaults();
1111 filter_store_populate();
1113 g_idle_add((GSourceFunc)filter_default_ok_scroll, gd->data);
1116 static void dummy_cancel_cb(GenericDialog *gd, gpointer data)
1118 /* no op, only so cancel button appears */
1121 static void filter_default_cb(GtkWidget *widget, gpointer data)
1125 gd = generic_dialog_new(_("Reset filters"),
1126 "reset_filter", widget, TRUE,
1127 dummy_cancel_cb, data);
1128 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset filters"),
1129 _("This will reset the file filters to the defaults.\nContinue?"), TRUE);
1130 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, filter_default_ok_cb, TRUE);
1131 gtk_widget_show(gd->dialog);
1134 static void filter_disable_cb(GtkWidget *widget, gpointer data)
1136 GtkWidget *frame = data;
1138 gtk_widget_set_sensitive(frame,
1139 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
1142 static void safe_delete_view_cb(GtkWidget *widget, gpointer data)
1144 layout_set_path(NULL, gtk_entry_get_text(GTK_ENTRY(safe_delete_path_entry)));
1147 static void safe_delete_clear_ok_cb(GenericDialog *gd, gpointer data)
1149 file_util_trash_clear();
1152 static void safe_delete_clear_cb(GtkWidget *widget, gpointer data)
1156 gd = generic_dialog_new(_("Clear trash"),
1157 "clear_trash", widget, TRUE,
1158 dummy_cancel_cb, NULL);
1159 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear trash"),
1160 _("This will remove the trash contents."), FALSE);
1161 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, safe_delete_clear_ok_cb, TRUE);
1162 entry = gtk_entry_new();
1163 gtk_widget_set_can_focus(entry, FALSE);
1164 gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE);
1165 if (options->file_ops.safe_delete_path) gtk_entry_set_text(GTK_ENTRY(entry), options->file_ops.safe_delete_path);
1166 gtk_box_pack_start(GTK_BOX(gd->vbox), entry, FALSE, FALSE, 0);
1167 gtk_widget_show(entry);
1168 gtk_widget_show(gd->dialog);
1171 static void image_overlay_template_view_changed_cb(GtkWidget *widget, gpointer data)
1173 GtkWidget *pTextView;
1174 GtkTextBuffer *pTextBuffer;
1178 pTextView = GTK_WIDGET(data);
1180 pTextBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pTextView));
1181 gtk_text_buffer_get_start_iter(pTextBuffer, &iStart);
1182 gtk_text_buffer_get_end_iter(pTextBuffer, &iEnd);
1184 set_image_overlay_template_string(&c_options->image_overlay.template_string,
1185 gtk_text_buffer_get_text(pTextBuffer, &iStart, &iEnd, TRUE));
1188 static void image_overlay_default_template_ok_cb(GenericDialog *gd, gpointer data)
1190 GtkTextView *text_view = data;
1191 GtkTextBuffer *buffer;
1193 set_default_image_overlay_template_string(&options->image_overlay.template_string);
1194 if (!configwindow) return;
1196 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
1197 gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1200 static void image_overlay_default_template_cb(GtkWidget *widget, gpointer data)
1204 gd = generic_dialog_new(_("Reset image overlay template string"),
1205 "reset_image_overlay_template_string", widget, TRUE,
1206 dummy_cancel_cb, data);
1207 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset image overlay template string"),
1208 _("This will reset the image overlay template string to the default.\nContinue?"), TRUE);
1209 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, image_overlay_default_template_ok_cb, TRUE);
1210 gtk_widget_show(gd->dialog);
1213 static void image_overlay_help_cb(GtkWidget *widget, gpointer data)
1215 help_window_show("GuideOptionsWindow.html#OverlayScreenDisplay");
1218 static void image_overlay_set_font_cb(GtkWidget *widget, gpointer data)
1220 #if GTK_CHECK_VERSION(3,4,0)
1223 PangoFontDescription *font_desc;
1225 dialog = gtk_font_chooser_dialog_new("Image Overlay Font", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1226 gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), options->image_overlay.font);
1228 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1230 font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
1231 font = pango_font_description_to_string(font_desc);
1232 g_free(c_options->image_overlay.font);
1233 c_options->image_overlay.font = g_strdup(font);
1237 gtk_widget_destroy(dialog);
1241 font = gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget));
1242 c_options->image_overlay.font = g_strdup(font);
1246 static void image_overlay_set_text_colour_cb(GtkWidget *widget, gpointer data)
1249 #if GTK_CHECK_VERSION(3,4,0)
1252 dialog = gtk_color_chooser_dialog_new("Image Overlay Text Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1253 colour.red = options->image_overlay.text_red;
1254 colour.green = options->image_overlay.text_green;
1255 colour.blue = options->image_overlay.text_blue;
1256 colour.alpha = options->image_overlay.text_alpha;
1257 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1258 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1260 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1262 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1263 c_options->image_overlay.text_red = colour.red*255;
1264 c_options->image_overlay.text_green = colour.green*255;
1265 c_options->image_overlay.text_blue = colour.blue*255;
1266 c_options->image_overlay.text_alpha = colour.alpha*255;
1268 gtk_widget_destroy(dialog);
1271 GtkColorSelection *colorsel;
1273 dialog = gtk_color_selection_dialog_new("Image Overlay Text Colour");
1274 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1275 colour.red = options->image_overlay.text_red*257;
1276 colour.green = options->image_overlay.text_green*257;
1277 colour.blue = options->image_overlay.text_blue*257;
1278 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1279 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1280 gtk_color_selection_set_current_color(colorsel, &colour);
1281 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.text_alpha*257);
1283 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1285 gtk_color_selection_get_current_color(colorsel, &colour);
1286 c_options->image_overlay.text_red = colour.red/257;
1287 c_options->image_overlay.text_green = colour.green/257;
1288 c_options->image_overlay.text_blue = colour.blue/257;
1289 c_options->image_overlay.text_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1291 gtk_widget_destroy (dialog);
1296 static void image_overlay_set_background_colour_cb(GtkWidget *widget, gpointer data)
1299 #if GTK_CHECK_VERSION(3,4,0)
1302 dialog = gtk_color_chooser_dialog_new("Image Overlay Background Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1303 colour.red = options->image_overlay.background_red;
1304 colour.green = options->image_overlay.background_green;
1305 colour.blue = options->image_overlay.background_blue;
1306 colour.alpha = options->image_overlay.background_alpha;
1307 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1308 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1310 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1312 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1313 c_options->image_overlay.background_red = colour.red*255;
1314 c_options->image_overlay.background_green = colour.green*255;
1315 c_options->image_overlay.background_blue = colour.blue*255;
1316 c_options->image_overlay.background_alpha = colour.alpha*255;
1318 gtk_widget_destroy(dialog);
1321 GtkColorSelection *colorsel;
1323 dialog = gtk_color_selection_dialog_new("Image Overlay Background Colour");
1324 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1325 colour.red = options->image_overlay.background_red*257;
1326 colour.green = options->image_overlay.background_green*257;
1327 colour.blue = options->image_overlay.background_blue*257;
1328 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1329 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1330 gtk_color_selection_set_current_color(colorsel, &colour);
1331 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.background_alpha*257);
1333 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1335 gtk_color_selection_get_current_color(colorsel, &colour);
1336 c_options->image_overlay.background_red = colour.red/257;
1337 c_options->image_overlay.background_green = colour.green/257;
1338 c_options->image_overlay.background_blue = colour.blue/257;
1339 c_options->image_overlay.background_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1341 gtk_widget_destroy(dialog);
1345 static void accel_store_populate(void)
1348 GList *groups, *actions;
1350 const gchar *accel_path;
1354 if (!accel_store || !layout_window_list || !layout_window_list->data) return;
1356 gtk_tree_store_clear(accel_store);
1357 lw = layout_window_list->data; /* get the actions from the first window, it should not matter, they should be the same in all windows */
1359 g_assert(lw && lw->ui_manager);
1360 groups = gtk_ui_manager_get_action_groups(lw->ui_manager);
1363 actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
1366 action = GTK_ACTION(actions->data);
1367 accel_path = gtk_action_get_accel_path(action);
1368 if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
1370 gchar *label, *label2, *tooltip, *accel;
1371 g_object_get(action,
1372 "tooltip", &tooltip,
1376 if (pango_parse_markup(label, -1, '_', NULL, &label2, NULL, NULL) && label2)
1382 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1386 gtk_tree_store_append(accel_store, &iter, NULL);
1387 gtk_tree_store_set(accel_store, &iter,
1390 AE_TOOLTIP, tooltip ? tooltip : "",
1391 AE_ACCEL, accel_path,
1399 actions = actions->next;
1402 groups = groups->next;
1406 static void accel_store_cleared_cb(GtkCellRendererAccel *accel, gchar *path_string, gpointer user_data)
1411 static gboolean accel_remove_key_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1413 gchar *accel1 = data;
1418 gtk_tree_model_get(model, iter, AE_KEY, &accel2, -1);
1420 gtk_accelerator_parse(accel1, &key1.accel_key, &key1.accel_mods);
1421 gtk_accelerator_parse(accel2, &key2.accel_key, &key2.accel_mods);
1423 if (key1.accel_key == key2.accel_key && key1.accel_mods == key2.accel_mods)
1425 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1426 DEBUG_1("accelerator key '%s' is already used, removing.", accel1);
1435 static void accel_store_edited_cb(GtkCellRendererAccel *accel, gchar *path_string, guint accel_key, GdkModifierType accel_mods, guint hardware_keycode, gpointer user_data)
1437 GtkTreeModel *model = (GtkTreeModel *)accel_store;
1441 GtkAccelKey old_key, key;
1442 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
1444 gtk_tree_model_get_iter(model, &iter, path);
1445 gtk_tree_model_get(model, &iter, AE_ACCEL, &accel_path, -1);
1447 /* test if the accelerator can be stored without conflicts*/
1448 gtk_accel_map_lookup_entry(accel_path, &old_key);
1450 /* change the key and read it back (change may fail on keys hardcoded in gtk)*/
1451 gtk_accel_map_change_entry(accel_path, accel_key, accel_mods, TRUE);
1452 gtk_accel_map_lookup_entry(accel_path, &key);
1454 /* restore the original for now, the key will be really changed when the changes are confirmed */
1455 gtk_accel_map_change_entry(accel_path, old_key.accel_key, old_key.accel_mods, TRUE);
1457 acc = gtk_accelerator_name(key.accel_key, key.accel_mods);
1458 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, acc);
1460 gtk_tree_store_set(accel_store, &iter, AE_KEY, acc, -1);
1461 gtk_tree_path_free(path);
1465 static gboolean accel_default_scroll(GtkTreeView *data)
1469 GtkTreeViewColumn *column;
1471 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(accel_store), &iter);
1472 path = gtk_tree_model_get_path(GTK_TREE_MODEL(accel_store), &iter);
1473 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1475 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1479 gtk_tree_path_free(path);
1484 static void accel_default_cb(GtkWidget *widget, gpointer data)
1486 accel_store_populate();
1488 g_idle_add((GSourceFunc)accel_default_scroll, data);
1491 void accel_remove_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1493 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1496 void accel_reset_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1499 gchar *accel_path, *accel;
1501 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, -1);
1502 gtk_accel_map_lookup_entry(accel_path, &key);
1503 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1505 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, accel);
1507 gtk_tree_store_set(accel_store, iter, AE_KEY, accel, -1);
1512 static void accel_reset_cb(GtkWidget *widget, gpointer data)
1514 GtkTreeSelection *selection;
1516 if (!accel_store) return;
1517 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data));
1518 gtk_tree_selection_selected_foreach(selection, &accel_reset_selection, NULL);
1523 static GtkWidget *scrolled_notebook_page(GtkWidget *notebook, const gchar *title)
1527 GtkWidget *scrolled;
1528 GtkWidget *viewport;
1530 scrolled = gtk_scrolled_window_new(NULL, NULL);
1531 gtk_container_set_border_width(GTK_CONTAINER(scrolled), PREF_PAD_BORDER);
1532 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1533 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1534 label = gtk_label_new(title);
1535 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, label);
1536 gtk_widget_show(scrolled);
1538 viewport = gtk_viewport_new(NULL, NULL);
1539 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1540 gtk_container_add(GTK_CONTAINER(scrolled), viewport);
1541 gtk_widget_show(viewport);
1543 vbox = gtk_vbox_new(FALSE, 0);
1544 gtk_container_add(GTK_CONTAINER(viewport), vbox);
1545 gtk_widget_show(vbox);
1550 static void cache_standard_cb(GtkWidget *widget, gpointer data)
1552 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1554 c_options->thumbnails.spec_standard =TRUE;
1555 c_options->thumbnails.cache_into_dirs = FALSE;
1559 c_options->thumbnails.spec_standard =FALSE;
1563 static void cache_geeqie_cb(GtkWidget *widget, gpointer data)
1565 if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1567 c_options->thumbnails.spec_standard =TRUE;
1568 c_options->thumbnails.cache_into_dirs = FALSE;
1572 c_options->thumbnails.spec_standard =FALSE;
1576 static void cache_local_cb(GtkWidget *widget, gpointer data)
1578 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1580 c_options->thumbnails.cache_into_dirs = TRUE;
1581 c_options->thumbnails.spec_standard =FALSE;
1585 c_options->thumbnails.cache_into_dirs = FALSE;
1589 static void help_search_engine_entry_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1590 GdkEvent *event, gpointer userdata)
1592 if (pos == GTK_ENTRY_ICON_PRIMARY)
1594 gtk_entry_set_text(GTK_ENTRY(userdata), HELP_SEARCH_ENGINE);
1598 gtk_entry_set_text(GTK_ENTRY(userdata), "");
1602 /* general options tab */
1603 static void config_tab_general(GtkWidget *notebook)
1608 GtkWidget *group_frame;
1609 GtkWidget *subgroup;
1611 GtkWidget *ct_button;
1614 gint hours, minutes, remainder;
1617 vbox = scrolled_notebook_page(notebook, _("General"));
1619 group = pref_group_new(vbox, FALSE, _("Thumbnails"), GTK_ORIENTATION_VERTICAL);
1621 table = pref_table_new(group, 2, 2, FALSE, FALSE);
1622 add_thumb_size_menu(table, 0, 0, _("Size:"));
1623 add_quality_menu(table, 0, 1, _("Quality:"), options->thumbnails.quality, &c_options->thumbnails.quality);
1625 ct_button = pref_checkbox_new_int(group, _("Cache thumbnails"),
1626 options->thumbnails.enable_caching, &c_options->thumbnails.enable_caching);
1628 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1629 pref_checkbox_link_sensitivity(ct_button, subgroup);
1631 group_frame = pref_frame_new(subgroup, TRUE, _("Use Geeqie thumbnail style and cache"),
1632 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1633 button = pref_radiobutton_new(group_frame, NULL, get_thumbnails_cache_dir(),
1634 !options->thumbnails.spec_standard,
1635 G_CALLBACK(cache_geeqie_cb), NULL);
1637 group_frame = pref_frame_new(subgroup, TRUE,
1638 _("Store thumbnails local to image folder (non-standard)"),
1639 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1640 pref_radiobutton_new(group_frame, button, "*/.thumbnails",
1641 options->thumbnails.cache_into_dirs,
1642 G_CALLBACK(cache_local_cb), NULL);
1644 group_frame = pref_frame_new(subgroup, TRUE,
1645 _("Use standard thumbnail style and cache, shared with other applications"),
1646 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1647 pref_radiobutton_new(group_frame, button, get_thumbnails_standard_cache_dir(),
1648 options->thumbnails.spec_standard,
1649 G_CALLBACK(cache_standard_cb), NULL);
1651 pref_checkbox_new_int(group, _("Use EXIF thumbnails when available (EXIF thumbnails may be outdated)"),
1652 options->thumbnails.use_exif, &c_options->thumbnails.use_exif);
1654 #ifdef HAVE_FFMPEGTHUMBNAILER_METADATA
1655 pref_checkbox_new_int(group, _("Use embedded metadata in video files as thumbnails when available"),
1656 options->thumbnails.use_ft_metadata, &c_options->thumbnails.use_ft_metadata);
1658 // pref_checkbox_new_int(group, _("Ignore embedded metadata if size is too small"),
1659 // options->thumbnails.use_ft_metadata_small, &c_options->thumbnails.use_ft_metadata_small);
1662 group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
1664 c_options->slideshow.delay = options->slideshow.delay;
1665 hours = options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
1666 remainder = options->slideshow.delay % (3600 * SLIDESHOW_SUBSECOND_PRECISION);
1667 minutes = remainder / (60 * SLIDESHOW_SUBSECOND_PRECISION);
1668 seconds = (gdouble)(remainder % (60 * SLIDESHOW_SUBSECOND_PRECISION)) /
1669 SLIDESHOW_SUBSECOND_PRECISION;
1671 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1673 spin = pref_spin_new(hbox, _("Delay between image change hrs:mins:secs.dec"), NULL,
1675 options->slideshow.delay ? hours : 0.0,
1676 G_CALLBACK(slideshow_delay_hours_cb), NULL);
1677 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1678 spin = pref_spin_new(hbox, ":" , NULL,
1680 options->slideshow.delay ? minutes: 0.0,
1681 G_CALLBACK(slideshow_delay_minutes_cb), NULL);
1682 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1683 spin = pref_spin_new(hbox, ":", NULL,
1684 SLIDESHOW_MIN_SECONDS, 59, 1.0, 1,
1685 options->slideshow.delay ? seconds : 10.0,
1686 G_CALLBACK(slideshow_delay_seconds_cb), NULL);
1687 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1689 pref_checkbox_new_int(group, _("Random"), options->slideshow.random, &c_options->slideshow.random);
1690 pref_checkbox_new_int(group, _("Repeat"), options->slideshow.repeat, &c_options->slideshow.repeat);
1692 group = pref_group_new(vbox, FALSE, _("Image loading and caching"), GTK_ORIENTATION_VERTICAL);
1694 pref_spin_new_int(group, _("Decoded image cache size (Mb):"), NULL,
1695 0, 99999, 1, options->image.image_cache_max, &c_options->image.image_cache_max);
1696 pref_checkbox_new_int(group, _("Preload next image"),
1697 options->image.enable_read_ahead, &c_options->image.enable_read_ahead);
1699 pref_checkbox_new_int(group, _("Refresh on file change"),
1700 options->update_on_time_change, &c_options->update_on_time_change);
1702 group = pref_group_new(vbox, FALSE, _("Info sidebar heights"), GTK_ORIENTATION_VERTICAL);
1703 pref_label_new(group, _("NOTE! Geeqie must be restarted for changes to take effect"));
1704 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1705 pref_spin_new_int(hbox, _("Keywords:"), NULL,
1707 options->info_keywords.height, &c_options->info_keywords.height);
1708 pref_spin_new_int(hbox, _("Title:"), NULL,
1710 options->info_title.height, &c_options->info_title.height);
1711 pref_spin_new_int(hbox, _("Comment:"), NULL,
1713 options->info_comment.height, &c_options->info_comment.height);
1714 pref_spin_new_int(hbox, _("Rating:"), NULL,
1716 options->info_rating.height, &c_options->info_rating.height);
1718 group = pref_group_new(vbox, FALSE, _("On-line help search engine"), GTK_ORIENTATION_VERTICAL);
1720 help_search_engine_entry = gtk_entry_new();
1721 gtk_entry_set_text(GTK_ENTRY(help_search_engine_entry), options->help_search_engine);
1722 gtk_box_pack_start(GTK_BOX(group), help_search_engine_entry, FALSE, FALSE, 0);
1723 gtk_widget_show(help_search_engine_entry);
1725 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"));
1727 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
1728 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
1729 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
1730 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
1731 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
1732 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
1733 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
1734 GTK_ENTRY_ICON_PRIMARY, _("Default"));
1735 g_signal_connect(GTK_ENTRY(help_search_engine_entry), "icon-press",
1736 G_CALLBACK(help_search_engine_entry_icon_cb),
1737 help_search_engine_entry);
1741 static void config_tab_image(GtkWidget *notebook)
1746 GtkWidget *ct_button;
1747 GtkWidget *enlargement_button;
1751 vbox = scrolled_notebook_page(notebook, _("Image"));
1753 group = pref_group_new(vbox, FALSE, _("Zoom"), GTK_ORIENTATION_VERTICAL);
1755 table = pref_table_new(group, 2, 1, FALSE, FALSE);
1756 add_quality_menu(table, 0, 0, _("Quality:"), options->image.zoom_quality, &c_options->image.zoom_quality);
1759 pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library"),
1760 options->image.use_clutter_renderer, &c_options->image.use_clutter_renderer);
1763 pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"),
1764 options->image.zoom_2pass, &c_options->image.zoom_2pass);
1766 c_options->image.zoom_increment = options->image.zoom_increment;
1767 spin = pref_spin_new(group, _("Zoom increment:"), NULL,
1768 0.01, 4.0, 0.01, 2, (gdouble)options->image.zoom_increment / 100.0,
1769 G_CALLBACK(zoom_increment_cb), NULL);
1770 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1772 group = pref_group_new(vbox, FALSE, _("Fit image to window"), GTK_ORIENTATION_VERTICAL);
1774 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1775 enlargement_button = pref_checkbox_new_int(hbox, _("Allow enlargement of image (max. size in %)"),
1776 options->image.zoom_to_fit_allow_expand, &c_options->image.zoom_to_fit_allow_expand);
1777 spin = pref_spin_new_int(hbox, NULL, NULL,
1779 options->image.max_enlargement_size, &c_options->image.max_enlargement_size);
1780 pref_checkbox_link_sensitivity(enlargement_button, spin);
1781 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."));
1783 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1784 ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (% of actual window):"),
1785 options->image.limit_autofit_size, &c_options->image.limit_autofit_size);
1786 spin = pref_spin_new_int(hbox, NULL, NULL,
1788 options->image.max_autofit_size, &c_options->image.max_autofit_size);
1789 pref_checkbox_link_sensitivity(ct_button, spin);
1790 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."));
1792 group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
1794 pref_checkbox_new_int(group, _("Use custom border color in window mode"),
1795 options->image.use_custom_border_color, &c_options->image.use_custom_border_color);
1797 pref_checkbox_new_int(group, _("Use custom border color in fullscreen mode"),
1798 options->image.use_custom_border_color_in_fullscreen, &c_options->image.use_custom_border_color_in_fullscreen);
1800 pref_color_button_new(group, _("Border color"), &options->image.border_color,
1801 G_CALLBACK(pref_color_button_set_cb), &c_options->image.border_color);
1803 c_options->image.border_color = options->image.border_color;
1805 pref_color_button_new(group, _("Alpha channel color 1"), &options->image.alpha_color_1,
1806 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_1);
1808 pref_color_button_new(group, _("Alpha channel color 2"), &options->image.alpha_color_2,
1809 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_2);
1811 c_options->image.alpha_color_1 = options->image.alpha_color_1;
1812 c_options->image.alpha_color_2 = options->image.alpha_color_2;
1814 group = pref_group_new(vbox, FALSE, _("Convenience"), GTK_ORIENTATION_VERTICAL);
1816 pref_checkbox_new_int(group, _("Auto rotate proofs using Exif information"),
1817 options->image.exif_proof_rotate_enable, &c_options->image.exif_proof_rotate_enable);
1821 static void config_tab_windows(GtkWidget *notebook)
1827 GtkWidget *ct_button;
1829 GtkWidget *image_overlay_template_view;
1830 GtkWidget *scrolled;
1831 GtkTextBuffer *buffer;
1833 vbox = scrolled_notebook_page(notebook, _("Windows"));
1835 group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
1837 ct_button = pref_checkbox_new_int(group, _("Remember window positions"),
1838 options->save_window_positions, &c_options->save_window_positions);
1840 button = pref_checkbox_new_int(group, _("Use saved window positions also for new windows"),
1841 options->use_saved_window_positions_for_new_windows, &c_options->use_saved_window_positions_for_new_windows);
1842 pref_checkbox_link_sensitivity(ct_button, button);
1844 pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
1845 options->tools_restore_state, &c_options->tools_restore_state);
1847 pref_checkbox_new_int(group, _("Remember dialog window positions"),
1848 options->save_dialog_window_positions, &c_options->save_dialog_window_positions);
1850 pref_checkbox_new_int(group, _("Show window IDs"),
1851 options->show_window_ids, &c_options->show_window_ids);
1853 group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
1855 pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
1856 options->image.fit_window_to_image, &c_options->image.fit_window_to_image);
1858 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1859 ct_button = pref_checkbox_new_int(hbox, _("Limit size when auto-sizing window (%):"),
1860 options->image.limit_window_size, &c_options->image.limit_window_size);
1861 spin = pref_spin_new_int(hbox, NULL, NULL,
1863 options->image.max_window_size, &c_options->image.max_window_size);
1864 pref_checkbox_link_sensitivity(ct_button, spin);
1866 group = pref_group_new(vbox, FALSE, _("Full screen"), GTK_ORIENTATION_VERTICAL);
1868 c_options->fullscreen.screen = options->fullscreen.screen;
1869 c_options->fullscreen.above = options->fullscreen.above;
1870 hbox = fullscreen_prefs_selection_new(_("Location:"), &c_options->fullscreen.screen, &c_options->fullscreen.above);
1871 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
1872 gtk_widget_show(hbox);
1874 pref_checkbox_new_int(group, _("Smooth image flip"),
1875 options->fullscreen.clean_flip, &c_options->fullscreen.clean_flip);
1876 pref_checkbox_new_int(group, _("Disable screen saver"),
1877 options->fullscreen.disable_saver, &c_options->fullscreen.disable_saver);
1880 group = pref_group_new(vbox, FALSE, _("Overlay Screen Display"), GTK_ORIENTATION_VERTICAL);
1882 pref_label_new(group, _("Image overlay template"));
1884 scrolled = gtk_scrolled_window_new(NULL, NULL);
1885 gtk_widget_set_size_request(scrolled, 200, 150);
1886 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
1887 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1888 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1889 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 5);
1890 gtk_widget_show(scrolled);
1892 image_overlay_template_view = gtk_text_view_new();
1894 gtk_widget_set_tooltip_markup(image_overlay_template_view,
1895 _("<i>%name%</i> results in the filename of the picture.\n"
1896 "Also available: <i>%collection%</i>, <i>%number%</i>, <i>%total%</i>, <i>%date%</i>,\n"
1897 "<i>%size%</i> (filesize), <i>%width%</i>, <i>%height%</i>, <i>%res%</i> (resolution),\n"
1898 "<i>%rating%</i>, <i>%keywords%</i>, <i>%comment%</i> (XMP), <i>%imagecomment%</i> (JPEG)\n"
1899 "To access exif data use the exif name, e. g. <i>%formatted.Camera%</i> is the formatted camera name,\n"
1900 "<i>%Exif.Photo.DateTimeOriginal%</i> the date of the original shot.\n"
1901 "<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"
1902 "If two or more variables are connected with the |-sign, it prints available variables with a separator.\n"
1903 "<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"
1904 "if there's no ISO information in the Exif data.\n"
1905 "If a line is empty, it is removed. This allows one to add lines that totally disappear when no data is available.\n"
1907 gtk_container_add(GTK_CONTAINER(scrolled), image_overlay_template_view);
1908 gtk_widget_show(image_overlay_template_view);
1910 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
1912 #if GTK_CHECK_VERSION(3,4,0)
1913 button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
1914 G_CALLBACK(image_overlay_set_font_cb), notebook);
1916 button = gtk_font_button_new();
1917 gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Image Overlay Font");
1918 gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->image_overlay.font);
1919 g_signal_connect(G_OBJECT(button), "font-set",
1920 G_CALLBACK(image_overlay_set_font_cb),NULL);
1922 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1923 gtk_widget_show(button);
1925 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Text"), FALSE,
1926 G_CALLBACK(image_overlay_set_text_colour_cb), NULL);
1927 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1928 gtk_widget_show(button);
1930 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Background"), FALSE,
1931 G_CALLBACK(image_overlay_set_background_colour_cb), NULL);
1932 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1933 gtk_widget_show(button);
1934 image_overlay_set_text_colours();
1936 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
1937 G_CALLBACK(image_overlay_default_template_cb), image_overlay_template_view);
1938 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1939 gtk_widget_show(button);
1941 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
1942 G_CALLBACK(image_overlay_help_cb), NULL);
1943 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1944 gtk_widget_show(button);
1946 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_overlay_template_view));
1947 if (options->image_overlay.template_string) gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1948 g_signal_connect(G_OBJECT(buffer), "changed",
1949 G_CALLBACK(image_overlay_template_view_changed_cb), image_overlay_template_view);
1954 static GtkTreeModel *create_class_model(void)
1956 GtkListStore *model;
1960 /* create list store */
1961 model = gtk_list_store_new(1, G_TYPE_STRING);
1962 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
1964 gtk_list_store_append(model, &iter);
1965 gtk_list_store_set(model, &iter, 0, _(format_class_list[i]), -1);
1967 return GTK_TREE_MODEL (model);
1972 static void config_tab_files(GtkWidget *notebook)
1979 GtkWidget *ct_button;
1980 GtkWidget *scrolled;
1981 GtkWidget *filter_view;
1982 GtkCellRenderer *renderer;
1983 GtkTreeSelection *selection;
1984 GtkTreeViewColumn *column;
1986 vbox = scrolled_notebook_page(notebook, _("Files"));
1988 group = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1990 pref_checkbox_new_int(group, _("Show hidden files or folders"),
1991 options->file_filter.show_hidden_files, &c_options->file_filter.show_hidden_files);
1992 pref_checkbox_new_int(group, _("Show parent folder (..)"),
1993 options->file_filter.show_parent_directory, &c_options->file_filter.show_parent_directory);
1994 pref_checkbox_new_int(group, _("Case sensitive sort"),
1995 options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
1996 pref_checkbox_new_int(group, _("Natural sort order"),
1997 options->file_sort.natural, &c_options->file_sort.natural);
1998 pref_checkbox_new_int(group, _("Disable file extension checks"),
1999 options->file_filter.disable_file_extension_checks, &c_options->file_filter.disable_file_extension_checks);
2001 ct_button = pref_checkbox_new_int(group, _("Disable File Filtering"),
2002 options->file_filter.disable, &c_options->file_filter.disable);
2005 group = pref_group_new(vbox, FALSE, _("Grouping sidecar extensions"), GTK_ORIENTATION_VERTICAL);
2007 sidecar_ext_entry = gtk_entry_new();
2008 gtk_entry_set_text(GTK_ENTRY(sidecar_ext_entry), options->sidecar.ext);
2009 gtk_box_pack_start(GTK_BOX(group), sidecar_ext_entry, FALSE, FALSE, 0);
2010 gtk_widget_show(sidecar_ext_entry);
2012 group = pref_group_new(vbox, TRUE, _("File types"), GTK_ORIENTATION_VERTICAL);
2014 frame = pref_group_parent(group);
2015 g_signal_connect(G_OBJECT(ct_button), "toggled",
2016 G_CALLBACK(filter_disable_cb), frame);
2017 gtk_widget_set_sensitive(frame, !options->file_filter.disable);
2019 scrolled = gtk_scrolled_window_new(NULL, NULL);
2020 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2021 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2022 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2023 gtk_widget_show(scrolled);
2025 filter_store = gtk_list_store_new(1, G_TYPE_POINTER);
2026 filter_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(filter_store));
2027 g_object_unref(filter_store);
2028 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
2029 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
2031 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), FALSE);
2033 column = gtk_tree_view_column_new();
2034 gtk_tree_view_column_set_title(column, _("Filter"));
2035 gtk_tree_view_column_set_resizable(column, TRUE);
2037 renderer = gtk_cell_renderer_toggle_new();
2038 g_signal_connect(G_OBJECT(renderer), "toggled",
2039 G_CALLBACK(filter_store_enable_cb), filter_store);
2040 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2041 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2042 GINT_TO_POINTER(FE_ENABLE), NULL);
2044 renderer = gtk_cell_renderer_text_new();
2045 g_signal_connect(G_OBJECT(renderer), "edited",
2046 G_CALLBACK(filter_store_ext_edit_cb), filter_store);
2047 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2048 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2049 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2050 GINT_TO_POINTER(FE_EXTENSION), NULL);
2051 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2053 column = gtk_tree_view_column_new();
2054 gtk_tree_view_column_set_title(column, _("Description"));
2055 gtk_tree_view_column_set_resizable(column, TRUE);
2056 gtk_tree_view_column_set_fixed_width(column, 200);
2057 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
2059 renderer = gtk_cell_renderer_text_new();
2060 g_signal_connect(G_OBJECT(renderer), "edited",
2061 G_CALLBACK(filter_store_desc_edit_cb), filter_store);
2062 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2063 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2064 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2065 GINT_TO_POINTER(FE_DESCRIPTION), NULL);
2066 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2068 column = gtk_tree_view_column_new();
2069 gtk_tree_view_column_set_title(column, _("Class"));
2070 gtk_tree_view_column_set_resizable(column, TRUE);
2071 renderer = gtk_cell_renderer_combo_new();
2072 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE,
2073 "model", create_class_model(),
2078 g_signal_connect(G_OBJECT(renderer), "edited",
2079 G_CALLBACK(filter_store_class_edit_cb), filter_store);
2080 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2081 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2082 GINT_TO_POINTER(FE_CLASS), NULL);
2083 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2085 column = gtk_tree_view_column_new();
2086 gtk_tree_view_column_set_title(column, _("Writable"));
2087 gtk_tree_view_column_set_resizable(column, FALSE);
2088 renderer = gtk_cell_renderer_toggle_new();
2089 g_signal_connect(G_OBJECT(renderer), "toggled",
2090 G_CALLBACK(filter_store_writable_cb), filter_store);
2091 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2092 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2093 GINT_TO_POINTER(FE_WRITABLE), NULL);
2094 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2096 column = gtk_tree_view_column_new();
2097 gtk_tree_view_column_set_title(column, _("Sidecar is allowed"));
2098 gtk_tree_view_column_set_resizable(column, FALSE);
2099 renderer = gtk_cell_renderer_toggle_new();
2100 g_signal_connect(G_OBJECT(renderer), "toggled",
2101 G_CALLBACK(filter_store_sidecar_cb), filter_store);
2102 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2103 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2104 GINT_TO_POINTER(FE_ALLOW_SIDECAR), NULL);
2105 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2108 filter_store_populate();
2109 gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
2110 gtk_widget_show(filter_view);
2112 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2114 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2115 G_CALLBACK(filter_default_cb), filter_view);
2116 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2117 gtk_widget_show(button);
2119 button = pref_button_new(NULL, GTK_STOCK_REMOVE, NULL, FALSE,
2120 G_CALLBACK(filter_remove_cb), filter_view);
2121 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2122 gtk_widget_show(button);
2124 button = pref_button_new(NULL, GTK_STOCK_ADD, NULL, FALSE,
2125 G_CALLBACK(filter_add_cb), filter_view);
2126 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2127 gtk_widget_show(button);
2131 static void config_tab_metadata(GtkWidget *notebook)
2136 GtkWidget *ct_button;
2140 vbox = scrolled_notebook_page(notebook, _("Metadata"));
2143 group = pref_group_new(vbox, FALSE, _("Metadata writing process"), GTK_ORIENTATION_VERTICAL);
2145 label = pref_label_new(group, _("Warning: Geeqie is built without Exiv2. Some options are disabled."));
2147 label = pref_label_new(group, _("Metadata are written in the following order. The process ends after first success."));
2148 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2150 ct_button = pref_checkbox_new_int(group, _("1) Save metadata in image files, or sidecar files, according to the XMP standard"),
2151 options->metadata.save_in_image_file, &c_options->metadata.save_in_image_file);
2153 gtk_widget_set_sensitive(ct_button, FALSE);
2156 pref_checkbox_new_int(group, _("2) Save metadata in '.metadata' folder, local to image folder (non-standard)"),
2157 options->metadata.enable_metadata_dirs, &c_options->metadata.enable_metadata_dirs);
2159 text = g_strdup_printf(_("3) Save metadata in Geeqie private directory '%s'"), get_metadata_cache_dir());
2160 label = pref_label_new(group, text);
2161 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2162 gtk_misc_set_padding(GTK_MISC(label), 22, 0);
2165 group = pref_group_new(vbox, FALSE, _("Step 1: Write to image files"), GTK_ORIENTATION_VERTICAL);
2167 gtk_widget_set_sensitive(group, FALSE);
2170 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2171 pref_checkbox_link_sensitivity(ct_button, hbox);
2173 pref_checkbox_new_int(hbox, _("Store metadata also in legacy IPTC tags (converted according to IPTC4XMP standard)"),
2174 options->metadata.save_legacy_IPTC, &c_options->metadata.save_legacy_IPTC);
2176 pref_checkbox_new_int(hbox, _("Warn if the image files are unwritable"),
2177 options->metadata.warn_on_write_problems, &c_options->metadata.warn_on_write_problems);
2179 pref_checkbox_new_int(hbox, _("Ask before writing to image files"),
2180 options->metadata.confirm_write, &c_options->metadata.confirm_write);
2182 pref_checkbox_new_int(hbox, _("Create sidecar files named image.ext.xmp (as opposed to image.xmp)"),
2183 options->metadata.sidecar_extended_name, &c_options->metadata.sidecar_extended_name);
2185 group = pref_group_new(vbox, FALSE, _("Step 2 and 3: write to Geeqie private files"), GTK_ORIENTATION_VERTICAL);
2187 gtk_widget_set_sensitive(group, FALSE);
2190 pref_checkbox_new_int(group, _("Use GQview legacy metadata format (supports only keywords and comments) instead of XMP"),
2191 options->metadata.save_legacy_format, &c_options->metadata.save_legacy_format);
2194 group = pref_group_new(vbox, FALSE, _("Miscellaneous"), GTK_ORIENTATION_VERTICAL);
2195 pref_checkbox_new_int(group, _("Write the same description tags (keywords, comment, etc.) to all grouped sidecars"),
2196 options->metadata.sync_grouped_files, &c_options->metadata.sync_grouped_files);
2198 pref_checkbox_new_int(group, _("Allow keywords to differ only in case"),
2199 options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
2201 ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"),
2202 options->metadata.write_orientation, &c_options->metadata.write_orientation);
2204 gtk_widget_set_sensitive(ct_button, FALSE);
2207 group = pref_group_new(vbox, FALSE, _("Auto-save options"), GTK_ORIENTATION_VERTICAL);
2209 ct_button = pref_checkbox_new_int(group, _("Write metadata after timeout"),
2210 options->metadata.confirm_after_timeout, &c_options->metadata.confirm_after_timeout);
2212 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2213 pref_checkbox_link_sensitivity(ct_button, hbox);
2215 pref_spin_new_int(hbox, _("Timeout (seconds):"), NULL, 0, 900, 1,
2216 options->metadata.confirm_timeout, &c_options->metadata.confirm_timeout);
2218 pref_checkbox_new_int(group, _("Write metadata on image change"),
2219 options->metadata.confirm_on_image_change, &c_options->metadata.confirm_on_image_change);
2221 pref_checkbox_new_int(group, _("Write metadata on directory change"),
2222 options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
2227 static void intent_menu_cb(GtkWidget *combo, gpointer data)
2229 gint *option = data;
2231 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
2235 *option = INTENT_PERCEPTUAL;
2238 *option = INTENT_RELATIVE_COLORIMETRIC;
2241 *option = INTENT_SATURATION;
2244 *option = INTENT_ABSOLUTE_COLORIMETRIC;
2249 static void add_intent_menu(GtkWidget *table, gint column, gint row, const gchar *text,
2250 gint option, gint *option_c)
2257 pref_table_label(table, column, row, text, 0.0);
2259 combo = gtk_combo_box_text_new();
2261 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Perceptual"));
2262 if (option == INTENT_PERCEPTUAL) current = 0;
2263 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Relative Colorimetric"));
2264 if (option == INTENT_RELATIVE_COLORIMETRIC) current = 1;
2265 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Saturation"));
2266 if (option == INTENT_SATURATION) current = 2;
2267 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Absolute Colorimetric"));
2268 if (option == INTENT_ABSOLUTE_COLORIMETRIC) current = 3;
2270 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
2272 gtk_widget_set_tooltip_text(combo,"Refer to the lcms documentation for the defaults used when the selected Intent is not available");
2274 g_signal_connect(G_OBJECT(combo), "changed",
2275 G_CALLBACK(intent_menu_cb), option_c);
2277 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
2278 GTK_EXPAND | GTK_FILL, 0, 0, 0);
2279 gtk_widget_show(combo);
2283 static void config_tab_color(GtkWidget *notebook)
2292 vbox = scrolled_notebook_page(notebook, _("Color management"));
2294 group = pref_group_new(vbox, FALSE, _("Input profiles"), GTK_ORIENTATION_VERTICAL);
2296 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
2299 table = pref_table_new(group, 3, COLOR_PROFILE_INPUTS + 1, FALSE, FALSE);
2300 gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
2302 label = pref_table_label(table, 0, 0, _("Type"), 0.0);
2303 pref_label_bold(label, TRUE, FALSE);
2305 label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
2306 pref_label_bold(label, TRUE, FALSE);
2308 label = pref_table_label(table, 2, 0, _("File"), 0.0);
2309 pref_label_bold(label, TRUE, FALSE);
2311 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
2316 buf = g_strdup_printf(_("Input %d:"), i + COLOR_PROFILE_FILE);
2317 pref_table_label(table, 0, i + 1, buf, 1.0);
2320 entry = gtk_entry_new();
2321 gtk_entry_set_max_length(GTK_ENTRY(entry), EDITOR_NAME_MAX_LENGTH);
2322 if (options->color_profile.input_name[i])
2324 gtk_entry_set_text(GTK_ENTRY(entry), options->color_profile.input_name[i]);
2326 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, i + 1, i + 2,
2327 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2328 gtk_widget_show(entry);
2329 color_profile_input_name_entry[i] = entry;
2331 tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, ".icc", "ICC Files", NULL);
2332 tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
2333 gtk_widget_set_size_request(entry, 160, -1);
2334 gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
2335 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2336 gtk_widget_show(tabcomp);
2337 color_profile_input_file_entry[i] = entry;
2340 group = pref_group_new(vbox, FALSE, _("Screen profile"), GTK_ORIENTATION_VERTICAL);
2342 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
2344 pref_checkbox_new_int(group, _("Use system screen profile if available"),
2345 options->color_profile.use_x11_screen_profile, &c_options->color_profile.use_x11_screen_profile);
2347 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2349 pref_table_label(table, 0, 0, _("Screen:"), 1.0);
2350 tabcomp = tab_completion_new(&color_profile_screen_file_entry,
2351 options->color_profile.screen_file, NULL, ".icc", "ICC Files", NULL);
2352 tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
2353 gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
2355 add_intent_menu(table, 0, 1, _("Render Intent:"), options->color_profile.render_intent, &c_options->color_profile.render_intent);
2357 gtk_table_attach(GTK_TABLE(table), tabcomp, 1, 2,
2359 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2361 gtk_widget_show(tabcomp);
2364 /* advanced entry tab */
2365 static void config_tab_behavior(GtkWidget *notebook)
2372 GtkWidget *ct_button;
2376 GtkWidget *with_rename;
2378 vbox = scrolled_notebook_page(notebook, _("Behavior"));
2380 group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
2382 pref_checkbox_new_int(group, _("Confirm file delete"),
2383 options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
2384 pref_checkbox_new_int(group, _("Enable Delete key"),
2385 options->file_ops.enable_delete_key, &c_options->file_ops.enable_delete_key);
2387 ct_button = pref_checkbox_new_int(group, _("Safe delete"),
2388 options->file_ops.safe_delete_enable, &c_options->file_ops.safe_delete_enable);
2390 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2391 pref_checkbox_link_sensitivity(ct_button, hbox);
2393 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
2394 pref_label_new(hbox, _("Folder:"));
2396 tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL, NULL, NULL);
2397 tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
2398 gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
2399 gtk_widget_show(tabcomp);
2401 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2402 pref_checkbox_link_sensitivity(ct_button, hbox);
2404 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
2405 spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MB"),
2406 0, 2048, 1, options->file_ops.safe_delete_folder_maxsize, &c_options->file_ops.safe_delete_folder_maxsize);
2407 gtk_widget_set_tooltip_markup(spin, _("Set to 0 for unlimited size"));
2408 button = pref_button_new(NULL, NULL, _("View"), FALSE,
2409 G_CALLBACK(safe_delete_view_cb), NULL);
2410 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2411 gtk_widget_show(button);
2413 button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
2414 G_CALLBACK(safe_delete_clear_cb), NULL);
2415 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2416 gtk_widget_show(button);
2419 group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
2421 pref_checkbox_new_int(group, _("Descend folders in tree view"),
2422 options->tree_descend_subdirs, &c_options->tree_descend_subdirs);
2424 pref_checkbox_new_int(group, _("In place renaming"),
2425 options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
2427 pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
2428 options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
2430 marks = pref_checkbox_new_int(group, _("Save marks on exit"),
2431 options->marks_save, &c_options->marks_save);
2432 gtk_widget_set_tooltip_text(marks,"Note that marks linked to a keyword will be saved irrespective of this setting");
2434 with_rename = pref_checkbox_new_int(group, _("Use \"With Rename\" as default for Copy/Move dialogs"),
2435 options->with_rename, &c_options->with_rename);
2436 gtk_widget_set_tooltip_text(with_rename,"Change the default button for Copy/Move dialogs");
2438 pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
2439 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
2441 pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
2442 16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
2444 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2445 add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
2447 group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
2449 pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
2450 options->progressive_key_scrolling, &c_options->progressive_key_scrolling);
2451 pref_spin_new_int(group, _("Keyboard scrolling step multiplier:"), NULL,
2452 1, 32, 1, options->keyboard_scroll_step, (int *)&c_options->keyboard_scroll_step);
2453 pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
2454 options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
2455 pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
2456 options->image_lm_click_nav, &c_options->image_lm_click_nav);
2457 pref_checkbox_new_int(group, _("Play video by left click on image"),
2458 options->image_l_click_video, &c_options->image_l_click_video);
2459 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2460 add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
2464 group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
2466 pref_spin_new_int(group, _("Debug level:"), NULL,
2467 DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
2469 pref_checkbox_new_int(group, _("Timer data"),
2470 options->log_window.timer_data, &c_options->log_window.timer_data);
2472 pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
2473 1, 99999, 1, options->log_window_lines, &options->log_window_lines);
2477 /* accelerators tab */
2478 static void config_tab_accelerators(GtkWidget *notebook)
2484 GtkWidget *scrolled;
2485 GtkWidget *accel_view;
2486 GtkCellRenderer *renderer;
2487 GtkTreeSelection *selection;
2488 GtkTreeViewColumn *column;
2490 vbox = scrolled_notebook_page(notebook, _("Keyboard"));
2492 group = pref_group_new(vbox, TRUE, _("Accelerators"), GTK_ORIENTATION_VERTICAL);
2494 scrolled = gtk_scrolled_window_new(NULL, NULL);
2495 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2496 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2497 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2498 gtk_widget_show(scrolled);
2500 accel_store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
2502 accel_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(accel_store));
2503 g_object_unref(accel_store);
2504 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(accel_view));
2505 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
2507 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(accel_view), FALSE);
2509 renderer = gtk_cell_renderer_text_new();
2511 column = gtk_tree_view_column_new_with_attributes(_("Action"),
2516 gtk_tree_view_column_set_sort_column_id(column, AE_ACTION);
2517 gtk_tree_view_column_set_resizable(column, TRUE);
2518 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
2521 renderer = gtk_cell_renderer_accel_new();
2522 g_signal_connect(G_OBJECT(renderer), "accel-cleared",
2523 G_CALLBACK(accel_store_cleared_cb), accel_store);
2524 g_signal_connect(G_OBJECT(renderer), "accel-edited",
2525 G_CALLBACK(accel_store_edited_cb), accel_store);
2528 g_object_set (renderer,
2530 "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
2533 column = gtk_tree_view_column_new_with_attributes(_("KEY"),
2538 gtk_tree_view_column_set_sort_column_id(column, AE_KEY);
2539 gtk_tree_view_column_set_resizable(column, TRUE);
2540 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
2542 renderer = gtk_cell_renderer_text_new();
2544 column = gtk_tree_view_column_new_with_attributes(_("Tooltip"),
2549 gtk_tree_view_column_set_sort_column_id(column, AE_TOOLTIP);
2550 gtk_tree_view_column_set_resizable(column, TRUE);
2551 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
2553 renderer = gtk_cell_renderer_text_new();
2555 column = gtk_tree_view_column_new_with_attributes("Accel",
2560 gtk_tree_view_column_set_sort_column_id(column, AE_ACCEL);
2561 gtk_tree_view_column_set_resizable(column, TRUE);
2562 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
2564 accel_store_populate();
2565 gtk_container_add(GTK_CONTAINER(scrolled), accel_view);
2566 gtk_widget_show(accel_view);
2568 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2570 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2571 G_CALLBACK(accel_default_cb), accel_view);
2572 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2573 gtk_widget_show(button);
2575 button = pref_button_new(NULL, NULL, _("Reset selected"), FALSE,
2576 G_CALLBACK(accel_reset_cb), accel_view);
2577 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2578 gtk_widget_show(button);
2582 static void config_tab_toolbar(GtkWidget *notebook)
2585 GtkWidget *toolbardata;
2588 lw = layout_window_list->data;
2590 vbox = scrolled_notebook_page(notebook, _("Toolbar"));
2592 toolbardata = toolbar_select_new(lw);
2593 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
2594 gtk_widget_show(vbox);
2598 static void config_tab_stereo(GtkWidget *notebook)
2606 GtkWidget *fs_button;
2607 vbox = scrolled_notebook_page(notebook, _("Stereo"));
2609 group = pref_group_new(vbox, FALSE, _("Windowed stereo mode"), GTK_ORIENTATION_VERTICAL);
2611 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2612 add_stereo_mode_menu(table, 0, 0, _("Windowed stereo mode"), options->stereo.mode, &c_options->stereo.mode, FALSE);
2614 table = pref_table_new(group, 2, 2, TRUE, FALSE);
2615 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
2616 pref_checkbox_new_int(box, _("Mirror left image"),
2617 options->stereo.mode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.mirror_left);
2618 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
2619 pref_checkbox_new_int(box, _("Flip left image"),
2620 options->stereo.mode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.flip_left);
2621 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
2622 pref_checkbox_new_int(box, _("Mirror right image"),
2623 options->stereo.mode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.mirror_right);
2624 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
2625 pref_checkbox_new_int(box, _("Flip right image"),
2626 options->stereo.mode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.flip_right);
2627 pref_checkbox_new_int(group, _("Swap left and right images"),
2628 options->stereo.mode & PR_STEREO_SWAP, &c_options->stereo.tmp.swap);
2629 pref_checkbox_new_int(group, _("Disable stereo mode on single image source"),
2630 options->stereo.mode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.temp_disable);
2632 group = pref_group_new(vbox, FALSE, _("Fullscreen stereo mode"), GTK_ORIENTATION_VERTICAL);
2633 fs_button = pref_checkbox_new_int(group, _("Use different settings for fullscreen"),
2634 options->stereo.enable_fsmode, &c_options->stereo.enable_fsmode);
2635 box2 = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2636 pref_checkbox_link_sensitivity(fs_button, box2);
2637 table = pref_table_new(box2, 2, 1, FALSE, FALSE);
2638 add_stereo_mode_menu(table, 0, 0, _("Fullscreen stereo mode"), options->stereo.fsmode, &c_options->stereo.fsmode, TRUE);
2639 table = pref_table_new(box2, 2, 2, TRUE, FALSE);
2640 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
2641 pref_checkbox_new_int(box, _("Mirror left image"),
2642 options->stereo.fsmode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.fs_mirror_left);
2643 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
2644 pref_checkbox_new_int(box, _("Flip left image"),
2645 options->stereo.fsmode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.fs_flip_left);
2646 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
2647 pref_checkbox_new_int(box, _("Mirror right image"),
2648 options->stereo.fsmode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.fs_mirror_right);
2649 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
2650 pref_checkbox_new_int(box, _("Flip right image"),
2651 options->stereo.fsmode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.fs_flip_right);
2652 pref_checkbox_new_int(box2, _("Swap left and right images"),
2653 options->stereo.fsmode & PR_STEREO_SWAP, &c_options->stereo.tmp.fs_swap);
2654 pref_checkbox_new_int(box2, _("Disable stereo mode on single image source"),
2655 options->stereo.fsmode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.fs_temp_disable);
2657 group2 = pref_group_new(box2, FALSE, _("Fixed position"), GTK_ORIENTATION_VERTICAL);
2658 table = pref_table_new(group2, 5, 3, FALSE, FALSE);
2659 pref_table_spin_new_int(table, 0, 0, _("Width"), NULL,
2660 1, 5000, 1, options->stereo.fixed_w, &c_options->stereo.fixed_w);
2661 pref_table_spin_new_int(table, 3, 0, _("Height"), NULL,
2662 1, 5000, 1, options->stereo.fixed_h, &c_options->stereo.fixed_h);
2663 pref_table_spin_new_int(table, 0, 1, _("Left X"), NULL,
2664 0, 5000, 1, options->stereo.fixed_x1, &c_options->stereo.fixed_x1);
2665 pref_table_spin_new_int(table, 3, 1, _("Left Y"), NULL,
2666 0, 5000, 1, options->stereo.fixed_y1, &c_options->stereo.fixed_y1);
2667 pref_table_spin_new_int(table, 0, 2, _("Right X"), NULL,
2668 0, 5000, 1, options->stereo.fixed_x2, &c_options->stereo.fixed_x2);
2669 pref_table_spin_new_int(table, 3, 2, _("Right Y"), NULL,
2670 0, 5000, 1, options->stereo.fixed_y2, &c_options->stereo.fixed_y2);
2674 /* Main preferences window */
2675 static void config_window_create(void)
2677 GtkWidget *win_vbox;
2679 GtkWidget *notebook;
2681 GtkWidget *ct_button;
2683 if (!c_options) c_options = init_options(NULL);
2685 configwindow = window_new(GTK_WINDOW_TOPLEVEL, "preferences", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Preferences"));
2686 gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
2687 g_signal_connect(G_OBJECT(configwindow), "delete_event",
2688 G_CALLBACK(config_window_delete), NULL);
2689 gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
2690 gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
2691 gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
2693 win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
2694 gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
2695 gtk_widget_show(win_vbox);
2697 notebook = gtk_notebook_new();
2698 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP);
2699 gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
2701 config_tab_general(notebook);
2702 config_tab_image(notebook);
2703 config_tab_windows(notebook);
2704 config_tab_accelerators(notebook);
2705 config_tab_files(notebook);
2706 config_tab_metadata(notebook);
2707 config_tab_color(notebook);
2708 config_tab_stereo(notebook);
2709 config_tab_behavior(notebook);
2710 config_tab_toolbar(notebook);
2712 hbox = gtk_hbutton_box_new();
2713 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
2714 gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
2715 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
2716 gtk_widget_show(hbox);
2718 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
2719 G_CALLBACK(config_window_help_cb), notebook);
2720 gtk_container_add(GTK_CONTAINER(hbox), button);
2721 gtk_widget_set_can_default(button, TRUE);
2722 gtk_widget_show(button);
2724 button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
2725 G_CALLBACK(config_window_ok_cb), NULL);
2726 gtk_container_add(GTK_CONTAINER(hbox), button);
2727 gtk_widget_set_can_default(button, TRUE);
2728 gtk_widget_grab_default(button);
2729 gtk_widget_show(button);
2733 button = pref_button_new(NULL, GTK_STOCK_SAVE, NULL, FALSE,
2734 G_CALLBACK(config_window_save_cb), NULL);
2735 gtk_container_add(GTK_CONTAINER(hbox), button);
2736 gtk_widget_set_can_default(button, TRUE);
2737 gtk_widget_show(button);
2739 button = pref_button_new(NULL, GTK_STOCK_APPLY, NULL, FALSE,
2740 G_CALLBACK(config_window_apply_cb), NULL);
2741 gtk_container_add(GTK_CONTAINER(hbox), button);
2742 gtk_widget_set_can_default(button, TRUE);
2743 gtk_widget_show(button);
2745 button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
2746 G_CALLBACK(config_window_close_cb), NULL);
2747 gtk_container_add(GTK_CONTAINER(hbox), button);
2748 gtk_widget_set_can_default(button, TRUE);
2749 gtk_widget_show(button);
2751 if (!generic_dialog_get_alternative_button_order(configwindow))
2753 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
2756 gtk_widget_show(notebook);
2758 gtk_widget_show(configwindow);
2762 *-----------------------------------------------------------------------------
2763 * config window show (public)
2764 *-----------------------------------------------------------------------------
2767 void show_config_window(void)
2771 gtk_window_present(GTK_WINDOW(configwindow));
2775 config_window_create();
2784 void show_about_window(LayoutWindow *lw)
2786 GdkPixbuf *pixbuf_logo;
2787 GdkPixbuf *pixbuf_icon;
2788 gchar *authors[1000];
2796 #define LINE_LENGTH 1000
2797 gchar line[LINE_LENGTH];
2799 copyright = g_string_new(NULL);
2800 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");
2802 zd_path = g_build_filename(GQ_BIN_DIR, TIMEZONE_DATABASE, NULL);
2803 cd = ZDOpenDatabase(zd_path);
2806 copyright = g_string_append(copyright, ZDGetNotice(cd));
2808 ZDCloseDatabase(cd);
2812 path = g_build_filename(GQ_HELPDIR, "AUTHORS", NULL);
2813 fp = fopen(path, "r");
2816 while(fgets(line, LINE_LENGTH, fp))
2818 /* get rid of ending \n from fgets */
2819 line[strlen(line) - 1] = '\0';
2820 authors[i_authors] = g_strdup(line);
2823 authors[i_authors] = NULL;
2828 comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
2829 "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
2831 pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
2832 pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
2833 gtk_show_about_dialog(GTK_WINDOW(lw->window),
2834 "title", _("About Geeqie"),
2836 "program-name", GQ_APPNAME,
2838 "logo", pixbuf_logo,
2839 "icon", pixbuf_icon,
2840 "website", GQ_WEBSITE,
2841 "website-label", "Website",
2842 "comments", comment,
2844 "translator-credits", _("translator-credits"),
2845 "wrap-license", TRUE,
2846 "license", copyright->str,
2849 g_string_free(copyright, TRUE);
2852 while(n < i_authors)
2862 static void image_overlay_set_text_colours()
2864 c_options->image_overlay.text_red = options->image_overlay.text_red;
2865 c_options->image_overlay.text_green = options->image_overlay.text_green;
2866 c_options->image_overlay.text_blue = options->image_overlay.text_blue;
2867 c_options->image_overlay.text_alpha = options->image_overlay.text_alpha;
2868 c_options->image_overlay.background_red = options->image_overlay.background_red;
2869 c_options->image_overlay.background_green = options->image_overlay.background_green;
2870 c_options->image_overlay.background_blue = options->image_overlay.background_blue;
2871 c_options->image_overlay.background_alpha = options->image_overlay.background_alpha;
2873 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */