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 static 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 config_entry_to_option(help_search_engine_entry, &options->help_search_engine, NULL);
415 set_debug_level(debug_c);
419 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
421 config_entry_to_option(color_profile_input_name_entry[i], &options->color_profile.input_name[i], NULL);
422 config_entry_to_option(color_profile_input_file_entry[i], &options->color_profile.input_file[i], NULL);
424 config_entry_to_option(color_profile_screen_file_entry, &options->color_profile.screen_file, NULL);
425 options->color_profile.use_x11_screen_profile = c_options->color_profile.use_x11_screen_profile;
426 if (options->color_profile.render_intent != c_options->color_profile.render_intent)
428 options->color_profile.render_intent = c_options->color_profile.render_intent;
433 image_options_sync();
438 layout_refresh(NULL);
441 if (accel_store) gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_apply_cb, NULL);
447 *-----------------------------------------------------------------------------
448 * config window main button callbacks (private)
449 *-----------------------------------------------------------------------------
452 static void config_window_close_cb(GtkWidget *widget, gpointer data)
454 gtk_widget_destroy(configwindow);
459 static void config_window_help_cb(GtkWidget *widget, gpointer data)
461 GtkWidget *notebook = data;
464 static gchar *html_section[] =
466 "GuideOptionsGeneral.html",
467 "GuideOptionsImage.html",
468 "GuideOptionsWindow.html",
469 "GuideOptionsKeyboard.html",
470 "GuideOptionsFiltering.html",
471 "GuideOptionsMetadata.html",
472 "GuideOptionsColor.html",
473 "GuideOptionsStereo.html",
474 "GuideOptionsBehavior.html",
475 "GuideOptionsToolbar.html"
478 i = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
479 help_window_show(html_section[i]);
482 static gboolean config_window_delete(GtkWidget *widget, GdkEventAny *event, gpointer data)
484 config_window_close_cb(NULL, NULL);
488 static void config_window_ok_cb(GtkWidget *widget, gpointer data)
490 config_window_apply();
491 config_window_close_cb(NULL, NULL);
494 static void config_window_apply_cb(GtkWidget *widget, gpointer data)
497 lw = layout_window_list->data;
499 config_window_apply();
500 layout_util_sync(lw);
503 static void config_window_save_cb(GtkWidget *widget, gpointer data)
505 config_window_apply();
506 save_options(options);
510 *-----------------------------------------------------------------------------
511 * config window setup (private)
512 *-----------------------------------------------------------------------------
515 static void quality_menu_cb(GtkWidget *combo, gpointer data)
519 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
523 *option = GDK_INTERP_NEAREST;
526 *option = GDK_INTERP_TILES;
529 *option = GDK_INTERP_BILINEAR;
532 *option = GDK_INTERP_HYPER;
537 static void clipboard_selection_menu_cb(GtkWidget *combo, gpointer data)
541 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
553 static void add_quality_menu(GtkWidget *table, gint column, gint row, const gchar *text,
554 guint option, guint *option_c)
561 pref_table_label(table, column, row, text, 0.0);
563 combo = gtk_combo_box_text_new();
565 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Nearest (worst, but fastest)"));
566 if (option == GDK_INTERP_NEAREST) current = 0;
567 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Tiles"));
568 if (option == GDK_INTERP_TILES) current = 1;
569 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Bilinear"));
570 if (option == GDK_INTERP_BILINEAR) current = 2;
571 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Hyper (best, but slowest)"));
572 if (option == GDK_INTERP_HYPER) current = 3;
574 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
576 g_signal_connect(G_OBJECT(combo), "changed",
577 G_CALLBACK(quality_menu_cb), option_c);
579 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
580 GTK_EXPAND | GTK_FILL, 0, 0, 0);
581 gtk_widget_show(combo);
584 static void add_clipboard_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
585 gint option, gint *option_c)
592 pref_table_label(table, column, row, text, 0.0);
594 combo = gtk_combo_box_text_new();
596 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("PRIMARY"));
597 if (option == PRIMARY) current = 0;
598 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("CLIPBOARD"));
599 if (option == CLIPBOARD) current = 1;
601 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
603 g_signal_connect(G_OBJECT(combo), "changed",
604 G_CALLBACK(clipboard_selection_menu_cb), option_c);
606 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
607 GTK_EXPAND | GTK_FILL, 0, 0, 0);
608 gtk_widget_show(combo);
611 static void thumb_size_menu_cb(GtkWidget *combo, gpointer data)
615 n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
618 if ((guint) n < sizeof(thumb_size_list) / sizeof(ThumbSize))
620 c_options->thumbnails.max_width = thumb_size_list[n].w;
621 c_options->thumbnails.max_height = thumb_size_list[n].h;
625 c_options->thumbnails.max_width = options->thumbnails.max_width;
626 c_options->thumbnails.max_height = options->thumbnails.max_height;
630 static void add_thumb_size_menu(GtkWidget *table, gint column, gint row, gchar *text)
636 c_options->thumbnails.max_width = options->thumbnails.max_width;
637 c_options->thumbnails.max_height = options->thumbnails.max_height;
639 pref_table_label(table, column, row, text, 0.0);
641 combo = gtk_combo_box_text_new();
644 for (i = 0; (guint) i < sizeof(thumb_size_list) / sizeof(ThumbSize); i++)
649 w = thumb_size_list[i].w;
650 h = thumb_size_list[i].h;
652 buf = g_strdup_printf("%d x %d", w, h);
653 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
656 if (w == options->thumbnails.max_width && h == options->thumbnails.max_height) current = i;
663 buf = g_strdup_printf("%s %d x %d", _("Custom"), options->thumbnails.max_width, options->thumbnails.max_height);
664 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
670 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
671 g_signal_connect(G_OBJECT(combo), "changed",
672 G_CALLBACK(thumb_size_menu_cb), NULL);
674 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
675 GTK_EXPAND | GTK_FILL, 0, 0, 0);
676 gtk_widget_show(combo);
679 static void stereo_mode_menu_cb(GtkWidget *combo, gpointer data)
683 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
687 *option = PR_STEREO_NONE;
690 *option = PR_STEREO_ANAGLYPH_RC;
693 *option = PR_STEREO_ANAGLYPH_GM;
696 *option = PR_STEREO_ANAGLYPH_YB;
699 *option = PR_STEREO_ANAGLYPH_GRAY_RC;
702 *option = PR_STEREO_ANAGLYPH_GRAY_GM;
705 *option = PR_STEREO_ANAGLYPH_GRAY_YB;
708 *option = PR_STEREO_ANAGLYPH_DB_RC;
711 *option = PR_STEREO_ANAGLYPH_DB_GM;
714 *option = PR_STEREO_ANAGLYPH_DB_YB;
717 *option = PR_STEREO_HORIZ;
720 *option = PR_STEREO_HORIZ | PR_STEREO_HALF;
723 *option = PR_STEREO_VERT;
726 *option = PR_STEREO_VERT | PR_STEREO_HALF;
729 *option = PR_STEREO_FIXED;
734 static void add_stereo_mode_menu(GtkWidget *table, gint column, gint row, const gchar *text,
735 gint option, gint *option_c, gboolean add_fixed)
742 pref_table_label(table, column, row, text, 0.0);
744 combo = gtk_combo_box_text_new();
746 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Single image"));
748 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Red-Cyan"));
749 if (option & PR_STEREO_ANAGLYPH_RC) current = 1;
750 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Green-Magenta"));
751 if (option & PR_STEREO_ANAGLYPH_GM) current = 2;
752 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Yellow-Blue"));
753 if (option & PR_STEREO_ANAGLYPH_YB) current = 3;
754 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Red-Cyan"));
755 if (option & PR_STEREO_ANAGLYPH_GRAY_RC) current = 4;
756 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Green-Magenta"));
757 if (option & PR_STEREO_ANAGLYPH_GRAY_GM) current = 5;
758 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Yellow-Blue"));
759 if (option & PR_STEREO_ANAGLYPH_GRAY_YB) current = 6;
760 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Red-Cyan"));
761 if (option & PR_STEREO_ANAGLYPH_DB_RC) current = 7;
762 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Green-Magenta"));
763 if (option & PR_STEREO_ANAGLYPH_DB_GM) current = 8;
764 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Yellow-Blue"));
765 if (option & PR_STEREO_ANAGLYPH_DB_YB) current = 9;
767 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side"));
768 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side Half size"));
769 if (option & PR_STEREO_HORIZ)
772 if (option & PR_STEREO_HALF) current = 11;
775 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom"));
776 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom Half size"));
777 if (option & PR_STEREO_VERT)
780 if (option & PR_STEREO_HALF) current = 13;
785 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Fixed position"));
786 if (option & PR_STEREO_FIXED) current = 14;
789 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
791 g_signal_connect(G_OBJECT(combo), "changed",
792 G_CALLBACK(stereo_mode_menu_cb), option_c);
794 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
795 GTK_EXPAND | GTK_FILL, 0, 0, 0);
796 gtk_widget_show(combo);
799 static void video_menu_cb(GtkWidget *combo, gpointer data)
801 gchar **option = data;
803 EditorDescription *ed = g_list_nth_data(editor_list_get(), gtk_combo_box_get_active(GTK_COMBO_BOX(combo)));
807 static void video_menu_populate(gpointer data, gpointer user_data)
809 GtkWidget *combo = user_data;
810 EditorDescription *ed = data;
812 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), ed->name);
815 static void add_video_menu(GtkWidget *table, gint column, gint row, const gchar *text,
816 gchar *option, gchar **option_c)
820 /* use lists since they are sorted */
821 GList *eds = editor_list_get();
825 pref_table_label(table, column, row, text, 0.0);
827 combo = gtk_combo_box_text_new();
828 g_list_foreach(eds,video_menu_populate,(gpointer)combo);
829 current = option ? g_list_index(eds,g_hash_table_lookup(editors,option)): -1;
831 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
833 g_signal_connect(G_OBJECT(combo), "changed",
834 G_CALLBACK(video_menu_cb), option_c);
836 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
837 GTK_EXPAND | GTK_FILL, 0, 0, 0);
838 gtk_widget_show(combo);
841 static void filter_store_populate(void)
845 if (!filter_store) return;
847 gtk_list_store_clear(filter_store);
849 work = filter_get_list();
858 gtk_list_store_append(filter_store, &iter);
859 gtk_list_store_set(filter_store, &iter, 0, fe, -1);
863 static void filter_store_ext_edit_cb(GtkCellRendererText *cell, gchar *path_str,
864 gchar *new_text, gpointer data)
866 GtkWidget *model = data;
867 FilterEntry *fe = data;
871 if (!new_text || strlen(new_text) < 1) return;
873 tpath = gtk_tree_path_new_from_string(path_str);
874 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
875 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
877 g_free(fe->extensions);
878 fe->extensions = g_strdup(new_text);
880 gtk_tree_path_free(tpath);
884 static void filter_store_class_edit_cb(GtkCellRendererText *cell, gchar *path_str,
885 gchar *new_text, gpointer data)
887 GtkWidget *model = data;
888 FilterEntry *fe = data;
893 if (!new_text || !new_text[0]) return;
895 tpath = gtk_tree_path_new_from_string(path_str);
896 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
897 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
899 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
901 if (strcmp(new_text, _(format_class_list[i])) == 0)
908 gtk_tree_path_free(tpath);
912 static void filter_store_desc_edit_cb(GtkCellRendererText *cell, gchar *path_str,
913 gchar *new_text, gpointer data)
915 GtkWidget *model = data;
920 if (!new_text || !new_text[0]) return;
922 tpath = gtk_tree_path_new_from_string(path_str);
923 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
924 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
926 g_free(fe->description);
927 fe->description = g_strdup(new_text);
929 gtk_tree_path_free(tpath);
932 static void filter_store_enable_cb(GtkCellRendererToggle *renderer,
933 gchar *path_str, gpointer data)
935 GtkWidget *model = data;
940 tpath = gtk_tree_path_new_from_string(path_str);
941 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
942 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
944 fe->enabled = !fe->enabled;
946 gtk_tree_path_free(tpath);
950 static void filter_store_writable_cb(GtkCellRendererToggle *renderer,
951 gchar *path_str, gpointer data)
953 GtkWidget *model = data;
958 tpath = gtk_tree_path_new_from_string(path_str);
959 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
960 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
962 fe->writable = !fe->writable;
963 if (fe->writable) fe->allow_sidecar = FALSE;
965 gtk_tree_path_free(tpath);
969 static void filter_store_sidecar_cb(GtkCellRendererToggle *renderer,
970 gchar *path_str, gpointer data)
972 GtkWidget *model = data;
977 tpath = gtk_tree_path_new_from_string(path_str);
978 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
979 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
981 fe->allow_sidecar = !fe->allow_sidecar;
982 if (fe->allow_sidecar) fe->writable = FALSE;
984 gtk_tree_path_free(tpath);
988 static void filter_set_func(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
989 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
993 gtk_tree_model_get(tree_model, iter, 0, &fe, -1);
995 switch (GPOINTER_TO_INT(data))
998 g_object_set(GTK_CELL_RENDERER(cell),
999 "active", fe->enabled, NULL);
1002 g_object_set(GTK_CELL_RENDERER(cell),
1003 "text", fe->extensions, NULL);
1005 case FE_DESCRIPTION:
1006 g_object_set(GTK_CELL_RENDERER(cell),
1007 "text", fe->description, NULL);
1010 g_object_set(GTK_CELL_RENDERER(cell),
1011 "text", _(format_class_list[fe->file_class]), NULL);
1014 g_object_set(GTK_CELL_RENDERER(cell),
1015 "active", fe->writable, NULL);
1017 case FE_ALLOW_SIDECAR:
1018 g_object_set(GTK_CELL_RENDERER(cell),
1019 "active", fe->allow_sidecar, NULL);
1024 static gboolean filter_add_scroll(gpointer data)
1028 GtkCellRenderer *cell;
1029 GtkTreeViewColumn *column;
1030 GList *list_columns;
1035 rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(filter_store), NULL);
1036 path = gtk_tree_path_new_from_indices(rows-1, -1);
1038 list_columns = gtk_tree_view_get_columns(GTK_TREE_VIEW(data));
1040 column = g_list_nth(list_columns,i)->data;
1041 title = gtk_tree_view_column_get_title(GTK_TREE_VIEW_COLUMN(column));
1043 } while (strcmp(title, "Filter") !=0 );
1045 list_cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column));
1046 cell = g_list_last(list_cells)->data;
1048 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1049 path, column, FALSE, 0.0, 0.0 );
1050 gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(data),
1051 path, column, cell, TRUE);
1053 gtk_tree_path_free(path);
1054 g_list_free(list_cells);
1055 g_list_free(list_columns);
1060 static void filter_add_cb(GtkWidget *widget, gpointer data)
1062 filter_add_unique("description", ".new", FORMAT_CLASS_IMAGE, TRUE, FALSE, TRUE);
1063 filter_store_populate();
1065 g_idle_add((GSourceFunc)filter_add_scroll, data);
1068 static void filter_remove_cb(GtkWidget *widget, gpointer data)
1070 GtkWidget *filter_view = data;
1071 GtkTreeSelection *selection;
1075 if (!filter_store) return;
1076 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1077 if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) return;
1078 gtk_tree_model_get(GTK_TREE_MODEL(filter_store), &iter, 0, &fe, -1);
1081 filter_remove_entry(fe);
1083 filter_store_populate();
1086 static gboolean filter_default_ok_scroll(GtkTreeView *data)
1090 GtkTreeViewColumn *column;
1092 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(filter_store), &iter);
1093 path = gtk_tree_model_get_path(GTK_TREE_MODEL(filter_store), &iter);
1094 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1096 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1100 gtk_tree_path_free(path);
1105 static void filter_default_ok_cb(GenericDialog *gd, gpointer data)
1108 filter_add_defaults();
1110 filter_store_populate();
1112 g_idle_add((GSourceFunc)filter_default_ok_scroll, gd->data);
1115 static void dummy_cancel_cb(GenericDialog *gd, gpointer data)
1117 /* no op, only so cancel button appears */
1120 static void filter_default_cb(GtkWidget *widget, gpointer data)
1124 gd = generic_dialog_new(_("Reset filters"),
1125 "reset_filter", widget, TRUE,
1126 dummy_cancel_cb, data);
1127 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset filters"),
1128 _("This will reset the file filters to the defaults.\nContinue?"), TRUE);
1129 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, filter_default_ok_cb, TRUE);
1130 gtk_widget_show(gd->dialog);
1133 static void filter_disable_cb(GtkWidget *widget, gpointer data)
1135 GtkWidget *frame = data;
1137 gtk_widget_set_sensitive(frame,
1138 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
1141 static void safe_delete_view_cb(GtkWidget *widget, gpointer data)
1143 layout_set_path(NULL, gtk_entry_get_text(GTK_ENTRY(safe_delete_path_entry)));
1146 static void safe_delete_clear_ok_cb(GenericDialog *gd, gpointer data)
1148 file_util_trash_clear();
1151 static void safe_delete_clear_cb(GtkWidget *widget, gpointer data)
1155 gd = generic_dialog_new(_("Clear trash"),
1156 "clear_trash", widget, TRUE,
1157 dummy_cancel_cb, NULL);
1158 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear trash"),
1159 _("This will remove the trash contents."), FALSE);
1160 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, safe_delete_clear_ok_cb, TRUE);
1161 entry = gtk_entry_new();
1162 gtk_widget_set_can_focus(entry, FALSE);
1163 gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE);
1164 if (options->file_ops.safe_delete_path) gtk_entry_set_text(GTK_ENTRY(entry), options->file_ops.safe_delete_path);
1165 gtk_box_pack_start(GTK_BOX(gd->vbox), entry, FALSE, FALSE, 0);
1166 gtk_widget_show(entry);
1167 gtk_widget_show(gd->dialog);
1170 static void image_overlay_template_view_changed_cb(GtkWidget *widget, gpointer data)
1172 GtkWidget *pTextView;
1173 GtkTextBuffer *pTextBuffer;
1177 pTextView = GTK_WIDGET(data);
1179 pTextBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pTextView));
1180 gtk_text_buffer_get_start_iter(pTextBuffer, &iStart);
1181 gtk_text_buffer_get_end_iter(pTextBuffer, &iEnd);
1183 set_image_overlay_template_string(&c_options->image_overlay.template_string,
1184 gtk_text_buffer_get_text(pTextBuffer, &iStart, &iEnd, TRUE));
1187 static void image_overlay_default_template_ok_cb(GenericDialog *gd, gpointer data)
1189 GtkTextView *text_view = data;
1190 GtkTextBuffer *buffer;
1192 set_default_image_overlay_template_string(&options->image_overlay.template_string);
1193 if (!configwindow) return;
1195 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
1196 gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1199 static void image_overlay_default_template_cb(GtkWidget *widget, gpointer data)
1203 gd = generic_dialog_new(_("Reset image overlay template string"),
1204 "reset_image_overlay_template_string", widget, TRUE,
1205 dummy_cancel_cb, data);
1206 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset image overlay template string"),
1207 _("This will reset the image overlay template string to the default.\nContinue?"), TRUE);
1208 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, image_overlay_default_template_ok_cb, TRUE);
1209 gtk_widget_show(gd->dialog);
1212 static void image_overlay_help_cb(GtkWidget *widget, gpointer data)
1214 help_window_show("GuideOptionsWindow.html#OverlayScreenDisplay");
1217 static void image_overlay_set_font_cb(GtkWidget *widget, gpointer data)
1219 #if GTK_CHECK_VERSION(3,4,0)
1222 PangoFontDescription *font_desc;
1224 dialog = gtk_font_chooser_dialog_new("Image Overlay Font", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1225 gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), options->image_overlay.font);
1227 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1229 font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
1230 font = pango_font_description_to_string(font_desc);
1231 g_free(c_options->image_overlay.font);
1232 c_options->image_overlay.font = g_strdup(font);
1236 gtk_widget_destroy(dialog);
1240 font = gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget));
1241 c_options->image_overlay.font = g_strdup(font);
1245 static void image_overlay_set_text_colour_cb(GtkWidget *widget, gpointer data)
1248 #if GTK_CHECK_VERSION(3,4,0)
1251 dialog = gtk_color_chooser_dialog_new("Image Overlay Text Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1252 colour.red = options->image_overlay.text_red;
1253 colour.green = options->image_overlay.text_green;
1254 colour.blue = options->image_overlay.text_blue;
1255 colour.alpha = options->image_overlay.text_alpha;
1256 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1257 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1259 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1261 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1262 c_options->image_overlay.text_red = colour.red*255;
1263 c_options->image_overlay.text_green = colour.green*255;
1264 c_options->image_overlay.text_blue = colour.blue*255;
1265 c_options->image_overlay.text_alpha = colour.alpha*255;
1267 gtk_widget_destroy(dialog);
1270 GtkColorSelection *colorsel;
1272 dialog = gtk_color_selection_dialog_new("Image Overlay Text Colour");
1273 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1274 colour.red = options->image_overlay.text_red*257;
1275 colour.green = options->image_overlay.text_green*257;
1276 colour.blue = options->image_overlay.text_blue*257;
1277 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1278 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1279 gtk_color_selection_set_current_color(colorsel, &colour);
1280 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.text_alpha*257);
1282 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1284 gtk_color_selection_get_current_color(colorsel, &colour);
1285 c_options->image_overlay.text_red = colour.red/257;
1286 c_options->image_overlay.text_green = colour.green/257;
1287 c_options->image_overlay.text_blue = colour.blue/257;
1288 c_options->image_overlay.text_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1290 gtk_widget_destroy (dialog);
1295 static void image_overlay_set_background_colour_cb(GtkWidget *widget, gpointer data)
1298 #if GTK_CHECK_VERSION(3,4,0)
1301 dialog = gtk_color_chooser_dialog_new("Image Overlay Background Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1302 colour.red = options->image_overlay.background_red;
1303 colour.green = options->image_overlay.background_green;
1304 colour.blue = options->image_overlay.background_blue;
1305 colour.alpha = options->image_overlay.background_alpha;
1306 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1307 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1309 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1311 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1312 c_options->image_overlay.background_red = colour.red*255;
1313 c_options->image_overlay.background_green = colour.green*255;
1314 c_options->image_overlay.background_blue = colour.blue*255;
1315 c_options->image_overlay.background_alpha = colour.alpha*255;
1317 gtk_widget_destroy(dialog);
1320 GtkColorSelection *colorsel;
1322 dialog = gtk_color_selection_dialog_new("Image Overlay Background Colour");
1323 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1324 colour.red = options->image_overlay.background_red*257;
1325 colour.green = options->image_overlay.background_green*257;
1326 colour.blue = options->image_overlay.background_blue*257;
1327 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1328 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1329 gtk_color_selection_set_current_color(colorsel, &colour);
1330 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.background_alpha*257);
1332 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1334 gtk_color_selection_get_current_color(colorsel, &colour);
1335 c_options->image_overlay.background_red = colour.red/257;
1336 c_options->image_overlay.background_green = colour.green/257;
1337 c_options->image_overlay.background_blue = colour.blue/257;
1338 c_options->image_overlay.background_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1340 gtk_widget_destroy(dialog);
1344 static void accel_store_populate(void)
1347 GList *groups, *actions;
1349 const gchar *accel_path;
1353 if (!accel_store || !layout_window_list || !layout_window_list->data) return;
1355 gtk_tree_store_clear(accel_store);
1356 lw = layout_window_list->data; /* get the actions from the first window, it should not matter, they should be the same in all windows */
1358 g_assert(lw && lw->ui_manager);
1359 groups = gtk_ui_manager_get_action_groups(lw->ui_manager);
1362 actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
1365 action = GTK_ACTION(actions->data);
1366 accel_path = gtk_action_get_accel_path(action);
1367 if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
1369 gchar *label, *label2, *tooltip, *accel;
1370 g_object_get(action,
1371 "tooltip", &tooltip,
1375 if (pango_parse_markup(label, -1, '_', NULL, &label2, NULL, NULL) && label2)
1381 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1385 gtk_tree_store_append(accel_store, &iter, NULL);
1386 gtk_tree_store_set(accel_store, &iter,
1389 AE_TOOLTIP, tooltip ? tooltip : "",
1390 AE_ACCEL, accel_path,
1398 actions = actions->next;
1401 groups = groups->next;
1405 static void accel_store_cleared_cb(GtkCellRendererAccel *accel, gchar *path_string, gpointer user_data)
1410 static gboolean accel_remove_key_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1412 gchar *accel1 = data;
1417 gtk_tree_model_get(model, iter, AE_KEY, &accel2, -1);
1419 gtk_accelerator_parse(accel1, &key1.accel_key, &key1.accel_mods);
1420 gtk_accelerator_parse(accel2, &key2.accel_key, &key2.accel_mods);
1422 if (key1.accel_key == key2.accel_key && key1.accel_mods == key2.accel_mods)
1424 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1425 DEBUG_1("accelerator key '%s' is already used, removing.", accel1);
1434 static void accel_store_edited_cb(GtkCellRendererAccel *accel, gchar *path_string, guint accel_key, GdkModifierType accel_mods, guint hardware_keycode, gpointer user_data)
1436 GtkTreeModel *model = (GtkTreeModel *)accel_store;
1440 GtkAccelKey old_key, key;
1441 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
1443 gtk_tree_model_get_iter(model, &iter, path);
1444 gtk_tree_model_get(model, &iter, AE_ACCEL, &accel_path, -1);
1446 /* test if the accelerator can be stored without conflicts*/
1447 gtk_accel_map_lookup_entry(accel_path, &old_key);
1449 /* change the key and read it back (change may fail on keys hardcoded in gtk)*/
1450 gtk_accel_map_change_entry(accel_path, accel_key, accel_mods, TRUE);
1451 gtk_accel_map_lookup_entry(accel_path, &key);
1453 /* restore the original for now, the key will be really changed when the changes are confirmed */
1454 gtk_accel_map_change_entry(accel_path, old_key.accel_key, old_key.accel_mods, TRUE);
1456 acc = gtk_accelerator_name(key.accel_key, key.accel_mods);
1457 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, acc);
1459 gtk_tree_store_set(accel_store, &iter, AE_KEY, acc, -1);
1460 gtk_tree_path_free(path);
1464 static gboolean accel_default_scroll(GtkTreeView *data)
1468 GtkTreeViewColumn *column;
1470 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(accel_store), &iter);
1471 path = gtk_tree_model_get_path(GTK_TREE_MODEL(accel_store), &iter);
1472 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1474 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1478 gtk_tree_path_free(path);
1483 static void accel_default_cb(GtkWidget *widget, gpointer data)
1485 accel_store_populate();
1487 g_idle_add((GSourceFunc)accel_default_scroll, data);
1490 void accel_remove_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1492 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1495 void accel_reset_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1498 gchar *accel_path, *accel;
1500 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, -1);
1501 gtk_accel_map_lookup_entry(accel_path, &key);
1502 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1504 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, accel);
1506 gtk_tree_store_set(accel_store, iter, AE_KEY, accel, -1);
1511 static void accel_reset_cb(GtkWidget *widget, gpointer data)
1513 GtkTreeSelection *selection;
1515 if (!accel_store) return;
1516 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data));
1517 gtk_tree_selection_selected_foreach(selection, &accel_reset_selection, NULL);
1522 static GtkWidget *scrolled_notebook_page(GtkWidget *notebook, const gchar *title)
1526 GtkWidget *scrolled;
1527 GtkWidget *viewport;
1529 scrolled = gtk_scrolled_window_new(NULL, NULL);
1530 gtk_container_set_border_width(GTK_CONTAINER(scrolled), PREF_PAD_BORDER);
1531 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1532 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1533 label = gtk_label_new(title);
1534 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, label);
1535 gtk_widget_show(scrolled);
1537 viewport = gtk_viewport_new(NULL, NULL);
1538 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1539 gtk_container_add(GTK_CONTAINER(scrolled), viewport);
1540 gtk_widget_show(viewport);
1542 vbox = gtk_vbox_new(FALSE, 0);
1543 gtk_container_add(GTK_CONTAINER(viewport), vbox);
1544 gtk_widget_show(vbox);
1549 static void cache_standard_cb(GtkWidget *widget, gpointer data)
1551 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1553 c_options->thumbnails.spec_standard =TRUE;
1554 c_options->thumbnails.cache_into_dirs = FALSE;
1558 c_options->thumbnails.spec_standard =FALSE;
1562 static void cache_geeqie_cb(GtkWidget *widget, gpointer data)
1564 if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1566 c_options->thumbnails.spec_standard =TRUE;
1567 c_options->thumbnails.cache_into_dirs = FALSE;
1571 c_options->thumbnails.spec_standard =FALSE;
1575 static void cache_local_cb(GtkWidget *widget, gpointer data)
1577 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1579 c_options->thumbnails.cache_into_dirs = TRUE;
1580 c_options->thumbnails.spec_standard =FALSE;
1584 c_options->thumbnails.cache_into_dirs = FALSE;
1588 static void help_search_engine_entry_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1589 GdkEvent *event, gpointer userdata)
1591 if (pos == GTK_ENTRY_ICON_PRIMARY)
1593 gtk_entry_set_text(GTK_ENTRY(userdata), HELP_SEARCH_ENGINE);
1597 gtk_entry_set_text(GTK_ENTRY(userdata), "");
1601 /* general options tab */
1602 static void config_tab_general(GtkWidget *notebook)
1607 GtkWidget *group_frame;
1608 GtkWidget *subgroup;
1610 GtkWidget *ct_button;
1613 gint hours, minutes, remainder;
1616 vbox = scrolled_notebook_page(notebook, _("General"));
1618 group = pref_group_new(vbox, FALSE, _("Thumbnails"), GTK_ORIENTATION_VERTICAL);
1620 table = pref_table_new(group, 2, 2, FALSE, FALSE);
1621 add_thumb_size_menu(table, 0, 0, _("Size:"));
1622 add_quality_menu(table, 0, 1, _("Quality:"), options->thumbnails.quality, &c_options->thumbnails.quality);
1624 ct_button = pref_checkbox_new_int(group, _("Cache thumbnails"),
1625 options->thumbnails.enable_caching, &c_options->thumbnails.enable_caching);
1627 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1628 pref_checkbox_link_sensitivity(ct_button, subgroup);
1630 group_frame = pref_frame_new(subgroup, TRUE, _("Use Geeqie thumbnail style and cache"),
1631 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1632 button = pref_radiobutton_new(group_frame, NULL, get_thumbnails_cache_dir(),
1633 !options->thumbnails.spec_standard,
1634 G_CALLBACK(cache_geeqie_cb), NULL);
1636 group_frame = pref_frame_new(subgroup, TRUE,
1637 _("Store thumbnails local to image folder (non-standard)"),
1638 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1639 pref_radiobutton_new(group_frame, button, "*/.thumbnails",
1640 options->thumbnails.cache_into_dirs,
1641 G_CALLBACK(cache_local_cb), NULL);
1643 group_frame = pref_frame_new(subgroup, TRUE,
1644 _("Use standard thumbnail style and cache, shared with other applications"),
1645 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1646 pref_radiobutton_new(group_frame, button, get_thumbnails_standard_cache_dir(),
1647 options->thumbnails.spec_standard,
1648 G_CALLBACK(cache_standard_cb), NULL);
1650 pref_checkbox_new_int(group, _("Use EXIF thumbnails when available (EXIF thumbnails may be outdated)"),
1651 options->thumbnails.use_exif, &c_options->thumbnails.use_exif);
1653 #ifdef HAVE_FFMPEGTHUMBNAILER_METADATA
1654 pref_checkbox_new_int(group, _("Use embedded metadata in video files as thumbnails when available"),
1655 options->thumbnails.use_ft_metadata, &c_options->thumbnails.use_ft_metadata);
1657 // pref_checkbox_new_int(group, _("Ignore embedded metadata if size is too small"),
1658 // options->thumbnails.use_ft_metadata_small, &c_options->thumbnails.use_ft_metadata_small);
1661 group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
1663 c_options->slideshow.delay = options->slideshow.delay;
1664 hours = options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
1665 remainder = options->slideshow.delay % (3600 * SLIDESHOW_SUBSECOND_PRECISION);
1666 minutes = remainder / (60 * SLIDESHOW_SUBSECOND_PRECISION);
1667 seconds = (gdouble)(remainder % (60 * SLIDESHOW_SUBSECOND_PRECISION)) /
1668 SLIDESHOW_SUBSECOND_PRECISION;
1670 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1672 spin = pref_spin_new(hbox, _("Delay between image change hrs:mins:secs.dec"), NULL,
1674 options->slideshow.delay ? hours : 0.0,
1675 G_CALLBACK(slideshow_delay_hours_cb), NULL);
1676 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1677 spin = pref_spin_new(hbox, ":" , NULL,
1679 options->slideshow.delay ? minutes: 0.0,
1680 G_CALLBACK(slideshow_delay_minutes_cb), NULL);
1681 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1682 spin = pref_spin_new(hbox, ":", NULL,
1683 SLIDESHOW_MIN_SECONDS, 59, 1.0, 1,
1684 options->slideshow.delay ? seconds : 10.0,
1685 G_CALLBACK(slideshow_delay_seconds_cb), NULL);
1686 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1688 pref_checkbox_new_int(group, _("Random"), options->slideshow.random, &c_options->slideshow.random);
1689 pref_checkbox_new_int(group, _("Repeat"), options->slideshow.repeat, &c_options->slideshow.repeat);
1691 group = pref_group_new(vbox, FALSE, _("Image loading and caching"), GTK_ORIENTATION_VERTICAL);
1693 pref_spin_new_int(group, _("Decoded image cache size (Mb):"), NULL,
1694 0, 99999, 1, options->image.image_cache_max, &c_options->image.image_cache_max);
1695 pref_checkbox_new_int(group, _("Preload next image"),
1696 options->image.enable_read_ahead, &c_options->image.enable_read_ahead);
1698 pref_checkbox_new_int(group, _("Refresh on file change"),
1699 options->update_on_time_change, &c_options->update_on_time_change);
1701 group = pref_group_new(vbox, FALSE, _("Info sidebar heights"), GTK_ORIENTATION_VERTICAL);
1702 pref_label_new(group, _("NOTE! Geeqie must be restarted for changes to take effect"));
1703 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1704 pref_spin_new_int(hbox, _("Keywords:"), NULL,
1706 options->info_keywords.height, &c_options->info_keywords.height);
1707 pref_spin_new_int(hbox, _("Title:"), NULL,
1709 options->info_title.height, &c_options->info_title.height);
1710 pref_spin_new_int(hbox, _("Comment:"), NULL,
1712 options->info_comment.height, &c_options->info_comment.height);
1713 pref_spin_new_int(hbox, _("Rating:"), NULL,
1715 options->info_rating.height, &c_options->info_rating.height);
1717 group = pref_group_new(vbox, FALSE, _("On-line help search engine"), GTK_ORIENTATION_VERTICAL);
1719 help_search_engine_entry = gtk_entry_new();
1720 gtk_entry_set_text(GTK_ENTRY(help_search_engine_entry), options->help_search_engine);
1721 gtk_box_pack_start(GTK_BOX(group), help_search_engine_entry, FALSE, FALSE, 0);
1722 gtk_widget_show(help_search_engine_entry);
1724 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"));
1726 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
1727 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
1728 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
1729 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
1730 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
1731 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
1732 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
1733 GTK_ENTRY_ICON_PRIMARY, _("Default"));
1734 g_signal_connect(GTK_ENTRY(help_search_engine_entry), "icon-press",
1735 G_CALLBACK(help_search_engine_entry_icon_cb),
1736 help_search_engine_entry);
1740 static void config_tab_image(GtkWidget *notebook)
1745 GtkWidget *ct_button;
1746 GtkWidget *enlargement_button;
1750 vbox = scrolled_notebook_page(notebook, _("Image"));
1752 group = pref_group_new(vbox, FALSE, _("Zoom"), GTK_ORIENTATION_VERTICAL);
1754 table = pref_table_new(group, 2, 1, FALSE, FALSE);
1755 add_quality_menu(table, 0, 0, _("Quality:"), options->image.zoom_quality, &c_options->image.zoom_quality);
1758 pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library"),
1759 options->image.use_clutter_renderer, &c_options->image.use_clutter_renderer);
1762 pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"),
1763 options->image.zoom_2pass, &c_options->image.zoom_2pass);
1765 c_options->image.zoom_increment = options->image.zoom_increment;
1766 spin = pref_spin_new(group, _("Zoom increment:"), NULL,
1767 0.01, 4.0, 0.01, 2, (gdouble)options->image.zoom_increment / 100.0,
1768 G_CALLBACK(zoom_increment_cb), NULL);
1769 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1771 group = pref_group_new(vbox, FALSE, _("Fit image to window"), GTK_ORIENTATION_VERTICAL);
1773 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1774 enlargement_button = pref_checkbox_new_int(hbox, _("Allow enlargement of image (max. size in %)"),
1775 options->image.zoom_to_fit_allow_expand, &c_options->image.zoom_to_fit_allow_expand);
1776 spin = pref_spin_new_int(hbox, NULL, NULL,
1778 options->image.max_enlargement_size, &c_options->image.max_enlargement_size);
1779 pref_checkbox_link_sensitivity(enlargement_button, spin);
1780 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."));
1782 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1783 ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (% of actual window):"),
1784 options->image.limit_autofit_size, &c_options->image.limit_autofit_size);
1785 spin = pref_spin_new_int(hbox, NULL, NULL,
1787 options->image.max_autofit_size, &c_options->image.max_autofit_size);
1788 pref_checkbox_link_sensitivity(ct_button, spin);
1789 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."));
1791 group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
1793 pref_checkbox_new_int(group, _("Use custom border color in window mode"),
1794 options->image.use_custom_border_color, &c_options->image.use_custom_border_color);
1796 pref_checkbox_new_int(group, _("Use custom border color in fullscreen mode"),
1797 options->image.use_custom_border_color_in_fullscreen, &c_options->image.use_custom_border_color_in_fullscreen);
1799 pref_color_button_new(group, _("Border color"), &options->image.border_color,
1800 G_CALLBACK(pref_color_button_set_cb), &c_options->image.border_color);
1802 c_options->image.border_color = options->image.border_color;
1804 pref_color_button_new(group, _("Alpha channel color 1"), &options->image.alpha_color_1,
1805 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_1);
1807 pref_color_button_new(group, _("Alpha channel color 2"), &options->image.alpha_color_2,
1808 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_2);
1810 c_options->image.alpha_color_1 = options->image.alpha_color_1;
1811 c_options->image.alpha_color_2 = options->image.alpha_color_2;
1813 group = pref_group_new(vbox, FALSE, _("Convenience"), GTK_ORIENTATION_VERTICAL);
1815 pref_checkbox_new_int(group, _("Auto rotate proofs using Exif information"),
1816 options->image.exif_proof_rotate_enable, &c_options->image.exif_proof_rotate_enable);
1820 static void config_tab_windows(GtkWidget *notebook)
1826 GtkWidget *ct_button;
1828 GtkWidget *image_overlay_template_view;
1829 GtkWidget *scrolled;
1830 GtkTextBuffer *buffer;
1832 vbox = scrolled_notebook_page(notebook, _("Windows"));
1834 group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
1836 ct_button = pref_checkbox_new_int(group, _("Remember window positions"),
1837 options->save_window_positions, &c_options->save_window_positions);
1839 button = pref_checkbox_new_int(group, _("Use saved window positions also for new windows"),
1840 options->use_saved_window_positions_for_new_windows, &c_options->use_saved_window_positions_for_new_windows);
1841 pref_checkbox_link_sensitivity(ct_button, button);
1843 pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
1844 options->tools_restore_state, &c_options->tools_restore_state);
1846 pref_checkbox_new_int(group, _("Remember dialog window positions"),
1847 options->save_dialog_window_positions, &c_options->save_dialog_window_positions);
1849 pref_checkbox_new_int(group, _("Show window IDs"),
1850 options->show_window_ids, &c_options->show_window_ids);
1852 group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
1854 pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
1855 options->image.fit_window_to_image, &c_options->image.fit_window_to_image);
1857 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1858 ct_button = pref_checkbox_new_int(hbox, _("Limit size when auto-sizing window (%):"),
1859 options->image.limit_window_size, &c_options->image.limit_window_size);
1860 spin = pref_spin_new_int(hbox, NULL, NULL,
1862 options->image.max_window_size, &c_options->image.max_window_size);
1863 pref_checkbox_link_sensitivity(ct_button, spin);
1865 group = pref_group_new(vbox, FALSE, _("Full screen"), GTK_ORIENTATION_VERTICAL);
1867 c_options->fullscreen.screen = options->fullscreen.screen;
1868 c_options->fullscreen.above = options->fullscreen.above;
1869 hbox = fullscreen_prefs_selection_new(_("Location:"), &c_options->fullscreen.screen, &c_options->fullscreen.above);
1870 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
1871 gtk_widget_show(hbox);
1873 pref_checkbox_new_int(group, _("Smooth image flip"),
1874 options->fullscreen.clean_flip, &c_options->fullscreen.clean_flip);
1875 pref_checkbox_new_int(group, _("Disable screen saver"),
1876 options->fullscreen.disable_saver, &c_options->fullscreen.disable_saver);
1879 group = pref_group_new(vbox, FALSE, _("Overlay Screen Display"), GTK_ORIENTATION_VERTICAL);
1881 pref_label_new(group, _("Image overlay template"));
1883 scrolled = gtk_scrolled_window_new(NULL, NULL);
1884 gtk_widget_set_size_request(scrolled, 200, 150);
1885 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
1886 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1887 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1888 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 5);
1889 gtk_widget_show(scrolled);
1891 image_overlay_template_view = gtk_text_view_new();
1893 gtk_widget_set_tooltip_markup(image_overlay_template_view,
1894 _("<i>%name%</i> results in the filename of the picture.\n"
1895 "Also available: <i>%collection%</i>, <i>%number%</i>, <i>%total%</i>, <i>%date%</i>,\n"
1896 "<i>%size%</i> (filesize), <i>%width%</i>, <i>%height%</i>, <i>%res%</i> (resolution),\n"
1897 "<i>%rating%</i>, <i>%keywords%</i>, <i>%comment%</i> (XMP), <i>%imagecomment%</i> (JPEG)\n"
1898 "To access exif data use the exif name, e. g. <i>%formatted.Camera%</i> is the formatted camera name,\n"
1899 "<i>%Exif.Photo.DateTimeOriginal%</i> the date of the original shot.\n"
1900 "<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"
1901 "If two or more variables are connected with the |-sign, it prints available variables with a separator.\n"
1902 "<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"
1903 "if there's no ISO information in the Exif data.\n"
1904 "If a line is empty, it is removed. This allows one to add lines that totally disappear when no data is available.\n"
1906 gtk_container_add(GTK_CONTAINER(scrolled), image_overlay_template_view);
1907 gtk_widget_show(image_overlay_template_view);
1909 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
1911 #if GTK_CHECK_VERSION(3,4,0)
1912 button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
1913 G_CALLBACK(image_overlay_set_font_cb), notebook);
1915 button = gtk_font_button_new();
1916 gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Image Overlay Font");
1917 gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->image_overlay.font);
1918 g_signal_connect(G_OBJECT(button), "font-set",
1919 G_CALLBACK(image_overlay_set_font_cb),NULL);
1921 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1922 gtk_widget_show(button);
1924 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Text"), FALSE,
1925 G_CALLBACK(image_overlay_set_text_colour_cb), NULL);
1926 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1927 gtk_widget_show(button);
1929 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Background"), FALSE,
1930 G_CALLBACK(image_overlay_set_background_colour_cb), NULL);
1931 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1932 gtk_widget_show(button);
1933 image_overlay_set_text_colours();
1935 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
1936 G_CALLBACK(image_overlay_default_template_cb), image_overlay_template_view);
1937 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1938 gtk_widget_show(button);
1940 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
1941 G_CALLBACK(image_overlay_help_cb), NULL);
1942 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1943 gtk_widget_show(button);
1945 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_overlay_template_view));
1946 if (options->image_overlay.template_string) gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1947 g_signal_connect(G_OBJECT(buffer), "changed",
1948 G_CALLBACK(image_overlay_template_view_changed_cb), image_overlay_template_view);
1953 static GtkTreeModel *create_class_model(void)
1955 GtkListStore *model;
1959 /* create list store */
1960 model = gtk_list_store_new(1, G_TYPE_STRING);
1961 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
1963 gtk_list_store_append(model, &iter);
1964 gtk_list_store_set(model, &iter, 0, _(format_class_list[i]), -1);
1966 return GTK_TREE_MODEL (model);
1971 static void config_tab_files(GtkWidget *notebook)
1978 GtkWidget *ct_button;
1979 GtkWidget *scrolled;
1980 GtkWidget *filter_view;
1981 GtkCellRenderer *renderer;
1982 GtkTreeSelection *selection;
1983 GtkTreeViewColumn *column;
1985 vbox = scrolled_notebook_page(notebook, _("Files"));
1987 group = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1989 pref_checkbox_new_int(group, _("Show hidden files or folders"),
1990 options->file_filter.show_hidden_files, &c_options->file_filter.show_hidden_files);
1991 pref_checkbox_new_int(group, _("Show parent folder (..)"),
1992 options->file_filter.show_parent_directory, &c_options->file_filter.show_parent_directory);
1993 pref_checkbox_new_int(group, _("Case sensitive sort"),
1994 options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
1995 pref_checkbox_new_int(group, _("Natural sort order"),
1996 options->file_sort.natural, &c_options->file_sort.natural);
1997 pref_checkbox_new_int(group, _("Disable file extension checks"),
1998 options->file_filter.disable_file_extension_checks, &c_options->file_filter.disable_file_extension_checks);
2000 ct_button = pref_checkbox_new_int(group, _("Disable File Filtering"),
2001 options->file_filter.disable, &c_options->file_filter.disable);
2004 group = pref_group_new(vbox, FALSE, _("Grouping sidecar extensions"), GTK_ORIENTATION_VERTICAL);
2006 sidecar_ext_entry = gtk_entry_new();
2007 gtk_entry_set_text(GTK_ENTRY(sidecar_ext_entry), options->sidecar.ext);
2008 gtk_box_pack_start(GTK_BOX(group), sidecar_ext_entry, FALSE, FALSE, 0);
2009 gtk_widget_show(sidecar_ext_entry);
2011 group = pref_group_new(vbox, TRUE, _("File types"), GTK_ORIENTATION_VERTICAL);
2013 frame = pref_group_parent(group);
2014 g_signal_connect(G_OBJECT(ct_button), "toggled",
2015 G_CALLBACK(filter_disable_cb), frame);
2016 gtk_widget_set_sensitive(frame, !options->file_filter.disable);
2018 scrolled = gtk_scrolled_window_new(NULL, NULL);
2019 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2020 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2021 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2022 gtk_widget_show(scrolled);
2024 filter_store = gtk_list_store_new(1, G_TYPE_POINTER);
2025 filter_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(filter_store));
2026 g_object_unref(filter_store);
2027 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
2028 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
2030 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), FALSE);
2032 column = gtk_tree_view_column_new();
2033 gtk_tree_view_column_set_title(column, _("Filter"));
2034 gtk_tree_view_column_set_resizable(column, TRUE);
2036 renderer = gtk_cell_renderer_toggle_new();
2037 g_signal_connect(G_OBJECT(renderer), "toggled",
2038 G_CALLBACK(filter_store_enable_cb), filter_store);
2039 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2040 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2041 GINT_TO_POINTER(FE_ENABLE), NULL);
2043 renderer = gtk_cell_renderer_text_new();
2044 g_signal_connect(G_OBJECT(renderer), "edited",
2045 G_CALLBACK(filter_store_ext_edit_cb), filter_store);
2046 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2047 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2048 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2049 GINT_TO_POINTER(FE_EXTENSION), NULL);
2050 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2052 column = gtk_tree_view_column_new();
2053 gtk_tree_view_column_set_title(column, _("Description"));
2054 gtk_tree_view_column_set_resizable(column, TRUE);
2055 gtk_tree_view_column_set_fixed_width(column, 200);
2056 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
2058 renderer = gtk_cell_renderer_text_new();
2059 g_signal_connect(G_OBJECT(renderer), "edited",
2060 G_CALLBACK(filter_store_desc_edit_cb), filter_store);
2061 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2062 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2063 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2064 GINT_TO_POINTER(FE_DESCRIPTION), NULL);
2065 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2067 column = gtk_tree_view_column_new();
2068 gtk_tree_view_column_set_title(column, _("Class"));
2069 gtk_tree_view_column_set_resizable(column, TRUE);
2070 renderer = gtk_cell_renderer_combo_new();
2071 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE,
2072 "model", create_class_model(),
2077 g_signal_connect(G_OBJECT(renderer), "edited",
2078 G_CALLBACK(filter_store_class_edit_cb), filter_store);
2079 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2080 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2081 GINT_TO_POINTER(FE_CLASS), NULL);
2082 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2084 column = gtk_tree_view_column_new();
2085 gtk_tree_view_column_set_title(column, _("Writable"));
2086 gtk_tree_view_column_set_resizable(column, FALSE);
2087 renderer = gtk_cell_renderer_toggle_new();
2088 g_signal_connect(G_OBJECT(renderer), "toggled",
2089 G_CALLBACK(filter_store_writable_cb), filter_store);
2090 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2091 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2092 GINT_TO_POINTER(FE_WRITABLE), NULL);
2093 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2095 column = gtk_tree_view_column_new();
2096 gtk_tree_view_column_set_title(column, _("Sidecar is allowed"));
2097 gtk_tree_view_column_set_resizable(column, FALSE);
2098 renderer = gtk_cell_renderer_toggle_new();
2099 g_signal_connect(G_OBJECT(renderer), "toggled",
2100 G_CALLBACK(filter_store_sidecar_cb), filter_store);
2101 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2102 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2103 GINT_TO_POINTER(FE_ALLOW_SIDECAR), NULL);
2104 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2107 filter_store_populate();
2108 gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
2109 gtk_widget_show(filter_view);
2111 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2113 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2114 G_CALLBACK(filter_default_cb), filter_view);
2115 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2116 gtk_widget_show(button);
2118 button = pref_button_new(NULL, GTK_STOCK_REMOVE, NULL, FALSE,
2119 G_CALLBACK(filter_remove_cb), filter_view);
2120 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2121 gtk_widget_show(button);
2123 button = pref_button_new(NULL, GTK_STOCK_ADD, NULL, FALSE,
2124 G_CALLBACK(filter_add_cb), filter_view);
2125 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2126 gtk_widget_show(button);
2130 static void config_tab_metadata(GtkWidget *notebook)
2135 GtkWidget *ct_button;
2139 vbox = scrolled_notebook_page(notebook, _("Metadata"));
2142 group = pref_group_new(vbox, FALSE, _("Metadata writing process"), GTK_ORIENTATION_VERTICAL);
2144 label = pref_label_new(group, _("Warning: Geeqie is built without Exiv2. Some options are disabled."));
2146 label = pref_label_new(group, _("Metadata are written in the following order. The process ends after first success."));
2147 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2149 ct_button = pref_checkbox_new_int(group, _("1) Save metadata in image files, or sidecar files, according to the XMP standard"),
2150 options->metadata.save_in_image_file, &c_options->metadata.save_in_image_file);
2152 gtk_widget_set_sensitive(ct_button, FALSE);
2155 pref_checkbox_new_int(group, _("2) Save metadata in '.metadata' folder, local to image folder (non-standard)"),
2156 options->metadata.enable_metadata_dirs, &c_options->metadata.enable_metadata_dirs);
2158 text = g_strdup_printf(_("3) Save metadata in Geeqie private directory '%s'"), get_metadata_cache_dir());
2159 label = pref_label_new(group, text);
2160 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2161 gtk_misc_set_padding(GTK_MISC(label), 22, 0);
2164 group = pref_group_new(vbox, FALSE, _("Step 1: Write to image files"), GTK_ORIENTATION_VERTICAL);
2166 gtk_widget_set_sensitive(group, FALSE);
2169 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2170 pref_checkbox_link_sensitivity(ct_button, hbox);
2172 pref_checkbox_new_int(hbox, _("Store metadata also in legacy IPTC tags (converted according to IPTC4XMP standard)"),
2173 options->metadata.save_legacy_IPTC, &c_options->metadata.save_legacy_IPTC);
2175 pref_checkbox_new_int(hbox, _("Warn if the image files are unwritable"),
2176 options->metadata.warn_on_write_problems, &c_options->metadata.warn_on_write_problems);
2178 pref_checkbox_new_int(hbox, _("Ask before writing to image files"),
2179 options->metadata.confirm_write, &c_options->metadata.confirm_write);
2181 pref_checkbox_new_int(hbox, _("Create sidecar files named image.ext.xmp (as opposed to image.xmp)"),
2182 options->metadata.sidecar_extended_name, &c_options->metadata.sidecar_extended_name);
2184 group = pref_group_new(vbox, FALSE, _("Step 2 and 3: write to Geeqie private files"), GTK_ORIENTATION_VERTICAL);
2186 gtk_widget_set_sensitive(group, FALSE);
2189 pref_checkbox_new_int(group, _("Use GQview legacy metadata format (supports only keywords and comments) instead of XMP"),
2190 options->metadata.save_legacy_format, &c_options->metadata.save_legacy_format);
2193 group = pref_group_new(vbox, FALSE, _("Miscellaneous"), GTK_ORIENTATION_VERTICAL);
2194 pref_checkbox_new_int(group, _("Write the same description tags (keywords, comment, etc.) to all grouped sidecars"),
2195 options->metadata.sync_grouped_files, &c_options->metadata.sync_grouped_files);
2197 pref_checkbox_new_int(group, _("Allow keywords to differ only in case"),
2198 options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
2200 ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"),
2201 options->metadata.write_orientation, &c_options->metadata.write_orientation);
2203 gtk_widget_set_sensitive(ct_button, FALSE);
2206 group = pref_group_new(vbox, FALSE, _("Auto-save options"), GTK_ORIENTATION_VERTICAL);
2208 ct_button = pref_checkbox_new_int(group, _("Write metadata after timeout"),
2209 options->metadata.confirm_after_timeout, &c_options->metadata.confirm_after_timeout);
2211 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2212 pref_checkbox_link_sensitivity(ct_button, hbox);
2214 pref_spin_new_int(hbox, _("Timeout (seconds):"), NULL, 0, 900, 1,
2215 options->metadata.confirm_timeout, &c_options->metadata.confirm_timeout);
2217 pref_checkbox_new_int(group, _("Write metadata on image change"),
2218 options->metadata.confirm_on_image_change, &c_options->metadata.confirm_on_image_change);
2220 pref_checkbox_new_int(group, _("Write metadata on directory change"),
2221 options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
2226 static void intent_menu_cb(GtkWidget *combo, gpointer data)
2228 gint *option = data;
2230 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
2234 *option = INTENT_PERCEPTUAL;
2237 *option = INTENT_RELATIVE_COLORIMETRIC;
2240 *option = INTENT_SATURATION;
2243 *option = INTENT_ABSOLUTE_COLORIMETRIC;
2248 static void add_intent_menu(GtkWidget *table, gint column, gint row, const gchar *text,
2249 gint option, gint *option_c)
2256 pref_table_label(table, column, row, text, 0.0);
2258 combo = gtk_combo_box_text_new();
2260 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Perceptual"));
2261 if (option == INTENT_PERCEPTUAL) current = 0;
2262 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Relative Colorimetric"));
2263 if (option == INTENT_RELATIVE_COLORIMETRIC) current = 1;
2264 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Saturation"));
2265 if (option == INTENT_SATURATION) current = 2;
2266 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Absolute Colorimetric"));
2267 if (option == INTENT_ABSOLUTE_COLORIMETRIC) current = 3;
2269 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
2271 gtk_widget_set_tooltip_text(combo,"Refer to the lcms documentation for the defaults used when the selected Intent is not available");
2273 g_signal_connect(G_OBJECT(combo), "changed",
2274 G_CALLBACK(intent_menu_cb), option_c);
2276 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
2277 GTK_EXPAND | GTK_FILL, 0, 0, 0);
2278 gtk_widget_show(combo);
2282 static void config_tab_color(GtkWidget *notebook)
2291 vbox = scrolled_notebook_page(notebook, _("Color management"));
2293 group = pref_group_new(vbox, FALSE, _("Input profiles"), GTK_ORIENTATION_VERTICAL);
2295 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
2298 table = pref_table_new(group, 3, COLOR_PROFILE_INPUTS + 1, FALSE, FALSE);
2299 gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
2301 label = pref_table_label(table, 0, 0, _("Type"), 0.0);
2302 pref_label_bold(label, TRUE, FALSE);
2304 label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
2305 pref_label_bold(label, TRUE, FALSE);
2307 label = pref_table_label(table, 2, 0, _("File"), 0.0);
2308 pref_label_bold(label, TRUE, FALSE);
2310 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
2315 buf = g_strdup_printf(_("Input %d:"), i + COLOR_PROFILE_FILE);
2316 pref_table_label(table, 0, i + 1, buf, 1.0);
2319 entry = gtk_entry_new();
2320 gtk_entry_set_max_length(GTK_ENTRY(entry), EDITOR_NAME_MAX_LENGTH);
2321 if (options->color_profile.input_name[i])
2323 gtk_entry_set_text(GTK_ENTRY(entry), options->color_profile.input_name[i]);
2325 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, i + 1, i + 2,
2326 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2327 gtk_widget_show(entry);
2328 color_profile_input_name_entry[i] = entry;
2330 tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, ".icc", "ICC Files", NULL);
2331 tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
2332 gtk_widget_set_size_request(entry, 160, -1);
2333 gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
2334 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2335 gtk_widget_show(tabcomp);
2336 color_profile_input_file_entry[i] = entry;
2339 group = pref_group_new(vbox, FALSE, _("Screen profile"), GTK_ORIENTATION_VERTICAL);
2341 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
2343 pref_checkbox_new_int(group, _("Use system screen profile if available"),
2344 options->color_profile.use_x11_screen_profile, &c_options->color_profile.use_x11_screen_profile);
2346 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2348 pref_table_label(table, 0, 0, _("Screen:"), 1.0);
2349 tabcomp = tab_completion_new(&color_profile_screen_file_entry,
2350 options->color_profile.screen_file, NULL, ".icc", "ICC Files", NULL);
2351 tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
2352 gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
2354 add_intent_menu(table, 0, 1, _("Render Intent:"), options->color_profile.render_intent, &c_options->color_profile.render_intent);
2356 gtk_table_attach(GTK_TABLE(table), tabcomp, 1, 2,
2358 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2360 gtk_widget_show(tabcomp);
2363 /* advanced entry tab */
2364 static void config_tab_behavior(GtkWidget *notebook)
2371 GtkWidget *ct_button;
2376 vbox = scrolled_notebook_page(notebook, _("Behavior"));
2378 group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
2380 pref_checkbox_new_int(group, _("Confirm file delete"),
2381 options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
2382 pref_checkbox_new_int(group, _("Enable Delete key"),
2383 options->file_ops.enable_delete_key, &c_options->file_ops.enable_delete_key);
2385 ct_button = pref_checkbox_new_int(group, _("Safe delete"),
2386 options->file_ops.safe_delete_enable, &c_options->file_ops.safe_delete_enable);
2388 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2389 pref_checkbox_link_sensitivity(ct_button, hbox);
2391 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
2392 pref_label_new(hbox, _("Folder:"));
2394 tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL, NULL, NULL);
2395 tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
2396 gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
2397 gtk_widget_show(tabcomp);
2399 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2400 pref_checkbox_link_sensitivity(ct_button, hbox);
2402 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
2403 spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MB"),
2404 0, 2048, 1, options->file_ops.safe_delete_folder_maxsize, &c_options->file_ops.safe_delete_folder_maxsize);
2405 gtk_widget_set_tooltip_markup(spin, _("Set to 0 for unlimited size"));
2406 button = pref_button_new(NULL, NULL, _("View"), FALSE,
2407 G_CALLBACK(safe_delete_view_cb), NULL);
2408 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2409 gtk_widget_show(button);
2411 button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
2412 G_CALLBACK(safe_delete_clear_cb), NULL);
2413 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2414 gtk_widget_show(button);
2417 group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
2419 pref_checkbox_new_int(group, _("Descend folders in tree view"),
2420 options->tree_descend_subdirs, &c_options->tree_descend_subdirs);
2422 pref_checkbox_new_int(group, _("In place renaming"),
2423 options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
2425 pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
2426 options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
2428 marks = pref_checkbox_new_int(group, _("Save marks on exit"),
2429 options->marks_save, &c_options->marks_save);
2430 gtk_widget_set_tooltip_text(marks,"Note that marks linked to a keyword will be saved irrespective of this setting");
2432 pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
2433 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
2435 pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
2436 16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
2438 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2439 add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
2441 group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
2443 pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
2444 options->progressive_key_scrolling, &c_options->progressive_key_scrolling);
2445 pref_spin_new_int(group, _("Keyboard scrolling step multiplier:"), NULL,
2446 1, 32, 1, options->keyboard_scroll_step, (int *)&c_options->keyboard_scroll_step);
2447 pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
2448 options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
2449 pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
2450 options->image_lm_click_nav, &c_options->image_lm_click_nav);
2451 pref_checkbox_new_int(group, _("Play video by left click on image"),
2452 options->image_l_click_video, &c_options->image_l_click_video);
2453 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2454 add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
2458 group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
2460 pref_spin_new_int(group, _("Debug level:"), NULL,
2461 DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
2463 pref_checkbox_new_int(group, _("Timer data"),
2464 options->log_window.timer_data, &c_options->log_window.timer_data);
2466 pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
2467 1, 99999, 1, options->log_window_lines, &options->log_window_lines);
2471 /* accelerators tab */
2472 static void config_tab_accelerators(GtkWidget *notebook)
2478 GtkWidget *scrolled;
2479 GtkWidget *accel_view;
2480 GtkCellRenderer *renderer;
2481 GtkTreeSelection *selection;
2482 GtkTreeViewColumn *column;
2484 vbox = scrolled_notebook_page(notebook, _("Keyboard"));
2486 group = pref_group_new(vbox, TRUE, _("Accelerators"), GTK_ORIENTATION_VERTICAL);
2488 scrolled = gtk_scrolled_window_new(NULL, NULL);
2489 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2490 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2491 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2492 gtk_widget_show(scrolled);
2494 accel_store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
2496 accel_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(accel_store));
2497 g_object_unref(accel_store);
2498 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(accel_view));
2499 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
2501 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(accel_view), FALSE);
2503 renderer = gtk_cell_renderer_text_new();
2505 column = gtk_tree_view_column_new_with_attributes(_("Action"),
2510 gtk_tree_view_column_set_sort_column_id(column, AE_ACTION);
2511 gtk_tree_view_column_set_resizable(column, TRUE);
2512 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
2515 renderer = gtk_cell_renderer_accel_new();
2516 g_signal_connect(G_OBJECT(renderer), "accel-cleared",
2517 G_CALLBACK(accel_store_cleared_cb), accel_store);
2518 g_signal_connect(G_OBJECT(renderer), "accel-edited",
2519 G_CALLBACK(accel_store_edited_cb), accel_store);
2522 g_object_set (renderer,
2524 "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
2527 column = gtk_tree_view_column_new_with_attributes(_("KEY"),
2532 gtk_tree_view_column_set_sort_column_id(column, AE_KEY);
2533 gtk_tree_view_column_set_resizable(column, TRUE);
2534 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
2536 renderer = gtk_cell_renderer_text_new();
2538 column = gtk_tree_view_column_new_with_attributes(_("Tooltip"),
2543 gtk_tree_view_column_set_sort_column_id(column, AE_TOOLTIP);
2544 gtk_tree_view_column_set_resizable(column, TRUE);
2545 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
2547 renderer = gtk_cell_renderer_text_new();
2549 column = gtk_tree_view_column_new_with_attributes("Accel",
2554 gtk_tree_view_column_set_sort_column_id(column, AE_ACCEL);
2555 gtk_tree_view_column_set_resizable(column, TRUE);
2556 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
2558 accel_store_populate();
2559 gtk_container_add(GTK_CONTAINER(scrolled), accel_view);
2560 gtk_widget_show(accel_view);
2562 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2564 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2565 G_CALLBACK(accel_default_cb), accel_view);
2566 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2567 gtk_widget_show(button);
2569 button = pref_button_new(NULL, NULL, _("Reset selected"), FALSE,
2570 G_CALLBACK(accel_reset_cb), accel_view);
2571 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2572 gtk_widget_show(button);
2576 static void config_tab_toolbar(GtkWidget *notebook)
2579 GtkWidget *toolbardata;
2582 lw = layout_window_list->data;
2584 vbox = scrolled_notebook_page(notebook, _("Toolbar"));
2586 toolbardata = toolbar_select_new(lw);
2587 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
2588 gtk_widget_show(vbox);
2592 static void config_tab_stereo(GtkWidget *notebook)
2600 GtkWidget *fs_button;
2601 vbox = scrolled_notebook_page(notebook, _("Stereo"));
2603 group = pref_group_new(vbox, FALSE, _("Windowed stereo mode"), GTK_ORIENTATION_VERTICAL);
2605 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2606 add_stereo_mode_menu(table, 0, 0, _("Windowed stereo mode"), options->stereo.mode, &c_options->stereo.mode, FALSE);
2608 table = pref_table_new(group, 2, 2, TRUE, FALSE);
2609 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
2610 pref_checkbox_new_int(box, _("Mirror left image"),
2611 options->stereo.mode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.mirror_left);
2612 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
2613 pref_checkbox_new_int(box, _("Flip left image"),
2614 options->stereo.mode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.flip_left);
2615 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
2616 pref_checkbox_new_int(box, _("Mirror right image"),
2617 options->stereo.mode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.mirror_right);
2618 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
2619 pref_checkbox_new_int(box, _("Flip right image"),
2620 options->stereo.mode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.flip_right);
2621 pref_checkbox_new_int(group, _("Swap left and right images"),
2622 options->stereo.mode & PR_STEREO_SWAP, &c_options->stereo.tmp.swap);
2623 pref_checkbox_new_int(group, _("Disable stereo mode on single image source"),
2624 options->stereo.mode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.temp_disable);
2626 group = pref_group_new(vbox, FALSE, _("Fullscreen stereo mode"), GTK_ORIENTATION_VERTICAL);
2627 fs_button = pref_checkbox_new_int(group, _("Use different settings for fullscreen"),
2628 options->stereo.enable_fsmode, &c_options->stereo.enable_fsmode);
2629 box2 = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2630 pref_checkbox_link_sensitivity(fs_button, box2);
2631 table = pref_table_new(box2, 2, 1, FALSE, FALSE);
2632 add_stereo_mode_menu(table, 0, 0, _("Fullscreen stereo mode"), options->stereo.fsmode, &c_options->stereo.fsmode, TRUE);
2633 table = pref_table_new(box2, 2, 2, TRUE, FALSE);
2634 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
2635 pref_checkbox_new_int(box, _("Mirror left image"),
2636 options->stereo.fsmode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.fs_mirror_left);
2637 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
2638 pref_checkbox_new_int(box, _("Flip left image"),
2639 options->stereo.fsmode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.fs_flip_left);
2640 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
2641 pref_checkbox_new_int(box, _("Mirror right image"),
2642 options->stereo.fsmode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.fs_mirror_right);
2643 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
2644 pref_checkbox_new_int(box, _("Flip right image"),
2645 options->stereo.fsmode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.fs_flip_right);
2646 pref_checkbox_new_int(box2, _("Swap left and right images"),
2647 options->stereo.fsmode & PR_STEREO_SWAP, &c_options->stereo.tmp.fs_swap);
2648 pref_checkbox_new_int(box2, _("Disable stereo mode on single image source"),
2649 options->stereo.fsmode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.fs_temp_disable);
2651 group2 = pref_group_new(box2, FALSE, _("Fixed position"), GTK_ORIENTATION_VERTICAL);
2652 table = pref_table_new(group2, 5, 3, FALSE, FALSE);
2653 pref_table_spin_new_int(table, 0, 0, _("Width"), NULL,
2654 1, 5000, 1, options->stereo.fixed_w, &c_options->stereo.fixed_w);
2655 pref_table_spin_new_int(table, 3, 0, _("Height"), NULL,
2656 1, 5000, 1, options->stereo.fixed_h, &c_options->stereo.fixed_h);
2657 pref_table_spin_new_int(table, 0, 1, _("Left X"), NULL,
2658 0, 5000, 1, options->stereo.fixed_x1, &c_options->stereo.fixed_x1);
2659 pref_table_spin_new_int(table, 3, 1, _("Left Y"), NULL,
2660 0, 5000, 1, options->stereo.fixed_y1, &c_options->stereo.fixed_y1);
2661 pref_table_spin_new_int(table, 0, 2, _("Right X"), NULL,
2662 0, 5000, 1, options->stereo.fixed_x2, &c_options->stereo.fixed_x2);
2663 pref_table_spin_new_int(table, 3, 2, _("Right Y"), NULL,
2664 0, 5000, 1, options->stereo.fixed_y2, &c_options->stereo.fixed_y2);
2668 /* Main preferences window */
2669 static void config_window_create(void)
2671 GtkWidget *win_vbox;
2673 GtkWidget *notebook;
2675 GtkWidget *ct_button;
2677 if (!c_options) c_options = init_options(NULL);
2679 configwindow = window_new(GTK_WINDOW_TOPLEVEL, "preferences", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Preferences"));
2680 gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
2681 g_signal_connect(G_OBJECT(configwindow), "delete_event",
2682 G_CALLBACK(config_window_delete), NULL);
2683 gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
2684 gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
2685 gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
2687 win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
2688 gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
2689 gtk_widget_show(win_vbox);
2691 notebook = gtk_notebook_new();
2692 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP);
2693 gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
2695 config_tab_general(notebook);
2696 config_tab_image(notebook);
2697 config_tab_windows(notebook);
2698 config_tab_accelerators(notebook);
2699 config_tab_files(notebook);
2700 config_tab_metadata(notebook);
2701 config_tab_color(notebook);
2702 config_tab_stereo(notebook);
2703 config_tab_behavior(notebook);
2704 config_tab_toolbar(notebook);
2706 hbox = gtk_hbutton_box_new();
2707 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
2708 gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
2709 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
2710 gtk_widget_show(hbox);
2712 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
2713 G_CALLBACK(config_window_help_cb), notebook);
2714 gtk_container_add(GTK_CONTAINER(hbox), button);
2715 gtk_widget_set_can_default(button, TRUE);
2716 gtk_widget_show(button);
2718 button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
2719 G_CALLBACK(config_window_ok_cb), NULL);
2720 gtk_container_add(GTK_CONTAINER(hbox), button);
2721 gtk_widget_set_can_default(button, TRUE);
2722 gtk_widget_grab_default(button);
2723 gtk_widget_show(button);
2727 button = pref_button_new(NULL, GTK_STOCK_SAVE, NULL, FALSE,
2728 G_CALLBACK(config_window_save_cb), NULL);
2729 gtk_container_add(GTK_CONTAINER(hbox), button);
2730 gtk_widget_set_can_default(button, TRUE);
2731 gtk_widget_show(button);
2733 button = pref_button_new(NULL, GTK_STOCK_APPLY, NULL, FALSE,
2734 G_CALLBACK(config_window_apply_cb), NULL);
2735 gtk_container_add(GTK_CONTAINER(hbox), button);
2736 gtk_widget_set_can_default(button, TRUE);
2737 gtk_widget_show(button);
2739 button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
2740 G_CALLBACK(config_window_close_cb), NULL);
2741 gtk_container_add(GTK_CONTAINER(hbox), button);
2742 gtk_widget_set_can_default(button, TRUE);
2743 gtk_widget_show(button);
2745 if (!generic_dialog_get_alternative_button_order(configwindow))
2747 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
2750 gtk_widget_show(notebook);
2752 gtk_widget_show(configwindow);
2756 *-----------------------------------------------------------------------------
2757 * config window show (public)
2758 *-----------------------------------------------------------------------------
2761 void show_config_window(void)
2765 gtk_window_present(GTK_WINDOW(configwindow));
2769 config_window_create();
2778 void show_about_window(LayoutWindow *lw)
2780 GdkPixbuf *pixbuf_logo;
2781 GdkPixbuf *pixbuf_icon;
2782 gchar *authors[1000];
2790 #define LINE_LENGTH 1000
2791 gchar line[LINE_LENGTH];
2793 copyright = g_string_new(NULL);
2794 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");
2796 zd_path = g_build_filename(GQ_BIN_DIR, TIMEZONE_DATABASE, NULL);
2797 cd = ZDOpenDatabase(zd_path);
2800 copyright = g_string_append(copyright, ZDGetNotice(cd));
2802 ZDCloseDatabase(cd);
2806 path = g_build_filename(GQ_HELPDIR, "AUTHORS", NULL);
2807 fp = fopen(path, "r");
2810 while(fgets(line, LINE_LENGTH, fp))
2812 /* get rid of ending \n from fgets */
2813 line[strlen(line) - 1] = '\0';
2814 authors[i_authors] = g_strdup(line);
2817 authors[i_authors] = NULL;
2822 comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
2823 "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
2825 pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
2826 pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
2827 gtk_show_about_dialog(GTK_WINDOW(lw->window),
2828 "title", _("About Geeqie"),
2830 "program-name", GQ_APPNAME,
2832 "logo", pixbuf_logo,
2833 "icon", pixbuf_icon,
2834 "website", GQ_WEBSITE,
2835 "website-label", "Website",
2836 "comments", comment,
2838 "translator-credits", _("translator-credits"),
2839 "wrap-license", TRUE,
2840 "license", copyright->str,
2843 g_string_free(copyright, TRUE);
2846 while(n < i_authors)
2856 static void image_overlay_set_text_colours()
2858 c_options->image_overlay.text_red = options->image_overlay.text_red;
2859 c_options->image_overlay.text_green = options->image_overlay.text_green;
2860 c_options->image_overlay.text_blue = options->image_overlay.text_blue;
2861 c_options->image_overlay.text_alpha = options->image_overlay.text_alpha;
2862 c_options->image_overlay.background_red = options->image_overlay.background_red;
2863 c_options->image_overlay.background_green = options->image_overlay.background_green;
2864 c_options->image_overlay.background_blue = options->image_overlay.background_blue;
2865 c_options->image_overlay.background_alpha = options->image_overlay.background_alpha;
2867 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */