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);
415 options->read_metadata_in_idle = c_options->read_metadata_in_idle;
417 set_debug_level(debug_c);
421 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
423 config_entry_to_option(color_profile_input_name_entry[i], &options->color_profile.input_name[i], NULL);
424 config_entry_to_option(color_profile_input_file_entry[i], &options->color_profile.input_file[i], NULL);
426 config_entry_to_option(color_profile_screen_file_entry, &options->color_profile.screen_file, NULL);
427 options->color_profile.use_x11_screen_profile = c_options->color_profile.use_x11_screen_profile;
428 if (options->color_profile.render_intent != c_options->color_profile.render_intent)
430 options->color_profile.render_intent = c_options->color_profile.render_intent;
435 image_options_sync();
440 layout_refresh(NULL);
443 if (accel_store) gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_apply_cb, NULL);
449 *-----------------------------------------------------------------------------
450 * config window main button callbacks (private)
451 *-----------------------------------------------------------------------------
454 static void config_window_close_cb(GtkWidget *widget, gpointer data)
456 gtk_widget_destroy(configwindow);
461 static void config_window_help_cb(GtkWidget *widget, gpointer data)
463 GtkWidget *notebook = data;
466 static gchar *html_section[] =
468 "GuideOptionsGeneral.html",
469 "GuideOptionsImage.html",
470 "GuideOptionsWindow.html",
471 "GuideOptionsKeyboard.html",
472 "GuideOptionsFiltering.html",
473 "GuideOptionsMetadata.html",
474 "GuideOptionsColor.html",
475 "GuideOptionsStereo.html",
476 "GuideOptionsBehavior.html",
477 "GuideOptionsToolbar.html"
480 i = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
481 help_window_show(html_section[i]);
484 static gboolean config_window_delete(GtkWidget *widget, GdkEventAny *event, gpointer data)
486 config_window_close_cb(NULL, NULL);
490 static void config_window_ok_cb(GtkWidget *widget, gpointer data)
492 config_window_apply();
493 config_window_close_cb(NULL, NULL);
496 static void config_window_apply_cb(GtkWidget *widget, gpointer data)
499 lw = layout_window_list->data;
501 config_window_apply();
502 layout_util_sync(lw);
505 static void config_window_save_cb(GtkWidget *widget, gpointer data)
507 config_window_apply();
508 save_options(options);
512 *-----------------------------------------------------------------------------
513 * config window setup (private)
514 *-----------------------------------------------------------------------------
517 static void quality_menu_cb(GtkWidget *combo, gpointer data)
521 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
525 *option = GDK_INTERP_NEAREST;
528 *option = GDK_INTERP_TILES;
531 *option = GDK_INTERP_BILINEAR;
534 *option = GDK_INTERP_HYPER;
539 static void clipboard_selection_menu_cb(GtkWidget *combo, gpointer data)
543 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
555 static void add_quality_menu(GtkWidget *table, gint column, gint row, const gchar *text,
556 guint option, guint *option_c)
563 pref_table_label(table, column, row, text, 0.0);
565 combo = gtk_combo_box_text_new();
567 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Nearest (worst, but fastest)"));
568 if (option == GDK_INTERP_NEAREST) current = 0;
569 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Tiles"));
570 if (option == GDK_INTERP_TILES) current = 1;
571 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Bilinear"));
572 if (option == GDK_INTERP_BILINEAR) current = 2;
573 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Hyper (best, but slowest)"));
574 if (option == GDK_INTERP_HYPER) current = 3;
576 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
578 g_signal_connect(G_OBJECT(combo), "changed",
579 G_CALLBACK(quality_menu_cb), option_c);
581 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
582 GTK_EXPAND | GTK_FILL, 0, 0, 0);
583 gtk_widget_show(combo);
586 static void add_clipboard_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
587 gint option, gint *option_c)
594 pref_table_label(table, column, row, text, 0.0);
596 combo = gtk_combo_box_text_new();
598 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("PRIMARY"));
599 if (option == PRIMARY) current = 0;
600 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("CLIPBOARD"));
601 if (option == CLIPBOARD) current = 1;
603 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
605 g_signal_connect(G_OBJECT(combo), "changed",
606 G_CALLBACK(clipboard_selection_menu_cb), option_c);
608 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
609 GTK_EXPAND | GTK_FILL, 0, 0, 0);
610 gtk_widget_show(combo);
613 static void thumb_size_menu_cb(GtkWidget *combo, gpointer data)
617 n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
620 if ((guint) n < sizeof(thumb_size_list) / sizeof(ThumbSize))
622 c_options->thumbnails.max_width = thumb_size_list[n].w;
623 c_options->thumbnails.max_height = thumb_size_list[n].h;
627 c_options->thumbnails.max_width = options->thumbnails.max_width;
628 c_options->thumbnails.max_height = options->thumbnails.max_height;
632 static void add_thumb_size_menu(GtkWidget *table, gint column, gint row, gchar *text)
638 c_options->thumbnails.max_width = options->thumbnails.max_width;
639 c_options->thumbnails.max_height = options->thumbnails.max_height;
641 pref_table_label(table, column, row, text, 0.0);
643 combo = gtk_combo_box_text_new();
646 for (i = 0; (guint) i < sizeof(thumb_size_list) / sizeof(ThumbSize); i++)
651 w = thumb_size_list[i].w;
652 h = thumb_size_list[i].h;
654 buf = g_strdup_printf("%d x %d", w, h);
655 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
658 if (w == options->thumbnails.max_width && h == options->thumbnails.max_height) current = i;
665 buf = g_strdup_printf("%s %d x %d", _("Custom"), options->thumbnails.max_width, options->thumbnails.max_height);
666 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
672 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
673 g_signal_connect(G_OBJECT(combo), "changed",
674 G_CALLBACK(thumb_size_menu_cb), NULL);
676 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
677 GTK_EXPAND | GTK_FILL, 0, 0, 0);
678 gtk_widget_show(combo);
681 static void stereo_mode_menu_cb(GtkWidget *combo, gpointer data)
685 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
689 *option = PR_STEREO_NONE;
692 *option = PR_STEREO_ANAGLYPH_RC;
695 *option = PR_STEREO_ANAGLYPH_GM;
698 *option = PR_STEREO_ANAGLYPH_YB;
701 *option = PR_STEREO_ANAGLYPH_GRAY_RC;
704 *option = PR_STEREO_ANAGLYPH_GRAY_GM;
707 *option = PR_STEREO_ANAGLYPH_GRAY_YB;
710 *option = PR_STEREO_ANAGLYPH_DB_RC;
713 *option = PR_STEREO_ANAGLYPH_DB_GM;
716 *option = PR_STEREO_ANAGLYPH_DB_YB;
719 *option = PR_STEREO_HORIZ;
722 *option = PR_STEREO_HORIZ | PR_STEREO_HALF;
725 *option = PR_STEREO_VERT;
728 *option = PR_STEREO_VERT | PR_STEREO_HALF;
731 *option = PR_STEREO_FIXED;
736 static void add_stereo_mode_menu(GtkWidget *table, gint column, gint row, const gchar *text,
737 gint option, gint *option_c, gboolean add_fixed)
744 pref_table_label(table, column, row, text, 0.0);
746 combo = gtk_combo_box_text_new();
748 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Single image"));
750 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Red-Cyan"));
751 if (option & PR_STEREO_ANAGLYPH_RC) current = 1;
752 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Green-Magenta"));
753 if (option & PR_STEREO_ANAGLYPH_GM) current = 2;
754 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Yellow-Blue"));
755 if (option & PR_STEREO_ANAGLYPH_YB) current = 3;
756 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Red-Cyan"));
757 if (option & PR_STEREO_ANAGLYPH_GRAY_RC) current = 4;
758 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Green-Magenta"));
759 if (option & PR_STEREO_ANAGLYPH_GRAY_GM) current = 5;
760 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Yellow-Blue"));
761 if (option & PR_STEREO_ANAGLYPH_GRAY_YB) current = 6;
762 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Red-Cyan"));
763 if (option & PR_STEREO_ANAGLYPH_DB_RC) current = 7;
764 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Green-Magenta"));
765 if (option & PR_STEREO_ANAGLYPH_DB_GM) current = 8;
766 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Yellow-Blue"));
767 if (option & PR_STEREO_ANAGLYPH_DB_YB) current = 9;
769 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side"));
770 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side Half size"));
771 if (option & PR_STEREO_HORIZ)
774 if (option & PR_STEREO_HALF) current = 11;
777 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom"));
778 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom Half size"));
779 if (option & PR_STEREO_VERT)
782 if (option & PR_STEREO_HALF) current = 13;
787 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Fixed position"));
788 if (option & PR_STEREO_FIXED) current = 14;
791 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
793 g_signal_connect(G_OBJECT(combo), "changed",
794 G_CALLBACK(stereo_mode_menu_cb), option_c);
796 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
797 GTK_EXPAND | GTK_FILL, 0, 0, 0);
798 gtk_widget_show(combo);
801 static void video_menu_cb(GtkWidget *combo, gpointer data)
803 gchar **option = data;
805 EditorDescription *ed = g_list_nth_data(editor_list_get(), gtk_combo_box_get_active(GTK_COMBO_BOX(combo)));
809 static void video_menu_populate(gpointer data, gpointer user_data)
811 GtkWidget *combo = user_data;
812 EditorDescription *ed = data;
814 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), ed->name);
817 static void add_video_menu(GtkWidget *table, gint column, gint row, const gchar *text,
818 gchar *option, gchar **option_c)
822 /* use lists since they are sorted */
823 GList *eds = editor_list_get();
827 pref_table_label(table, column, row, text, 0.0);
829 combo = gtk_combo_box_text_new();
830 g_list_foreach(eds,video_menu_populate,(gpointer)combo);
831 current = option ? g_list_index(eds,g_hash_table_lookup(editors,option)): -1;
833 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
835 g_signal_connect(G_OBJECT(combo), "changed",
836 G_CALLBACK(video_menu_cb), option_c);
838 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
839 GTK_EXPAND | GTK_FILL, 0, 0, 0);
840 gtk_widget_show(combo);
843 static void filter_store_populate(void)
847 if (!filter_store) return;
849 gtk_list_store_clear(filter_store);
851 work = filter_get_list();
860 gtk_list_store_append(filter_store, &iter);
861 gtk_list_store_set(filter_store, &iter, 0, fe, -1);
865 static void filter_store_ext_edit_cb(GtkCellRendererText *cell, gchar *path_str,
866 gchar *new_text, gpointer data)
868 GtkWidget *model = data;
869 FilterEntry *fe = data;
873 if (!new_text || strlen(new_text) < 1) return;
875 tpath = gtk_tree_path_new_from_string(path_str);
876 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
877 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
879 g_free(fe->extensions);
880 fe->extensions = g_strdup(new_text);
882 gtk_tree_path_free(tpath);
886 static void filter_store_class_edit_cb(GtkCellRendererText *cell, gchar *path_str,
887 gchar *new_text, gpointer data)
889 GtkWidget *model = data;
890 FilterEntry *fe = data;
895 if (!new_text || !new_text[0]) return;
897 tpath = gtk_tree_path_new_from_string(path_str);
898 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
899 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
901 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
903 if (strcmp(new_text, _(format_class_list[i])) == 0)
910 gtk_tree_path_free(tpath);
914 static void filter_store_desc_edit_cb(GtkCellRendererText *cell, gchar *path_str,
915 gchar *new_text, gpointer data)
917 GtkWidget *model = data;
922 if (!new_text || !new_text[0]) return;
924 tpath = gtk_tree_path_new_from_string(path_str);
925 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
926 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
928 g_free(fe->description);
929 fe->description = g_strdup(new_text);
931 gtk_tree_path_free(tpath);
934 static void filter_store_enable_cb(GtkCellRendererToggle *renderer,
935 gchar *path_str, gpointer data)
937 GtkWidget *model = data;
942 tpath = gtk_tree_path_new_from_string(path_str);
943 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
944 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
946 fe->enabled = !fe->enabled;
948 gtk_tree_path_free(tpath);
952 static void filter_store_writable_cb(GtkCellRendererToggle *renderer,
953 gchar *path_str, gpointer data)
955 GtkWidget *model = data;
960 tpath = gtk_tree_path_new_from_string(path_str);
961 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
962 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
964 fe->writable = !fe->writable;
965 if (fe->writable) fe->allow_sidecar = FALSE;
967 gtk_tree_path_free(tpath);
971 static void filter_store_sidecar_cb(GtkCellRendererToggle *renderer,
972 gchar *path_str, gpointer data)
974 GtkWidget *model = data;
979 tpath = gtk_tree_path_new_from_string(path_str);
980 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
981 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
983 fe->allow_sidecar = !fe->allow_sidecar;
984 if (fe->allow_sidecar) fe->writable = FALSE;
986 gtk_tree_path_free(tpath);
990 static void filter_set_func(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
991 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
995 gtk_tree_model_get(tree_model, iter, 0, &fe, -1);
997 switch (GPOINTER_TO_INT(data))
1000 g_object_set(GTK_CELL_RENDERER(cell),
1001 "active", fe->enabled, NULL);
1004 g_object_set(GTK_CELL_RENDERER(cell),
1005 "text", fe->extensions, NULL);
1007 case FE_DESCRIPTION:
1008 g_object_set(GTK_CELL_RENDERER(cell),
1009 "text", fe->description, NULL);
1012 g_object_set(GTK_CELL_RENDERER(cell),
1013 "text", _(format_class_list[fe->file_class]), NULL);
1016 g_object_set(GTK_CELL_RENDERER(cell),
1017 "active", fe->writable, NULL);
1019 case FE_ALLOW_SIDECAR:
1020 g_object_set(GTK_CELL_RENDERER(cell),
1021 "active", fe->allow_sidecar, NULL);
1026 static gboolean filter_add_scroll(gpointer data)
1030 GtkCellRenderer *cell;
1031 GtkTreeViewColumn *column;
1032 GList *list_columns;
1037 rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(filter_store), NULL);
1038 path = gtk_tree_path_new_from_indices(rows-1, -1);
1040 list_columns = gtk_tree_view_get_columns(GTK_TREE_VIEW(data));
1042 column = g_list_nth(list_columns,i)->data;
1043 title = gtk_tree_view_column_get_title(GTK_TREE_VIEW_COLUMN(column));
1045 } while (strcmp(title, "Filter") !=0 );
1047 list_cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column));
1048 cell = g_list_last(list_cells)->data;
1050 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1051 path, column, FALSE, 0.0, 0.0 );
1052 gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(data),
1053 path, column, cell, TRUE);
1055 gtk_tree_path_free(path);
1056 g_list_free(list_cells);
1057 g_list_free(list_columns);
1062 static void filter_add_cb(GtkWidget *widget, gpointer data)
1064 filter_add_unique("description", ".new", FORMAT_CLASS_IMAGE, TRUE, FALSE, TRUE);
1065 filter_store_populate();
1067 g_idle_add((GSourceFunc)filter_add_scroll, data);
1070 static void filter_remove_cb(GtkWidget *widget, gpointer data)
1072 GtkWidget *filter_view = data;
1073 GtkTreeSelection *selection;
1077 if (!filter_store) return;
1078 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1079 if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) return;
1080 gtk_tree_model_get(GTK_TREE_MODEL(filter_store), &iter, 0, &fe, -1);
1083 filter_remove_entry(fe);
1085 filter_store_populate();
1088 static gboolean filter_default_ok_scroll(GtkTreeView *data)
1092 GtkTreeViewColumn *column;
1094 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(filter_store), &iter);
1095 path = gtk_tree_model_get_path(GTK_TREE_MODEL(filter_store), &iter);
1096 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1098 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1102 gtk_tree_path_free(path);
1107 static void filter_default_ok_cb(GenericDialog *gd, gpointer data)
1110 filter_add_defaults();
1112 filter_store_populate();
1114 g_idle_add((GSourceFunc)filter_default_ok_scroll, gd->data);
1117 static void dummy_cancel_cb(GenericDialog *gd, gpointer data)
1119 /* no op, only so cancel button appears */
1122 static void filter_default_cb(GtkWidget *widget, gpointer data)
1126 gd = generic_dialog_new(_("Reset filters"),
1127 "reset_filter", widget, TRUE,
1128 dummy_cancel_cb, data);
1129 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset filters"),
1130 _("This will reset the file filters to the defaults.\nContinue?"), TRUE);
1131 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, filter_default_ok_cb, TRUE);
1132 gtk_widget_show(gd->dialog);
1135 static void filter_disable_cb(GtkWidget *widget, gpointer data)
1137 GtkWidget *frame = data;
1139 gtk_widget_set_sensitive(frame,
1140 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
1143 static void safe_delete_view_cb(GtkWidget *widget, gpointer data)
1145 layout_set_path(NULL, gtk_entry_get_text(GTK_ENTRY(safe_delete_path_entry)));
1148 static void safe_delete_clear_ok_cb(GenericDialog *gd, gpointer data)
1150 file_util_trash_clear();
1153 static void safe_delete_clear_cb(GtkWidget *widget, gpointer data)
1157 gd = generic_dialog_new(_("Clear trash"),
1158 "clear_trash", widget, TRUE,
1159 dummy_cancel_cb, NULL);
1160 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear trash"),
1161 _("This will remove the trash contents."), FALSE);
1162 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, safe_delete_clear_ok_cb, TRUE);
1163 entry = gtk_entry_new();
1164 gtk_widget_set_can_focus(entry, FALSE);
1165 gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE);
1166 if (options->file_ops.safe_delete_path) gtk_entry_set_text(GTK_ENTRY(entry), options->file_ops.safe_delete_path);
1167 gtk_box_pack_start(GTK_BOX(gd->vbox), entry, FALSE, FALSE, 0);
1168 gtk_widget_show(entry);
1169 gtk_widget_show(gd->dialog);
1172 static void image_overlay_template_view_changed_cb(GtkWidget *widget, gpointer data)
1174 GtkWidget *pTextView;
1175 GtkTextBuffer *pTextBuffer;
1179 pTextView = GTK_WIDGET(data);
1181 pTextBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pTextView));
1182 gtk_text_buffer_get_start_iter(pTextBuffer, &iStart);
1183 gtk_text_buffer_get_end_iter(pTextBuffer, &iEnd);
1185 set_image_overlay_template_string(&c_options->image_overlay.template_string,
1186 gtk_text_buffer_get_text(pTextBuffer, &iStart, &iEnd, TRUE));
1189 static void image_overlay_default_template_ok_cb(GenericDialog *gd, gpointer data)
1191 GtkTextView *text_view = data;
1192 GtkTextBuffer *buffer;
1194 set_default_image_overlay_template_string(&options->image_overlay.template_string);
1195 if (!configwindow) return;
1197 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
1198 gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1201 static void image_overlay_default_template_cb(GtkWidget *widget, gpointer data)
1205 gd = generic_dialog_new(_("Reset image overlay template string"),
1206 "reset_image_overlay_template_string", widget, TRUE,
1207 dummy_cancel_cb, data);
1208 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset image overlay template string"),
1209 _("This will reset the image overlay template string to the default.\nContinue?"), TRUE);
1210 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, image_overlay_default_template_ok_cb, TRUE);
1211 gtk_widget_show(gd->dialog);
1214 static void image_overlay_help_cb(GtkWidget *widget, gpointer data)
1216 help_window_show("GuideOptionsWindow.html#OverlayScreenDisplay");
1219 static void image_overlay_set_font_cb(GtkWidget *widget, gpointer data)
1221 #if GTK_CHECK_VERSION(3,4,0)
1224 PangoFontDescription *font_desc;
1226 dialog = gtk_font_chooser_dialog_new("Image Overlay Font", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1227 gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), options->image_overlay.font);
1229 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1231 font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
1232 font = pango_font_description_to_string(font_desc);
1233 g_free(c_options->image_overlay.font);
1234 c_options->image_overlay.font = g_strdup(font);
1238 gtk_widget_destroy(dialog);
1242 font = gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget));
1243 c_options->image_overlay.font = g_strdup(font);
1247 static void image_overlay_set_text_colour_cb(GtkWidget *widget, gpointer data)
1250 #if GTK_CHECK_VERSION(3,4,0)
1253 dialog = gtk_color_chooser_dialog_new("Image Overlay Text Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1254 colour.red = options->image_overlay.text_red;
1255 colour.green = options->image_overlay.text_green;
1256 colour.blue = options->image_overlay.text_blue;
1257 colour.alpha = options->image_overlay.text_alpha;
1258 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1259 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1261 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1263 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1264 c_options->image_overlay.text_red = colour.red*255;
1265 c_options->image_overlay.text_green = colour.green*255;
1266 c_options->image_overlay.text_blue = colour.blue*255;
1267 c_options->image_overlay.text_alpha = colour.alpha*255;
1269 gtk_widget_destroy(dialog);
1272 GtkColorSelection *colorsel;
1274 dialog = gtk_color_selection_dialog_new("Image Overlay Text Colour");
1275 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1276 colour.red = options->image_overlay.text_red*257;
1277 colour.green = options->image_overlay.text_green*257;
1278 colour.blue = options->image_overlay.text_blue*257;
1279 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1280 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1281 gtk_color_selection_set_current_color(colorsel, &colour);
1282 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.text_alpha*257);
1284 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1286 gtk_color_selection_get_current_color(colorsel, &colour);
1287 c_options->image_overlay.text_red = colour.red/257;
1288 c_options->image_overlay.text_green = colour.green/257;
1289 c_options->image_overlay.text_blue = colour.blue/257;
1290 c_options->image_overlay.text_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1292 gtk_widget_destroy (dialog);
1297 static void image_overlay_set_background_colour_cb(GtkWidget *widget, gpointer data)
1300 #if GTK_CHECK_VERSION(3,4,0)
1303 dialog = gtk_color_chooser_dialog_new("Image Overlay Background Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1304 colour.red = options->image_overlay.background_red;
1305 colour.green = options->image_overlay.background_green;
1306 colour.blue = options->image_overlay.background_blue;
1307 colour.alpha = options->image_overlay.background_alpha;
1308 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1309 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1311 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1313 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1314 c_options->image_overlay.background_red = colour.red*255;
1315 c_options->image_overlay.background_green = colour.green*255;
1316 c_options->image_overlay.background_blue = colour.blue*255;
1317 c_options->image_overlay.background_alpha = colour.alpha*255;
1319 gtk_widget_destroy(dialog);
1322 GtkColorSelection *colorsel;
1324 dialog = gtk_color_selection_dialog_new("Image Overlay Background Colour");
1325 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1326 colour.red = options->image_overlay.background_red*257;
1327 colour.green = options->image_overlay.background_green*257;
1328 colour.blue = options->image_overlay.background_blue*257;
1329 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1330 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1331 gtk_color_selection_set_current_color(colorsel, &colour);
1332 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.background_alpha*257);
1334 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1336 gtk_color_selection_get_current_color(colorsel, &colour);
1337 c_options->image_overlay.background_red = colour.red/257;
1338 c_options->image_overlay.background_green = colour.green/257;
1339 c_options->image_overlay.background_blue = colour.blue/257;
1340 c_options->image_overlay.background_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1342 gtk_widget_destroy(dialog);
1346 static void accel_store_populate(void)
1349 GList *groups, *actions;
1351 const gchar *accel_path;
1355 if (!accel_store || !layout_window_list || !layout_window_list->data) return;
1357 gtk_tree_store_clear(accel_store);
1358 lw = layout_window_list->data; /* get the actions from the first window, it should not matter, they should be the same in all windows */
1360 g_assert(lw && lw->ui_manager);
1361 groups = gtk_ui_manager_get_action_groups(lw->ui_manager);
1364 actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
1367 action = GTK_ACTION(actions->data);
1368 accel_path = gtk_action_get_accel_path(action);
1369 if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
1371 gchar *label, *label2, *tooltip, *accel;
1372 g_object_get(action,
1373 "tooltip", &tooltip,
1377 if (pango_parse_markup(label, -1, '_', NULL, &label2, NULL, NULL) && label2)
1383 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1387 gtk_tree_store_append(accel_store, &iter, NULL);
1388 gtk_tree_store_set(accel_store, &iter,
1391 AE_TOOLTIP, tooltip ? tooltip : "",
1392 AE_ACCEL, accel_path,
1400 actions = actions->next;
1403 groups = groups->next;
1407 static void accel_store_cleared_cb(GtkCellRendererAccel *accel, gchar *path_string, gpointer user_data)
1412 static gboolean accel_remove_key_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1414 gchar *accel1 = data;
1419 gtk_tree_model_get(model, iter, AE_KEY, &accel2, -1);
1421 gtk_accelerator_parse(accel1, &key1.accel_key, &key1.accel_mods);
1422 gtk_accelerator_parse(accel2, &key2.accel_key, &key2.accel_mods);
1424 if (key1.accel_key == key2.accel_key && key1.accel_mods == key2.accel_mods)
1426 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1427 DEBUG_1("accelerator key '%s' is already used, removing.", accel1);
1436 static void accel_store_edited_cb(GtkCellRendererAccel *accel, gchar *path_string, guint accel_key, GdkModifierType accel_mods, guint hardware_keycode, gpointer user_data)
1438 GtkTreeModel *model = (GtkTreeModel *)accel_store;
1442 GtkAccelKey old_key, key;
1443 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
1445 gtk_tree_model_get_iter(model, &iter, path);
1446 gtk_tree_model_get(model, &iter, AE_ACCEL, &accel_path, -1);
1448 /* test if the accelerator can be stored without conflicts*/
1449 gtk_accel_map_lookup_entry(accel_path, &old_key);
1451 /* change the key and read it back (change may fail on keys hardcoded in gtk)*/
1452 gtk_accel_map_change_entry(accel_path, accel_key, accel_mods, TRUE);
1453 gtk_accel_map_lookup_entry(accel_path, &key);
1455 /* restore the original for now, the key will be really changed when the changes are confirmed */
1456 gtk_accel_map_change_entry(accel_path, old_key.accel_key, old_key.accel_mods, TRUE);
1458 acc = gtk_accelerator_name(key.accel_key, key.accel_mods);
1459 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, acc);
1461 gtk_tree_store_set(accel_store, &iter, AE_KEY, acc, -1);
1462 gtk_tree_path_free(path);
1466 static gboolean accel_default_scroll(GtkTreeView *data)
1470 GtkTreeViewColumn *column;
1472 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(accel_store), &iter);
1473 path = gtk_tree_model_get_path(GTK_TREE_MODEL(accel_store), &iter);
1474 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1476 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1480 gtk_tree_path_free(path);
1485 static void accel_default_cb(GtkWidget *widget, gpointer data)
1487 accel_store_populate();
1489 g_idle_add((GSourceFunc)accel_default_scroll, data);
1492 void accel_remove_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1494 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1497 void accel_reset_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1500 gchar *accel_path, *accel;
1502 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, -1);
1503 gtk_accel_map_lookup_entry(accel_path, &key);
1504 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1506 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, accel);
1508 gtk_tree_store_set(accel_store, iter, AE_KEY, accel, -1);
1513 static void accel_reset_cb(GtkWidget *widget, gpointer data)
1515 GtkTreeSelection *selection;
1517 if (!accel_store) return;
1518 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data));
1519 gtk_tree_selection_selected_foreach(selection, &accel_reset_selection, NULL);
1524 static GtkWidget *scrolled_notebook_page(GtkWidget *notebook, const gchar *title)
1528 GtkWidget *scrolled;
1529 GtkWidget *viewport;
1531 scrolled = gtk_scrolled_window_new(NULL, NULL);
1532 gtk_container_set_border_width(GTK_CONTAINER(scrolled), PREF_PAD_BORDER);
1533 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1534 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1535 label = gtk_label_new(title);
1536 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, label);
1537 gtk_widget_show(scrolled);
1539 viewport = gtk_viewport_new(NULL, NULL);
1540 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1541 gtk_container_add(GTK_CONTAINER(scrolled), viewport);
1542 gtk_widget_show(viewport);
1544 vbox = gtk_vbox_new(FALSE, 0);
1545 gtk_container_add(GTK_CONTAINER(viewport), vbox);
1546 gtk_widget_show(vbox);
1551 static void cache_standard_cb(GtkWidget *widget, gpointer data)
1553 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1555 c_options->thumbnails.spec_standard =TRUE;
1556 c_options->thumbnails.cache_into_dirs = FALSE;
1560 c_options->thumbnails.spec_standard =FALSE;
1564 static void cache_geeqie_cb(GtkWidget *widget, gpointer data)
1566 if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1568 c_options->thumbnails.spec_standard =TRUE;
1569 c_options->thumbnails.cache_into_dirs = FALSE;
1573 c_options->thumbnails.spec_standard =FALSE;
1577 static void cache_local_cb(GtkWidget *widget, gpointer data)
1579 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1581 c_options->thumbnails.cache_into_dirs = TRUE;
1582 c_options->thumbnails.spec_standard =FALSE;
1586 c_options->thumbnails.cache_into_dirs = FALSE;
1590 static void help_search_engine_entry_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1591 GdkEvent *event, gpointer userdata)
1593 if (pos == GTK_ENTRY_ICON_PRIMARY)
1595 gtk_entry_set_text(GTK_ENTRY(userdata), HELP_SEARCH_ENGINE);
1599 gtk_entry_set_text(GTK_ENTRY(userdata), "");
1603 /* general options tab */
1604 static void config_tab_general(GtkWidget *notebook)
1609 GtkWidget *group_frame;
1610 GtkWidget *subgroup;
1612 GtkWidget *ct_button;
1615 gint hours, minutes, remainder;
1618 vbox = scrolled_notebook_page(notebook, _("General"));
1620 group = pref_group_new(vbox, FALSE, _("Thumbnails"), GTK_ORIENTATION_VERTICAL);
1622 table = pref_table_new(group, 2, 2, FALSE, FALSE);
1623 add_thumb_size_menu(table, 0, 0, _("Size:"));
1624 add_quality_menu(table, 0, 1, _("Quality:"), options->thumbnails.quality, &c_options->thumbnails.quality);
1626 ct_button = pref_checkbox_new_int(group, _("Cache thumbnails"),
1627 options->thumbnails.enable_caching, &c_options->thumbnails.enable_caching);
1629 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1630 pref_checkbox_link_sensitivity(ct_button, subgroup);
1632 group_frame = pref_frame_new(subgroup, TRUE, _("Use Geeqie thumbnail style and cache"),
1633 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1634 button = pref_radiobutton_new(group_frame, NULL, get_thumbnails_cache_dir(),
1635 !options->thumbnails.spec_standard,
1636 G_CALLBACK(cache_geeqie_cb), NULL);
1638 group_frame = pref_frame_new(subgroup, TRUE,
1639 _("Store thumbnails local to image folder (non-standard)"),
1640 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1641 pref_radiobutton_new(group_frame, button, "*/.thumbnails",
1642 options->thumbnails.cache_into_dirs,
1643 G_CALLBACK(cache_local_cb), NULL);
1645 group_frame = pref_frame_new(subgroup, TRUE,
1646 _("Use standard thumbnail style and cache, shared with other applications"),
1647 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1648 pref_radiobutton_new(group_frame, button, get_thumbnails_standard_cache_dir(),
1649 options->thumbnails.spec_standard,
1650 G_CALLBACK(cache_standard_cb), NULL);
1652 pref_checkbox_new_int(group, _("Use EXIF thumbnails when available (EXIF thumbnails may be outdated)"),
1653 options->thumbnails.use_exif, &c_options->thumbnails.use_exif);
1655 #ifdef HAVE_FFMPEGTHUMBNAILER_METADATA
1656 pref_checkbox_new_int(group, _("Use embedded metadata in video files as thumbnails when available"),
1657 options->thumbnails.use_ft_metadata, &c_options->thumbnails.use_ft_metadata);
1659 // pref_checkbox_new_int(group, _("Ignore embedded metadata if size is too small"),
1660 // options->thumbnails.use_ft_metadata_small, &c_options->thumbnails.use_ft_metadata_small);
1663 group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
1665 c_options->slideshow.delay = options->slideshow.delay;
1666 hours = options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
1667 remainder = options->slideshow.delay % (3600 * SLIDESHOW_SUBSECOND_PRECISION);
1668 minutes = remainder / (60 * SLIDESHOW_SUBSECOND_PRECISION);
1669 seconds = (gdouble)(remainder % (60 * SLIDESHOW_SUBSECOND_PRECISION)) /
1670 SLIDESHOW_SUBSECOND_PRECISION;
1672 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1674 spin = pref_spin_new(hbox, _("Delay between image change hrs:mins:secs.dec"), NULL,
1676 options->slideshow.delay ? hours : 0.0,
1677 G_CALLBACK(slideshow_delay_hours_cb), NULL);
1678 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1679 spin = pref_spin_new(hbox, ":" , NULL,
1681 options->slideshow.delay ? minutes: 0.0,
1682 G_CALLBACK(slideshow_delay_minutes_cb), NULL);
1683 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1684 spin = pref_spin_new(hbox, ":", NULL,
1685 SLIDESHOW_MIN_SECONDS, 59, 1.0, 1,
1686 options->slideshow.delay ? seconds : 10.0,
1687 G_CALLBACK(slideshow_delay_seconds_cb), NULL);
1688 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1690 pref_checkbox_new_int(group, _("Random"), options->slideshow.random, &c_options->slideshow.random);
1691 pref_checkbox_new_int(group, _("Repeat"), options->slideshow.repeat, &c_options->slideshow.repeat);
1693 group = pref_group_new(vbox, FALSE, _("Image loading and caching"), GTK_ORIENTATION_VERTICAL);
1695 pref_spin_new_int(group, _("Decoded image cache size (Mb):"), NULL,
1696 0, 99999, 1, options->image.image_cache_max, &c_options->image.image_cache_max);
1697 pref_checkbox_new_int(group, _("Preload next image"),
1698 options->image.enable_read_ahead, &c_options->image.enable_read_ahead);
1700 pref_checkbox_new_int(group, _("Refresh on file change"),
1701 options->update_on_time_change, &c_options->update_on_time_change);
1703 group = pref_group_new(vbox, FALSE, _("Info sidebar heights"), GTK_ORIENTATION_VERTICAL);
1704 pref_label_new(group, _("NOTE! Geeqie must be restarted for changes to take effect"));
1705 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1706 pref_spin_new_int(hbox, _("Keywords:"), NULL,
1708 options->info_keywords.height, &c_options->info_keywords.height);
1709 pref_spin_new_int(hbox, _("Title:"), NULL,
1711 options->info_title.height, &c_options->info_title.height);
1712 pref_spin_new_int(hbox, _("Comment:"), NULL,
1714 options->info_comment.height, &c_options->info_comment.height);
1715 pref_spin_new_int(hbox, _("Rating:"), NULL,
1717 options->info_rating.height, &c_options->info_rating.height);
1719 group = pref_group_new(vbox, FALSE, _("On-line help search engine"), GTK_ORIENTATION_VERTICAL);
1721 help_search_engine_entry = gtk_entry_new();
1722 gtk_entry_set_text(GTK_ENTRY(help_search_engine_entry), options->help_search_engine);
1723 gtk_box_pack_start(GTK_BOX(group), help_search_engine_entry, FALSE, FALSE, 0);
1724 gtk_widget_show(help_search_engine_entry);
1726 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"));
1728 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
1729 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
1730 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
1731 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
1732 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
1733 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
1734 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
1735 GTK_ENTRY_ICON_PRIMARY, _("Default"));
1736 g_signal_connect(GTK_ENTRY(help_search_engine_entry), "icon-press",
1737 G_CALLBACK(help_search_engine_entry_icon_cb),
1738 help_search_engine_entry);
1742 static void config_tab_image(GtkWidget *notebook)
1747 GtkWidget *ct_button;
1748 GtkWidget *enlargement_button;
1752 vbox = scrolled_notebook_page(notebook, _("Image"));
1754 group = pref_group_new(vbox, FALSE, _("Zoom"), GTK_ORIENTATION_VERTICAL);
1756 table = pref_table_new(group, 2, 1, FALSE, FALSE);
1757 add_quality_menu(table, 0, 0, _("Quality:"), options->image.zoom_quality, &c_options->image.zoom_quality);
1760 pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library"),
1761 options->image.use_clutter_renderer, &c_options->image.use_clutter_renderer);
1764 pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"),
1765 options->image.zoom_2pass, &c_options->image.zoom_2pass);
1767 c_options->image.zoom_increment = options->image.zoom_increment;
1768 spin = pref_spin_new(group, _("Zoom increment:"), NULL,
1769 0.01, 4.0, 0.01, 2, (gdouble)options->image.zoom_increment / 100.0,
1770 G_CALLBACK(zoom_increment_cb), NULL);
1771 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1773 group = pref_group_new(vbox, FALSE, _("Fit image to window"), GTK_ORIENTATION_VERTICAL);
1775 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1776 enlargement_button = pref_checkbox_new_int(hbox, _("Allow enlargement of image (max. size in %)"),
1777 options->image.zoom_to_fit_allow_expand, &c_options->image.zoom_to_fit_allow_expand);
1778 spin = pref_spin_new_int(hbox, NULL, NULL,
1780 options->image.max_enlargement_size, &c_options->image.max_enlargement_size);
1781 pref_checkbox_link_sensitivity(enlargement_button, spin);
1782 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."));
1784 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1785 ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (% of actual window):"),
1786 options->image.limit_autofit_size, &c_options->image.limit_autofit_size);
1787 spin = pref_spin_new_int(hbox, NULL, NULL,
1789 options->image.max_autofit_size, &c_options->image.max_autofit_size);
1790 pref_checkbox_link_sensitivity(ct_button, spin);
1791 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."));
1793 group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
1795 pref_checkbox_new_int(group, _("Use custom border color in window mode"),
1796 options->image.use_custom_border_color, &c_options->image.use_custom_border_color);
1798 pref_checkbox_new_int(group, _("Use custom border color in fullscreen mode"),
1799 options->image.use_custom_border_color_in_fullscreen, &c_options->image.use_custom_border_color_in_fullscreen);
1801 pref_color_button_new(group, _("Border color"), &options->image.border_color,
1802 G_CALLBACK(pref_color_button_set_cb), &c_options->image.border_color);
1804 c_options->image.border_color = options->image.border_color;
1806 pref_color_button_new(group, _("Alpha channel color 1"), &options->image.alpha_color_1,
1807 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_1);
1809 pref_color_button_new(group, _("Alpha channel color 2"), &options->image.alpha_color_2,
1810 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_2);
1812 c_options->image.alpha_color_1 = options->image.alpha_color_1;
1813 c_options->image.alpha_color_2 = options->image.alpha_color_2;
1815 group = pref_group_new(vbox, FALSE, _("Convenience"), GTK_ORIENTATION_VERTICAL);
1817 pref_checkbox_new_int(group, _("Auto rotate proofs using Exif information"),
1818 options->image.exif_proof_rotate_enable, &c_options->image.exif_proof_rotate_enable);
1822 static void config_tab_windows(GtkWidget *notebook)
1828 GtkWidget *ct_button;
1830 GtkWidget *image_overlay_template_view;
1831 GtkWidget *scrolled;
1832 GtkTextBuffer *buffer;
1834 vbox = scrolled_notebook_page(notebook, _("Windows"));
1836 group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
1838 ct_button = pref_checkbox_new_int(group, _("Remember window positions"),
1839 options->save_window_positions, &c_options->save_window_positions);
1841 button = pref_checkbox_new_int(group, _("Use saved window positions also for new windows"),
1842 options->use_saved_window_positions_for_new_windows, &c_options->use_saved_window_positions_for_new_windows);
1843 pref_checkbox_link_sensitivity(ct_button, button);
1845 pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
1846 options->tools_restore_state, &c_options->tools_restore_state);
1848 pref_checkbox_new_int(group, _("Remember dialog window positions"),
1849 options->save_dialog_window_positions, &c_options->save_dialog_window_positions);
1851 pref_checkbox_new_int(group, _("Show window IDs"),
1852 options->show_window_ids, &c_options->show_window_ids);
1854 group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
1856 pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
1857 options->image.fit_window_to_image, &c_options->image.fit_window_to_image);
1859 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1860 ct_button = pref_checkbox_new_int(hbox, _("Limit size when auto-sizing window (%):"),
1861 options->image.limit_window_size, &c_options->image.limit_window_size);
1862 spin = pref_spin_new_int(hbox, NULL, NULL,
1864 options->image.max_window_size, &c_options->image.max_window_size);
1865 pref_checkbox_link_sensitivity(ct_button, spin);
1867 group = pref_group_new(vbox, FALSE, _("Full screen"), GTK_ORIENTATION_VERTICAL);
1869 c_options->fullscreen.screen = options->fullscreen.screen;
1870 c_options->fullscreen.above = options->fullscreen.above;
1871 hbox = fullscreen_prefs_selection_new(_("Location:"), &c_options->fullscreen.screen, &c_options->fullscreen.above);
1872 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
1873 gtk_widget_show(hbox);
1875 pref_checkbox_new_int(group, _("Smooth image flip"),
1876 options->fullscreen.clean_flip, &c_options->fullscreen.clean_flip);
1877 pref_checkbox_new_int(group, _("Disable screen saver"),
1878 options->fullscreen.disable_saver, &c_options->fullscreen.disable_saver);
1881 group = pref_group_new(vbox, FALSE, _("Overlay Screen Display"), GTK_ORIENTATION_VERTICAL);
1883 pref_label_new(group, _("Image overlay template"));
1885 scrolled = gtk_scrolled_window_new(NULL, NULL);
1886 gtk_widget_set_size_request(scrolled, 200, 150);
1887 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
1888 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1889 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1890 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 5);
1891 gtk_widget_show(scrolled);
1893 image_overlay_template_view = gtk_text_view_new();
1895 gtk_widget_set_tooltip_markup(image_overlay_template_view,
1896 _("<i>%name%</i> results in the filename of the picture.\n"
1897 "Also available: <i>%collection%</i>, <i>%number%</i>, <i>%total%</i>, <i>%date%</i>,\n"
1898 "<i>%size%</i> (filesize), <i>%width%</i>, <i>%height%</i>, <i>%res%</i> (resolution),\n"
1899 "<i>%rating%</i>, <i>%keywords%</i>, <i>%comment%</i> (XMP), <i>%imagecomment%</i> (JPEG)\n"
1900 "To access exif data use the exif name, e. g. <i>%formatted.Camera%</i> is the formatted camera name,\n"
1901 "<i>%Exif.Photo.DateTimeOriginal%</i> the date of the original shot.\n"
1902 "<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"
1903 "If two or more variables are connected with the |-sign, it prints available variables with a separator.\n"
1904 "<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"
1905 "if there's no ISO information in the Exif data.\n"
1906 "If a line is empty, it is removed. This allows one to add lines that totally disappear when no data is available.\n"
1908 gtk_container_add(GTK_CONTAINER(scrolled), image_overlay_template_view);
1909 gtk_widget_show(image_overlay_template_view);
1911 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
1913 #if GTK_CHECK_VERSION(3,4,0)
1914 button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
1915 G_CALLBACK(image_overlay_set_font_cb), notebook);
1917 button = gtk_font_button_new();
1918 gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Image Overlay Font");
1919 gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->image_overlay.font);
1920 g_signal_connect(G_OBJECT(button), "font-set",
1921 G_CALLBACK(image_overlay_set_font_cb),NULL);
1923 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1924 gtk_widget_show(button);
1926 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Text"), FALSE,
1927 G_CALLBACK(image_overlay_set_text_colour_cb), NULL);
1928 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1929 gtk_widget_show(button);
1931 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Background"), FALSE,
1932 G_CALLBACK(image_overlay_set_background_colour_cb), NULL);
1933 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1934 gtk_widget_show(button);
1935 image_overlay_set_text_colours();
1937 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
1938 G_CALLBACK(image_overlay_default_template_cb), image_overlay_template_view);
1939 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1940 gtk_widget_show(button);
1942 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
1943 G_CALLBACK(image_overlay_help_cb), NULL);
1944 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1945 gtk_widget_show(button);
1947 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_overlay_template_view));
1948 if (options->image_overlay.template_string) gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1949 g_signal_connect(G_OBJECT(buffer), "changed",
1950 G_CALLBACK(image_overlay_template_view_changed_cb), image_overlay_template_view);
1955 static GtkTreeModel *create_class_model(void)
1957 GtkListStore *model;
1961 /* create list store */
1962 model = gtk_list_store_new(1, G_TYPE_STRING);
1963 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
1965 gtk_list_store_append(model, &iter);
1966 gtk_list_store_set(model, &iter, 0, _(format_class_list[i]), -1);
1968 return GTK_TREE_MODEL (model);
1973 static void config_tab_files(GtkWidget *notebook)
1980 GtkWidget *ct_button;
1981 GtkWidget *scrolled;
1982 GtkWidget *filter_view;
1983 GtkCellRenderer *renderer;
1984 GtkTreeSelection *selection;
1985 GtkTreeViewColumn *column;
1987 vbox = scrolled_notebook_page(notebook, _("Files"));
1989 group = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1991 pref_checkbox_new_int(group, _("Show hidden files or folders"),
1992 options->file_filter.show_hidden_files, &c_options->file_filter.show_hidden_files);
1993 pref_checkbox_new_int(group, _("Show parent folder (..)"),
1994 options->file_filter.show_parent_directory, &c_options->file_filter.show_parent_directory);
1995 pref_checkbox_new_int(group, _("Case sensitive sort"),
1996 options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
1997 pref_checkbox_new_int(group, _("Natural sort order"),
1998 options->file_sort.natural, &c_options->file_sort.natural);
1999 pref_checkbox_new_int(group, _("Disable file extension checks"),
2000 options->file_filter.disable_file_extension_checks, &c_options->file_filter.disable_file_extension_checks);
2002 ct_button = pref_checkbox_new_int(group, _("Disable File Filtering"),
2003 options->file_filter.disable, &c_options->file_filter.disable);
2006 group = pref_group_new(vbox, FALSE, _("Grouping sidecar extensions"), GTK_ORIENTATION_VERTICAL);
2008 sidecar_ext_entry = gtk_entry_new();
2009 gtk_entry_set_text(GTK_ENTRY(sidecar_ext_entry), options->sidecar.ext);
2010 gtk_box_pack_start(GTK_BOX(group), sidecar_ext_entry, FALSE, FALSE, 0);
2011 gtk_widget_show(sidecar_ext_entry);
2013 group = pref_group_new(vbox, TRUE, _("File types"), GTK_ORIENTATION_VERTICAL);
2015 frame = pref_group_parent(group);
2016 g_signal_connect(G_OBJECT(ct_button), "toggled",
2017 G_CALLBACK(filter_disable_cb), frame);
2018 gtk_widget_set_sensitive(frame, !options->file_filter.disable);
2020 scrolled = gtk_scrolled_window_new(NULL, NULL);
2021 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2022 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2023 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2024 gtk_widget_show(scrolled);
2026 filter_store = gtk_list_store_new(1, G_TYPE_POINTER);
2027 filter_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(filter_store));
2028 g_object_unref(filter_store);
2029 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
2030 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
2032 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), FALSE);
2034 column = gtk_tree_view_column_new();
2035 gtk_tree_view_column_set_title(column, _("Filter"));
2036 gtk_tree_view_column_set_resizable(column, TRUE);
2038 renderer = gtk_cell_renderer_toggle_new();
2039 g_signal_connect(G_OBJECT(renderer), "toggled",
2040 G_CALLBACK(filter_store_enable_cb), filter_store);
2041 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2042 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2043 GINT_TO_POINTER(FE_ENABLE), NULL);
2045 renderer = gtk_cell_renderer_text_new();
2046 g_signal_connect(G_OBJECT(renderer), "edited",
2047 G_CALLBACK(filter_store_ext_edit_cb), filter_store);
2048 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2049 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2050 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2051 GINT_TO_POINTER(FE_EXTENSION), NULL);
2052 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2054 column = gtk_tree_view_column_new();
2055 gtk_tree_view_column_set_title(column, _("Description"));
2056 gtk_tree_view_column_set_resizable(column, TRUE);
2057 gtk_tree_view_column_set_fixed_width(column, 200);
2058 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
2060 renderer = gtk_cell_renderer_text_new();
2061 g_signal_connect(G_OBJECT(renderer), "edited",
2062 G_CALLBACK(filter_store_desc_edit_cb), filter_store);
2063 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2064 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2065 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2066 GINT_TO_POINTER(FE_DESCRIPTION), NULL);
2067 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2069 column = gtk_tree_view_column_new();
2070 gtk_tree_view_column_set_title(column, _("Class"));
2071 gtk_tree_view_column_set_resizable(column, TRUE);
2072 renderer = gtk_cell_renderer_combo_new();
2073 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE,
2074 "model", create_class_model(),
2079 g_signal_connect(G_OBJECT(renderer), "edited",
2080 G_CALLBACK(filter_store_class_edit_cb), filter_store);
2081 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2082 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2083 GINT_TO_POINTER(FE_CLASS), NULL);
2084 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2086 column = gtk_tree_view_column_new();
2087 gtk_tree_view_column_set_title(column, _("Writable"));
2088 gtk_tree_view_column_set_resizable(column, FALSE);
2089 renderer = gtk_cell_renderer_toggle_new();
2090 g_signal_connect(G_OBJECT(renderer), "toggled",
2091 G_CALLBACK(filter_store_writable_cb), filter_store);
2092 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2093 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2094 GINT_TO_POINTER(FE_WRITABLE), NULL);
2095 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2097 column = gtk_tree_view_column_new();
2098 gtk_tree_view_column_set_title(column, _("Sidecar is allowed"));
2099 gtk_tree_view_column_set_resizable(column, FALSE);
2100 renderer = gtk_cell_renderer_toggle_new();
2101 g_signal_connect(G_OBJECT(renderer), "toggled",
2102 G_CALLBACK(filter_store_sidecar_cb), filter_store);
2103 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2104 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2105 GINT_TO_POINTER(FE_ALLOW_SIDECAR), NULL);
2106 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2109 filter_store_populate();
2110 gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
2111 gtk_widget_show(filter_view);
2113 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2115 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2116 G_CALLBACK(filter_default_cb), filter_view);
2117 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2118 gtk_widget_show(button);
2120 button = pref_button_new(NULL, GTK_STOCK_REMOVE, NULL, FALSE,
2121 G_CALLBACK(filter_remove_cb), filter_view);
2122 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2123 gtk_widget_show(button);
2125 button = pref_button_new(NULL, GTK_STOCK_ADD, NULL, FALSE,
2126 G_CALLBACK(filter_add_cb), filter_view);
2127 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2128 gtk_widget_show(button);
2132 static void config_tab_metadata(GtkWidget *notebook)
2137 GtkWidget *ct_button;
2141 vbox = scrolled_notebook_page(notebook, _("Metadata"));
2144 group = pref_group_new(vbox, FALSE, _("Metadata writing process"), GTK_ORIENTATION_VERTICAL);
2146 label = pref_label_new(group, _("Warning: Geeqie is built without Exiv2. Some options are disabled."));
2148 label = pref_label_new(group, _("Metadata are written in the following order. The process ends after first success."));
2149 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2151 ct_button = pref_checkbox_new_int(group, _("1) Save metadata in image files, or sidecar files, according to the XMP standard"),
2152 options->metadata.save_in_image_file, &c_options->metadata.save_in_image_file);
2154 gtk_widget_set_sensitive(ct_button, FALSE);
2157 pref_checkbox_new_int(group, _("2) Save metadata in '.metadata' folder, local to image folder (non-standard)"),
2158 options->metadata.enable_metadata_dirs, &c_options->metadata.enable_metadata_dirs);
2160 text = g_strdup_printf(_("3) Save metadata in Geeqie private directory '%s'"), get_metadata_cache_dir());
2161 label = pref_label_new(group, text);
2162 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2163 gtk_misc_set_padding(GTK_MISC(label), 22, 0);
2166 group = pref_group_new(vbox, FALSE, _("Step 1: Write to image files"), GTK_ORIENTATION_VERTICAL);
2168 gtk_widget_set_sensitive(group, FALSE);
2171 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2172 pref_checkbox_link_sensitivity(ct_button, hbox);
2174 pref_checkbox_new_int(hbox, _("Store metadata also in legacy IPTC tags (converted according to IPTC4XMP standard)"),
2175 options->metadata.save_legacy_IPTC, &c_options->metadata.save_legacy_IPTC);
2177 pref_checkbox_new_int(hbox, _("Warn if the image files are unwritable"),
2178 options->metadata.warn_on_write_problems, &c_options->metadata.warn_on_write_problems);
2180 pref_checkbox_new_int(hbox, _("Ask before writing to image files"),
2181 options->metadata.confirm_write, &c_options->metadata.confirm_write);
2183 pref_checkbox_new_int(hbox, _("Create sidecar files named image.ext.xmp (as opposed to image.xmp)"),
2184 options->metadata.sidecar_extended_name, &c_options->metadata.sidecar_extended_name);
2186 group = pref_group_new(vbox, FALSE, _("Step 2 and 3: write to Geeqie private files"), GTK_ORIENTATION_VERTICAL);
2188 gtk_widget_set_sensitive(group, FALSE);
2191 pref_checkbox_new_int(group, _("Use GQview legacy metadata format (supports only keywords and comments) instead of XMP"),
2192 options->metadata.save_legacy_format, &c_options->metadata.save_legacy_format);
2195 group = pref_group_new(vbox, FALSE, _("Miscellaneous"), GTK_ORIENTATION_VERTICAL);
2196 pref_checkbox_new_int(group, _("Write the same description tags (keywords, comment, etc.) to all grouped sidecars"),
2197 options->metadata.sync_grouped_files, &c_options->metadata.sync_grouped_files);
2199 pref_checkbox_new_int(group, _("Allow keywords to differ only in case"),
2200 options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
2202 ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"),
2203 options->metadata.write_orientation, &c_options->metadata.write_orientation);
2205 gtk_widget_set_sensitive(ct_button, FALSE);
2208 group = pref_group_new(vbox, FALSE, _("Auto-save options"), GTK_ORIENTATION_VERTICAL);
2210 ct_button = pref_checkbox_new_int(group, _("Write metadata after timeout"),
2211 options->metadata.confirm_after_timeout, &c_options->metadata.confirm_after_timeout);
2213 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2214 pref_checkbox_link_sensitivity(ct_button, hbox);
2216 pref_spin_new_int(hbox, _("Timeout (seconds):"), NULL, 0, 900, 1,
2217 options->metadata.confirm_timeout, &c_options->metadata.confirm_timeout);
2219 pref_checkbox_new_int(group, _("Write metadata on image change"),
2220 options->metadata.confirm_on_image_change, &c_options->metadata.confirm_on_image_change);
2222 pref_checkbox_new_int(group, _("Write metadata on directory change"),
2223 options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
2225 group = pref_group_new(vbox, FALSE, _("Pre-load metadata"), GTK_ORIENTATION_VERTICAL);
2227 ct_button = pref_checkbox_new_int(group, _("Read metadata in background"),
2228 options->read_metadata_in_idle, &c_options->read_metadata_in_idle);
2229 gtk_widget_set_tooltip_text(ct_button,"On folder change, read DateTimeOriginal, DateTimeDigitized and Star Rating in the idle loop.\nIf this is not selected, initial loading of the folder will be faster but sorting on these items will be slower");
2234 static void intent_menu_cb(GtkWidget *combo, gpointer data)
2236 gint *option = data;
2238 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
2242 *option = INTENT_PERCEPTUAL;
2245 *option = INTENT_RELATIVE_COLORIMETRIC;
2248 *option = INTENT_SATURATION;
2251 *option = INTENT_ABSOLUTE_COLORIMETRIC;
2256 static void add_intent_menu(GtkWidget *table, gint column, gint row, const gchar *text,
2257 gint option, gint *option_c)
2264 pref_table_label(table, column, row, text, 0.0);
2266 combo = gtk_combo_box_text_new();
2268 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Perceptual"));
2269 if (option == INTENT_PERCEPTUAL) current = 0;
2270 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Relative Colorimetric"));
2271 if (option == INTENT_RELATIVE_COLORIMETRIC) current = 1;
2272 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Saturation"));
2273 if (option == INTENT_SATURATION) current = 2;
2274 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Absolute Colorimetric"));
2275 if (option == INTENT_ABSOLUTE_COLORIMETRIC) current = 3;
2277 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
2279 gtk_widget_set_tooltip_text(combo,"Refer to the lcms documentation for the defaults used when the selected Intent is not available");
2281 g_signal_connect(G_OBJECT(combo), "changed",
2282 G_CALLBACK(intent_menu_cb), option_c);
2284 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
2285 GTK_EXPAND | GTK_FILL, 0, 0, 0);
2286 gtk_widget_show(combo);
2290 static void config_tab_color(GtkWidget *notebook)
2299 vbox = scrolled_notebook_page(notebook, _("Color management"));
2301 group = pref_group_new(vbox, FALSE, _("Input profiles"), GTK_ORIENTATION_VERTICAL);
2303 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
2306 table = pref_table_new(group, 3, COLOR_PROFILE_INPUTS + 1, FALSE, FALSE);
2307 gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
2309 label = pref_table_label(table, 0, 0, _("Type"), 0.0);
2310 pref_label_bold(label, TRUE, FALSE);
2312 label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
2313 pref_label_bold(label, TRUE, FALSE);
2315 label = pref_table_label(table, 2, 0, _("File"), 0.0);
2316 pref_label_bold(label, TRUE, FALSE);
2318 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
2323 buf = g_strdup_printf(_("Input %d:"), i + COLOR_PROFILE_FILE);
2324 pref_table_label(table, 0, i + 1, buf, 1.0);
2327 entry = gtk_entry_new();
2328 gtk_entry_set_max_length(GTK_ENTRY(entry), EDITOR_NAME_MAX_LENGTH);
2329 if (options->color_profile.input_name[i])
2331 gtk_entry_set_text(GTK_ENTRY(entry), options->color_profile.input_name[i]);
2333 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, i + 1, i + 2,
2334 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2335 gtk_widget_show(entry);
2336 color_profile_input_name_entry[i] = entry;
2338 tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, ".icc", "ICC Files", NULL);
2339 tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
2340 gtk_widget_set_size_request(entry, 160, -1);
2341 gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
2342 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2343 gtk_widget_show(tabcomp);
2344 color_profile_input_file_entry[i] = entry;
2347 group = pref_group_new(vbox, FALSE, _("Screen profile"), GTK_ORIENTATION_VERTICAL);
2349 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
2351 pref_checkbox_new_int(group, _("Use system screen profile if available"),
2352 options->color_profile.use_x11_screen_profile, &c_options->color_profile.use_x11_screen_profile);
2354 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2356 pref_table_label(table, 0, 0, _("Screen:"), 1.0);
2357 tabcomp = tab_completion_new(&color_profile_screen_file_entry,
2358 options->color_profile.screen_file, NULL, ".icc", "ICC Files", NULL);
2359 tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
2360 gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
2362 add_intent_menu(table, 0, 1, _("Render Intent:"), options->color_profile.render_intent, &c_options->color_profile.render_intent);
2364 gtk_table_attach(GTK_TABLE(table), tabcomp, 1, 2,
2366 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2368 gtk_widget_show(tabcomp);
2371 /* advanced entry tab */
2372 static void config_tab_behavior(GtkWidget *notebook)
2379 GtkWidget *ct_button;
2383 GtkWidget *with_rename;
2385 vbox = scrolled_notebook_page(notebook, _("Behavior"));
2387 group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
2389 pref_checkbox_new_int(group, _("Confirm file delete"),
2390 options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
2391 pref_checkbox_new_int(group, _("Enable Delete key"),
2392 options->file_ops.enable_delete_key, &c_options->file_ops.enable_delete_key);
2394 ct_button = pref_checkbox_new_int(group, _("Safe delete"),
2395 options->file_ops.safe_delete_enable, &c_options->file_ops.safe_delete_enable);
2397 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2398 pref_checkbox_link_sensitivity(ct_button, hbox);
2400 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
2401 pref_label_new(hbox, _("Folder:"));
2403 tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL, NULL, NULL);
2404 tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
2405 gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
2406 gtk_widget_show(tabcomp);
2408 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2409 pref_checkbox_link_sensitivity(ct_button, hbox);
2411 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
2412 spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MB"),
2413 0, 2048, 1, options->file_ops.safe_delete_folder_maxsize, &c_options->file_ops.safe_delete_folder_maxsize);
2414 gtk_widget_set_tooltip_markup(spin, _("Set to 0 for unlimited size"));
2415 button = pref_button_new(NULL, NULL, _("View"), FALSE,
2416 G_CALLBACK(safe_delete_view_cb), NULL);
2417 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2418 gtk_widget_show(button);
2420 button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
2421 G_CALLBACK(safe_delete_clear_cb), NULL);
2422 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2423 gtk_widget_show(button);
2426 group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
2428 pref_checkbox_new_int(group, _("Descend folders in tree view"),
2429 options->tree_descend_subdirs, &c_options->tree_descend_subdirs);
2431 pref_checkbox_new_int(group, _("In place renaming"),
2432 options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
2434 pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
2435 options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
2437 marks = pref_checkbox_new_int(group, _("Save marks on exit"),
2438 options->marks_save, &c_options->marks_save);
2439 gtk_widget_set_tooltip_text(marks,"Note that marks linked to a keyword will be saved irrespective of this setting");
2441 with_rename = pref_checkbox_new_int(group, _("Use \"With Rename\" as default for Copy/Move dialogs"),
2442 options->with_rename, &c_options->with_rename);
2443 gtk_widget_set_tooltip_text(with_rename,"Change the default button for Copy/Move dialogs");
2445 pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
2446 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
2448 pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
2449 16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
2451 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2452 add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
2454 group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
2456 pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
2457 options->progressive_key_scrolling, &c_options->progressive_key_scrolling);
2458 pref_spin_new_int(group, _("Keyboard scrolling step multiplier:"), NULL,
2459 1, 32, 1, options->keyboard_scroll_step, (int *)&c_options->keyboard_scroll_step);
2460 pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
2461 options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
2462 pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
2463 options->image_lm_click_nav, &c_options->image_lm_click_nav);
2464 pref_checkbox_new_int(group, _("Play video by left click on image"),
2465 options->image_l_click_video, &c_options->image_l_click_video);
2466 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2467 add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
2471 group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
2473 pref_spin_new_int(group, _("Debug level:"), NULL,
2474 DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
2476 pref_checkbox_new_int(group, _("Timer data"),
2477 options->log_window.timer_data, &c_options->log_window.timer_data);
2479 pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
2480 1, 99999, 1, options->log_window_lines, &options->log_window_lines);
2484 /* accelerators tab */
2485 static void config_tab_accelerators(GtkWidget *notebook)
2491 GtkWidget *scrolled;
2492 GtkWidget *accel_view;
2493 GtkCellRenderer *renderer;
2494 GtkTreeSelection *selection;
2495 GtkTreeViewColumn *column;
2497 vbox = scrolled_notebook_page(notebook, _("Keyboard"));
2499 group = pref_group_new(vbox, TRUE, _("Accelerators"), GTK_ORIENTATION_VERTICAL);
2501 scrolled = gtk_scrolled_window_new(NULL, NULL);
2502 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2503 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2504 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2505 gtk_widget_show(scrolled);
2507 accel_store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
2509 accel_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(accel_store));
2510 g_object_unref(accel_store);
2511 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(accel_view));
2512 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
2514 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(accel_view), FALSE);
2516 renderer = gtk_cell_renderer_text_new();
2518 column = gtk_tree_view_column_new_with_attributes(_("Action"),
2523 gtk_tree_view_column_set_sort_column_id(column, AE_ACTION);
2524 gtk_tree_view_column_set_resizable(column, TRUE);
2525 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
2528 renderer = gtk_cell_renderer_accel_new();
2529 g_signal_connect(G_OBJECT(renderer), "accel-cleared",
2530 G_CALLBACK(accel_store_cleared_cb), accel_store);
2531 g_signal_connect(G_OBJECT(renderer), "accel-edited",
2532 G_CALLBACK(accel_store_edited_cb), accel_store);
2535 g_object_set (renderer,
2537 "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
2540 column = gtk_tree_view_column_new_with_attributes(_("KEY"),
2545 gtk_tree_view_column_set_sort_column_id(column, AE_KEY);
2546 gtk_tree_view_column_set_resizable(column, TRUE);
2547 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
2549 renderer = gtk_cell_renderer_text_new();
2551 column = gtk_tree_view_column_new_with_attributes(_("Tooltip"),
2556 gtk_tree_view_column_set_sort_column_id(column, AE_TOOLTIP);
2557 gtk_tree_view_column_set_resizable(column, TRUE);
2558 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
2560 renderer = gtk_cell_renderer_text_new();
2562 column = gtk_tree_view_column_new_with_attributes("Accel",
2567 gtk_tree_view_column_set_sort_column_id(column, AE_ACCEL);
2568 gtk_tree_view_column_set_resizable(column, TRUE);
2569 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
2571 accel_store_populate();
2572 gtk_container_add(GTK_CONTAINER(scrolled), accel_view);
2573 gtk_widget_show(accel_view);
2575 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2577 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2578 G_CALLBACK(accel_default_cb), accel_view);
2579 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2580 gtk_widget_show(button);
2582 button = pref_button_new(NULL, NULL, _("Reset selected"), FALSE,
2583 G_CALLBACK(accel_reset_cb), accel_view);
2584 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2585 gtk_widget_show(button);
2589 static void config_tab_toolbar(GtkWidget *notebook)
2592 GtkWidget *toolbardata;
2595 lw = layout_window_list->data;
2597 vbox = scrolled_notebook_page(notebook, _("Toolbar"));
2599 toolbardata = toolbar_select_new(lw);
2600 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
2601 gtk_widget_show(vbox);
2605 static void config_tab_stereo(GtkWidget *notebook)
2613 GtkWidget *fs_button;
2614 vbox = scrolled_notebook_page(notebook, _("Stereo"));
2616 group = pref_group_new(vbox, FALSE, _("Windowed stereo mode"), GTK_ORIENTATION_VERTICAL);
2618 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2619 add_stereo_mode_menu(table, 0, 0, _("Windowed stereo mode"), options->stereo.mode, &c_options->stereo.mode, FALSE);
2621 table = pref_table_new(group, 2, 2, TRUE, FALSE);
2622 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
2623 pref_checkbox_new_int(box, _("Mirror left image"),
2624 options->stereo.mode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.mirror_left);
2625 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
2626 pref_checkbox_new_int(box, _("Flip left image"),
2627 options->stereo.mode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.flip_left);
2628 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
2629 pref_checkbox_new_int(box, _("Mirror right image"),
2630 options->stereo.mode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.mirror_right);
2631 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
2632 pref_checkbox_new_int(box, _("Flip right image"),
2633 options->stereo.mode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.flip_right);
2634 pref_checkbox_new_int(group, _("Swap left and right images"),
2635 options->stereo.mode & PR_STEREO_SWAP, &c_options->stereo.tmp.swap);
2636 pref_checkbox_new_int(group, _("Disable stereo mode on single image source"),
2637 options->stereo.mode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.temp_disable);
2639 group = pref_group_new(vbox, FALSE, _("Fullscreen stereo mode"), GTK_ORIENTATION_VERTICAL);
2640 fs_button = pref_checkbox_new_int(group, _("Use different settings for fullscreen"),
2641 options->stereo.enable_fsmode, &c_options->stereo.enable_fsmode);
2642 box2 = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2643 pref_checkbox_link_sensitivity(fs_button, box2);
2644 table = pref_table_new(box2, 2, 1, FALSE, FALSE);
2645 add_stereo_mode_menu(table, 0, 0, _("Fullscreen stereo mode"), options->stereo.fsmode, &c_options->stereo.fsmode, TRUE);
2646 table = pref_table_new(box2, 2, 2, TRUE, FALSE);
2647 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
2648 pref_checkbox_new_int(box, _("Mirror left image"),
2649 options->stereo.fsmode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.fs_mirror_left);
2650 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
2651 pref_checkbox_new_int(box, _("Flip left image"),
2652 options->stereo.fsmode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.fs_flip_left);
2653 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
2654 pref_checkbox_new_int(box, _("Mirror right image"),
2655 options->stereo.fsmode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.fs_mirror_right);
2656 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
2657 pref_checkbox_new_int(box, _("Flip right image"),
2658 options->stereo.fsmode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.fs_flip_right);
2659 pref_checkbox_new_int(box2, _("Swap left and right images"),
2660 options->stereo.fsmode & PR_STEREO_SWAP, &c_options->stereo.tmp.fs_swap);
2661 pref_checkbox_new_int(box2, _("Disable stereo mode on single image source"),
2662 options->stereo.fsmode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.fs_temp_disable);
2664 group2 = pref_group_new(box2, FALSE, _("Fixed position"), GTK_ORIENTATION_VERTICAL);
2665 table = pref_table_new(group2, 5, 3, FALSE, FALSE);
2666 pref_table_spin_new_int(table, 0, 0, _("Width"), NULL,
2667 1, 5000, 1, options->stereo.fixed_w, &c_options->stereo.fixed_w);
2668 pref_table_spin_new_int(table, 3, 0, _("Height"), NULL,
2669 1, 5000, 1, options->stereo.fixed_h, &c_options->stereo.fixed_h);
2670 pref_table_spin_new_int(table, 0, 1, _("Left X"), NULL,
2671 0, 5000, 1, options->stereo.fixed_x1, &c_options->stereo.fixed_x1);
2672 pref_table_spin_new_int(table, 3, 1, _("Left Y"), NULL,
2673 0, 5000, 1, options->stereo.fixed_y1, &c_options->stereo.fixed_y1);
2674 pref_table_spin_new_int(table, 0, 2, _("Right X"), NULL,
2675 0, 5000, 1, options->stereo.fixed_x2, &c_options->stereo.fixed_x2);
2676 pref_table_spin_new_int(table, 3, 2, _("Right Y"), NULL,
2677 0, 5000, 1, options->stereo.fixed_y2, &c_options->stereo.fixed_y2);
2681 /* Main preferences window */
2682 static void config_window_create(void)
2684 GtkWidget *win_vbox;
2686 GtkWidget *notebook;
2688 GtkWidget *ct_button;
2690 if (!c_options) c_options = init_options(NULL);
2692 configwindow = window_new(GTK_WINDOW_TOPLEVEL, "preferences", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Preferences"));
2693 gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
2694 g_signal_connect(G_OBJECT(configwindow), "delete_event",
2695 G_CALLBACK(config_window_delete), NULL);
2696 gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
2697 gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
2698 gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
2700 win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
2701 gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
2702 gtk_widget_show(win_vbox);
2704 notebook = gtk_notebook_new();
2705 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP);
2706 gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
2708 config_tab_general(notebook);
2709 config_tab_image(notebook);
2710 config_tab_windows(notebook);
2711 config_tab_accelerators(notebook);
2712 config_tab_files(notebook);
2713 config_tab_metadata(notebook);
2714 config_tab_color(notebook);
2715 config_tab_stereo(notebook);
2716 config_tab_behavior(notebook);
2717 config_tab_toolbar(notebook);
2719 hbox = gtk_hbutton_box_new();
2720 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
2721 gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
2722 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
2723 gtk_widget_show(hbox);
2725 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
2726 G_CALLBACK(config_window_help_cb), notebook);
2727 gtk_container_add(GTK_CONTAINER(hbox), button);
2728 gtk_widget_set_can_default(button, TRUE);
2729 gtk_widget_show(button);
2731 button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
2732 G_CALLBACK(config_window_ok_cb), NULL);
2733 gtk_container_add(GTK_CONTAINER(hbox), button);
2734 gtk_widget_set_can_default(button, TRUE);
2735 gtk_widget_grab_default(button);
2736 gtk_widget_show(button);
2740 button = pref_button_new(NULL, GTK_STOCK_SAVE, NULL, FALSE,
2741 G_CALLBACK(config_window_save_cb), NULL);
2742 gtk_container_add(GTK_CONTAINER(hbox), button);
2743 gtk_widget_set_can_default(button, TRUE);
2744 gtk_widget_show(button);
2746 button = pref_button_new(NULL, GTK_STOCK_APPLY, NULL, FALSE,
2747 G_CALLBACK(config_window_apply_cb), NULL);
2748 gtk_container_add(GTK_CONTAINER(hbox), button);
2749 gtk_widget_set_can_default(button, TRUE);
2750 gtk_widget_show(button);
2752 button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
2753 G_CALLBACK(config_window_close_cb), NULL);
2754 gtk_container_add(GTK_CONTAINER(hbox), button);
2755 gtk_widget_set_can_default(button, TRUE);
2756 gtk_widget_show(button);
2758 if (!generic_dialog_get_alternative_button_order(configwindow))
2760 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
2763 gtk_widget_show(notebook);
2765 gtk_widget_show(configwindow);
2769 *-----------------------------------------------------------------------------
2770 * config window show (public)
2771 *-----------------------------------------------------------------------------
2774 void show_config_window(void)
2778 gtk_window_present(GTK_WINDOW(configwindow));
2782 config_window_create();
2791 void show_about_window(LayoutWindow *lw)
2793 GdkPixbuf *pixbuf_logo;
2794 GdkPixbuf *pixbuf_icon;
2795 gchar *authors[1000];
2803 #define LINE_LENGTH 1000
2804 gchar line[LINE_LENGTH];
2806 copyright = g_string_new(NULL);
2807 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");
2809 zd_path = g_build_filename(GQ_BIN_DIR, TIMEZONE_DATABASE, NULL);
2810 cd = ZDOpenDatabase(zd_path);
2813 copyright = g_string_append(copyright, ZDGetNotice(cd));
2815 ZDCloseDatabase(cd);
2819 path = g_build_filename(GQ_HELPDIR, "AUTHORS", NULL);
2820 fp = fopen(path, "r");
2823 while(fgets(line, LINE_LENGTH, fp))
2825 /* get rid of ending \n from fgets */
2826 line[strlen(line) - 1] = '\0';
2827 authors[i_authors] = g_strdup(line);
2830 authors[i_authors] = NULL;
2835 comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
2836 "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
2838 pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
2839 pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
2840 gtk_show_about_dialog(GTK_WINDOW(lw->window),
2841 "title", _("About Geeqie"),
2843 "program-name", GQ_APPNAME,
2845 "logo", pixbuf_logo,
2846 "icon", pixbuf_icon,
2847 "website", GQ_WEBSITE,
2848 "website-label", "Website",
2849 "comments", comment,
2851 "translator-credits", _("translator-credits"),
2852 "wrap-license", TRUE,
2853 "license", copyright->str,
2856 g_string_free(copyright, TRUE);
2859 while(n < i_authors)
2869 static void image_overlay_set_text_colours()
2871 c_options->image_overlay.text_red = options->image_overlay.text_red;
2872 c_options->image_overlay.text_green = options->image_overlay.text_green;
2873 c_options->image_overlay.text_blue = options->image_overlay.text_blue;
2874 c_options->image_overlay.text_alpha = options->image_overlay.text_alpha;
2875 c_options->image_overlay.background_red = options->image_overlay.background_red;
2876 c_options->image_overlay.background_green = options->image_overlay.background_green;
2877 c_options->image_overlay.background_blue = options->image_overlay.background_blue;
2878 c_options->image_overlay.background_alpha = options->image_overlay.background_alpha;
2880 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */