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;
136 #define CONFIG_WINDOW_DEF_WIDTH 700
137 #define CONFIG_WINDOW_DEF_HEIGHT 600
140 *-----------------------------------------------------------------------------
141 * option widget callbacks (private)
142 *-----------------------------------------------------------------------------
145 static void zoom_increment_cb(GtkWidget *spin, gpointer data)
147 c_options->image.zoom_increment = (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) * 100.0 + 0.01);
150 static void slideshow_delay_hours_cb(GtkWidget *spin, gpointer data)
152 gint mins_secs_tenths, delay;
154 mins_secs_tenths = c_options->slideshow.delay %
155 (3600 * SLIDESHOW_SUBSECOND_PRECISION);
157 delay = (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
158 (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
161 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
162 SLIDESHOW_SUBSECOND_PRECISION;
165 static void slideshow_delay_minutes_cb(GtkWidget *spin, gpointer data)
167 gint hours, secs_tenths, delay;
169 hours = c_options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
170 secs_tenths = c_options->slideshow.delay % (60 * SLIDESHOW_SUBSECOND_PRECISION);
172 delay = hours * (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
173 (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
174 (60 * SLIDESHOW_SUBSECOND_PRECISION) + secs_tenths);
176 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
177 SLIDESHOW_SUBSECOND_PRECISION;
180 static void slideshow_delay_seconds_cb(GtkWidget *spin, gpointer data)
182 gint hours_mins, delay;
184 hours_mins = c_options->slideshow.delay / (60 * SLIDESHOW_SUBSECOND_PRECISION);
186 delay = (hours_mins * (60 * SLIDESHOW_SUBSECOND_PRECISION)) +
187 (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
188 (gdouble)(SLIDESHOW_SUBSECOND_PRECISION) + 0.01);
190 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
191 SLIDESHOW_SUBSECOND_PRECISION;
195 *-----------------------------------------------------------------------------
196 * sync progam to config window routine (private)
197 *-----------------------------------------------------------------------------
200 void config_entry_to_option(GtkWidget *entry, gchar **option, gchar *(*func)(const gchar *))
206 buf = gtk_entry_get_text(GTK_ENTRY(entry));
207 if (buf && strlen(buf) > 0)
212 *option = g_strdup(buf);
217 static gboolean accel_apply_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
219 gchar *accel_path, *accel;
221 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, AE_KEY, &accel, -1);
223 if (accel_path && accel_path[0])
226 gtk_accelerator_parse(accel, &key.accel_key, &key.accel_mods);
227 gtk_accel_map_change_entry(accel_path, key.accel_key, key.accel_mods, TRUE);
237 static void config_window_apply(void)
240 gboolean refresh = FALSE;
242 config_entry_to_option(safe_delete_path_entry, &options->file_ops.safe_delete_path, remove_trailing_slash);
244 if (options->file_filter.show_hidden_files != c_options->file_filter.show_hidden_files) refresh = TRUE;
245 if (options->file_filter.show_parent_directory != c_options->file_filter.show_parent_directory) refresh = TRUE;
246 if (options->file_filter.show_dot_directory != c_options->file_filter.show_dot_directory) refresh = TRUE;
247 if (options->file_sort.case_sensitive != c_options->file_sort.case_sensitive) refresh = TRUE;
248 if (options->file_sort.natural != c_options->file_sort.natural) refresh = TRUE;
249 if (options->file_filter.disable_file_extension_checks != c_options->file_filter.disable_file_extension_checks) refresh = TRUE;
250 if (options->file_filter.disable != c_options->file_filter.disable) refresh = TRUE;
252 options->file_ops.confirm_delete = c_options->file_ops.confirm_delete;
253 options->file_ops.enable_delete_key = c_options->file_ops.enable_delete_key;
254 options->file_ops.safe_delete_enable = c_options->file_ops.safe_delete_enable;
255 options->file_ops.safe_delete_folder_maxsize = c_options->file_ops.safe_delete_folder_maxsize;
256 options->tools_restore_state = c_options->tools_restore_state;
257 options->save_window_positions = c_options->save_window_positions;
258 options->use_saved_window_positions_for_new_windows = c_options->use_saved_window_positions_for_new_windows;
259 options->save_dialog_window_positions = c_options->save_dialog_window_positions;
260 options->show_window_ids = c_options->show_window_ids;
261 options->image.scroll_reset_method = c_options->image.scroll_reset_method;
262 options->image.zoom_2pass = c_options->image.zoom_2pass;
263 options->image.fit_window_to_image = c_options->image.fit_window_to_image;
264 options->image.limit_window_size = c_options->image.limit_window_size;
265 options->image.zoom_to_fit_allow_expand = c_options->image.zoom_to_fit_allow_expand;
266 options->image.max_window_size = c_options->image.max_window_size;
267 options->image.limit_autofit_size = c_options->image.limit_autofit_size;
268 options->image.max_autofit_size = c_options->image.max_autofit_size;
269 options->image.max_enlargement_size = c_options->image.max_enlargement_size;
270 options->image.use_clutter_renderer = c_options->image.use_clutter_renderer;
271 options->progressive_key_scrolling = c_options->progressive_key_scrolling;
272 options->keyboard_scroll_step = c_options->keyboard_scroll_step;
274 if (options->thumbnails.max_width != c_options->thumbnails.max_width
275 || options->thumbnails.max_height != c_options->thumbnails.max_height
276 || options->thumbnails.quality != c_options->thumbnails.quality)
278 thumb_format_changed = TRUE;
280 options->thumbnails.max_width = c_options->thumbnails.max_width;
281 options->thumbnails.max_height = c_options->thumbnails.max_height;
282 options->thumbnails.quality = c_options->thumbnails.quality;
284 options->thumbnails.enable_caching = c_options->thumbnails.enable_caching;
285 options->thumbnails.cache_into_dirs = c_options->thumbnails.cache_into_dirs;
286 options->thumbnails.use_exif = c_options->thumbnails.use_exif;
287 options->thumbnails.use_ft_metadata = c_options->thumbnails.use_ft_metadata;
288 // options->thumbnails.use_ft_metadata_small = c_options->thumbnails.use_ft_metadata_small;
289 options->thumbnails.spec_standard = c_options->thumbnails.spec_standard;
290 options->metadata.enable_metadata_dirs = c_options->metadata.enable_metadata_dirs;
291 options->file_filter.show_hidden_files = c_options->file_filter.show_hidden_files;
292 options->file_filter.show_parent_directory = c_options->file_filter.show_parent_directory;
293 options->file_filter.show_dot_directory = c_options->file_filter.show_dot_directory;
294 options->file_filter.disable_file_extension_checks = c_options->file_filter.disable_file_extension_checks;
296 options->file_sort.case_sensitive = c_options->file_sort.case_sensitive;
297 options->file_sort.natural = c_options->file_sort.natural;
298 options->file_filter.disable = c_options->file_filter.disable;
300 config_entry_to_option(sidecar_ext_entry, &options->sidecar.ext, NULL);
301 sidecar_ext_parse(options->sidecar.ext);
303 options->slideshow.random = c_options->slideshow.random;
304 options->slideshow.repeat = c_options->slideshow.repeat;
305 options->slideshow.delay = c_options->slideshow.delay;
307 options->mousewheel_scrolls = c_options->mousewheel_scrolls;
308 options->image_lm_click_nav = c_options->image_lm_click_nav;
309 options->image_l_click_video = c_options->image_l_click_video;
310 options->image_l_click_video_editor = c_options->image_l_click_video_editor;
312 options->file_ops.enable_in_place_rename = c_options->file_ops.enable_in_place_rename;
314 options->image.tile_cache_max = c_options->image.tile_cache_max;
315 options->image.image_cache_max = c_options->image.image_cache_max;
317 options->image.zoom_quality = c_options->image.zoom_quality;
319 options->image.zoom_increment = c_options->image.zoom_increment;
321 options->image.enable_read_ahead = c_options->image.enable_read_ahead;
324 if (options->image.use_custom_border_color != c_options->image.use_custom_border_color
325 || options->image.use_custom_border_color_in_fullscreen != c_options->image.use_custom_border_color_in_fullscreen
326 || !gdk_color_equal(&options->image.border_color, &c_options->image.border_color))
328 options->image.use_custom_border_color_in_fullscreen = c_options->image.use_custom_border_color_in_fullscreen;
329 options->image.use_custom_border_color = c_options->image.use_custom_border_color;
330 options->image.border_color = c_options->image.border_color;
331 layout_colors_update();
332 view_window_colors_update();
335 options->image.alpha_color_1 = c_options->image.alpha_color_1;
336 options->image.alpha_color_2 = c_options->image.alpha_color_2;
338 options->fullscreen.screen = c_options->fullscreen.screen;
339 options->fullscreen.clean_flip = c_options->fullscreen.clean_flip;
340 options->fullscreen.disable_saver = c_options->fullscreen.disable_saver;
341 options->fullscreen.above = c_options->fullscreen.above;
342 if (c_options->image_overlay.template_string)
343 set_image_overlay_template_string(&options->image_overlay.template_string,
344 c_options->image_overlay.template_string);
345 if (c_options->image_overlay.font)
346 set_image_overlay_font_string(&options->image_overlay.font,
347 c_options->image_overlay.font);
348 options->image_overlay.text_red = c_options->image_overlay.text_red;
349 options->image_overlay.text_green = c_options->image_overlay.text_green;
350 options->image_overlay.text_blue = c_options->image_overlay.text_blue;
351 options->image_overlay.text_alpha = c_options->image_overlay.text_alpha;
352 options->image_overlay.background_red = c_options->image_overlay.background_red;
353 options->image_overlay.background_green = c_options->image_overlay.background_green;
354 options->image_overlay.background_blue = c_options->image_overlay.background_blue;
355 options->image_overlay.background_alpha = c_options->image_overlay.background_alpha;
356 options->update_on_time_change = c_options->update_on_time_change;
357 options->image.exif_proof_rotate_enable = c_options->image.exif_proof_rotate_enable;
359 options->duplicates_similarity_threshold = c_options->duplicates_similarity_threshold;
360 options->rot_invariant_sim = c_options->rot_invariant_sim;
362 options->tree_descend_subdirs = c_options->tree_descend_subdirs;
364 options->view_dir_list_single_click_enter = c_options->view_dir_list_single_click_enter;
366 options->open_recent_list_maxsize = c_options->open_recent_list_maxsize;
367 options->dnd_icon_size = c_options->dnd_icon_size;
368 options->clipboard_selection = c_options->clipboard_selection;
370 options->metadata.save_in_image_file = c_options->metadata.save_in_image_file;
371 options->metadata.save_legacy_IPTC = c_options->metadata.save_legacy_IPTC;
372 options->metadata.warn_on_write_problems = c_options->metadata.warn_on_write_problems;
373 options->metadata.save_legacy_format = c_options->metadata.save_legacy_format;
374 options->metadata.sync_grouped_files = c_options->metadata.sync_grouped_files;
375 options->metadata.confirm_write = c_options->metadata.confirm_write;
376 options->metadata.sidecar_extended_name = c_options->metadata.sidecar_extended_name;
377 options->metadata.confirm_timeout = c_options->metadata.confirm_timeout;
378 options->metadata.confirm_after_timeout = c_options->metadata.confirm_after_timeout;
379 options->metadata.confirm_on_image_change = c_options->metadata.confirm_on_image_change;
380 options->metadata.confirm_on_dir_change = c_options->metadata.confirm_on_dir_change;
381 options->metadata.keywords_case_sensitive = c_options->metadata.keywords_case_sensitive;
382 options->metadata.write_orientation = c_options->metadata.write_orientation;
383 options->stereo.mode = (c_options->stereo.mode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
384 (c_options->stereo.tmp.mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
385 (c_options->stereo.tmp.flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
386 (c_options->stereo.tmp.mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
387 (c_options->stereo.tmp.flip_left ? PR_STEREO_FLIP_LEFT : 0) |
388 (c_options->stereo.tmp.swap ? PR_STEREO_SWAP : 0) |
389 (c_options->stereo.tmp.temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
390 options->stereo.fsmode = (c_options->stereo.fsmode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
391 (c_options->stereo.tmp.fs_mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
392 (c_options->stereo.tmp.fs_flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
393 (c_options->stereo.tmp.fs_mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
394 (c_options->stereo.tmp.fs_flip_left ? PR_STEREO_FLIP_LEFT : 0) |
395 (c_options->stereo.tmp.fs_swap ? PR_STEREO_SWAP : 0) |
396 (c_options->stereo.tmp.fs_temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
397 options->stereo.enable_fsmode = c_options->stereo.enable_fsmode;
398 options->stereo.fixed_w = c_options->stereo.fixed_w;
399 options->stereo.fixed_h = c_options->stereo.fixed_h;
400 options->stereo.fixed_x1 = c_options->stereo.fixed_x1;
401 options->stereo.fixed_y1 = c_options->stereo.fixed_y1;
402 options->stereo.fixed_x2 = c_options->stereo.fixed_x2;
403 options->stereo.fixed_y2 = c_options->stereo.fixed_y2;
405 options->info_keywords.height = c_options->info_keywords.height;
406 options->info_title.height = c_options->info_title.height;
407 options->info_comment.height = c_options->info_comment.height;
408 options->info_rating.height = c_options->info_rating.height;
410 options->marks_save = c_options->marks_save;
413 set_debug_level(debug_c);
417 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
419 config_entry_to_option(color_profile_input_name_entry[i], &options->color_profile.input_name[i], NULL);
420 config_entry_to_option(color_profile_input_file_entry[i], &options->color_profile.input_file[i], NULL);
422 config_entry_to_option(color_profile_screen_file_entry, &options->color_profile.screen_file, NULL);
423 options->color_profile.use_x11_screen_profile = c_options->color_profile.use_x11_screen_profile;
424 if (options->color_profile.render_intent != c_options->color_profile.render_intent)
426 options->color_profile.render_intent = c_options->color_profile.render_intent;
431 image_options_sync();
436 layout_refresh(NULL);
439 if (accel_store) gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_apply_cb, NULL);
445 *-----------------------------------------------------------------------------
446 * config window main button callbacks (private)
447 *-----------------------------------------------------------------------------
450 static void config_window_close_cb(GtkWidget *widget, gpointer data)
452 gtk_widget_destroy(configwindow);
457 static void config_window_help_cb(GtkWidget *widget, gpointer data)
459 GtkWidget *notebook = data;
462 static gchar *html_section[] =
464 "GuideOptionsGeneral.html",
465 "GuideOptionsImage.html",
466 "GuideOptionsWindow.html",
467 "GuideOptionsKeyboard.html",
468 "GuideOptionsFiltering.html",
469 "GuideOptionsMetadata.html",
470 "GuideOptionsColor.html",
471 "GuideOptionsStereo.html",
472 "GuideOptionsBehavior.html",
473 "GuideOptionsToolbar.html"
476 i = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
477 help_window_show(html_section[i]);
480 static gboolean config_window_delete(GtkWidget *widget, GdkEventAny *event, gpointer data)
482 config_window_close_cb(NULL, NULL);
486 static void config_window_ok_cb(GtkWidget *widget, gpointer data)
488 config_window_apply();
489 config_window_close_cb(NULL, NULL);
492 static void config_window_apply_cb(GtkWidget *widget, gpointer data)
495 lw = layout_window_list->data;
497 config_window_apply();
498 layout_util_sync(lw);
501 static void config_window_save_cb(GtkWidget *widget, gpointer data)
503 config_window_apply();
504 save_options(options);
508 *-----------------------------------------------------------------------------
509 * config window setup (private)
510 *-----------------------------------------------------------------------------
513 static void quality_menu_cb(GtkWidget *combo, gpointer data)
517 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
521 *option = GDK_INTERP_NEAREST;
524 *option = GDK_INTERP_TILES;
527 *option = GDK_INTERP_BILINEAR;
530 *option = GDK_INTERP_HYPER;
535 static void clipboard_selection_menu_cb(GtkWidget *combo, gpointer data)
539 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
551 static void add_quality_menu(GtkWidget *table, gint column, gint row, const gchar *text,
552 guint option, guint *option_c)
559 pref_table_label(table, column, row, text, 0.0);
561 combo = gtk_combo_box_text_new();
563 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Nearest (worst, but fastest)"));
564 if (option == GDK_INTERP_NEAREST) current = 0;
565 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Tiles"));
566 if (option == GDK_INTERP_TILES) current = 1;
567 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Bilinear"));
568 if (option == GDK_INTERP_BILINEAR) current = 2;
569 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Hyper (best, but slowest)"));
570 if (option == GDK_INTERP_HYPER) current = 3;
572 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
574 g_signal_connect(G_OBJECT(combo), "changed",
575 G_CALLBACK(quality_menu_cb), option_c);
577 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
578 GTK_EXPAND | GTK_FILL, 0, 0, 0);
579 gtk_widget_show(combo);
582 static void add_clipboard_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
583 gint option, gint *option_c)
590 pref_table_label(table, column, row, text, 0.0);
592 combo = gtk_combo_box_text_new();
594 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("PRIMARY"));
595 if (option == PRIMARY) current = 0;
596 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("CLIPBOARD"));
597 if (option == CLIPBOARD) current = 1;
599 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
601 g_signal_connect(G_OBJECT(combo), "changed",
602 G_CALLBACK(clipboard_selection_menu_cb), option_c);
604 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
605 GTK_EXPAND | GTK_FILL, 0, 0, 0);
606 gtk_widget_show(combo);
609 static void thumb_size_menu_cb(GtkWidget *combo, gpointer data)
613 n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
616 if ((guint) n < sizeof(thumb_size_list) / sizeof(ThumbSize))
618 c_options->thumbnails.max_width = thumb_size_list[n].w;
619 c_options->thumbnails.max_height = thumb_size_list[n].h;
623 c_options->thumbnails.max_width = options->thumbnails.max_width;
624 c_options->thumbnails.max_height = options->thumbnails.max_height;
628 static void add_thumb_size_menu(GtkWidget *table, gint column, gint row, gchar *text)
634 c_options->thumbnails.max_width = options->thumbnails.max_width;
635 c_options->thumbnails.max_height = options->thumbnails.max_height;
637 pref_table_label(table, column, row, text, 0.0);
639 combo = gtk_combo_box_text_new();
642 for (i = 0; (guint) i < sizeof(thumb_size_list) / sizeof(ThumbSize); i++)
647 w = thumb_size_list[i].w;
648 h = thumb_size_list[i].h;
650 buf = g_strdup_printf("%d x %d", w, h);
651 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
654 if (w == options->thumbnails.max_width && h == options->thumbnails.max_height) current = i;
661 buf = g_strdup_printf("%s %d x %d", _("Custom"), options->thumbnails.max_width, options->thumbnails.max_height);
662 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
668 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
669 g_signal_connect(G_OBJECT(combo), "changed",
670 G_CALLBACK(thumb_size_menu_cb), NULL);
672 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
673 GTK_EXPAND | GTK_FILL, 0, 0, 0);
674 gtk_widget_show(combo);
677 static void stereo_mode_menu_cb(GtkWidget *combo, gpointer data)
681 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
685 *option = PR_STEREO_NONE;
688 *option = PR_STEREO_ANAGLYPH_RC;
691 *option = PR_STEREO_ANAGLYPH_GM;
694 *option = PR_STEREO_ANAGLYPH_YB;
697 *option = PR_STEREO_ANAGLYPH_GRAY_RC;
700 *option = PR_STEREO_ANAGLYPH_GRAY_GM;
703 *option = PR_STEREO_ANAGLYPH_GRAY_YB;
706 *option = PR_STEREO_ANAGLYPH_DB_RC;
709 *option = PR_STEREO_ANAGLYPH_DB_GM;
712 *option = PR_STEREO_ANAGLYPH_DB_YB;
715 *option = PR_STEREO_HORIZ;
718 *option = PR_STEREO_HORIZ | PR_STEREO_HALF;
721 *option = PR_STEREO_VERT;
724 *option = PR_STEREO_VERT | PR_STEREO_HALF;
727 *option = PR_STEREO_FIXED;
732 static void add_stereo_mode_menu(GtkWidget *table, gint column, gint row, const gchar *text,
733 gint option, gint *option_c, gboolean add_fixed)
740 pref_table_label(table, column, row, text, 0.0);
742 combo = gtk_combo_box_text_new();
744 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Single image"));
746 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Red-Cyan"));
747 if (option & PR_STEREO_ANAGLYPH_RC) current = 1;
748 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Green-Magenta"));
749 if (option & PR_STEREO_ANAGLYPH_GM) current = 2;
750 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Yellow-Blue"));
751 if (option & PR_STEREO_ANAGLYPH_YB) current = 3;
752 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Red-Cyan"));
753 if (option & PR_STEREO_ANAGLYPH_GRAY_RC) current = 4;
754 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Green-Magenta"));
755 if (option & PR_STEREO_ANAGLYPH_GRAY_GM) current = 5;
756 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Yellow-Blue"));
757 if (option & PR_STEREO_ANAGLYPH_GRAY_YB) current = 6;
758 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Red-Cyan"));
759 if (option & PR_STEREO_ANAGLYPH_DB_RC) current = 7;
760 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Green-Magenta"));
761 if (option & PR_STEREO_ANAGLYPH_DB_GM) current = 8;
762 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Yellow-Blue"));
763 if (option & PR_STEREO_ANAGLYPH_DB_YB) current = 9;
765 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side"));
766 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side Half size"));
767 if (option & PR_STEREO_HORIZ)
770 if (option & PR_STEREO_HALF) current = 11;
773 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom"));
774 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom Half size"));
775 if (option & PR_STEREO_VERT)
778 if (option & PR_STEREO_HALF) current = 13;
783 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Fixed position"));
784 if (option & PR_STEREO_FIXED) current = 14;
787 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
789 g_signal_connect(G_OBJECT(combo), "changed",
790 G_CALLBACK(stereo_mode_menu_cb), option_c);
792 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
793 GTK_EXPAND | GTK_FILL, 0, 0, 0);
794 gtk_widget_show(combo);
797 static void video_menu_cb(GtkWidget *combo, gpointer data)
799 gchar **option = data;
801 EditorDescription *ed = g_list_nth_data(editor_list_get(), gtk_combo_box_get_active(GTK_COMBO_BOX(combo)));
805 static void video_menu_populate(gpointer data, gpointer user_data)
807 GtkWidget *combo = user_data;
808 EditorDescription *ed = data;
810 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), ed->name);
813 static void add_video_menu(GtkWidget *table, gint column, gint row, const gchar *text,
814 gchar *option, gchar **option_c)
818 /* use lists since they are sorted */
819 GList *eds = editor_list_get();
823 pref_table_label(table, column, row, text, 0.0);
825 combo = gtk_combo_box_text_new();
826 g_list_foreach(eds,video_menu_populate,(gpointer)combo);
827 current = option ? g_list_index(eds,g_hash_table_lookup(editors,option)): -1;
829 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
831 g_signal_connect(G_OBJECT(combo), "changed",
832 G_CALLBACK(video_menu_cb), option_c);
834 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
835 GTK_EXPAND | GTK_FILL, 0, 0, 0);
836 gtk_widget_show(combo);
839 static void filter_store_populate(void)
843 if (!filter_store) return;
845 gtk_list_store_clear(filter_store);
847 work = filter_get_list();
856 gtk_list_store_append(filter_store, &iter);
857 gtk_list_store_set(filter_store, &iter, 0, fe, -1);
861 static void filter_store_ext_edit_cb(GtkCellRendererText *cell, gchar *path_str,
862 gchar *new_text, gpointer data)
864 GtkWidget *model = data;
865 FilterEntry *fe = data;
869 if (!new_text || strlen(new_text) < 1) return;
871 tpath = gtk_tree_path_new_from_string(path_str);
872 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
873 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
875 g_free(fe->extensions);
876 fe->extensions = g_strdup(new_text);
878 gtk_tree_path_free(tpath);
882 static void filter_store_class_edit_cb(GtkCellRendererText *cell, gchar *path_str,
883 gchar *new_text, gpointer data)
885 GtkWidget *model = data;
886 FilterEntry *fe = data;
891 if (!new_text || !new_text[0]) return;
893 tpath = gtk_tree_path_new_from_string(path_str);
894 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
895 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
897 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
899 if (strcmp(new_text, _(format_class_list[i])) == 0)
906 gtk_tree_path_free(tpath);
910 static void filter_store_desc_edit_cb(GtkCellRendererText *cell, gchar *path_str,
911 gchar *new_text, gpointer data)
913 GtkWidget *model = data;
918 if (!new_text || !new_text[0]) return;
920 tpath = gtk_tree_path_new_from_string(path_str);
921 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
922 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
924 g_free(fe->description);
925 fe->description = g_strdup(new_text);
927 gtk_tree_path_free(tpath);
930 static void filter_store_enable_cb(GtkCellRendererToggle *renderer,
931 gchar *path_str, gpointer data)
933 GtkWidget *model = data;
938 tpath = gtk_tree_path_new_from_string(path_str);
939 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
940 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
942 fe->enabled = !fe->enabled;
944 gtk_tree_path_free(tpath);
948 static void filter_store_writable_cb(GtkCellRendererToggle *renderer,
949 gchar *path_str, gpointer data)
951 GtkWidget *model = data;
956 tpath = gtk_tree_path_new_from_string(path_str);
957 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
958 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
960 fe->writable = !fe->writable;
961 if (fe->writable) fe->allow_sidecar = FALSE;
963 gtk_tree_path_free(tpath);
967 static void filter_store_sidecar_cb(GtkCellRendererToggle *renderer,
968 gchar *path_str, gpointer data)
970 GtkWidget *model = data;
975 tpath = gtk_tree_path_new_from_string(path_str);
976 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
977 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
979 fe->allow_sidecar = !fe->allow_sidecar;
980 if (fe->allow_sidecar) fe->writable = FALSE;
982 gtk_tree_path_free(tpath);
986 static void filter_set_func(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
987 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
991 gtk_tree_model_get(tree_model, iter, 0, &fe, -1);
993 switch (GPOINTER_TO_INT(data))
996 g_object_set(GTK_CELL_RENDERER(cell),
997 "active", fe->enabled, NULL);
1000 g_object_set(GTK_CELL_RENDERER(cell),
1001 "text", fe->extensions, NULL);
1003 case FE_DESCRIPTION:
1004 g_object_set(GTK_CELL_RENDERER(cell),
1005 "text", fe->description, NULL);
1008 g_object_set(GTK_CELL_RENDERER(cell),
1009 "text", _(format_class_list[fe->file_class]), NULL);
1012 g_object_set(GTK_CELL_RENDERER(cell),
1013 "active", fe->writable, NULL);
1015 case FE_ALLOW_SIDECAR:
1016 g_object_set(GTK_CELL_RENDERER(cell),
1017 "active", fe->allow_sidecar, NULL);
1022 static gboolean filter_add_scroll(gpointer data)
1026 GtkCellRenderer *cell;
1027 GtkTreeViewColumn *column;
1028 GList *list_columns;
1033 rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(filter_store), NULL);
1034 path = gtk_tree_path_new_from_indices(rows-1, -1);
1036 list_columns = gtk_tree_view_get_columns(GTK_TREE_VIEW(data));
1038 column = g_list_nth(list_columns,i)->data;
1039 title = gtk_tree_view_column_get_title(GTK_TREE_VIEW_COLUMN(column));
1041 } while (strcmp(title, "Filter") !=0 );
1043 list_cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column));
1044 cell = g_list_last(list_cells)->data;
1046 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1047 path, column, FALSE, 0.0, 0.0 );
1048 gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(data),
1049 path, column, cell, TRUE);
1051 gtk_tree_path_free(path);
1052 g_list_free(list_cells);
1053 g_list_free(list_columns);
1058 static void filter_add_cb(GtkWidget *widget, gpointer data)
1060 filter_add_unique("description", ".new", FORMAT_CLASS_IMAGE, TRUE, FALSE, TRUE);
1061 filter_store_populate();
1063 g_idle_add((GSourceFunc)filter_add_scroll, data);
1066 static void filter_remove_cb(GtkWidget *widget, gpointer data)
1068 GtkWidget *filter_view = data;
1069 GtkTreeSelection *selection;
1073 if (!filter_store) return;
1074 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1075 if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) return;
1076 gtk_tree_model_get(GTK_TREE_MODEL(filter_store), &iter, 0, &fe, -1);
1079 filter_remove_entry(fe);
1081 filter_store_populate();
1084 static gboolean filter_default_ok_scroll(GtkTreeView *data)
1088 GtkTreeViewColumn *column;
1090 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(filter_store), &iter);
1091 path = gtk_tree_model_get_path(GTK_TREE_MODEL(filter_store), &iter);
1092 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1094 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1098 gtk_tree_path_free(path);
1103 static void filter_default_ok_cb(GenericDialog *gd, gpointer data)
1106 filter_add_defaults();
1108 filter_store_populate();
1110 g_idle_add((GSourceFunc)filter_default_ok_scroll, gd->data);
1113 static void dummy_cancel_cb(GenericDialog *gd, gpointer data)
1115 /* no op, only so cancel button appears */
1118 static void filter_default_cb(GtkWidget *widget, gpointer data)
1122 gd = generic_dialog_new(_("Reset filters"),
1123 "reset_filter", widget, TRUE,
1124 dummy_cancel_cb, data);
1125 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset filters"),
1126 _("This will reset the file filters to the defaults.\nContinue?"), TRUE);
1127 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, filter_default_ok_cb, TRUE);
1128 gtk_widget_show(gd->dialog);
1131 static void filter_disable_cb(GtkWidget *widget, gpointer data)
1133 GtkWidget *frame = data;
1135 gtk_widget_set_sensitive(frame,
1136 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
1139 static void safe_delete_view_cb(GtkWidget *widget, gpointer data)
1141 layout_set_path(NULL, gtk_entry_get_text(GTK_ENTRY(safe_delete_path_entry)));
1144 static void safe_delete_clear_ok_cb(GenericDialog *gd, gpointer data)
1146 file_util_trash_clear();
1149 static void safe_delete_clear_cb(GtkWidget *widget, gpointer data)
1153 gd = generic_dialog_new(_("Clear trash"),
1154 "clear_trash", widget, TRUE,
1155 dummy_cancel_cb, NULL);
1156 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear trash"),
1157 _("This will remove the trash contents."), FALSE);
1158 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, safe_delete_clear_ok_cb, TRUE);
1159 entry = gtk_entry_new();
1160 gtk_widget_set_can_focus(entry, FALSE);
1161 gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE);
1162 if (options->file_ops.safe_delete_path) gtk_entry_set_text(GTK_ENTRY(entry), options->file_ops.safe_delete_path);
1163 gtk_box_pack_start(GTK_BOX(gd->vbox), entry, FALSE, FALSE, 0);
1164 gtk_widget_show(entry);
1165 gtk_widget_show(gd->dialog);
1168 static void image_overlay_template_view_changed_cb(GtkWidget *widget, gpointer data)
1170 GtkWidget *pTextView;
1171 GtkTextBuffer *pTextBuffer;
1175 pTextView = GTK_WIDGET(data);
1177 pTextBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pTextView));
1178 gtk_text_buffer_get_start_iter(pTextBuffer, &iStart);
1179 gtk_text_buffer_get_end_iter(pTextBuffer, &iEnd);
1181 set_image_overlay_template_string(&c_options->image_overlay.template_string,
1182 gtk_text_buffer_get_text(pTextBuffer, &iStart, &iEnd, TRUE));
1185 static void image_overlay_default_template_ok_cb(GenericDialog *gd, gpointer data)
1187 GtkTextView *text_view = data;
1188 GtkTextBuffer *buffer;
1190 set_default_image_overlay_template_string(&options->image_overlay.template_string);
1191 if (!configwindow) return;
1193 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
1194 gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1197 static void image_overlay_default_template_cb(GtkWidget *widget, gpointer data)
1201 gd = generic_dialog_new(_("Reset image overlay template string"),
1202 "reset_image_overlay_template_string", widget, TRUE,
1203 dummy_cancel_cb, data);
1204 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset image overlay template string"),
1205 _("This will reset the image overlay template string to the default.\nContinue?"), TRUE);
1206 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, image_overlay_default_template_ok_cb, TRUE);
1207 gtk_widget_show(gd->dialog);
1210 static void image_overlay_help_cb(GtkWidget *widget, gpointer data)
1212 help_window_show("GuideOptionsWindow.html#OverlayScreenDisplay");
1215 static void image_overlay_set_font_cb(GtkWidget *widget, gpointer data)
1217 #if GTK_CHECK_VERSION(3,4,0)
1220 PangoFontDescription *font_desc;
1222 dialog = gtk_font_chooser_dialog_new("Image Overlay Font", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1223 gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), options->image_overlay.font);
1225 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1227 font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
1228 font = pango_font_description_to_string(font_desc);
1229 g_free(c_options->image_overlay.font);
1230 c_options->image_overlay.font = g_strdup(font);
1234 gtk_widget_destroy(dialog);
1238 font = gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget));
1239 c_options->image_overlay.font = g_strdup(font);
1243 static void image_overlay_set_text_colour_cb(GtkWidget *widget, gpointer data)
1246 #if GTK_CHECK_VERSION(3,4,0)
1249 dialog = gtk_color_chooser_dialog_new("Image Overlay Text Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1250 colour.red = options->image_overlay.text_red;
1251 colour.green = options->image_overlay.text_green;
1252 colour.blue = options->image_overlay.text_blue;
1253 colour.alpha = options->image_overlay.text_alpha;
1254 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1255 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1257 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1259 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1260 c_options->image_overlay.text_red = colour.red*255;
1261 c_options->image_overlay.text_green = colour.green*255;
1262 c_options->image_overlay.text_blue = colour.blue*255;
1263 c_options->image_overlay.text_alpha = colour.alpha*255;
1265 gtk_widget_destroy(dialog);
1268 GtkColorSelection *colorsel;
1270 dialog = gtk_color_selection_dialog_new("Image Overlay Text Colour");
1271 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1272 colour.red = options->image_overlay.text_red*257;
1273 colour.green = options->image_overlay.text_green*257;
1274 colour.blue = options->image_overlay.text_blue*257;
1275 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1276 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1277 gtk_color_selection_set_current_color(colorsel, &colour);
1278 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.text_alpha*257);
1280 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1282 gtk_color_selection_get_current_color(colorsel, &colour);
1283 c_options->image_overlay.text_red = colour.red/257;
1284 c_options->image_overlay.text_green = colour.green/257;
1285 c_options->image_overlay.text_blue = colour.blue/257;
1286 c_options->image_overlay.text_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1288 gtk_widget_destroy (dialog);
1293 static void image_overlay_set_background_colour_cb(GtkWidget *widget, gpointer data)
1296 #if GTK_CHECK_VERSION(3,4,0)
1299 dialog = gtk_color_chooser_dialog_new("Image Overlay Background Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1300 colour.red = options->image_overlay.background_red;
1301 colour.green = options->image_overlay.background_green;
1302 colour.blue = options->image_overlay.background_blue;
1303 colour.alpha = options->image_overlay.background_alpha;
1304 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1305 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1307 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1309 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1310 c_options->image_overlay.background_red = colour.red*255;
1311 c_options->image_overlay.background_green = colour.green*255;
1312 c_options->image_overlay.background_blue = colour.blue*255;
1313 c_options->image_overlay.background_alpha = colour.alpha*255;
1315 gtk_widget_destroy(dialog);
1318 GtkColorSelection *colorsel;
1320 dialog = gtk_color_selection_dialog_new("Image Overlay Background Colour");
1321 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1322 colour.red = options->image_overlay.background_red*257;
1323 colour.green = options->image_overlay.background_green*257;
1324 colour.blue = options->image_overlay.background_blue*257;
1325 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1326 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1327 gtk_color_selection_set_current_color(colorsel, &colour);
1328 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.background_alpha*257);
1330 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1332 gtk_color_selection_get_current_color(colorsel, &colour);
1333 c_options->image_overlay.background_red = colour.red/257;
1334 c_options->image_overlay.background_green = colour.green/257;
1335 c_options->image_overlay.background_blue = colour.blue/257;
1336 c_options->image_overlay.background_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1338 gtk_widget_destroy(dialog);
1342 static void accel_store_populate(void)
1345 GList *groups, *actions;
1347 const gchar *accel_path;
1351 if (!accel_store || !layout_window_list || !layout_window_list->data) return;
1353 gtk_tree_store_clear(accel_store);
1354 lw = layout_window_list->data; /* get the actions from the first window, it should not matter, they should be the same in all windows */
1356 g_assert(lw && lw->ui_manager);
1357 groups = gtk_ui_manager_get_action_groups(lw->ui_manager);
1360 actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
1363 action = GTK_ACTION(actions->data);
1364 accel_path = gtk_action_get_accel_path(action);
1365 if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
1367 gchar *label, *label2, *tooltip, *accel;
1368 g_object_get(action,
1369 "tooltip", &tooltip,
1373 if (pango_parse_markup(label, -1, '_', NULL, &label2, NULL, NULL) && label2)
1379 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1383 gtk_tree_store_append(accel_store, &iter, NULL);
1384 gtk_tree_store_set(accel_store, &iter,
1387 AE_TOOLTIP, tooltip ? tooltip : "",
1388 AE_ACCEL, accel_path,
1396 actions = actions->next;
1399 groups = groups->next;
1403 static void accel_store_cleared_cb(GtkCellRendererAccel *accel, gchar *path_string, gpointer user_data)
1408 static gboolean accel_remove_key_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1410 gchar *accel1 = data;
1415 gtk_tree_model_get(model, iter, AE_KEY, &accel2, -1);
1417 gtk_accelerator_parse(accel1, &key1.accel_key, &key1.accel_mods);
1418 gtk_accelerator_parse(accel2, &key2.accel_key, &key2.accel_mods);
1420 if (key1.accel_key == key2.accel_key && key1.accel_mods == key2.accel_mods)
1422 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1423 DEBUG_1("accelerator key '%s' is already used, removing.", accel1);
1432 static void accel_store_edited_cb(GtkCellRendererAccel *accel, gchar *path_string, guint accel_key, GdkModifierType accel_mods, guint hardware_keycode, gpointer user_data)
1434 GtkTreeModel *model = (GtkTreeModel *)accel_store;
1438 GtkAccelKey old_key, key;
1439 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
1441 gtk_tree_model_get_iter(model, &iter, path);
1442 gtk_tree_model_get(model, &iter, AE_ACCEL, &accel_path, -1);
1444 /* test if the accelerator can be stored without conflicts*/
1445 gtk_accel_map_lookup_entry(accel_path, &old_key);
1447 /* change the key and read it back (change may fail on keys hardcoded in gtk)*/
1448 gtk_accel_map_change_entry(accel_path, accel_key, accel_mods, TRUE);
1449 gtk_accel_map_lookup_entry(accel_path, &key);
1451 /* restore the original for now, the key will be really changed when the changes are confirmed */
1452 gtk_accel_map_change_entry(accel_path, old_key.accel_key, old_key.accel_mods, TRUE);
1454 acc = gtk_accelerator_name(key.accel_key, key.accel_mods);
1455 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, acc);
1457 gtk_tree_store_set(accel_store, &iter, AE_KEY, acc, -1);
1458 gtk_tree_path_free(path);
1462 static gboolean accel_default_scroll(GtkTreeView *data)
1466 GtkTreeViewColumn *column;
1468 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(accel_store), &iter);
1469 path = gtk_tree_model_get_path(GTK_TREE_MODEL(accel_store), &iter);
1470 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1472 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1476 gtk_tree_path_free(path);
1481 static void accel_default_cb(GtkWidget *widget, gpointer data)
1483 accel_store_populate();
1485 g_idle_add((GSourceFunc)accel_default_scroll, data);
1488 void accel_remove_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1490 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1493 void accel_reset_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1496 gchar *accel_path, *accel;
1498 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, -1);
1499 gtk_accel_map_lookup_entry(accel_path, &key);
1500 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1502 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, accel);
1504 gtk_tree_store_set(accel_store, iter, AE_KEY, accel, -1);
1509 static void accel_reset_cb(GtkWidget *widget, gpointer data)
1511 GtkTreeSelection *selection;
1513 if (!accel_store) return;
1514 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data));
1515 gtk_tree_selection_selected_foreach(selection, &accel_reset_selection, NULL);
1520 static GtkWidget *scrolled_notebook_page(GtkWidget *notebook, const gchar *title)
1524 GtkWidget *scrolled;
1525 GtkWidget *viewport;
1527 scrolled = gtk_scrolled_window_new(NULL, NULL);
1528 gtk_container_set_border_width(GTK_CONTAINER(scrolled), PREF_PAD_BORDER);
1529 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1530 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1531 label = gtk_label_new(title);
1532 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, label);
1533 gtk_widget_show(scrolled);
1535 viewport = gtk_viewport_new(NULL, NULL);
1536 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1537 gtk_container_add(GTK_CONTAINER(scrolled), viewport);
1538 gtk_widget_show(viewport);
1540 vbox = gtk_vbox_new(FALSE, 0);
1541 gtk_container_add(GTK_CONTAINER(viewport), vbox);
1542 gtk_widget_show(vbox);
1547 static void cache_standard_cb(GtkWidget *widget, gpointer data)
1549 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1551 c_options->thumbnails.spec_standard =TRUE;
1552 c_options->thumbnails.cache_into_dirs = FALSE;
1556 c_options->thumbnails.spec_standard =FALSE;
1560 static void cache_geeqie_cb(GtkWidget *widget, gpointer data)
1562 if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1564 c_options->thumbnails.spec_standard =TRUE;
1565 c_options->thumbnails.cache_into_dirs = FALSE;
1569 c_options->thumbnails.spec_standard =FALSE;
1573 static void cache_local_cb(GtkWidget *widget, gpointer data)
1575 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1577 c_options->thumbnails.cache_into_dirs = TRUE;
1578 c_options->thumbnails.spec_standard =FALSE;
1582 c_options->thumbnails.cache_into_dirs = FALSE;
1586 /* general options tab */
1587 static void config_tab_general(GtkWidget *notebook)
1592 GtkWidget *group_frame;
1593 GtkWidget *subgroup;
1595 GtkWidget *ct_button;
1598 gint hours, minutes, remainder;
1601 vbox = scrolled_notebook_page(notebook, _("General"));
1603 group = pref_group_new(vbox, FALSE, _("Thumbnails"), GTK_ORIENTATION_VERTICAL);
1605 table = pref_table_new(group, 2, 2, FALSE, FALSE);
1606 add_thumb_size_menu(table, 0, 0, _("Size:"));
1607 add_quality_menu(table, 0, 1, _("Quality:"), options->thumbnails.quality, &c_options->thumbnails.quality);
1609 ct_button = pref_checkbox_new_int(group, _("Cache thumbnails"),
1610 options->thumbnails.enable_caching, &c_options->thumbnails.enable_caching);
1612 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1613 pref_checkbox_link_sensitivity(ct_button, subgroup);
1615 group_frame = pref_frame_new(subgroup, TRUE, _("Use Geeqie thumbnail style and cache"),
1616 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1617 button = pref_radiobutton_new(group_frame, NULL, get_thumbnails_cache_dir(),
1618 !options->thumbnails.spec_standard,
1619 G_CALLBACK(cache_geeqie_cb), NULL);
1621 group_frame = pref_frame_new(subgroup, TRUE,
1622 _("Store thumbnails local to image folder (non-standard)"),
1623 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1624 pref_radiobutton_new(group_frame, button, "*/.thumbnails",
1625 options->thumbnails.cache_into_dirs,
1626 G_CALLBACK(cache_local_cb), NULL);
1628 group_frame = pref_frame_new(subgroup, TRUE,
1629 _("Use standard thumbnail style and cache, shared with other applications"),
1630 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1631 pref_radiobutton_new(group_frame, button, get_thumbnails_standard_cache_dir(),
1632 options->thumbnails.spec_standard,
1633 G_CALLBACK(cache_standard_cb), NULL);
1635 pref_checkbox_new_int(group, _("Use EXIF thumbnails when available (EXIF thumbnails may be outdated)"),
1636 options->thumbnails.use_exif, &c_options->thumbnails.use_exif);
1638 #ifdef HAVE_FFMPEGTHUMBNAILER_METADATA
1639 pref_checkbox_new_int(group, _("Use embedded metadata in video files as thumbnails when available"),
1640 options->thumbnails.use_ft_metadata, &c_options->thumbnails.use_ft_metadata);
1642 // pref_checkbox_new_int(group, _("Ignore embedded metadata if size is too small"),
1643 // options->thumbnails.use_ft_metadata_small, &c_options->thumbnails.use_ft_metadata_small);
1646 group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
1648 c_options->slideshow.delay = options->slideshow.delay;
1649 hours = options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
1650 remainder = options->slideshow.delay % (3600 * SLIDESHOW_SUBSECOND_PRECISION);
1651 minutes = remainder / (60 * SLIDESHOW_SUBSECOND_PRECISION);
1652 seconds = (gdouble)(remainder % (60 * SLIDESHOW_SUBSECOND_PRECISION)) /
1653 SLIDESHOW_SUBSECOND_PRECISION;
1655 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1657 spin = pref_spin_new(hbox, _("Delay between image change hrs:mins:secs.dec"), NULL,
1659 options->slideshow.delay ? hours : 0.0,
1660 G_CALLBACK(slideshow_delay_hours_cb), NULL);
1661 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1662 spin = pref_spin_new(hbox, ":" , NULL,
1664 options->slideshow.delay ? minutes: 0.0,
1665 G_CALLBACK(slideshow_delay_minutes_cb), NULL);
1666 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1667 spin = pref_spin_new(hbox, ":", NULL,
1668 SLIDESHOW_MIN_SECONDS, 59, 1.0, 1,
1669 options->slideshow.delay ? seconds : 10.0,
1670 G_CALLBACK(slideshow_delay_seconds_cb), NULL);
1671 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1673 pref_checkbox_new_int(group, _("Random"), options->slideshow.random, &c_options->slideshow.random);
1674 pref_checkbox_new_int(group, _("Repeat"), options->slideshow.repeat, &c_options->slideshow.repeat);
1676 group = pref_group_new(vbox, FALSE, _("Image loading and caching"), GTK_ORIENTATION_VERTICAL);
1678 pref_spin_new_int(group, _("Decoded image cache size (Mb):"), NULL,
1679 0, 99999, 1, options->image.image_cache_max, &c_options->image.image_cache_max);
1680 pref_checkbox_new_int(group, _("Preload next image"),
1681 options->image.enable_read_ahead, &c_options->image.enable_read_ahead);
1683 pref_checkbox_new_int(group, _("Refresh on file change"),
1684 options->update_on_time_change, &c_options->update_on_time_change);
1686 group = pref_group_new(vbox, FALSE, _("Info sidebar heights"), GTK_ORIENTATION_VERTICAL);
1687 pref_label_new(group, _("NOTE! Geeqie must be restarted for changes to take effect"));
1688 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1689 pref_spin_new_int(hbox, _("Keywords:"), NULL,
1691 options->info_keywords.height, &c_options->info_keywords.height);
1692 pref_spin_new_int(hbox, _("Title:"), NULL,
1694 options->info_title.height, &c_options->info_title.height);
1695 pref_spin_new_int(hbox, _("Comment:"), NULL,
1697 options->info_comment.height, &c_options->info_comment.height);
1698 pref_spin_new_int(hbox, _("Rating:"), NULL,
1700 options->info_rating.height, &c_options->info_rating.height);
1704 static void config_tab_image(GtkWidget *notebook)
1709 GtkWidget *ct_button;
1710 GtkWidget *enlargement_button;
1714 vbox = scrolled_notebook_page(notebook, _("Image"));
1716 group = pref_group_new(vbox, FALSE, _("Zoom"), GTK_ORIENTATION_VERTICAL);
1718 table = pref_table_new(group, 2, 1, FALSE, FALSE);
1719 add_quality_menu(table, 0, 0, _("Quality:"), options->image.zoom_quality, &c_options->image.zoom_quality);
1722 pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library"),
1723 options->image.use_clutter_renderer, &c_options->image.use_clutter_renderer);
1726 pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"),
1727 options->image.zoom_2pass, &c_options->image.zoom_2pass);
1729 c_options->image.zoom_increment = options->image.zoom_increment;
1730 spin = pref_spin_new(group, _("Zoom increment:"), NULL,
1731 0.01, 4.0, 0.01, 2, (gdouble)options->image.zoom_increment / 100.0,
1732 G_CALLBACK(zoom_increment_cb), NULL);
1733 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1735 group = pref_group_new(vbox, FALSE, _("Fit image to window"), GTK_ORIENTATION_VERTICAL);
1737 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1738 enlargement_button = pref_checkbox_new_int(hbox, _("Allow enlargement of image (max. size in %)"),
1739 options->image.zoom_to_fit_allow_expand, &c_options->image.zoom_to_fit_allow_expand);
1740 spin = pref_spin_new_int(hbox, NULL, NULL,
1742 options->image.max_enlargement_size, &c_options->image.max_enlargement_size);
1743 pref_checkbox_link_sensitivity(enlargement_button, spin);
1744 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."));
1746 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1747 ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (% of actual window):"),
1748 options->image.limit_autofit_size, &c_options->image.limit_autofit_size);
1749 spin = pref_spin_new_int(hbox, NULL, NULL,
1751 options->image.max_autofit_size, &c_options->image.max_autofit_size);
1752 pref_checkbox_link_sensitivity(ct_button, spin);
1753 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."));
1755 group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
1757 pref_checkbox_new_int(group, _("Use custom border color in window mode"),
1758 options->image.use_custom_border_color, &c_options->image.use_custom_border_color);
1760 pref_checkbox_new_int(group, _("Use custom border color in fullscreen mode"),
1761 options->image.use_custom_border_color_in_fullscreen, &c_options->image.use_custom_border_color_in_fullscreen);
1763 pref_color_button_new(group, _("Border color"), &options->image.border_color,
1764 G_CALLBACK(pref_color_button_set_cb), &c_options->image.border_color);
1766 c_options->image.border_color = options->image.border_color;
1768 pref_color_button_new(group, _("Alpha channel color 1"), &options->image.alpha_color_1,
1769 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_1);
1771 pref_color_button_new(group, _("Alpha channel color 2"), &options->image.alpha_color_2,
1772 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_2);
1774 c_options->image.alpha_color_1 = options->image.alpha_color_1;
1775 c_options->image.alpha_color_2 = options->image.alpha_color_2;
1777 group = pref_group_new(vbox, FALSE, _("Convenience"), GTK_ORIENTATION_VERTICAL);
1779 pref_checkbox_new_int(group, _("Auto rotate proofs using Exif information"),
1780 options->image.exif_proof_rotate_enable, &c_options->image.exif_proof_rotate_enable);
1784 static void config_tab_windows(GtkWidget *notebook)
1790 GtkWidget *ct_button;
1792 GtkWidget *image_overlay_template_view;
1793 GtkWidget *scrolled;
1794 GtkTextBuffer *buffer;
1796 vbox = scrolled_notebook_page(notebook, _("Windows"));
1798 group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
1800 ct_button = pref_checkbox_new_int(group, _("Remember window positions"),
1801 options->save_window_positions, &c_options->save_window_positions);
1803 button = pref_checkbox_new_int(group, _("Use saved window positions also for new windows"),
1804 options->use_saved_window_positions_for_new_windows, &c_options->use_saved_window_positions_for_new_windows);
1805 pref_checkbox_link_sensitivity(ct_button, button);
1807 pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
1808 options->tools_restore_state, &c_options->tools_restore_state);
1810 pref_checkbox_new_int(group, _("Remember dialog window positions"),
1811 options->save_dialog_window_positions, &c_options->save_dialog_window_positions);
1813 pref_checkbox_new_int(group, _("Show window IDs"),
1814 options->show_window_ids, &c_options->show_window_ids);
1816 group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
1818 pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
1819 options->image.fit_window_to_image, &c_options->image.fit_window_to_image);
1821 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1822 ct_button = pref_checkbox_new_int(hbox, _("Limit size when auto-sizing window (%):"),
1823 options->image.limit_window_size, &c_options->image.limit_window_size);
1824 spin = pref_spin_new_int(hbox, NULL, NULL,
1826 options->image.max_window_size, &c_options->image.max_window_size);
1827 pref_checkbox_link_sensitivity(ct_button, spin);
1829 group = pref_group_new(vbox, FALSE, _("Full screen"), GTK_ORIENTATION_VERTICAL);
1831 c_options->fullscreen.screen = options->fullscreen.screen;
1832 c_options->fullscreen.above = options->fullscreen.above;
1833 hbox = fullscreen_prefs_selection_new(_("Location:"), &c_options->fullscreen.screen, &c_options->fullscreen.above);
1834 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
1835 gtk_widget_show(hbox);
1837 pref_checkbox_new_int(group, _("Smooth image flip"),
1838 options->fullscreen.clean_flip, &c_options->fullscreen.clean_flip);
1839 pref_checkbox_new_int(group, _("Disable screen saver"),
1840 options->fullscreen.disable_saver, &c_options->fullscreen.disable_saver);
1843 group = pref_group_new(vbox, FALSE, _("Overlay Screen Display"), GTK_ORIENTATION_VERTICAL);
1845 pref_label_new(group, _("Image overlay template"));
1847 scrolled = gtk_scrolled_window_new(NULL, NULL);
1848 gtk_widget_set_size_request(scrolled, 200, 150);
1849 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
1850 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1851 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1852 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 5);
1853 gtk_widget_show(scrolled);
1855 image_overlay_template_view = gtk_text_view_new();
1857 gtk_widget_set_tooltip_markup(image_overlay_template_view,
1858 _("<i>%name%</i> results in the filename of the picture.\n"
1859 "Also available: <i>%collection%</i>, <i>%number%</i>, <i>%total%</i>, <i>%date%</i>,\n"
1860 "<i>%size%</i> (filesize), <i>%width%</i>, <i>%height%</i>, <i>%res%</i> (resolution),\n"
1861 "<i>%rating%</i>, <i>%keywords%</i>, <i>%comment%</i> (XMP), <i>%imagecomment%</i> (JPEG)\n"
1862 "To access exif data use the exif name, e. g. <i>%formatted.Camera%</i> is the formatted camera name,\n"
1863 "<i>%Exif.Photo.DateTimeOriginal%</i> the date of the original shot.\n"
1864 "<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"
1865 "If two or more variables are connected with the |-sign, it prints available variables with a separator.\n"
1866 "<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"
1867 "if there's no ISO information in the Exif data.\n"
1868 "If a line is empty, it is removed. This allows one to add lines that totally disappear when no data is available.\n"
1870 gtk_container_add(GTK_CONTAINER(scrolled), image_overlay_template_view);
1871 gtk_widget_show(image_overlay_template_view);
1873 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
1875 #if GTK_CHECK_VERSION(3,4,0)
1876 button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
1877 G_CALLBACK(image_overlay_set_font_cb), notebook);
1879 button = gtk_font_button_new();
1880 gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Image Overlay Font");
1881 gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->image_overlay.font);
1882 g_signal_connect(G_OBJECT(button), "font-set",
1883 G_CALLBACK(image_overlay_set_font_cb),NULL);
1885 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1886 gtk_widget_show(button);
1888 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Text"), FALSE,
1889 G_CALLBACK(image_overlay_set_text_colour_cb), NULL);
1890 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1891 gtk_widget_show(button);
1893 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Background"), FALSE,
1894 G_CALLBACK(image_overlay_set_background_colour_cb), NULL);
1895 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1896 gtk_widget_show(button);
1897 image_overlay_set_text_colours();
1899 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
1900 G_CALLBACK(image_overlay_default_template_cb), image_overlay_template_view);
1901 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1902 gtk_widget_show(button);
1904 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
1905 G_CALLBACK(image_overlay_help_cb), NULL);
1906 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1907 gtk_widget_show(button);
1909 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_overlay_template_view));
1910 if (options->image_overlay.template_string) gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1911 g_signal_connect(G_OBJECT(buffer), "changed",
1912 G_CALLBACK(image_overlay_template_view_changed_cb), image_overlay_template_view);
1917 static GtkTreeModel *create_class_model(void)
1919 GtkListStore *model;
1923 /* create list store */
1924 model = gtk_list_store_new(1, G_TYPE_STRING);
1925 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
1927 gtk_list_store_append(model, &iter);
1928 gtk_list_store_set(model, &iter, 0, _(format_class_list[i]), -1);
1930 return GTK_TREE_MODEL (model);
1935 static void config_tab_files(GtkWidget *notebook)
1942 GtkWidget *ct_button;
1943 GtkWidget *scrolled;
1944 GtkWidget *filter_view;
1945 GtkCellRenderer *renderer;
1946 GtkTreeSelection *selection;
1947 GtkTreeViewColumn *column;
1949 vbox = scrolled_notebook_page(notebook, _("Files"));
1951 group = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1953 pref_checkbox_new_int(group, _("Show hidden files or folders"),
1954 options->file_filter.show_hidden_files, &c_options->file_filter.show_hidden_files);
1955 pref_checkbox_new_int(group, _("Show parent folder (..)"),
1956 options->file_filter.show_parent_directory, &c_options->file_filter.show_parent_directory);
1957 pref_checkbox_new_int(group, _("Case sensitive sort"),
1958 options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
1959 pref_checkbox_new_int(group, _("Natural sort order"),
1960 options->file_sort.natural, &c_options->file_sort.natural);
1961 pref_checkbox_new_int(group, _("Disable file extension checks"),
1962 options->file_filter.disable_file_extension_checks, &c_options->file_filter.disable_file_extension_checks);
1964 ct_button = pref_checkbox_new_int(group, _("Disable File Filtering"),
1965 options->file_filter.disable, &c_options->file_filter.disable);
1968 group = pref_group_new(vbox, FALSE, _("Grouping sidecar extensions"), GTK_ORIENTATION_VERTICAL);
1970 sidecar_ext_entry = gtk_entry_new();
1971 gtk_entry_set_text(GTK_ENTRY(sidecar_ext_entry), options->sidecar.ext);
1972 gtk_box_pack_start(GTK_BOX(group), sidecar_ext_entry, FALSE, FALSE, 0);
1973 gtk_widget_show(sidecar_ext_entry);
1975 group = pref_group_new(vbox, TRUE, _("File types"), GTK_ORIENTATION_VERTICAL);
1977 frame = pref_group_parent(group);
1978 g_signal_connect(G_OBJECT(ct_button), "toggled",
1979 G_CALLBACK(filter_disable_cb), frame);
1980 gtk_widget_set_sensitive(frame, !options->file_filter.disable);
1982 scrolled = gtk_scrolled_window_new(NULL, NULL);
1983 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
1984 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
1985 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
1986 gtk_widget_show(scrolled);
1988 filter_store = gtk_list_store_new(1, G_TYPE_POINTER);
1989 filter_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(filter_store));
1990 g_object_unref(filter_store);
1991 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1992 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
1994 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), FALSE);
1996 column = gtk_tree_view_column_new();
1997 gtk_tree_view_column_set_title(column, _("Filter"));
1998 gtk_tree_view_column_set_resizable(column, TRUE);
2000 renderer = gtk_cell_renderer_toggle_new();
2001 g_signal_connect(G_OBJECT(renderer), "toggled",
2002 G_CALLBACK(filter_store_enable_cb), filter_store);
2003 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2004 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2005 GINT_TO_POINTER(FE_ENABLE), NULL);
2007 renderer = gtk_cell_renderer_text_new();
2008 g_signal_connect(G_OBJECT(renderer), "edited",
2009 G_CALLBACK(filter_store_ext_edit_cb), filter_store);
2010 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2011 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2012 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2013 GINT_TO_POINTER(FE_EXTENSION), NULL);
2014 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2016 column = gtk_tree_view_column_new();
2017 gtk_tree_view_column_set_title(column, _("Description"));
2018 gtk_tree_view_column_set_resizable(column, TRUE);
2019 gtk_tree_view_column_set_fixed_width(column, 200);
2020 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
2022 renderer = gtk_cell_renderer_text_new();
2023 g_signal_connect(G_OBJECT(renderer), "edited",
2024 G_CALLBACK(filter_store_desc_edit_cb), filter_store);
2025 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2026 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2027 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2028 GINT_TO_POINTER(FE_DESCRIPTION), NULL);
2029 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2031 column = gtk_tree_view_column_new();
2032 gtk_tree_view_column_set_title(column, _("Class"));
2033 gtk_tree_view_column_set_resizable(column, TRUE);
2034 renderer = gtk_cell_renderer_combo_new();
2035 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE,
2036 "model", create_class_model(),
2041 g_signal_connect(G_OBJECT(renderer), "edited",
2042 G_CALLBACK(filter_store_class_edit_cb), filter_store);
2043 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2044 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2045 GINT_TO_POINTER(FE_CLASS), NULL);
2046 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2048 column = gtk_tree_view_column_new();
2049 gtk_tree_view_column_set_title(column, _("Writable"));
2050 gtk_tree_view_column_set_resizable(column, FALSE);
2051 renderer = gtk_cell_renderer_toggle_new();
2052 g_signal_connect(G_OBJECT(renderer), "toggled",
2053 G_CALLBACK(filter_store_writable_cb), filter_store);
2054 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2055 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2056 GINT_TO_POINTER(FE_WRITABLE), NULL);
2057 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2059 column = gtk_tree_view_column_new();
2060 gtk_tree_view_column_set_title(column, _("Sidecar is allowed"));
2061 gtk_tree_view_column_set_resizable(column, FALSE);
2062 renderer = gtk_cell_renderer_toggle_new();
2063 g_signal_connect(G_OBJECT(renderer), "toggled",
2064 G_CALLBACK(filter_store_sidecar_cb), filter_store);
2065 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2066 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2067 GINT_TO_POINTER(FE_ALLOW_SIDECAR), NULL);
2068 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2071 filter_store_populate();
2072 gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
2073 gtk_widget_show(filter_view);
2075 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2077 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2078 G_CALLBACK(filter_default_cb), filter_view);
2079 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2080 gtk_widget_show(button);
2082 button = pref_button_new(NULL, GTK_STOCK_REMOVE, NULL, FALSE,
2083 G_CALLBACK(filter_remove_cb), filter_view);
2084 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2085 gtk_widget_show(button);
2087 button = pref_button_new(NULL, GTK_STOCK_ADD, NULL, FALSE,
2088 G_CALLBACK(filter_add_cb), filter_view);
2089 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2090 gtk_widget_show(button);
2094 static void config_tab_metadata(GtkWidget *notebook)
2099 GtkWidget *ct_button;
2103 vbox = scrolled_notebook_page(notebook, _("Metadata"));
2106 group = pref_group_new(vbox, FALSE, _("Metadata writing process"), GTK_ORIENTATION_VERTICAL);
2108 label = pref_label_new(group, _("Warning: Geeqie is built without Exiv2. Some options are disabled."));
2110 label = pref_label_new(group, _("Metadata are written in the following order. The process ends after first success."));
2111 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2113 ct_button = pref_checkbox_new_int(group, _("1) Save metadata in image files, or sidecar files, according to the XMP standard"),
2114 options->metadata.save_in_image_file, &c_options->metadata.save_in_image_file);
2116 gtk_widget_set_sensitive(ct_button, FALSE);
2119 pref_checkbox_new_int(group, _("2) Save metadata in '.metadata' folder, local to image folder (non-standard)"),
2120 options->metadata.enable_metadata_dirs, &c_options->metadata.enable_metadata_dirs);
2122 text = g_strdup_printf(_("3) Save metadata in Geeqie private directory '%s'"), get_metadata_cache_dir());
2123 label = pref_label_new(group, text);
2124 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2125 gtk_misc_set_padding(GTK_MISC(label), 22, 0);
2128 group = pref_group_new(vbox, FALSE, _("Step 1: Write to image files"), GTK_ORIENTATION_VERTICAL);
2130 gtk_widget_set_sensitive(group, FALSE);
2133 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2134 pref_checkbox_link_sensitivity(ct_button, hbox);
2136 pref_checkbox_new_int(hbox, _("Store metadata also in legacy IPTC tags (converted according to IPTC4XMP standard)"),
2137 options->metadata.save_legacy_IPTC, &c_options->metadata.save_legacy_IPTC);
2139 pref_checkbox_new_int(hbox, _("Warn if the image files are unwritable"),
2140 options->metadata.warn_on_write_problems, &c_options->metadata.warn_on_write_problems);
2142 pref_checkbox_new_int(hbox, _("Ask before writing to image files"),
2143 options->metadata.confirm_write, &c_options->metadata.confirm_write);
2145 pref_checkbox_new_int(hbox, _("Create sidecar files named image.ext.xmp (as opposed to image.xmp)"),
2146 options->metadata.sidecar_extended_name, &c_options->metadata.sidecar_extended_name);
2148 group = pref_group_new(vbox, FALSE, _("Step 2 and 3: write to Geeqie private files"), GTK_ORIENTATION_VERTICAL);
2150 gtk_widget_set_sensitive(group, FALSE);
2153 pref_checkbox_new_int(group, _("Use GQview legacy metadata format (supports only keywords and comments) instead of XMP"),
2154 options->metadata.save_legacy_format, &c_options->metadata.save_legacy_format);
2157 group = pref_group_new(vbox, FALSE, _("Miscellaneous"), GTK_ORIENTATION_VERTICAL);
2158 pref_checkbox_new_int(group, _("Write the same description tags (keywords, comment, etc.) to all grouped sidecars"),
2159 options->metadata.sync_grouped_files, &c_options->metadata.sync_grouped_files);
2161 pref_checkbox_new_int(group, _("Allow keywords to differ only in case"),
2162 options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
2164 ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"),
2165 options->metadata.write_orientation, &c_options->metadata.write_orientation);
2167 gtk_widget_set_sensitive(ct_button, FALSE);
2170 group = pref_group_new(vbox, FALSE, _("Auto-save options"), GTK_ORIENTATION_VERTICAL);
2172 ct_button = pref_checkbox_new_int(group, _("Write metadata after timeout"),
2173 options->metadata.confirm_after_timeout, &c_options->metadata.confirm_after_timeout);
2175 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2176 pref_checkbox_link_sensitivity(ct_button, hbox);
2178 pref_spin_new_int(hbox, _("Timeout (seconds):"), NULL, 0, 900, 1,
2179 options->metadata.confirm_timeout, &c_options->metadata.confirm_timeout);
2181 pref_checkbox_new_int(group, _("Write metadata on image change"),
2182 options->metadata.confirm_on_image_change, &c_options->metadata.confirm_on_image_change);
2184 pref_checkbox_new_int(group, _("Write metadata on directory change"),
2185 options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
2190 static void intent_menu_cb(GtkWidget *combo, gpointer data)
2192 gint *option = data;
2194 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
2198 *option = INTENT_PERCEPTUAL;
2201 *option = INTENT_RELATIVE_COLORIMETRIC;
2204 *option = INTENT_SATURATION;
2207 *option = INTENT_ABSOLUTE_COLORIMETRIC;
2212 static void add_intent_menu(GtkWidget *table, gint column, gint row, const gchar *text,
2213 gint option, gint *option_c)
2220 pref_table_label(table, column, row, text, 0.0);
2222 combo = gtk_combo_box_text_new();
2224 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Perceptual"));
2225 if (option == INTENT_PERCEPTUAL) current = 0;
2226 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Relative Colorimetric"));
2227 if (option == INTENT_RELATIVE_COLORIMETRIC) current = 1;
2228 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Saturation"));
2229 if (option == INTENT_SATURATION) current = 2;
2230 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Absolute Colorimetric"));
2231 if (option == INTENT_ABSOLUTE_COLORIMETRIC) current = 3;
2233 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
2235 gtk_widget_set_tooltip_text(combo,"Refer to the lcms documentation for the defaults used when the selected Intent is not available");
2237 g_signal_connect(G_OBJECT(combo), "changed",
2238 G_CALLBACK(intent_menu_cb), option_c);
2240 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
2241 GTK_EXPAND | GTK_FILL, 0, 0, 0);
2242 gtk_widget_show(combo);
2246 static void config_tab_color(GtkWidget *notebook)
2255 vbox = scrolled_notebook_page(notebook, _("Color management"));
2257 group = pref_group_new(vbox, FALSE, _("Input profiles"), GTK_ORIENTATION_VERTICAL);
2259 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
2262 table = pref_table_new(group, 3, COLOR_PROFILE_INPUTS + 1, FALSE, FALSE);
2263 gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
2265 label = pref_table_label(table, 0, 0, _("Type"), 0.0);
2266 pref_label_bold(label, TRUE, FALSE);
2268 label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
2269 pref_label_bold(label, TRUE, FALSE);
2271 label = pref_table_label(table, 2, 0, _("File"), 0.0);
2272 pref_label_bold(label, TRUE, FALSE);
2274 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
2279 buf = g_strdup_printf(_("Input %d:"), i + COLOR_PROFILE_FILE);
2280 pref_table_label(table, 0, i + 1, buf, 1.0);
2283 entry = gtk_entry_new();
2284 gtk_entry_set_max_length(GTK_ENTRY(entry), EDITOR_NAME_MAX_LENGTH);
2285 if (options->color_profile.input_name[i])
2287 gtk_entry_set_text(GTK_ENTRY(entry), options->color_profile.input_name[i]);
2289 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, i + 1, i + 2,
2290 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2291 gtk_widget_show(entry);
2292 color_profile_input_name_entry[i] = entry;
2294 tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, ".icc", "ICC Files", NULL);
2295 tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
2296 gtk_widget_set_size_request(entry, 160, -1);
2297 gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
2298 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2299 gtk_widget_show(tabcomp);
2300 color_profile_input_file_entry[i] = entry;
2303 group = pref_group_new(vbox, FALSE, _("Screen profile"), GTK_ORIENTATION_VERTICAL);
2305 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
2307 pref_checkbox_new_int(group, _("Use system screen profile if available"),
2308 options->color_profile.use_x11_screen_profile, &c_options->color_profile.use_x11_screen_profile);
2310 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2312 pref_table_label(table, 0, 0, _("Screen:"), 1.0);
2313 tabcomp = tab_completion_new(&color_profile_screen_file_entry,
2314 options->color_profile.screen_file, NULL, ".icc", "ICC Files", NULL);
2315 tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
2316 gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
2318 add_intent_menu(table, 0, 1, _("Render Intent:"), options->color_profile.render_intent, &c_options->color_profile.render_intent);
2320 gtk_table_attach(GTK_TABLE(table), tabcomp, 1, 2,
2322 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2324 gtk_widget_show(tabcomp);
2327 /* advanced entry tab */
2328 static void config_tab_behavior(GtkWidget *notebook)
2335 GtkWidget *ct_button;
2340 vbox = scrolled_notebook_page(notebook, _("Behavior"));
2342 group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
2344 pref_checkbox_new_int(group, _("Confirm file delete"),
2345 options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
2346 pref_checkbox_new_int(group, _("Enable Delete key"),
2347 options->file_ops.enable_delete_key, &c_options->file_ops.enable_delete_key);
2349 ct_button = pref_checkbox_new_int(group, _("Safe delete"),
2350 options->file_ops.safe_delete_enable, &c_options->file_ops.safe_delete_enable);
2352 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2353 pref_checkbox_link_sensitivity(ct_button, hbox);
2355 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
2356 pref_label_new(hbox, _("Folder:"));
2358 tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL, NULL, NULL);
2359 tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
2360 gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
2361 gtk_widget_show(tabcomp);
2363 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2364 pref_checkbox_link_sensitivity(ct_button, hbox);
2366 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
2367 spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MB"),
2368 0, 2048, 1, options->file_ops.safe_delete_folder_maxsize, &c_options->file_ops.safe_delete_folder_maxsize);
2369 gtk_widget_set_tooltip_markup(spin, _("Set to 0 for unlimited size"));
2370 button = pref_button_new(NULL, NULL, _("View"), FALSE,
2371 G_CALLBACK(safe_delete_view_cb), NULL);
2372 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2373 gtk_widget_show(button);
2375 button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
2376 G_CALLBACK(safe_delete_clear_cb), NULL);
2377 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2378 gtk_widget_show(button);
2381 group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
2383 pref_checkbox_new_int(group, _("Descend folders in tree view"),
2384 options->tree_descend_subdirs, &c_options->tree_descend_subdirs);
2386 pref_checkbox_new_int(group, _("In place renaming"),
2387 options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
2389 pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
2390 options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
2392 marks = pref_checkbox_new_int(group, _("Save marks on exit"),
2393 options->marks_save, &c_options->marks_save);
2394 gtk_widget_set_tooltip_text(marks,"Note that marks linked to a keyword will be saved irrespective of this setting");
2396 pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
2397 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
2399 pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
2400 16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
2402 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2403 add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
2405 group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
2407 pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
2408 options->progressive_key_scrolling, &c_options->progressive_key_scrolling);
2409 pref_spin_new_int(group, _("Keyboard scrolling step multiplier:"), NULL,
2410 1, 32, 1, options->keyboard_scroll_step, (int *)&c_options->keyboard_scroll_step);
2411 pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
2412 options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
2413 pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
2414 options->image_lm_click_nav, &c_options->image_lm_click_nav);
2415 pref_checkbox_new_int(group, _("Play video by left click on image"),
2416 options->image_l_click_video, &c_options->image_l_click_video);
2417 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2418 add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
2422 group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
2424 pref_spin_new_int(group, _("Debug level:"), NULL,
2425 DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
2427 pref_checkbox_new_int(group, _("Timer data"),
2428 options->log_window.timer_data, &c_options->log_window.timer_data);
2430 pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
2431 1, 99999, 1, options->log_window_lines, &options->log_window_lines);
2435 /* accelerators tab */
2436 static void config_tab_accelerators(GtkWidget *notebook)
2442 GtkWidget *scrolled;
2443 GtkWidget *accel_view;
2444 GtkCellRenderer *renderer;
2445 GtkTreeSelection *selection;
2446 GtkTreeViewColumn *column;
2448 vbox = scrolled_notebook_page(notebook, _("Keyboard"));
2450 group = pref_group_new(vbox, TRUE, _("Accelerators"), GTK_ORIENTATION_VERTICAL);
2452 scrolled = gtk_scrolled_window_new(NULL, NULL);
2453 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2454 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2455 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2456 gtk_widget_show(scrolled);
2458 accel_store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
2460 accel_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(accel_store));
2461 g_object_unref(accel_store);
2462 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(accel_view));
2463 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
2465 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(accel_view), FALSE);
2467 renderer = gtk_cell_renderer_text_new();
2469 column = gtk_tree_view_column_new_with_attributes(_("Action"),
2474 gtk_tree_view_column_set_sort_column_id(column, AE_ACTION);
2475 gtk_tree_view_column_set_resizable(column, TRUE);
2476 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
2479 renderer = gtk_cell_renderer_accel_new();
2480 g_signal_connect(G_OBJECT(renderer), "accel-cleared",
2481 G_CALLBACK(accel_store_cleared_cb), accel_store);
2482 g_signal_connect(G_OBJECT(renderer), "accel-edited",
2483 G_CALLBACK(accel_store_edited_cb), accel_store);
2486 g_object_set (renderer,
2488 "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
2491 column = gtk_tree_view_column_new_with_attributes(_("KEY"),
2496 gtk_tree_view_column_set_sort_column_id(column, AE_KEY);
2497 gtk_tree_view_column_set_resizable(column, TRUE);
2498 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
2500 renderer = gtk_cell_renderer_text_new();
2502 column = gtk_tree_view_column_new_with_attributes(_("Tooltip"),
2507 gtk_tree_view_column_set_sort_column_id(column, AE_TOOLTIP);
2508 gtk_tree_view_column_set_resizable(column, TRUE);
2509 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
2511 renderer = gtk_cell_renderer_text_new();
2513 column = gtk_tree_view_column_new_with_attributes("Accel",
2518 gtk_tree_view_column_set_sort_column_id(column, AE_ACCEL);
2519 gtk_tree_view_column_set_resizable(column, TRUE);
2520 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
2522 accel_store_populate();
2523 gtk_container_add(GTK_CONTAINER(scrolled), accel_view);
2524 gtk_widget_show(accel_view);
2526 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2528 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2529 G_CALLBACK(accel_default_cb), accel_view);
2530 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2531 gtk_widget_show(button);
2533 button = pref_button_new(NULL, NULL, _("Reset selected"), FALSE,
2534 G_CALLBACK(accel_reset_cb), accel_view);
2535 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2536 gtk_widget_show(button);
2540 static void config_tab_toolbar(GtkWidget *notebook)
2543 GtkWidget *toolbardata;
2546 lw = layout_window_list->data;
2548 vbox = scrolled_notebook_page(notebook, _("Toolbar"));
2550 toolbardata = toolbar_select_new(lw);
2551 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
2552 gtk_widget_show(vbox);
2556 static void config_tab_stereo(GtkWidget *notebook)
2564 GtkWidget *fs_button;
2565 vbox = scrolled_notebook_page(notebook, _("Stereo"));
2567 group = pref_group_new(vbox, FALSE, _("Windowed stereo mode"), GTK_ORIENTATION_VERTICAL);
2569 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2570 add_stereo_mode_menu(table, 0, 0, _("Windowed stereo mode"), options->stereo.mode, &c_options->stereo.mode, FALSE);
2572 table = pref_table_new(group, 2, 2, TRUE, FALSE);
2573 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
2574 pref_checkbox_new_int(box, _("Mirror left image"),
2575 options->stereo.mode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.mirror_left);
2576 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
2577 pref_checkbox_new_int(box, _("Flip left image"),
2578 options->stereo.mode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.flip_left);
2579 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
2580 pref_checkbox_new_int(box, _("Mirror right image"),
2581 options->stereo.mode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.mirror_right);
2582 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
2583 pref_checkbox_new_int(box, _("Flip right image"),
2584 options->stereo.mode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.flip_right);
2585 pref_checkbox_new_int(group, _("Swap left and right images"),
2586 options->stereo.mode & PR_STEREO_SWAP, &c_options->stereo.tmp.swap);
2587 pref_checkbox_new_int(group, _("Disable stereo mode on single image source"),
2588 options->stereo.mode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.temp_disable);
2590 group = pref_group_new(vbox, FALSE, _("Fullscreen stereo mode"), GTK_ORIENTATION_VERTICAL);
2591 fs_button = pref_checkbox_new_int(group, _("Use different settings for fullscreen"),
2592 options->stereo.enable_fsmode, &c_options->stereo.enable_fsmode);
2593 box2 = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2594 pref_checkbox_link_sensitivity(fs_button, box2);
2595 table = pref_table_new(box2, 2, 1, FALSE, FALSE);
2596 add_stereo_mode_menu(table, 0, 0, _("Fullscreen stereo mode"), options->stereo.fsmode, &c_options->stereo.fsmode, TRUE);
2597 table = pref_table_new(box2, 2, 2, TRUE, FALSE);
2598 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
2599 pref_checkbox_new_int(box, _("Mirror left image"),
2600 options->stereo.fsmode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.fs_mirror_left);
2601 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
2602 pref_checkbox_new_int(box, _("Flip left image"),
2603 options->stereo.fsmode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.fs_flip_left);
2604 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
2605 pref_checkbox_new_int(box, _("Mirror right image"),
2606 options->stereo.fsmode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.fs_mirror_right);
2607 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
2608 pref_checkbox_new_int(box, _("Flip right image"),
2609 options->stereo.fsmode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.fs_flip_right);
2610 pref_checkbox_new_int(box2, _("Swap left and right images"),
2611 options->stereo.fsmode & PR_STEREO_SWAP, &c_options->stereo.tmp.fs_swap);
2612 pref_checkbox_new_int(box2, _("Disable stereo mode on single image source"),
2613 options->stereo.fsmode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.fs_temp_disable);
2615 group2 = pref_group_new(box2, FALSE, _("Fixed position"), GTK_ORIENTATION_VERTICAL);
2616 table = pref_table_new(group2, 5, 3, FALSE, FALSE);
2617 pref_table_spin_new_int(table, 0, 0, _("Width"), NULL,
2618 1, 5000, 1, options->stereo.fixed_w, &c_options->stereo.fixed_w);
2619 pref_table_spin_new_int(table, 3, 0, _("Height"), NULL,
2620 1, 5000, 1, options->stereo.fixed_h, &c_options->stereo.fixed_h);
2621 pref_table_spin_new_int(table, 0, 1, _("Left X"), NULL,
2622 0, 5000, 1, options->stereo.fixed_x1, &c_options->stereo.fixed_x1);
2623 pref_table_spin_new_int(table, 3, 1, _("Left Y"), NULL,
2624 0, 5000, 1, options->stereo.fixed_y1, &c_options->stereo.fixed_y1);
2625 pref_table_spin_new_int(table, 0, 2, _("Right X"), NULL,
2626 0, 5000, 1, options->stereo.fixed_x2, &c_options->stereo.fixed_x2);
2627 pref_table_spin_new_int(table, 3, 2, _("Right Y"), NULL,
2628 0, 5000, 1, options->stereo.fixed_y2, &c_options->stereo.fixed_y2);
2632 /* Main preferences window */
2633 static void config_window_create(void)
2635 GtkWidget *win_vbox;
2637 GtkWidget *notebook;
2639 GtkWidget *ct_button;
2641 if (!c_options) c_options = init_options(NULL);
2643 configwindow = window_new(GTK_WINDOW_TOPLEVEL, "preferences", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Preferences"));
2644 gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
2645 g_signal_connect(G_OBJECT(configwindow), "delete_event",
2646 G_CALLBACK(config_window_delete), NULL);
2647 gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
2648 gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
2649 gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
2651 win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
2652 gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
2653 gtk_widget_show(win_vbox);
2655 notebook = gtk_notebook_new();
2656 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP);
2657 gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
2659 config_tab_general(notebook);
2660 config_tab_image(notebook);
2661 config_tab_windows(notebook);
2662 config_tab_accelerators(notebook);
2663 config_tab_files(notebook);
2664 config_tab_metadata(notebook);
2665 config_tab_color(notebook);
2666 config_tab_stereo(notebook);
2667 config_tab_behavior(notebook);
2668 config_tab_toolbar(notebook);
2670 hbox = gtk_hbutton_box_new();
2671 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
2672 gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
2673 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
2674 gtk_widget_show(hbox);
2676 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
2677 G_CALLBACK(config_window_help_cb), notebook);
2678 gtk_container_add(GTK_CONTAINER(hbox), button);
2679 gtk_widget_set_can_default(button, TRUE);
2680 gtk_widget_show(button);
2682 button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
2683 G_CALLBACK(config_window_ok_cb), NULL);
2684 gtk_container_add(GTK_CONTAINER(hbox), button);
2685 gtk_widget_set_can_default(button, TRUE);
2686 gtk_widget_grab_default(button);
2687 gtk_widget_show(button);
2691 button = pref_button_new(NULL, GTK_STOCK_SAVE, NULL, FALSE,
2692 G_CALLBACK(config_window_save_cb), NULL);
2693 gtk_container_add(GTK_CONTAINER(hbox), button);
2694 gtk_widget_set_can_default(button, TRUE);
2695 gtk_widget_show(button);
2697 button = pref_button_new(NULL, GTK_STOCK_APPLY, NULL, FALSE,
2698 G_CALLBACK(config_window_apply_cb), NULL);
2699 gtk_container_add(GTK_CONTAINER(hbox), button);
2700 gtk_widget_set_can_default(button, TRUE);
2701 gtk_widget_show(button);
2703 button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
2704 G_CALLBACK(config_window_close_cb), NULL);
2705 gtk_container_add(GTK_CONTAINER(hbox), button);
2706 gtk_widget_set_can_default(button, TRUE);
2707 gtk_widget_show(button);
2709 if (!generic_dialog_get_alternative_button_order(configwindow))
2711 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
2714 gtk_widget_show(notebook);
2716 gtk_widget_show(configwindow);
2720 *-----------------------------------------------------------------------------
2721 * config window show (public)
2722 *-----------------------------------------------------------------------------
2725 void show_config_window(void)
2729 gtk_window_present(GTK_WINDOW(configwindow));
2733 config_window_create();
2742 void show_about_window(LayoutWindow *lw)
2744 GdkPixbuf *pixbuf_logo;
2745 GdkPixbuf *pixbuf_icon;
2746 gchar *authors[1000];
2754 #define LINE_LENGTH 1000
2755 gchar line[LINE_LENGTH];
2757 copyright = g_string_new(NULL);
2758 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");
2760 zd_path = g_build_filename(GQ_BIN_DIR, TIMEZONE_DATABASE, NULL);
2761 cd = ZDOpenDatabase(zd_path);
2764 copyright = g_string_append(copyright, ZDGetNotice(cd));
2766 ZDCloseDatabase(cd);
2770 path = g_build_filename(GQ_HELPDIR, "AUTHORS", NULL);
2771 fp = fopen(path, "r");
2774 while(fgets(line, LINE_LENGTH, fp))
2776 /* get rid of ending \n from fgets */
2777 line[strlen(line) - 1] = '\0';
2778 authors[i_authors] = g_strdup(line);
2781 authors[i_authors] = NULL;
2786 comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
2787 "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
2789 pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
2790 pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
2791 gtk_show_about_dialog(GTK_WINDOW(lw->window),
2792 "title", _("About Geeqie"),
2794 "program-name", GQ_APPNAME,
2796 "logo", pixbuf_logo,
2797 "icon", pixbuf_icon,
2798 "website", GQ_WEBSITE,
2799 "website-label", "Website",
2800 "comments", comment,
2802 "translator-credits", _("translator-credits"),
2803 "wrap-license", TRUE,
2804 "license", copyright->str,
2807 g_string_free(copyright, TRUE);
2810 while(n < i_authors)
2820 static void image_overlay_set_text_colours()
2822 c_options->image_overlay.text_red = options->image_overlay.text_red;
2823 c_options->image_overlay.text_green = options->image_overlay.text_green;
2824 c_options->image_overlay.text_blue = options->image_overlay.text_blue;
2825 c_options->image_overlay.text_alpha = options->image_overlay.text_alpha;
2826 c_options->image_overlay.background_red = options->image_overlay.background_red;
2827 c_options->image_overlay.background_green = options->image_overlay.background_green;
2828 c_options->image_overlay.background_blue = options->image_overlay.background_blue;
2829 c_options->image_overlay.background_alpha = options->image_overlay.background_alpha;
2831 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */