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;
411 set_debug_level(debug_c);
415 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
417 config_entry_to_option(color_profile_input_name_entry[i], &options->color_profile.input_name[i], NULL);
418 config_entry_to_option(color_profile_input_file_entry[i], &options->color_profile.input_file[i], NULL);
420 config_entry_to_option(color_profile_screen_file_entry, &options->color_profile.screen_file, NULL);
421 options->color_profile.use_x11_screen_profile = c_options->color_profile.use_x11_screen_profile;
422 if (options->color_profile.render_intent != c_options->color_profile.render_intent)
424 options->color_profile.render_intent = c_options->color_profile.render_intent;
429 image_options_sync();
434 layout_refresh(NULL);
437 if (accel_store) gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_apply_cb, NULL);
443 *-----------------------------------------------------------------------------
444 * config window main button callbacks (private)
445 *-----------------------------------------------------------------------------
448 static void config_window_close_cb(GtkWidget *widget, gpointer data)
450 gtk_widget_destroy(configwindow);
455 static void config_window_help_cb(GtkWidget *widget, gpointer data)
457 GtkWidget *notebook = data;
460 static gchar *html_section[] =
462 "GuideOptionsGeneral.html",
463 "GuideOptionsImage.html",
464 "GuideOptionsWindow.html",
465 "GuideOptionsKeyboard.html",
466 "GuideOptionsFiltering.html",
467 "GuideOptionsMetadata.html",
468 "GuideOptionsColor.html",
469 "GuideOptionsStereo.html",
470 "GuideOptionsBehavior.html",
471 "GuideOptionsToolbar.html"
474 i = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
475 help_window_show(html_section[i]);
478 static gboolean config_window_delete(GtkWidget *widget, GdkEventAny *event, gpointer data)
480 config_window_close_cb(NULL, NULL);
484 static void config_window_ok_cb(GtkWidget *widget, gpointer data)
486 config_window_apply();
487 config_window_close_cb(NULL, NULL);
490 static void config_window_apply_cb(GtkWidget *widget, gpointer data)
493 lw = layout_window_list->data;
495 config_window_apply();
496 layout_util_sync(lw);
499 static void config_window_save_cb(GtkWidget *widget, gpointer data)
501 config_window_apply();
502 save_options(options);
506 *-----------------------------------------------------------------------------
507 * config window setup (private)
508 *-----------------------------------------------------------------------------
511 static void quality_menu_cb(GtkWidget *combo, gpointer data)
515 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
519 *option = GDK_INTERP_NEAREST;
522 *option = GDK_INTERP_TILES;
525 *option = GDK_INTERP_BILINEAR;
528 *option = GDK_INTERP_HYPER;
533 static void clipboard_selection_menu_cb(GtkWidget *combo, gpointer data)
537 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
549 static void add_quality_menu(GtkWidget *table, gint column, gint row, const gchar *text,
550 guint option, guint *option_c)
557 pref_table_label(table, column, row, text, 0.0);
559 combo = gtk_combo_box_text_new();
561 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Nearest (worst, but fastest)"));
562 if (option == GDK_INTERP_NEAREST) current = 0;
563 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Tiles"));
564 if (option == GDK_INTERP_TILES) current = 1;
565 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Bilinear"));
566 if (option == GDK_INTERP_BILINEAR) current = 2;
567 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Hyper (best, but slowest)"));
568 if (option == GDK_INTERP_HYPER) current = 3;
570 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
572 g_signal_connect(G_OBJECT(combo), "changed",
573 G_CALLBACK(quality_menu_cb), option_c);
575 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
576 GTK_EXPAND | GTK_FILL, 0, 0, 0);
577 gtk_widget_show(combo);
580 static void add_clipboard_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
581 gint option, gint *option_c)
588 pref_table_label(table, column, row, text, 0.0);
590 combo = gtk_combo_box_text_new();
592 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("PRIMARY"));
593 if (option == PRIMARY) current = 0;
594 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("CLIPBOARD"));
595 if (option == CLIPBOARD) current = 1;
597 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
599 g_signal_connect(G_OBJECT(combo), "changed",
600 G_CALLBACK(clipboard_selection_menu_cb), option_c);
602 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
603 GTK_EXPAND | GTK_FILL, 0, 0, 0);
604 gtk_widget_show(combo);
607 static void thumb_size_menu_cb(GtkWidget *combo, gpointer data)
611 n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
614 if ((guint) n < sizeof(thumb_size_list) / sizeof(ThumbSize))
616 c_options->thumbnails.max_width = thumb_size_list[n].w;
617 c_options->thumbnails.max_height = thumb_size_list[n].h;
621 c_options->thumbnails.max_width = options->thumbnails.max_width;
622 c_options->thumbnails.max_height = options->thumbnails.max_height;
626 static void add_thumb_size_menu(GtkWidget *table, gint column, gint row, gchar *text)
632 c_options->thumbnails.max_width = options->thumbnails.max_width;
633 c_options->thumbnails.max_height = options->thumbnails.max_height;
635 pref_table_label(table, column, row, text, 0.0);
637 combo = gtk_combo_box_text_new();
640 for (i = 0; (guint) i < sizeof(thumb_size_list) / sizeof(ThumbSize); i++)
645 w = thumb_size_list[i].w;
646 h = thumb_size_list[i].h;
648 buf = g_strdup_printf("%d x %d", w, h);
649 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
652 if (w == options->thumbnails.max_width && h == options->thumbnails.max_height) current = i;
659 buf = g_strdup_printf("%s %d x %d", _("Custom"), options->thumbnails.max_width, options->thumbnails.max_height);
660 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
666 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
667 g_signal_connect(G_OBJECT(combo), "changed",
668 G_CALLBACK(thumb_size_menu_cb), NULL);
670 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
671 GTK_EXPAND | GTK_FILL, 0, 0, 0);
672 gtk_widget_show(combo);
675 static void stereo_mode_menu_cb(GtkWidget *combo, gpointer data)
679 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
683 *option = PR_STEREO_NONE;
686 *option = PR_STEREO_ANAGLYPH_RC;
689 *option = PR_STEREO_ANAGLYPH_GM;
692 *option = PR_STEREO_ANAGLYPH_YB;
695 *option = PR_STEREO_ANAGLYPH_GRAY_RC;
698 *option = PR_STEREO_ANAGLYPH_GRAY_GM;
701 *option = PR_STEREO_ANAGLYPH_GRAY_YB;
704 *option = PR_STEREO_ANAGLYPH_DB_RC;
707 *option = PR_STEREO_ANAGLYPH_DB_GM;
710 *option = PR_STEREO_ANAGLYPH_DB_YB;
713 *option = PR_STEREO_HORIZ;
716 *option = PR_STEREO_HORIZ | PR_STEREO_HALF;
719 *option = PR_STEREO_VERT;
722 *option = PR_STEREO_VERT | PR_STEREO_HALF;
725 *option = PR_STEREO_FIXED;
730 static void add_stereo_mode_menu(GtkWidget *table, gint column, gint row, const gchar *text,
731 gint option, gint *option_c, gboolean add_fixed)
738 pref_table_label(table, column, row, text, 0.0);
740 combo = gtk_combo_box_text_new();
742 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Single image"));
744 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Red-Cyan"));
745 if (option & PR_STEREO_ANAGLYPH_RC) current = 1;
746 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Green-Magenta"));
747 if (option & PR_STEREO_ANAGLYPH_GM) current = 2;
748 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Yellow-Blue"));
749 if (option & PR_STEREO_ANAGLYPH_YB) current = 3;
750 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Red-Cyan"));
751 if (option & PR_STEREO_ANAGLYPH_GRAY_RC) current = 4;
752 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Green-Magenta"));
753 if (option & PR_STEREO_ANAGLYPH_GRAY_GM) current = 5;
754 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Yellow-Blue"));
755 if (option & PR_STEREO_ANAGLYPH_GRAY_YB) current = 6;
756 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Red-Cyan"));
757 if (option & PR_STEREO_ANAGLYPH_DB_RC) current = 7;
758 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Green-Magenta"));
759 if (option & PR_STEREO_ANAGLYPH_DB_GM) current = 8;
760 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Yellow-Blue"));
761 if (option & PR_STEREO_ANAGLYPH_DB_YB) current = 9;
763 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side"));
764 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side Half size"));
765 if (option & PR_STEREO_HORIZ)
768 if (option & PR_STEREO_HALF) current = 11;
771 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom"));
772 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom Half size"));
773 if (option & PR_STEREO_VERT)
776 if (option & PR_STEREO_HALF) current = 13;
781 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Fixed position"));
782 if (option & PR_STEREO_FIXED) current = 14;
785 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
787 g_signal_connect(G_OBJECT(combo), "changed",
788 G_CALLBACK(stereo_mode_menu_cb), option_c);
790 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
791 GTK_EXPAND | GTK_FILL, 0, 0, 0);
792 gtk_widget_show(combo);
795 static void video_menu_cb(GtkWidget *combo, gpointer data)
797 gchar **option = data;
799 EditorDescription *ed = g_list_nth_data(editor_list_get(), gtk_combo_box_get_active(GTK_COMBO_BOX(combo)));
803 static void video_menu_populate(gpointer data, gpointer user_data)
805 GtkWidget *combo = user_data;
806 EditorDescription *ed = data;
808 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), ed->name);
811 static void add_video_menu(GtkWidget *table, gint column, gint row, const gchar *text,
812 gchar *option, gchar **option_c)
816 /* use lists since they are sorted */
817 GList *eds = editor_list_get();
821 pref_table_label(table, column, row, text, 0.0);
823 combo = gtk_combo_box_text_new();
824 g_list_foreach(eds,video_menu_populate,(gpointer)combo);
825 current = option ? g_list_index(eds,g_hash_table_lookup(editors,option)): -1;
827 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
829 g_signal_connect(G_OBJECT(combo), "changed",
830 G_CALLBACK(video_menu_cb), option_c);
832 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
833 GTK_EXPAND | GTK_FILL, 0, 0, 0);
834 gtk_widget_show(combo);
837 static void filter_store_populate(void)
841 if (!filter_store) return;
843 gtk_list_store_clear(filter_store);
845 work = filter_get_list();
854 gtk_list_store_append(filter_store, &iter);
855 gtk_list_store_set(filter_store, &iter, 0, fe, -1);
859 static void filter_store_ext_edit_cb(GtkCellRendererText *cell, gchar *path_str,
860 gchar *new_text, gpointer data)
862 GtkWidget *model = data;
863 FilterEntry *fe = data;
867 if (!new_text || strlen(new_text) < 1) return;
869 tpath = gtk_tree_path_new_from_string(path_str);
870 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
871 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
873 g_free(fe->extensions);
874 fe->extensions = g_strdup(new_text);
876 gtk_tree_path_free(tpath);
880 static void filter_store_class_edit_cb(GtkCellRendererText *cell, gchar *path_str,
881 gchar *new_text, gpointer data)
883 GtkWidget *model = data;
884 FilterEntry *fe = data;
889 if (!new_text || !new_text[0]) return;
891 tpath = gtk_tree_path_new_from_string(path_str);
892 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
893 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
895 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
897 if (strcmp(new_text, _(format_class_list[i])) == 0)
904 gtk_tree_path_free(tpath);
908 static void filter_store_desc_edit_cb(GtkCellRendererText *cell, gchar *path_str,
909 gchar *new_text, gpointer data)
911 GtkWidget *model = data;
916 if (!new_text || !new_text[0]) return;
918 tpath = gtk_tree_path_new_from_string(path_str);
919 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
920 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
922 g_free(fe->description);
923 fe->description = g_strdup(new_text);
925 gtk_tree_path_free(tpath);
928 static void filter_store_enable_cb(GtkCellRendererToggle *renderer,
929 gchar *path_str, gpointer data)
931 GtkWidget *model = data;
936 tpath = gtk_tree_path_new_from_string(path_str);
937 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
938 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
940 fe->enabled = !fe->enabled;
942 gtk_tree_path_free(tpath);
946 static void filter_store_writable_cb(GtkCellRendererToggle *renderer,
947 gchar *path_str, gpointer data)
949 GtkWidget *model = data;
954 tpath = gtk_tree_path_new_from_string(path_str);
955 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
956 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
958 fe->writable = !fe->writable;
959 if (fe->writable) fe->allow_sidecar = FALSE;
961 gtk_tree_path_free(tpath);
965 static void filter_store_sidecar_cb(GtkCellRendererToggle *renderer,
966 gchar *path_str, gpointer data)
968 GtkWidget *model = data;
973 tpath = gtk_tree_path_new_from_string(path_str);
974 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
975 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
977 fe->allow_sidecar = !fe->allow_sidecar;
978 if (fe->allow_sidecar) fe->writable = FALSE;
980 gtk_tree_path_free(tpath);
984 static void filter_set_func(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
985 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
989 gtk_tree_model_get(tree_model, iter, 0, &fe, -1);
991 switch (GPOINTER_TO_INT(data))
994 g_object_set(GTK_CELL_RENDERER(cell),
995 "active", fe->enabled, NULL);
998 g_object_set(GTK_CELL_RENDERER(cell),
999 "text", fe->extensions, NULL);
1001 case FE_DESCRIPTION:
1002 g_object_set(GTK_CELL_RENDERER(cell),
1003 "text", fe->description, NULL);
1006 g_object_set(GTK_CELL_RENDERER(cell),
1007 "text", _(format_class_list[fe->file_class]), NULL);
1010 g_object_set(GTK_CELL_RENDERER(cell),
1011 "active", fe->writable, NULL);
1013 case FE_ALLOW_SIDECAR:
1014 g_object_set(GTK_CELL_RENDERER(cell),
1015 "active", fe->allow_sidecar, NULL);
1020 static gboolean filter_add_scroll(gpointer data)
1024 GtkCellRenderer *cell;
1025 GtkTreeViewColumn *column;
1026 GList *list_columns;
1031 rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(filter_store), NULL);
1032 path = gtk_tree_path_new_from_indices(rows-1, -1);
1034 list_columns = gtk_tree_view_get_columns(GTK_TREE_VIEW(data));
1036 column = g_list_nth(list_columns,i)->data;
1037 title = gtk_tree_view_column_get_title(GTK_TREE_VIEW_COLUMN(column));
1039 } while (strcmp(title, "Filter") !=0 );
1041 list_cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column));
1042 cell = g_list_last(list_cells)->data;
1044 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1045 path, column, FALSE, 0.0, 0.0 );
1046 gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(data),
1047 path, column, cell, TRUE);
1049 gtk_tree_path_free(path);
1050 g_list_free(list_cells);
1051 g_list_free(list_columns);
1056 static void filter_add_cb(GtkWidget *widget, gpointer data)
1058 filter_add_unique("description", ".new", FORMAT_CLASS_IMAGE, TRUE, FALSE, TRUE);
1059 filter_store_populate();
1061 g_idle_add((GSourceFunc)filter_add_scroll, data);
1064 static void filter_remove_cb(GtkWidget *widget, gpointer data)
1066 GtkWidget *filter_view = data;
1067 GtkTreeSelection *selection;
1071 if (!filter_store) return;
1072 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1073 if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) return;
1074 gtk_tree_model_get(GTK_TREE_MODEL(filter_store), &iter, 0, &fe, -1);
1077 filter_remove_entry(fe);
1079 filter_store_populate();
1082 static gboolean filter_default_ok_scroll(GtkTreeView *data)
1086 GtkTreeViewColumn *column;
1088 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(filter_store), &iter);
1089 path = gtk_tree_model_get_path(GTK_TREE_MODEL(filter_store), &iter);
1090 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1092 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1096 gtk_tree_path_free(path);
1101 static void filter_default_ok_cb(GenericDialog *gd, gpointer data)
1104 filter_add_defaults();
1106 filter_store_populate();
1108 g_idle_add((GSourceFunc)filter_default_ok_scroll, gd->data);
1111 static void dummy_cancel_cb(GenericDialog *gd, gpointer data)
1113 /* no op, only so cancel button appears */
1116 static void filter_default_cb(GtkWidget *widget, gpointer data)
1120 gd = generic_dialog_new(_("Reset filters"),
1121 "reset_filter", widget, TRUE,
1122 dummy_cancel_cb, data);
1123 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset filters"),
1124 _("This will reset the file filters to the defaults.\nContinue?"), TRUE);
1125 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, filter_default_ok_cb, TRUE);
1126 gtk_widget_show(gd->dialog);
1129 static void filter_disable_cb(GtkWidget *widget, gpointer data)
1131 GtkWidget *frame = data;
1133 gtk_widget_set_sensitive(frame,
1134 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
1137 static void safe_delete_view_cb(GtkWidget *widget, gpointer data)
1139 layout_set_path(NULL, gtk_entry_get_text(GTK_ENTRY(safe_delete_path_entry)));
1142 static void safe_delete_clear_ok_cb(GenericDialog *gd, gpointer data)
1144 file_util_trash_clear();
1147 static void safe_delete_clear_cb(GtkWidget *widget, gpointer data)
1151 gd = generic_dialog_new(_("Clear trash"),
1152 "clear_trash", widget, TRUE,
1153 dummy_cancel_cb, NULL);
1154 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear trash"),
1155 _("This will remove the trash contents."), FALSE);
1156 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, safe_delete_clear_ok_cb, TRUE);
1157 entry = gtk_entry_new();
1158 gtk_widget_set_can_focus(entry, FALSE);
1159 gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE);
1160 if (options->file_ops.safe_delete_path) gtk_entry_set_text(GTK_ENTRY(entry), options->file_ops.safe_delete_path);
1161 gtk_box_pack_start(GTK_BOX(gd->vbox), entry, FALSE, FALSE, 0);
1162 gtk_widget_show(entry);
1163 gtk_widget_show(gd->dialog);
1166 static void image_overlay_template_view_changed_cb(GtkWidget *widget, gpointer data)
1168 GtkWidget *pTextView;
1169 GtkTextBuffer *pTextBuffer;
1173 pTextView = GTK_WIDGET(data);
1175 pTextBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pTextView));
1176 gtk_text_buffer_get_start_iter(pTextBuffer, &iStart);
1177 gtk_text_buffer_get_end_iter(pTextBuffer, &iEnd);
1179 set_image_overlay_template_string(&c_options->image_overlay.template_string,
1180 gtk_text_buffer_get_text(pTextBuffer, &iStart, &iEnd, TRUE));
1183 static void image_overlay_default_template_ok_cb(GenericDialog *gd, gpointer data)
1185 GtkTextView *text_view = data;
1186 GtkTextBuffer *buffer;
1188 set_default_image_overlay_template_string(&options->image_overlay.template_string);
1189 if (!configwindow) return;
1191 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
1192 gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1195 static void image_overlay_default_template_cb(GtkWidget *widget, gpointer data)
1199 gd = generic_dialog_new(_("Reset image overlay template string"),
1200 "reset_image_overlay_template_string", widget, TRUE,
1201 dummy_cancel_cb, data);
1202 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset image overlay template string"),
1203 _("This will reset the image overlay template string to the default.\nContinue?"), TRUE);
1204 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, image_overlay_default_template_ok_cb, TRUE);
1205 gtk_widget_show(gd->dialog);
1208 static void image_overlay_help_cb(GtkWidget *widget, gpointer data)
1210 help_window_show("GuideOptionsWindow.html#OverlayScreenDisplay");
1213 static void image_overlay_set_font_cb(GtkWidget *widget, gpointer data)
1215 #if GTK_CHECK_VERSION(3,4,0)
1218 PangoFontDescription *font_desc;
1220 dialog = gtk_font_chooser_dialog_new("Image Overlay Font", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1221 gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), options->image_overlay.font);
1223 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1225 font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
1226 font = pango_font_description_to_string(font_desc);
1227 g_free(c_options->image_overlay.font);
1228 c_options->image_overlay.font = g_strdup(font);
1232 gtk_widget_destroy(dialog);
1236 font = gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget));
1237 c_options->image_overlay.font = g_strdup(font);
1241 static void image_overlay_set_text_colour_cb(GtkWidget *widget, gpointer data)
1244 #if GTK_CHECK_VERSION(3,4,0)
1247 dialog = gtk_color_chooser_dialog_new("Image Overlay Text Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1248 colour.red = options->image_overlay.text_red;
1249 colour.green = options->image_overlay.text_green;
1250 colour.blue = options->image_overlay.text_blue;
1251 colour.alpha = options->image_overlay.text_alpha;
1252 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1253 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1255 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1257 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1258 c_options->image_overlay.text_red = colour.red*255;
1259 c_options->image_overlay.text_green = colour.green*255;
1260 c_options->image_overlay.text_blue = colour.blue*255;
1261 c_options->image_overlay.text_alpha = colour.alpha*255;
1263 gtk_widget_destroy(dialog);
1266 GtkColorSelection *colorsel;
1268 dialog = gtk_color_selection_dialog_new("Image Overlay Text Colour");
1269 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1270 colour.red = options->image_overlay.text_red*257;
1271 colour.green = options->image_overlay.text_green*257;
1272 colour.blue = options->image_overlay.text_blue*257;
1273 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1274 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1275 gtk_color_selection_set_current_color(colorsel, &colour);
1276 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.text_alpha*257);
1278 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1280 gtk_color_selection_get_current_color(colorsel, &colour);
1281 c_options->image_overlay.text_red = colour.red/257;
1282 c_options->image_overlay.text_green = colour.green/257;
1283 c_options->image_overlay.text_blue = colour.blue/257;
1284 c_options->image_overlay.text_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1286 gtk_widget_destroy (dialog);
1291 static void image_overlay_set_background_colour_cb(GtkWidget *widget, gpointer data)
1294 #if GTK_CHECK_VERSION(3,4,0)
1297 dialog = gtk_color_chooser_dialog_new("Image Overlay Background Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1298 colour.red = options->image_overlay.background_red;
1299 colour.green = options->image_overlay.background_green;
1300 colour.blue = options->image_overlay.background_blue;
1301 colour.alpha = options->image_overlay.background_alpha;
1302 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1303 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1305 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1307 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1308 c_options->image_overlay.background_red = colour.red*255;
1309 c_options->image_overlay.background_green = colour.green*255;
1310 c_options->image_overlay.background_blue = colour.blue*255;
1311 c_options->image_overlay.background_alpha = colour.alpha*255;
1313 gtk_widget_destroy(dialog);
1316 GtkColorSelection *colorsel;
1318 dialog = gtk_color_selection_dialog_new("Image Overlay Background Colour");
1319 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1320 colour.red = options->image_overlay.background_red*257;
1321 colour.green = options->image_overlay.background_green*257;
1322 colour.blue = options->image_overlay.background_blue*257;
1323 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1324 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1325 gtk_color_selection_set_current_color(colorsel, &colour);
1326 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.background_alpha*257);
1328 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1330 gtk_color_selection_get_current_color(colorsel, &colour);
1331 c_options->image_overlay.background_red = colour.red/257;
1332 c_options->image_overlay.background_green = colour.green/257;
1333 c_options->image_overlay.background_blue = colour.blue/257;
1334 c_options->image_overlay.background_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1336 gtk_widget_destroy(dialog);
1340 static void accel_store_populate(void)
1343 GList *groups, *actions;
1345 const gchar *accel_path;
1349 if (!accel_store || !layout_window_list || !layout_window_list->data) return;
1351 gtk_tree_store_clear(accel_store);
1352 lw = layout_window_list->data; /* get the actions from the first window, it should not matter, they should be the same in all windows */
1354 g_assert(lw && lw->ui_manager);
1355 groups = gtk_ui_manager_get_action_groups(lw->ui_manager);
1358 actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
1361 action = GTK_ACTION(actions->data);
1362 accel_path = gtk_action_get_accel_path(action);
1363 if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
1365 gchar *label, *label2, *tooltip, *accel;
1366 g_object_get(action,
1367 "tooltip", &tooltip,
1371 if (pango_parse_markup(label, -1, '_', NULL, &label2, NULL, NULL) && label2)
1377 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1381 gtk_tree_store_append(accel_store, &iter, NULL);
1382 gtk_tree_store_set(accel_store, &iter,
1385 AE_TOOLTIP, tooltip ? tooltip : "",
1386 AE_ACCEL, accel_path,
1394 actions = actions->next;
1397 groups = groups->next;
1401 static void accel_store_cleared_cb(GtkCellRendererAccel *accel, gchar *path_string, gpointer user_data)
1406 static gboolean accel_remove_key_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1408 gchar *accel1 = data;
1413 gtk_tree_model_get(model, iter, AE_KEY, &accel2, -1);
1415 gtk_accelerator_parse(accel1, &key1.accel_key, &key1.accel_mods);
1416 gtk_accelerator_parse(accel2, &key2.accel_key, &key2.accel_mods);
1418 if (key1.accel_key == key2.accel_key && key1.accel_mods == key2.accel_mods)
1420 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1421 DEBUG_1("accelerator key '%s' is already used, removing.", accel1);
1430 static void accel_store_edited_cb(GtkCellRendererAccel *accel, gchar *path_string, guint accel_key, GdkModifierType accel_mods, guint hardware_keycode, gpointer user_data)
1432 GtkTreeModel *model = (GtkTreeModel *)accel_store;
1436 GtkAccelKey old_key, key;
1437 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
1439 gtk_tree_model_get_iter(model, &iter, path);
1440 gtk_tree_model_get(model, &iter, AE_ACCEL, &accel_path, -1);
1442 /* test if the accelerator can be stored without conflicts*/
1443 gtk_accel_map_lookup_entry(accel_path, &old_key);
1445 /* change the key and read it back (change may fail on keys hardcoded in gtk)*/
1446 gtk_accel_map_change_entry(accel_path, accel_key, accel_mods, TRUE);
1447 gtk_accel_map_lookup_entry(accel_path, &key);
1449 /* restore the original for now, the key will be really changed when the changes are confirmed */
1450 gtk_accel_map_change_entry(accel_path, old_key.accel_key, old_key.accel_mods, TRUE);
1452 acc = gtk_accelerator_name(key.accel_key, key.accel_mods);
1453 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, acc);
1455 gtk_tree_store_set(accel_store, &iter, AE_KEY, acc, -1);
1456 gtk_tree_path_free(path);
1460 static gboolean accel_default_scroll(GtkTreeView *data)
1464 GtkTreeViewColumn *column;
1466 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(accel_store), &iter);
1467 path = gtk_tree_model_get_path(GTK_TREE_MODEL(accel_store), &iter);
1468 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1470 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1474 gtk_tree_path_free(path);
1479 static void accel_default_cb(GtkWidget *widget, gpointer data)
1481 accel_store_populate();
1483 g_idle_add((GSourceFunc)accel_default_scroll, data);
1486 void accel_remove_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1488 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1491 void accel_reset_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1494 gchar *accel_path, *accel;
1496 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, -1);
1497 gtk_accel_map_lookup_entry(accel_path, &key);
1498 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1500 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, accel);
1502 gtk_tree_store_set(accel_store, iter, AE_KEY, accel, -1);
1507 static void accel_reset_cb(GtkWidget *widget, gpointer data)
1509 GtkTreeSelection *selection;
1511 if (!accel_store) return;
1512 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data));
1513 gtk_tree_selection_selected_foreach(selection, &accel_reset_selection, NULL);
1518 static GtkWidget *scrolled_notebook_page(GtkWidget *notebook, const gchar *title)
1522 GtkWidget *scrolled;
1523 GtkWidget *viewport;
1525 scrolled = gtk_scrolled_window_new(NULL, NULL);
1526 gtk_container_set_border_width(GTK_CONTAINER(scrolled), PREF_PAD_BORDER);
1527 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1528 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1529 label = gtk_label_new(title);
1530 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, label);
1531 gtk_widget_show(scrolled);
1533 viewport = gtk_viewport_new(NULL, NULL);
1534 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1535 gtk_container_add(GTK_CONTAINER(scrolled), viewport);
1536 gtk_widget_show(viewport);
1538 vbox = gtk_vbox_new(FALSE, 0);
1539 gtk_container_add(GTK_CONTAINER(viewport), vbox);
1540 gtk_widget_show(vbox);
1545 static void cache_standard_cb(GtkWidget *widget, gpointer data)
1547 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1549 c_options->thumbnails.spec_standard =TRUE;
1550 c_options->thumbnails.cache_into_dirs = FALSE;
1554 c_options->thumbnails.spec_standard =FALSE;
1558 static void cache_geeqie_cb(GtkWidget *widget, gpointer data)
1560 if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1562 c_options->thumbnails.spec_standard =TRUE;
1563 c_options->thumbnails.cache_into_dirs = FALSE;
1567 c_options->thumbnails.spec_standard =FALSE;
1571 static void cache_local_cb(GtkWidget *widget, gpointer data)
1573 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1575 c_options->thumbnails.cache_into_dirs = TRUE;
1576 c_options->thumbnails.spec_standard =FALSE;
1580 c_options->thumbnails.cache_into_dirs = FALSE;
1584 /* general options tab */
1585 static void config_tab_general(GtkWidget *notebook)
1590 GtkWidget *group_frame;
1591 GtkWidget *subgroup;
1593 GtkWidget *ct_button;
1596 gint hours, minutes, remainder;
1599 vbox = scrolled_notebook_page(notebook, _("General"));
1601 group = pref_group_new(vbox, FALSE, _("Thumbnails"), GTK_ORIENTATION_VERTICAL);
1603 table = pref_table_new(group, 2, 2, FALSE, FALSE);
1604 add_thumb_size_menu(table, 0, 0, _("Size:"));
1605 add_quality_menu(table, 0, 1, _("Quality:"), options->thumbnails.quality, &c_options->thumbnails.quality);
1607 ct_button = pref_checkbox_new_int(group, _("Cache thumbnails"),
1608 options->thumbnails.enable_caching, &c_options->thumbnails.enable_caching);
1610 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1611 pref_checkbox_link_sensitivity(ct_button, subgroup);
1613 group_frame = pref_frame_new(subgroup, TRUE, _("Use Geeqie thumbnail style and cache"),
1614 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1615 button = pref_radiobutton_new(group_frame, NULL, get_thumbnails_cache_dir(),
1616 !options->thumbnails.spec_standard,
1617 G_CALLBACK(cache_geeqie_cb), NULL);
1619 group_frame = pref_frame_new(subgroup, TRUE,
1620 _("Store thumbnails local to image folder (non-standard)"),
1621 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1622 pref_radiobutton_new(group_frame, button, "*/.thumbnails",
1623 options->thumbnails.cache_into_dirs,
1624 G_CALLBACK(cache_local_cb), NULL);
1626 group_frame = pref_frame_new(subgroup, TRUE,
1627 _("Use standard thumbnail style and cache, shared with other applications"),
1628 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1629 pref_radiobutton_new(group_frame, button, get_thumbnails_standard_cache_dir(),
1630 options->thumbnails.spec_standard,
1631 G_CALLBACK(cache_standard_cb), NULL);
1633 pref_checkbox_new_int(group, _("Use EXIF thumbnails when available (EXIF thumbnails may be outdated)"),
1634 options->thumbnails.use_exif, &c_options->thumbnails.use_exif);
1636 #ifdef HAVE_FFMPEGTHUMBNAILER_METADATA
1637 pref_checkbox_new_int(group, _("Use embedded metadata in video files as thumbnails when available"),
1638 options->thumbnails.use_ft_metadata, &c_options->thumbnails.use_ft_metadata);
1640 // pref_checkbox_new_int(group, _("Ignore embedded metadata if size is too small"),
1641 // options->thumbnails.use_ft_metadata_small, &c_options->thumbnails.use_ft_metadata_small);
1644 group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
1646 c_options->slideshow.delay = options->slideshow.delay;
1647 hours = options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
1648 remainder = options->slideshow.delay % (3600 * SLIDESHOW_SUBSECOND_PRECISION);
1649 minutes = remainder / (60 * SLIDESHOW_SUBSECOND_PRECISION);
1650 seconds = (gdouble)(remainder % (60 * SLIDESHOW_SUBSECOND_PRECISION)) /
1651 SLIDESHOW_SUBSECOND_PRECISION;
1653 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1655 spin = pref_spin_new(hbox, _("Delay between image change hrs:mins:secs.dec"), NULL,
1657 options->slideshow.delay ? hours : 0.0,
1658 G_CALLBACK(slideshow_delay_hours_cb), NULL);
1659 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1660 spin = pref_spin_new(hbox, ":" , NULL,
1662 options->slideshow.delay ? minutes: 0.0,
1663 G_CALLBACK(slideshow_delay_minutes_cb), NULL);
1664 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1665 spin = pref_spin_new(hbox, ":", NULL,
1666 SLIDESHOW_MIN_SECONDS, 59, 1.0, 1,
1667 options->slideshow.delay ? seconds : 10.0,
1668 G_CALLBACK(slideshow_delay_seconds_cb), NULL);
1669 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1671 pref_checkbox_new_int(group, _("Random"), options->slideshow.random, &c_options->slideshow.random);
1672 pref_checkbox_new_int(group, _("Repeat"), options->slideshow.repeat, &c_options->slideshow.repeat);
1674 group = pref_group_new(vbox, FALSE, _("Image loading and caching"), GTK_ORIENTATION_VERTICAL);
1676 pref_spin_new_int(group, _("Decoded image cache size (Mb):"), NULL,
1677 0, 99999, 1, options->image.image_cache_max, &c_options->image.image_cache_max);
1678 pref_checkbox_new_int(group, _("Preload next image"),
1679 options->image.enable_read_ahead, &c_options->image.enable_read_ahead);
1681 pref_checkbox_new_int(group, _("Refresh on file change"),
1682 options->update_on_time_change, &c_options->update_on_time_change);
1684 group = pref_group_new(vbox, FALSE, _("Info sidebar heights"), GTK_ORIENTATION_VERTICAL);
1685 pref_label_new(group, _("NOTE! Geeqie must be restarted for changes to take effect"));
1686 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1687 pref_spin_new_int(hbox, _("Keywords:"), NULL,
1689 options->info_keywords.height, &c_options->info_keywords.height);
1690 pref_spin_new_int(hbox, _("Title:"), NULL,
1692 options->info_title.height, &c_options->info_title.height);
1693 pref_spin_new_int(hbox, _("Comment:"), NULL,
1695 options->info_comment.height, &c_options->info_comment.height);
1696 pref_spin_new_int(hbox, _("Rating:"), NULL,
1698 options->info_rating.height, &c_options->info_rating.height);
1702 static void config_tab_image(GtkWidget *notebook)
1707 GtkWidget *ct_button;
1708 GtkWidget *enlargement_button;
1712 vbox = scrolled_notebook_page(notebook, _("Image"));
1714 group = pref_group_new(vbox, FALSE, _("Zoom"), GTK_ORIENTATION_VERTICAL);
1716 table = pref_table_new(group, 2, 1, FALSE, FALSE);
1717 add_quality_menu(table, 0, 0, _("Quality:"), options->image.zoom_quality, &c_options->image.zoom_quality);
1720 pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library"),
1721 options->image.use_clutter_renderer, &c_options->image.use_clutter_renderer);
1724 pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"),
1725 options->image.zoom_2pass, &c_options->image.zoom_2pass);
1727 c_options->image.zoom_increment = options->image.zoom_increment;
1728 spin = pref_spin_new(group, _("Zoom increment:"), NULL,
1729 0.01, 4.0, 0.01, 2, (gdouble)options->image.zoom_increment / 100.0,
1730 G_CALLBACK(zoom_increment_cb), NULL);
1731 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1733 group = pref_group_new(vbox, FALSE, _("Fit image to window"), GTK_ORIENTATION_VERTICAL);
1735 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1736 enlargement_button = pref_checkbox_new_int(hbox, _("Allow enlargement of image (max. size in %)"),
1737 options->image.zoom_to_fit_allow_expand, &c_options->image.zoom_to_fit_allow_expand);
1738 spin = pref_spin_new_int(hbox, NULL, NULL,
1740 options->image.max_enlargement_size, &c_options->image.max_enlargement_size);
1741 pref_checkbox_link_sensitivity(enlargement_button, spin);
1742 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."));
1744 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1745 ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (% of actual window):"),
1746 options->image.limit_autofit_size, &c_options->image.limit_autofit_size);
1747 spin = pref_spin_new_int(hbox, NULL, NULL,
1749 options->image.max_autofit_size, &c_options->image.max_autofit_size);
1750 pref_checkbox_link_sensitivity(ct_button, spin);
1751 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."));
1753 group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
1755 pref_checkbox_new_int(group, _("Use custom border color in window mode"),
1756 options->image.use_custom_border_color, &c_options->image.use_custom_border_color);
1758 pref_checkbox_new_int(group, _("Use custom border color in fullscreen mode"),
1759 options->image.use_custom_border_color_in_fullscreen, &c_options->image.use_custom_border_color_in_fullscreen);
1761 pref_color_button_new(group, _("Border color"), &options->image.border_color,
1762 G_CALLBACK(pref_color_button_set_cb), &c_options->image.border_color);
1764 c_options->image.border_color = options->image.border_color;
1766 pref_color_button_new(group, _("Alpha channel color 1"), &options->image.alpha_color_1,
1767 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_1);
1769 pref_color_button_new(group, _("Alpha channel color 2"), &options->image.alpha_color_2,
1770 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_2);
1772 c_options->image.alpha_color_1 = options->image.alpha_color_1;
1773 c_options->image.alpha_color_2 = options->image.alpha_color_2;
1775 group = pref_group_new(vbox, FALSE, _("Convenience"), GTK_ORIENTATION_VERTICAL);
1777 pref_checkbox_new_int(group, _("Auto rotate proofs using Exif information"),
1778 options->image.exif_proof_rotate_enable, &c_options->image.exif_proof_rotate_enable);
1782 static void config_tab_windows(GtkWidget *notebook)
1788 GtkWidget *ct_button;
1790 GtkWidget *image_overlay_template_view;
1791 GtkWidget *scrolled;
1792 GtkTextBuffer *buffer;
1794 vbox = scrolled_notebook_page(notebook, _("Windows"));
1796 group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
1798 ct_button = pref_checkbox_new_int(group, _("Remember window positions"),
1799 options->save_window_positions, &c_options->save_window_positions);
1801 button = pref_checkbox_new_int(group, _("Use saved window positions also for new windows"),
1802 options->use_saved_window_positions_for_new_windows, &c_options->use_saved_window_positions_for_new_windows);
1803 pref_checkbox_link_sensitivity(ct_button, button);
1805 pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
1806 options->tools_restore_state, &c_options->tools_restore_state);
1808 pref_checkbox_new_int(group, _("Remember dialog window positions"),
1809 options->save_dialog_window_positions, &c_options->save_dialog_window_positions);
1811 pref_checkbox_new_int(group, _("Show window IDs"),
1812 options->show_window_ids, &c_options->show_window_ids);
1814 group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
1816 pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
1817 options->image.fit_window_to_image, &c_options->image.fit_window_to_image);
1819 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1820 ct_button = pref_checkbox_new_int(hbox, _("Limit size when auto-sizing window (%):"),
1821 options->image.limit_window_size, &c_options->image.limit_window_size);
1822 spin = pref_spin_new_int(hbox, NULL, NULL,
1824 options->image.max_window_size, &c_options->image.max_window_size);
1825 pref_checkbox_link_sensitivity(ct_button, spin);
1827 group = pref_group_new(vbox, FALSE, _("Full screen"), GTK_ORIENTATION_VERTICAL);
1829 c_options->fullscreen.screen = options->fullscreen.screen;
1830 c_options->fullscreen.above = options->fullscreen.above;
1831 hbox = fullscreen_prefs_selection_new(_("Location:"), &c_options->fullscreen.screen, &c_options->fullscreen.above);
1832 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
1833 gtk_widget_show(hbox);
1835 pref_checkbox_new_int(group, _("Smooth image flip"),
1836 options->fullscreen.clean_flip, &c_options->fullscreen.clean_flip);
1837 pref_checkbox_new_int(group, _("Disable screen saver"),
1838 options->fullscreen.disable_saver, &c_options->fullscreen.disable_saver);
1841 group = pref_group_new(vbox, FALSE, _("Overlay Screen Display"), GTK_ORIENTATION_VERTICAL);
1843 pref_label_new(group, _("Image overlay template"));
1845 scrolled = gtk_scrolled_window_new(NULL, NULL);
1846 gtk_widget_set_size_request(scrolled, 200, 150);
1847 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
1848 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1849 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1850 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 5);
1851 gtk_widget_show(scrolled);
1853 image_overlay_template_view = gtk_text_view_new();
1855 gtk_widget_set_tooltip_markup(image_overlay_template_view,
1856 _("<i>%name%</i> results in the filename of the picture.\n"
1857 "Also available: <i>%collection%</i>, <i>%number%</i>, <i>%total%</i>, <i>%date%</i>,\n"
1858 "<i>%size%</i> (filesize), <i>%width%</i>, <i>%height%</i>, <i>%res%</i> (resolution),\n"
1859 "<i>%rating%</i>, <i>%keywords%</i>, <i>%comment%</i> (XMP), <i>%imagecomment%</i> (JPEG)\n"
1860 "To access exif data use the exif name, e. g. <i>%formatted.Camera%</i> is the formatted camera name,\n"
1861 "<i>%Exif.Photo.DateTimeOriginal%</i> the date of the original shot.\n"
1862 "<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"
1863 "If two or more variables are connected with the |-sign, it prints available variables with a separator.\n"
1864 "<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"
1865 "if there's no ISO information in the Exif data.\n"
1866 "If a line is empty, it is removed. This allows one to add lines that totally disappear when no data is available.\n"
1868 gtk_container_add(GTK_CONTAINER(scrolled), image_overlay_template_view);
1869 gtk_widget_show(image_overlay_template_view);
1871 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
1873 #if GTK_CHECK_VERSION(3,4,0)
1874 button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
1875 G_CALLBACK(image_overlay_set_font_cb), notebook);
1877 button = gtk_font_button_new();
1878 gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Image Overlay Font");
1879 gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->image_overlay.font);
1880 g_signal_connect(G_OBJECT(button), "font-set",
1881 G_CALLBACK(image_overlay_set_font_cb),NULL);
1883 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1884 gtk_widget_show(button);
1886 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Text"), FALSE,
1887 G_CALLBACK(image_overlay_set_text_colour_cb), NULL);
1888 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1889 gtk_widget_show(button);
1891 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Background"), FALSE,
1892 G_CALLBACK(image_overlay_set_background_colour_cb), NULL);
1893 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1894 gtk_widget_show(button);
1895 image_overlay_set_text_colours();
1897 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
1898 G_CALLBACK(image_overlay_default_template_cb), image_overlay_template_view);
1899 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1900 gtk_widget_show(button);
1902 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
1903 G_CALLBACK(image_overlay_help_cb), NULL);
1904 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1905 gtk_widget_show(button);
1907 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_overlay_template_view));
1908 if (options->image_overlay.template_string) gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1909 g_signal_connect(G_OBJECT(buffer), "changed",
1910 G_CALLBACK(image_overlay_template_view_changed_cb), image_overlay_template_view);
1915 static GtkTreeModel *create_class_model(void)
1917 GtkListStore *model;
1921 /* create list store */
1922 model = gtk_list_store_new(1, G_TYPE_STRING);
1923 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
1925 gtk_list_store_append(model, &iter);
1926 gtk_list_store_set(model, &iter, 0, _(format_class_list[i]), -1);
1928 return GTK_TREE_MODEL (model);
1933 static void config_tab_files(GtkWidget *notebook)
1940 GtkWidget *ct_button;
1941 GtkWidget *scrolled;
1942 GtkWidget *filter_view;
1943 GtkCellRenderer *renderer;
1944 GtkTreeSelection *selection;
1945 GtkTreeViewColumn *column;
1947 vbox = scrolled_notebook_page(notebook, _("Files"));
1949 group = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1951 pref_checkbox_new_int(group, _("Show hidden files or folders"),
1952 options->file_filter.show_hidden_files, &c_options->file_filter.show_hidden_files);
1953 pref_checkbox_new_int(group, _("Show parent folder (..)"),
1954 options->file_filter.show_parent_directory, &c_options->file_filter.show_parent_directory);
1955 pref_checkbox_new_int(group, _("Case sensitive sort"),
1956 options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
1957 pref_checkbox_new_int(group, _("Natural sort order"),
1958 options->file_sort.natural, &c_options->file_sort.natural);
1959 pref_checkbox_new_int(group, _("Disable file extension checks"),
1960 options->file_filter.disable_file_extension_checks, &c_options->file_filter.disable_file_extension_checks);
1962 ct_button = pref_checkbox_new_int(group, _("Disable File Filtering"),
1963 options->file_filter.disable, &c_options->file_filter.disable);
1966 group = pref_group_new(vbox, FALSE, _("Grouping sidecar extensions"), GTK_ORIENTATION_VERTICAL);
1968 sidecar_ext_entry = gtk_entry_new();
1969 gtk_entry_set_text(GTK_ENTRY(sidecar_ext_entry), options->sidecar.ext);
1970 gtk_box_pack_start(GTK_BOX(group), sidecar_ext_entry, FALSE, FALSE, 0);
1971 gtk_widget_show(sidecar_ext_entry);
1973 group = pref_group_new(vbox, TRUE, _("File types"), GTK_ORIENTATION_VERTICAL);
1975 frame = pref_group_parent(group);
1976 g_signal_connect(G_OBJECT(ct_button), "toggled",
1977 G_CALLBACK(filter_disable_cb), frame);
1978 gtk_widget_set_sensitive(frame, !options->file_filter.disable);
1980 scrolled = gtk_scrolled_window_new(NULL, NULL);
1981 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
1982 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
1983 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
1984 gtk_widget_show(scrolled);
1986 filter_store = gtk_list_store_new(1, G_TYPE_POINTER);
1987 filter_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(filter_store));
1988 g_object_unref(filter_store);
1989 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1990 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
1992 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), FALSE);
1994 column = gtk_tree_view_column_new();
1995 gtk_tree_view_column_set_title(column, _("Filter"));
1996 gtk_tree_view_column_set_resizable(column, TRUE);
1998 renderer = gtk_cell_renderer_toggle_new();
1999 g_signal_connect(G_OBJECT(renderer), "toggled",
2000 G_CALLBACK(filter_store_enable_cb), filter_store);
2001 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2002 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2003 GINT_TO_POINTER(FE_ENABLE), NULL);
2005 renderer = gtk_cell_renderer_text_new();
2006 g_signal_connect(G_OBJECT(renderer), "edited",
2007 G_CALLBACK(filter_store_ext_edit_cb), filter_store);
2008 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2009 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2010 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2011 GINT_TO_POINTER(FE_EXTENSION), NULL);
2012 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2014 column = gtk_tree_view_column_new();
2015 gtk_tree_view_column_set_title(column, _("Description"));
2016 gtk_tree_view_column_set_resizable(column, TRUE);
2017 gtk_tree_view_column_set_fixed_width(column, 200);
2018 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
2020 renderer = gtk_cell_renderer_text_new();
2021 g_signal_connect(G_OBJECT(renderer), "edited",
2022 G_CALLBACK(filter_store_desc_edit_cb), filter_store);
2023 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2024 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2025 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2026 GINT_TO_POINTER(FE_DESCRIPTION), NULL);
2027 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2029 column = gtk_tree_view_column_new();
2030 gtk_tree_view_column_set_title(column, _("Class"));
2031 gtk_tree_view_column_set_resizable(column, TRUE);
2032 renderer = gtk_cell_renderer_combo_new();
2033 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE,
2034 "model", create_class_model(),
2039 g_signal_connect(G_OBJECT(renderer), "edited",
2040 G_CALLBACK(filter_store_class_edit_cb), filter_store);
2041 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2042 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2043 GINT_TO_POINTER(FE_CLASS), NULL);
2044 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2046 column = gtk_tree_view_column_new();
2047 gtk_tree_view_column_set_title(column, _("Writable"));
2048 gtk_tree_view_column_set_resizable(column, FALSE);
2049 renderer = gtk_cell_renderer_toggle_new();
2050 g_signal_connect(G_OBJECT(renderer), "toggled",
2051 G_CALLBACK(filter_store_writable_cb), filter_store);
2052 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2053 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2054 GINT_TO_POINTER(FE_WRITABLE), NULL);
2055 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2057 column = gtk_tree_view_column_new();
2058 gtk_tree_view_column_set_title(column, _("Sidecar is allowed"));
2059 gtk_tree_view_column_set_resizable(column, FALSE);
2060 renderer = gtk_cell_renderer_toggle_new();
2061 g_signal_connect(G_OBJECT(renderer), "toggled",
2062 G_CALLBACK(filter_store_sidecar_cb), filter_store);
2063 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2064 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2065 GINT_TO_POINTER(FE_ALLOW_SIDECAR), NULL);
2066 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2069 filter_store_populate();
2070 gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
2071 gtk_widget_show(filter_view);
2073 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2075 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2076 G_CALLBACK(filter_default_cb), filter_view);
2077 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2078 gtk_widget_show(button);
2080 button = pref_button_new(NULL, GTK_STOCK_REMOVE, NULL, FALSE,
2081 G_CALLBACK(filter_remove_cb), filter_view);
2082 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2083 gtk_widget_show(button);
2085 button = pref_button_new(NULL, GTK_STOCK_ADD, NULL, FALSE,
2086 G_CALLBACK(filter_add_cb), filter_view);
2087 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2088 gtk_widget_show(button);
2092 static void config_tab_metadata(GtkWidget *notebook)
2097 GtkWidget *ct_button;
2101 vbox = scrolled_notebook_page(notebook, _("Metadata"));
2104 group = pref_group_new(vbox, FALSE, _("Metadata writing process"), GTK_ORIENTATION_VERTICAL);
2106 label = pref_label_new(group, _("Warning: Geeqie is built without Exiv2. Some options are disabled."));
2108 label = pref_label_new(group, _("Metadata are written in the following order. The process ends after first success."));
2109 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2111 ct_button = pref_checkbox_new_int(group, _("1) Save metadata in image files, or sidecar files, according to the XMP standard"),
2112 options->metadata.save_in_image_file, &c_options->metadata.save_in_image_file);
2114 gtk_widget_set_sensitive(ct_button, FALSE);
2117 pref_checkbox_new_int(group, _("2) Save metadata in '.metadata' folder, local to image folder (non-standard)"),
2118 options->metadata.enable_metadata_dirs, &c_options->metadata.enable_metadata_dirs);
2120 text = g_strdup_printf(_("3) Save metadata in Geeqie private directory '%s'"), get_metadata_cache_dir());
2121 label = pref_label_new(group, text);
2122 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2123 gtk_misc_set_padding(GTK_MISC(label), 22, 0);
2126 group = pref_group_new(vbox, FALSE, _("Step 1: Write to image files"), GTK_ORIENTATION_VERTICAL);
2128 gtk_widget_set_sensitive(group, FALSE);
2131 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2132 pref_checkbox_link_sensitivity(ct_button, hbox);
2134 pref_checkbox_new_int(hbox, _("Store metadata also in legacy IPTC tags (converted according to IPTC4XMP standard)"),
2135 options->metadata.save_legacy_IPTC, &c_options->metadata.save_legacy_IPTC);
2137 pref_checkbox_new_int(hbox, _("Warn if the image files are unwritable"),
2138 options->metadata.warn_on_write_problems, &c_options->metadata.warn_on_write_problems);
2140 pref_checkbox_new_int(hbox, _("Ask before writing to image files"),
2141 options->metadata.confirm_write, &c_options->metadata.confirm_write);
2143 pref_checkbox_new_int(hbox, _("Create sidecar files named image.ext.xmp (as opposed to image.xmp)"),
2144 options->metadata.sidecar_extended_name, &c_options->metadata.sidecar_extended_name);
2146 group = pref_group_new(vbox, FALSE, _("Step 2 and 3: write to Geeqie private files"), GTK_ORIENTATION_VERTICAL);
2148 gtk_widget_set_sensitive(group, FALSE);
2151 pref_checkbox_new_int(group, _("Use GQview legacy metadata format (supports only keywords and comments) instead of XMP"),
2152 options->metadata.save_legacy_format, &c_options->metadata.save_legacy_format);
2155 group = pref_group_new(vbox, FALSE, _("Miscellaneous"), GTK_ORIENTATION_VERTICAL);
2156 pref_checkbox_new_int(group, _("Write the same description tags (keywords, comment, etc.) to all grouped sidecars"),
2157 options->metadata.sync_grouped_files, &c_options->metadata.sync_grouped_files);
2159 pref_checkbox_new_int(group, _("Allow keywords to differ only in case"),
2160 options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
2162 ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"),
2163 options->metadata.write_orientation, &c_options->metadata.write_orientation);
2165 gtk_widget_set_sensitive(ct_button, FALSE);
2168 group = pref_group_new(vbox, FALSE, _("Auto-save options"), GTK_ORIENTATION_VERTICAL);
2170 ct_button = pref_checkbox_new_int(group, _("Write metadata after timeout"),
2171 options->metadata.confirm_after_timeout, &c_options->metadata.confirm_after_timeout);
2173 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2174 pref_checkbox_link_sensitivity(ct_button, hbox);
2176 pref_spin_new_int(hbox, _("Timeout (seconds):"), NULL, 0, 900, 1,
2177 options->metadata.confirm_timeout, &c_options->metadata.confirm_timeout);
2179 pref_checkbox_new_int(group, _("Write metadata on image change"),
2180 options->metadata.confirm_on_image_change, &c_options->metadata.confirm_on_image_change);
2182 pref_checkbox_new_int(group, _("Write metadata on directory change"),
2183 options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
2188 static void intent_menu_cb(GtkWidget *combo, gpointer data)
2190 gint *option = data;
2192 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
2196 *option = INTENT_PERCEPTUAL;
2199 *option = INTENT_RELATIVE_COLORIMETRIC;
2202 *option = INTENT_SATURATION;
2205 *option = INTENT_ABSOLUTE_COLORIMETRIC;
2210 static void add_intent_menu(GtkWidget *table, gint column, gint row, const gchar *text,
2211 gint option, gint *option_c)
2218 pref_table_label(table, column, row, text, 0.0);
2220 combo = gtk_combo_box_text_new();
2222 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Perceptual"));
2223 if (option == INTENT_PERCEPTUAL) current = 0;
2224 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Relative Colorimetric"));
2225 if (option == INTENT_RELATIVE_COLORIMETRIC) current = 1;
2226 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Saturation"));
2227 if (option == INTENT_SATURATION) current = 2;
2228 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Absolute Colorimetric"));
2229 if (option == INTENT_ABSOLUTE_COLORIMETRIC) current = 3;
2231 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
2233 gtk_widget_set_tooltip_text(combo,"Refer to the lcms documentation for the defaults used when the selected Intent is not available");
2235 g_signal_connect(G_OBJECT(combo), "changed",
2236 G_CALLBACK(intent_menu_cb), option_c);
2238 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
2239 GTK_EXPAND | GTK_FILL, 0, 0, 0);
2240 gtk_widget_show(combo);
2244 static void config_tab_color(GtkWidget *notebook)
2253 vbox = scrolled_notebook_page(notebook, _("Color management"));
2255 group = pref_group_new(vbox, FALSE, _("Input profiles"), GTK_ORIENTATION_VERTICAL);
2257 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
2260 table = pref_table_new(group, 3, COLOR_PROFILE_INPUTS + 1, FALSE, FALSE);
2261 gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
2263 label = pref_table_label(table, 0, 0, _("Type"), 0.0);
2264 pref_label_bold(label, TRUE, FALSE);
2266 label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
2267 pref_label_bold(label, TRUE, FALSE);
2269 label = pref_table_label(table, 2, 0, _("File"), 0.0);
2270 pref_label_bold(label, TRUE, FALSE);
2272 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
2277 buf = g_strdup_printf(_("Input %d:"), i + COLOR_PROFILE_FILE);
2278 pref_table_label(table, 0, i + 1, buf, 1.0);
2281 entry = gtk_entry_new();
2282 gtk_entry_set_max_length(GTK_ENTRY(entry), EDITOR_NAME_MAX_LENGTH);
2283 if (options->color_profile.input_name[i])
2285 gtk_entry_set_text(GTK_ENTRY(entry), options->color_profile.input_name[i]);
2287 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, i + 1, i + 2,
2288 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2289 gtk_widget_show(entry);
2290 color_profile_input_name_entry[i] = entry;
2292 tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, ".icc", "ICC Files", NULL);
2293 tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
2294 gtk_widget_set_size_request(entry, 160, -1);
2295 gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
2296 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2297 gtk_widget_show(tabcomp);
2298 color_profile_input_file_entry[i] = entry;
2301 group = pref_group_new(vbox, FALSE, _("Screen profile"), GTK_ORIENTATION_VERTICAL);
2303 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
2305 pref_checkbox_new_int(group, _("Use system screen profile if available"),
2306 options->color_profile.use_x11_screen_profile, &c_options->color_profile.use_x11_screen_profile);
2308 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2310 pref_table_label(table, 0, 0, _("Screen:"), 1.0);
2311 tabcomp = tab_completion_new(&color_profile_screen_file_entry,
2312 options->color_profile.screen_file, NULL, ".icc", "ICC Files", NULL);
2313 tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
2314 gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
2316 add_intent_menu(table, 0, 1, _("Render Intent:"), options->color_profile.render_intent, &c_options->color_profile.render_intent);
2318 gtk_table_attach(GTK_TABLE(table), tabcomp, 1, 2,
2320 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2322 gtk_widget_show(tabcomp);
2325 /* advanced entry tab */
2326 static void config_tab_behavior(GtkWidget *notebook)
2333 GtkWidget *ct_button;
2337 vbox = scrolled_notebook_page(notebook, _("Behavior"));
2339 group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
2341 pref_checkbox_new_int(group, _("Confirm file delete"),
2342 options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
2343 pref_checkbox_new_int(group, _("Enable Delete key"),
2344 options->file_ops.enable_delete_key, &c_options->file_ops.enable_delete_key);
2346 ct_button = pref_checkbox_new_int(group, _("Safe delete"),
2347 options->file_ops.safe_delete_enable, &c_options->file_ops.safe_delete_enable);
2349 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2350 pref_checkbox_link_sensitivity(ct_button, hbox);
2352 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
2353 pref_label_new(hbox, _("Folder:"));
2355 tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL, NULL, NULL);
2356 tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
2357 gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
2358 gtk_widget_show(tabcomp);
2360 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2361 pref_checkbox_link_sensitivity(ct_button, hbox);
2363 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
2364 spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MB"),
2365 0, 2048, 1, options->file_ops.safe_delete_folder_maxsize, &c_options->file_ops.safe_delete_folder_maxsize);
2366 gtk_widget_set_tooltip_markup(spin, _("Set to 0 for unlimited size"));
2367 button = pref_button_new(NULL, NULL, _("View"), FALSE,
2368 G_CALLBACK(safe_delete_view_cb), NULL);
2369 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2370 gtk_widget_show(button);
2372 button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
2373 G_CALLBACK(safe_delete_clear_cb), NULL);
2374 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2375 gtk_widget_show(button);
2378 group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
2380 pref_checkbox_new_int(group, _("Descend folders in tree view"),
2381 options->tree_descend_subdirs, &c_options->tree_descend_subdirs);
2383 pref_checkbox_new_int(group, _("In place renaming"),
2384 options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
2386 pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
2387 options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
2389 pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
2390 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
2392 pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
2393 16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
2395 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2396 add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
2398 group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
2400 pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
2401 options->progressive_key_scrolling, &c_options->progressive_key_scrolling);
2402 pref_spin_new_int(group, _("Keyboard scrolling step multiplier:"), NULL,
2403 1, 32, 1, options->keyboard_scroll_step, (int *)&c_options->keyboard_scroll_step);
2404 pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
2405 options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
2406 pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
2407 options->image_lm_click_nav, &c_options->image_lm_click_nav);
2408 pref_checkbox_new_int(group, _("Play video by left click on image"),
2409 options->image_l_click_video, &c_options->image_l_click_video);
2410 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2411 add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
2415 group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
2417 pref_spin_new_int(group, _("Debug level:"), NULL,
2418 DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
2420 pref_checkbox_new_int(group, _("Timer data"),
2421 options->log_window.timer_data, &c_options->log_window.timer_data);
2423 pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
2424 1, 99999, 1, options->log_window_lines, &options->log_window_lines);
2428 /* accelerators tab */
2429 static void config_tab_accelerators(GtkWidget *notebook)
2435 GtkWidget *scrolled;
2436 GtkWidget *accel_view;
2437 GtkCellRenderer *renderer;
2438 GtkTreeSelection *selection;
2439 GtkTreeViewColumn *column;
2441 vbox = scrolled_notebook_page(notebook, _("Keyboard"));
2443 group = pref_group_new(vbox, TRUE, _("Accelerators"), GTK_ORIENTATION_VERTICAL);
2445 scrolled = gtk_scrolled_window_new(NULL, NULL);
2446 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2447 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2448 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2449 gtk_widget_show(scrolled);
2451 accel_store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
2453 accel_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(accel_store));
2454 g_object_unref(accel_store);
2455 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(accel_view));
2456 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
2458 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(accel_view), FALSE);
2460 renderer = gtk_cell_renderer_text_new();
2462 column = gtk_tree_view_column_new_with_attributes(_("Action"),
2467 gtk_tree_view_column_set_sort_column_id(column, AE_ACTION);
2468 gtk_tree_view_column_set_resizable(column, TRUE);
2469 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
2472 renderer = gtk_cell_renderer_accel_new();
2473 g_signal_connect(G_OBJECT(renderer), "accel-cleared",
2474 G_CALLBACK(accel_store_cleared_cb), accel_store);
2475 g_signal_connect(G_OBJECT(renderer), "accel-edited",
2476 G_CALLBACK(accel_store_edited_cb), accel_store);
2479 g_object_set (renderer,
2481 "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
2484 column = gtk_tree_view_column_new_with_attributes(_("KEY"),
2489 gtk_tree_view_column_set_sort_column_id(column, AE_KEY);
2490 gtk_tree_view_column_set_resizable(column, TRUE);
2491 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
2493 renderer = gtk_cell_renderer_text_new();
2495 column = gtk_tree_view_column_new_with_attributes(_("Tooltip"),
2500 gtk_tree_view_column_set_sort_column_id(column, AE_TOOLTIP);
2501 gtk_tree_view_column_set_resizable(column, TRUE);
2502 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
2504 renderer = gtk_cell_renderer_text_new();
2506 column = gtk_tree_view_column_new_with_attributes("Accel",
2511 gtk_tree_view_column_set_sort_column_id(column, AE_ACCEL);
2512 gtk_tree_view_column_set_resizable(column, TRUE);
2513 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
2515 accel_store_populate();
2516 gtk_container_add(GTK_CONTAINER(scrolled), accel_view);
2517 gtk_widget_show(accel_view);
2519 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2521 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2522 G_CALLBACK(accel_default_cb), accel_view);
2523 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2524 gtk_widget_show(button);
2526 button = pref_button_new(NULL, NULL, _("Reset selected"), FALSE,
2527 G_CALLBACK(accel_reset_cb), accel_view);
2528 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2529 gtk_widget_show(button);
2533 static void config_tab_toolbar(GtkWidget *notebook)
2536 GtkWidget *toolbardata;
2539 lw = layout_window_list->data;
2541 vbox = scrolled_notebook_page(notebook, _("Toolbar"));
2543 toolbardata = toolbar_select_new(lw);
2544 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
2545 gtk_widget_show(vbox);
2549 static void config_tab_stereo(GtkWidget *notebook)
2557 GtkWidget *fs_button;
2558 vbox = scrolled_notebook_page(notebook, _("Stereo"));
2560 group = pref_group_new(vbox, FALSE, _("Windowed stereo mode"), GTK_ORIENTATION_VERTICAL);
2562 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2563 add_stereo_mode_menu(table, 0, 0, _("Windowed stereo mode"), options->stereo.mode, &c_options->stereo.mode, FALSE);
2565 table = pref_table_new(group, 2, 2, TRUE, FALSE);
2566 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
2567 pref_checkbox_new_int(box, _("Mirror left image"),
2568 options->stereo.mode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.mirror_left);
2569 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
2570 pref_checkbox_new_int(box, _("Flip left image"),
2571 options->stereo.mode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.flip_left);
2572 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
2573 pref_checkbox_new_int(box, _("Mirror right image"),
2574 options->stereo.mode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.mirror_right);
2575 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
2576 pref_checkbox_new_int(box, _("Flip right image"),
2577 options->stereo.mode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.flip_right);
2578 pref_checkbox_new_int(group, _("Swap left and right images"),
2579 options->stereo.mode & PR_STEREO_SWAP, &c_options->stereo.tmp.swap);
2580 pref_checkbox_new_int(group, _("Disable stereo mode on single image source"),
2581 options->stereo.mode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.temp_disable);
2583 group = pref_group_new(vbox, FALSE, _("Fullscreen stereo mode"), GTK_ORIENTATION_VERTICAL);
2584 fs_button = pref_checkbox_new_int(group, _("Use different settings for fullscreen"),
2585 options->stereo.enable_fsmode, &c_options->stereo.enable_fsmode);
2586 box2 = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2587 pref_checkbox_link_sensitivity(fs_button, box2);
2588 table = pref_table_new(box2, 2, 1, FALSE, FALSE);
2589 add_stereo_mode_menu(table, 0, 0, _("Fullscreen stereo mode"), options->stereo.fsmode, &c_options->stereo.fsmode, TRUE);
2590 table = pref_table_new(box2, 2, 2, TRUE, FALSE);
2591 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
2592 pref_checkbox_new_int(box, _("Mirror left image"),
2593 options->stereo.fsmode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.fs_mirror_left);
2594 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
2595 pref_checkbox_new_int(box, _("Flip left image"),
2596 options->stereo.fsmode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.fs_flip_left);
2597 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
2598 pref_checkbox_new_int(box, _("Mirror right image"),
2599 options->stereo.fsmode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.fs_mirror_right);
2600 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
2601 pref_checkbox_new_int(box, _("Flip right image"),
2602 options->stereo.fsmode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.fs_flip_right);
2603 pref_checkbox_new_int(box2, _("Swap left and right images"),
2604 options->stereo.fsmode & PR_STEREO_SWAP, &c_options->stereo.tmp.fs_swap);
2605 pref_checkbox_new_int(box2, _("Disable stereo mode on single image source"),
2606 options->stereo.fsmode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.fs_temp_disable);
2608 group2 = pref_group_new(box2, FALSE, _("Fixed position"), GTK_ORIENTATION_VERTICAL);
2609 table = pref_table_new(group2, 5, 3, FALSE, FALSE);
2610 pref_table_spin_new_int(table, 0, 0, _("Width"), NULL,
2611 1, 5000, 1, options->stereo.fixed_w, &c_options->stereo.fixed_w);
2612 pref_table_spin_new_int(table, 3, 0, _("Height"), NULL,
2613 1, 5000, 1, options->stereo.fixed_h, &c_options->stereo.fixed_h);
2614 pref_table_spin_new_int(table, 0, 1, _("Left X"), NULL,
2615 0, 5000, 1, options->stereo.fixed_x1, &c_options->stereo.fixed_x1);
2616 pref_table_spin_new_int(table, 3, 1, _("Left Y"), NULL,
2617 0, 5000, 1, options->stereo.fixed_y1, &c_options->stereo.fixed_y1);
2618 pref_table_spin_new_int(table, 0, 2, _("Right X"), NULL,
2619 0, 5000, 1, options->stereo.fixed_x2, &c_options->stereo.fixed_x2);
2620 pref_table_spin_new_int(table, 3, 2, _("Right Y"), NULL,
2621 0, 5000, 1, options->stereo.fixed_y2, &c_options->stereo.fixed_y2);
2625 /* Main preferences window */
2626 static void config_window_create(void)
2628 GtkWidget *win_vbox;
2630 GtkWidget *notebook;
2632 GtkWidget *ct_button;
2634 if (!c_options) c_options = init_options(NULL);
2636 configwindow = window_new(GTK_WINDOW_TOPLEVEL, "preferences", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Preferences"));
2637 gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
2638 g_signal_connect(G_OBJECT(configwindow), "delete_event",
2639 G_CALLBACK(config_window_delete), NULL);
2640 gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
2641 gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
2642 gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
2644 win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
2645 gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
2646 gtk_widget_show(win_vbox);
2648 notebook = gtk_notebook_new();
2649 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP);
2650 gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
2652 config_tab_general(notebook);
2653 config_tab_image(notebook);
2654 config_tab_windows(notebook);
2655 config_tab_accelerators(notebook);
2656 config_tab_files(notebook);
2657 config_tab_metadata(notebook);
2658 config_tab_color(notebook);
2659 config_tab_stereo(notebook);
2660 config_tab_behavior(notebook);
2661 config_tab_toolbar(notebook);
2663 hbox = gtk_hbutton_box_new();
2664 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
2665 gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
2666 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
2667 gtk_widget_show(hbox);
2669 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
2670 G_CALLBACK(config_window_help_cb), notebook);
2671 gtk_container_add(GTK_CONTAINER(hbox), button);
2672 gtk_widget_set_can_default(button, TRUE);
2673 gtk_widget_show(button);
2675 button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
2676 G_CALLBACK(config_window_ok_cb), NULL);
2677 gtk_container_add(GTK_CONTAINER(hbox), button);
2678 gtk_widget_set_can_default(button, TRUE);
2679 gtk_widget_grab_default(button);
2680 gtk_widget_show(button);
2684 button = pref_button_new(NULL, GTK_STOCK_SAVE, NULL, FALSE,
2685 G_CALLBACK(config_window_save_cb), NULL);
2686 gtk_container_add(GTK_CONTAINER(hbox), button);
2687 gtk_widget_set_can_default(button, TRUE);
2688 gtk_widget_show(button);
2690 button = pref_button_new(NULL, GTK_STOCK_APPLY, NULL, FALSE,
2691 G_CALLBACK(config_window_apply_cb), NULL);
2692 gtk_container_add(GTK_CONTAINER(hbox), button);
2693 gtk_widget_set_can_default(button, TRUE);
2694 gtk_widget_show(button);
2696 button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
2697 G_CALLBACK(config_window_close_cb), NULL);
2698 gtk_container_add(GTK_CONTAINER(hbox), button);
2699 gtk_widget_set_can_default(button, TRUE);
2700 gtk_widget_show(button);
2702 if (!generic_dialog_get_alternative_button_order(configwindow))
2704 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
2707 gtk_widget_show(notebook);
2709 gtk_widget_show(configwindow);
2713 *-----------------------------------------------------------------------------
2714 * config window show (public)
2715 *-----------------------------------------------------------------------------
2718 void show_config_window(void)
2722 gtk_window_present(GTK_WINDOW(configwindow));
2726 config_window_create();
2735 void show_about_window(LayoutWindow *lw)
2737 GdkPixbuf *pixbuf_logo;
2738 GdkPixbuf *pixbuf_icon;
2739 gchar *authors[1000];
2747 #define LINE_LENGTH 1000
2748 gchar line[LINE_LENGTH];
2750 copyright = g_string_new(NULL);
2751 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");
2753 zd_path = g_build_filename(GQ_BIN_DIR, TIMEZONE_DATABASE, NULL);
2754 cd = ZDOpenDatabase(zd_path);
2757 copyright = g_string_append(copyright, ZDGetNotice(cd));
2759 ZDCloseDatabase(cd);
2763 path = g_build_filename(GQ_HELPDIR, "AUTHORS", NULL);
2764 fp = fopen(path, "r");
2767 while(fgets(line, LINE_LENGTH, fp))
2769 /* get rid of ending \n from fgets */
2770 line[strlen(line) - 1] = '\0';
2771 authors[i_authors] = g_strdup(line);
2774 authors[i_authors] = NULL;
2779 comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
2780 "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
2782 pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
2783 pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
2784 gtk_show_about_dialog(GTK_WINDOW(lw->window),
2785 "title", _("About Geeqie"),
2787 "program-name", GQ_APPNAME,
2789 "logo", pixbuf_logo,
2790 "icon", pixbuf_icon,
2791 "website", GQ_WEBSITE,
2792 "website-label", "Website",
2793 "comments", comment,
2795 "translator-credits", _("translator-credits"),
2796 "wrap-license", TRUE,
2797 "license", copyright->str,
2800 g_string_free(copyright, TRUE);
2803 while(n < i_authors)
2813 static void image_overlay_set_text_colours()
2815 c_options->image_overlay.text_red = options->image_overlay.text_red;
2816 c_options->image_overlay.text_green = options->image_overlay.text_green;
2817 c_options->image_overlay.text_blue = options->image_overlay.text_blue;
2818 c_options->image_overlay.text_alpha = options->image_overlay.text_alpha;
2819 c_options->image_overlay.background_red = options->image_overlay.background_red;
2820 c_options->image_overlay.background_green = options->image_overlay.background_green;
2821 c_options->image_overlay.background_blue = options->image_overlay.background_blue;
2822 c_options->image_overlay.background_alpha = options->image_overlay.background_alpha;
2824 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */