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"
60 #define EDITOR_NAME_MAX_LENGTH 32
61 #define EDITOR_COMMAND_MAX_LENGTH 1024
63 static void image_overlay_set_text_colours();
65 typedef struct _ThumbSize ThumbSize;
72 static ThumbSize thumb_size_list[] =
106 static gchar *format_class_list[] = {
114 /* config memory values */
115 static ConfOptions *c_options = NULL;
122 static GtkWidget *configwindow = NULL;
123 static GtkListStore *filter_store = NULL;
124 static GtkTreeStore *accel_store = NULL;
126 static GtkWidget *safe_delete_path_entry;
128 static GtkWidget *color_profile_input_file_entry[COLOR_PROFILE_INPUTS];
129 static GtkWidget *color_profile_input_name_entry[COLOR_PROFILE_INPUTS];
130 static GtkWidget *color_profile_screen_file_entry;
132 static GtkWidget *sidecar_ext_entry;
135 #define CONFIG_WINDOW_DEF_WIDTH 700
136 #define CONFIG_WINDOW_DEF_HEIGHT 600
139 *-----------------------------------------------------------------------------
140 * option widget callbacks (private)
141 *-----------------------------------------------------------------------------
144 static void zoom_increment_cb(GtkWidget *spin, gpointer data)
146 c_options->image.zoom_increment = (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) * 100.0 + 0.01);
149 static void slideshow_delay_hours_cb(GtkWidget *spin, gpointer data)
151 gint mins_secs_tenths, delay;
153 mins_secs_tenths = c_options->slideshow.delay %
154 (3600 * SLIDESHOW_SUBSECOND_PRECISION);
156 delay = (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
157 (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
160 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
161 SLIDESHOW_SUBSECOND_PRECISION;
164 static void slideshow_delay_minutes_cb(GtkWidget *spin, gpointer data)
166 gint hours, secs_tenths, delay;
168 hours = c_options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
169 secs_tenths = c_options->slideshow.delay % (60 * SLIDESHOW_SUBSECOND_PRECISION);
171 delay = hours * (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
172 (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
173 (60 * SLIDESHOW_SUBSECOND_PRECISION) + secs_tenths);
175 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
176 SLIDESHOW_SUBSECOND_PRECISION;
179 static void slideshow_delay_seconds_cb(GtkWidget *spin, gpointer data)
181 gint hours_mins, delay;
183 hours_mins = c_options->slideshow.delay / (60 * SLIDESHOW_SUBSECOND_PRECISION);
185 delay = (hours_mins * (60 * SLIDESHOW_SUBSECOND_PRECISION)) +
186 (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
187 (gdouble)(SLIDESHOW_SUBSECOND_PRECISION) + 0.01);
189 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
190 SLIDESHOW_SUBSECOND_PRECISION;
194 *-----------------------------------------------------------------------------
195 * sync progam to config window routine (private)
196 *-----------------------------------------------------------------------------
199 void config_entry_to_option(GtkWidget *entry, gchar **option, gchar *(*func)(const gchar *))
205 buf = gtk_entry_get_text(GTK_ENTRY(entry));
206 if (buf && strlen(buf) > 0)
211 *option = g_strdup(buf);
216 static gboolean accel_apply_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
218 gchar *accel_path, *accel;
220 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, AE_KEY, &accel, -1);
222 if (accel_path && accel_path[0])
225 gtk_accelerator_parse(accel, &key.accel_key, &key.accel_mods);
226 gtk_accel_map_change_entry(accel_path, key.accel_key, key.accel_mods, TRUE);
236 static void config_window_apply(void)
239 gboolean refresh = FALSE;
241 config_entry_to_option(safe_delete_path_entry, &options->file_ops.safe_delete_path, remove_trailing_slash);
243 if (options->file_filter.show_hidden_files != c_options->file_filter.show_hidden_files) refresh = TRUE;
244 if (options->file_filter.show_parent_directory != c_options->file_filter.show_parent_directory) refresh = TRUE;
245 if (options->file_filter.show_dot_directory != c_options->file_filter.show_dot_directory) refresh = TRUE;
246 if (options->file_sort.case_sensitive != c_options->file_sort.case_sensitive) refresh = TRUE;
247 if (options->file_sort.natural != c_options->file_sort.natural) refresh = TRUE;
248 if (options->file_filter.disable_file_extension_checks != c_options->file_filter.disable_file_extension_checks) refresh = TRUE;
249 if (options->file_filter.disable != c_options->file_filter.disable) refresh = TRUE;
251 options->file_ops.confirm_delete = c_options->file_ops.confirm_delete;
252 options->file_ops.enable_delete_key = c_options->file_ops.enable_delete_key;
253 options->file_ops.safe_delete_enable = c_options->file_ops.safe_delete_enable;
254 options->file_ops.safe_delete_folder_maxsize = c_options->file_ops.safe_delete_folder_maxsize;
255 options->tools_restore_state = c_options->tools_restore_state;
256 options->save_window_positions = c_options->save_window_positions;
257 options->use_saved_window_positions_for_new_windows = c_options->use_saved_window_positions_for_new_windows;
258 options->save_dialog_window_positions = c_options->save_dialog_window_positions;
259 options->show_window_ids = c_options->show_window_ids;
260 options->image.scroll_reset_method = c_options->image.scroll_reset_method;
261 options->image.zoom_2pass = c_options->image.zoom_2pass;
262 options->image.fit_window_to_image = c_options->image.fit_window_to_image;
263 options->image.limit_window_size = c_options->image.limit_window_size;
264 options->image.zoom_to_fit_allow_expand = c_options->image.zoom_to_fit_allow_expand;
265 options->image.max_window_size = c_options->image.max_window_size;
266 options->image.limit_autofit_size = c_options->image.limit_autofit_size;
267 options->image.max_autofit_size = c_options->image.max_autofit_size;
268 options->image.max_enlargement_size = c_options->image.max_enlargement_size;
269 options->image.use_clutter_renderer = c_options->image.use_clutter_renderer;
270 options->progressive_key_scrolling = c_options->progressive_key_scrolling;
271 options->keyboard_scroll_step = c_options->keyboard_scroll_step;
273 if (options->thumbnails.max_width != c_options->thumbnails.max_width
274 || options->thumbnails.max_height != c_options->thumbnails.max_height
275 || options->thumbnails.quality != c_options->thumbnails.quality)
277 thumb_format_changed = TRUE;
279 options->thumbnails.max_width = c_options->thumbnails.max_width;
280 options->thumbnails.max_height = c_options->thumbnails.max_height;
281 options->thumbnails.quality = c_options->thumbnails.quality;
283 options->thumbnails.enable_caching = c_options->thumbnails.enable_caching;
284 options->thumbnails.cache_into_dirs = c_options->thumbnails.cache_into_dirs;
285 options->thumbnails.use_exif = c_options->thumbnails.use_exif;
286 options->thumbnails.use_ft_metadata = c_options->thumbnails.use_ft_metadata;
287 // options->thumbnails.use_ft_metadata_small = c_options->thumbnails.use_ft_metadata_small;
288 options->thumbnails.spec_standard = c_options->thumbnails.spec_standard;
289 options->metadata.enable_metadata_dirs = c_options->metadata.enable_metadata_dirs;
290 options->file_filter.show_hidden_files = c_options->file_filter.show_hidden_files;
291 options->file_filter.show_parent_directory = c_options->file_filter.show_parent_directory;
292 options->file_filter.show_dot_directory = c_options->file_filter.show_dot_directory;
293 options->file_filter.disable_file_extension_checks = c_options->file_filter.disable_file_extension_checks;
295 options->file_sort.case_sensitive = c_options->file_sort.case_sensitive;
296 options->file_sort.natural = c_options->file_sort.natural;
297 options->file_filter.disable = c_options->file_filter.disable;
299 config_entry_to_option(sidecar_ext_entry, &options->sidecar.ext, NULL);
300 sidecar_ext_parse(options->sidecar.ext);
302 options->slideshow.random = c_options->slideshow.random;
303 options->slideshow.repeat = c_options->slideshow.repeat;
304 options->slideshow.delay = c_options->slideshow.delay;
306 options->mousewheel_scrolls = c_options->mousewheel_scrolls;
307 options->image_lm_click_nav = c_options->image_lm_click_nav;
308 options->image_l_click_video = c_options->image_l_click_video;
309 options->image_l_click_video_editor = c_options->image_l_click_video_editor;
311 options->file_ops.enable_in_place_rename = c_options->file_ops.enable_in_place_rename;
313 options->image.tile_cache_max = c_options->image.tile_cache_max;
314 options->image.image_cache_max = c_options->image.image_cache_max;
316 options->image.zoom_quality = c_options->image.zoom_quality;
318 options->image.zoom_increment = c_options->image.zoom_increment;
320 options->image.enable_read_ahead = c_options->image.enable_read_ahead;
323 if (options->image.use_custom_border_color != c_options->image.use_custom_border_color
324 || options->image.use_custom_border_color_in_fullscreen != c_options->image.use_custom_border_color_in_fullscreen
325 || !gdk_color_equal(&options->image.border_color, &c_options->image.border_color))
327 options->image.use_custom_border_color_in_fullscreen = c_options->image.use_custom_border_color_in_fullscreen;
328 options->image.use_custom_border_color = c_options->image.use_custom_border_color;
329 options->image.border_color = c_options->image.border_color;
330 layout_colors_update();
331 view_window_colors_update();
334 options->image.alpha_color_1 = c_options->image.alpha_color_1;
335 options->image.alpha_color_2 = c_options->image.alpha_color_2;
337 options->fullscreen.screen = c_options->fullscreen.screen;
338 options->fullscreen.clean_flip = c_options->fullscreen.clean_flip;
339 options->fullscreen.disable_saver = c_options->fullscreen.disable_saver;
340 options->fullscreen.above = c_options->fullscreen.above;
341 if (c_options->image_overlay.template_string)
342 set_image_overlay_template_string(&options->image_overlay.template_string,
343 c_options->image_overlay.template_string);
344 if (c_options->image_overlay.font)
345 set_image_overlay_font_string(&options->image_overlay.font,
346 c_options->image_overlay.font);
347 options->image_overlay.text_red = c_options->image_overlay.text_red;
348 options->image_overlay.text_green = c_options->image_overlay.text_green;
349 options->image_overlay.text_blue = c_options->image_overlay.text_blue;
350 options->image_overlay.text_alpha = c_options->image_overlay.text_alpha;
351 options->image_overlay.background_red = c_options->image_overlay.background_red;
352 options->image_overlay.background_green = c_options->image_overlay.background_green;
353 options->image_overlay.background_blue = c_options->image_overlay.background_blue;
354 options->image_overlay.background_alpha = c_options->image_overlay.background_alpha;
355 options->update_on_time_change = c_options->update_on_time_change;
356 options->image.exif_proof_rotate_enable = c_options->image.exif_proof_rotate_enable;
358 options->duplicates_similarity_threshold = c_options->duplicates_similarity_threshold;
359 options->rot_invariant_sim = c_options->rot_invariant_sim;
361 options->tree_descend_subdirs = c_options->tree_descend_subdirs;
363 options->view_dir_list_single_click_enter = c_options->view_dir_list_single_click_enter;
365 options->open_recent_list_maxsize = c_options->open_recent_list_maxsize;
366 options->dnd_icon_size = c_options->dnd_icon_size;
367 options->clipboard_selection = c_options->clipboard_selection;
369 options->metadata.save_in_image_file = c_options->metadata.save_in_image_file;
370 options->metadata.save_legacy_IPTC = c_options->metadata.save_legacy_IPTC;
371 options->metadata.warn_on_write_problems = c_options->metadata.warn_on_write_problems;
372 options->metadata.save_legacy_format = c_options->metadata.save_legacy_format;
373 options->metadata.sync_grouped_files = c_options->metadata.sync_grouped_files;
374 options->metadata.confirm_write = c_options->metadata.confirm_write;
375 options->metadata.sidecar_extended_name = c_options->metadata.sidecar_extended_name;
376 options->metadata.confirm_timeout = c_options->metadata.confirm_timeout;
377 options->metadata.confirm_after_timeout = c_options->metadata.confirm_after_timeout;
378 options->metadata.confirm_on_image_change = c_options->metadata.confirm_on_image_change;
379 options->metadata.confirm_on_dir_change = c_options->metadata.confirm_on_dir_change;
380 options->metadata.keywords_case_sensitive = c_options->metadata.keywords_case_sensitive;
381 options->metadata.write_orientation = c_options->metadata.write_orientation;
382 options->stereo.mode = (c_options->stereo.mode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
383 (c_options->stereo.tmp.mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
384 (c_options->stereo.tmp.flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
385 (c_options->stereo.tmp.mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
386 (c_options->stereo.tmp.flip_left ? PR_STEREO_FLIP_LEFT : 0) |
387 (c_options->stereo.tmp.swap ? PR_STEREO_SWAP : 0) |
388 (c_options->stereo.tmp.temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
389 options->stereo.fsmode = (c_options->stereo.fsmode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
390 (c_options->stereo.tmp.fs_mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
391 (c_options->stereo.tmp.fs_flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
392 (c_options->stereo.tmp.fs_mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
393 (c_options->stereo.tmp.fs_flip_left ? PR_STEREO_FLIP_LEFT : 0) |
394 (c_options->stereo.tmp.fs_swap ? PR_STEREO_SWAP : 0) |
395 (c_options->stereo.tmp.fs_temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
396 options->stereo.enable_fsmode = c_options->stereo.enable_fsmode;
397 options->stereo.fixed_w = c_options->stereo.fixed_w;
398 options->stereo.fixed_h = c_options->stereo.fixed_h;
399 options->stereo.fixed_x1 = c_options->stereo.fixed_x1;
400 options->stereo.fixed_y1 = c_options->stereo.fixed_y1;
401 options->stereo.fixed_x2 = c_options->stereo.fixed_x2;
402 options->stereo.fixed_y2 = c_options->stereo.fixed_y2;
404 options->info_keywords.height = c_options->info_keywords.height;
405 options->info_title.height = c_options->info_title.height;
406 options->info_comment.height = c_options->info_comment.height;
407 options->info_rating.height = c_options->info_rating.height;
410 set_debug_level(debug_c);
414 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
416 config_entry_to_option(color_profile_input_name_entry[i], &options->color_profile.input_name[i], NULL);
417 config_entry_to_option(color_profile_input_file_entry[i], &options->color_profile.input_file[i], NULL);
419 config_entry_to_option(color_profile_screen_file_entry, &options->color_profile.screen_file, NULL);
420 options->color_profile.use_x11_screen_profile = c_options->color_profile.use_x11_screen_profile;
421 if (options->color_profile.render_intent != c_options->color_profile.render_intent)
423 options->color_profile.render_intent = c_options->color_profile.render_intent;
428 image_options_sync();
433 layout_refresh(NULL);
436 if (accel_store) gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_apply_cb, NULL);
442 *-----------------------------------------------------------------------------
443 * config window main button callbacks (private)
444 *-----------------------------------------------------------------------------
447 static void config_window_close_cb(GtkWidget *widget, gpointer data)
449 gtk_widget_destroy(configwindow);
454 static void config_window_help_cb(GtkWidget *widget, gpointer data)
456 GtkWidget *notebook = data;
459 static gchar *html_section[] =
461 "GuideOptionsGeneral.html",
462 "GuideOptionsImage.html",
463 "GuideOptionsWindow.html",
464 "GuideOptionsKeyboard.html",
465 "GuideOptionsFiltering.html",
466 "GuideOptionsMetadata.html",
467 "GuideOptionsColor.html",
468 "GuideOptionsStereo.html",
469 "GuideOptionsBehavior.html",
470 "GuideOptionsToolbar.html"
473 i = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
474 help_window_show(html_section[i]);
477 static gboolean config_window_delete(GtkWidget *widget, GdkEventAny *event, gpointer data)
479 config_window_close_cb(NULL, NULL);
483 static void config_window_ok_cb(GtkWidget *widget, gpointer data)
485 config_window_apply();
486 config_window_close_cb(NULL, NULL);
489 static void config_window_apply_cb(GtkWidget *widget, gpointer data)
492 lw = layout_window_list->data;
494 config_window_apply();
495 layout_util_sync(lw);
498 static void config_window_save_cb(GtkWidget *widget, gpointer data)
500 config_window_apply();
501 save_options(options);
505 *-----------------------------------------------------------------------------
506 * config window setup (private)
507 *-----------------------------------------------------------------------------
510 static void quality_menu_cb(GtkWidget *combo, gpointer data)
514 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
518 *option = GDK_INTERP_NEAREST;
521 *option = GDK_INTERP_TILES;
524 *option = GDK_INTERP_BILINEAR;
527 *option = GDK_INTERP_HYPER;
532 static void clipboard_selection_menu_cb(GtkWidget *combo, gpointer data)
536 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
548 static void add_quality_menu(GtkWidget *table, gint column, gint row, const gchar *text,
549 guint option, guint *option_c)
556 pref_table_label(table, column, row, text, 0.0);
558 combo = gtk_combo_box_text_new();
560 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Nearest (worst, but fastest)"));
561 if (option == GDK_INTERP_NEAREST) current = 0;
562 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Tiles"));
563 if (option == GDK_INTERP_TILES) current = 1;
564 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Bilinear"));
565 if (option == GDK_INTERP_BILINEAR) current = 2;
566 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Hyper (best, but slowest)"));
567 if (option == GDK_INTERP_HYPER) current = 3;
569 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
571 g_signal_connect(G_OBJECT(combo), "changed",
572 G_CALLBACK(quality_menu_cb), option_c);
574 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
575 GTK_EXPAND | GTK_FILL, 0, 0, 0);
576 gtk_widget_show(combo);
579 static void add_clipboard_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
580 gint option, gint *option_c)
587 pref_table_label(table, column, row, text, 0.0);
589 combo = gtk_combo_box_text_new();
591 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("PRIMARY"));
592 if (option == PRIMARY) current = 0;
593 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("CLIPBOARD"));
594 if (option == CLIPBOARD) current = 1;
596 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
598 g_signal_connect(G_OBJECT(combo), "changed",
599 G_CALLBACK(clipboard_selection_menu_cb), option_c);
601 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
602 GTK_EXPAND | GTK_FILL, 0, 0, 0);
603 gtk_widget_show(combo);
606 static void thumb_size_menu_cb(GtkWidget *combo, gpointer data)
610 n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
613 if ((guint) n < sizeof(thumb_size_list) / sizeof(ThumbSize))
615 c_options->thumbnails.max_width = thumb_size_list[n].w;
616 c_options->thumbnails.max_height = thumb_size_list[n].h;
620 c_options->thumbnails.max_width = options->thumbnails.max_width;
621 c_options->thumbnails.max_height = options->thumbnails.max_height;
625 static void add_thumb_size_menu(GtkWidget *table, gint column, gint row, gchar *text)
631 c_options->thumbnails.max_width = options->thumbnails.max_width;
632 c_options->thumbnails.max_height = options->thumbnails.max_height;
634 pref_table_label(table, column, row, text, 0.0);
636 combo = gtk_combo_box_text_new();
639 for (i = 0; (guint) i < sizeof(thumb_size_list) / sizeof(ThumbSize); i++)
644 w = thumb_size_list[i].w;
645 h = thumb_size_list[i].h;
647 buf = g_strdup_printf("%d x %d", w, h);
648 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
651 if (w == options->thumbnails.max_width && h == options->thumbnails.max_height) current = i;
658 buf = g_strdup_printf("%s %d x %d", _("Custom"), options->thumbnails.max_width, options->thumbnails.max_height);
659 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
665 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
666 g_signal_connect(G_OBJECT(combo), "changed",
667 G_CALLBACK(thumb_size_menu_cb), NULL);
669 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
670 GTK_EXPAND | GTK_FILL, 0, 0, 0);
671 gtk_widget_show(combo);
674 static void stereo_mode_menu_cb(GtkWidget *combo, gpointer data)
678 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
682 *option = PR_STEREO_NONE;
685 *option = PR_STEREO_ANAGLYPH_RC;
688 *option = PR_STEREO_ANAGLYPH_GM;
691 *option = PR_STEREO_ANAGLYPH_YB;
694 *option = PR_STEREO_ANAGLYPH_GRAY_RC;
697 *option = PR_STEREO_ANAGLYPH_GRAY_GM;
700 *option = PR_STEREO_ANAGLYPH_GRAY_YB;
703 *option = PR_STEREO_ANAGLYPH_DB_RC;
706 *option = PR_STEREO_ANAGLYPH_DB_GM;
709 *option = PR_STEREO_ANAGLYPH_DB_YB;
712 *option = PR_STEREO_HORIZ;
715 *option = PR_STEREO_HORIZ | PR_STEREO_HALF;
718 *option = PR_STEREO_VERT;
721 *option = PR_STEREO_VERT | PR_STEREO_HALF;
724 *option = PR_STEREO_FIXED;
729 static void add_stereo_mode_menu(GtkWidget *table, gint column, gint row, const gchar *text,
730 gint option, gint *option_c, gboolean add_fixed)
737 pref_table_label(table, column, row, text, 0.0);
739 combo = gtk_combo_box_text_new();
741 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Single image"));
743 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Red-Cyan"));
744 if (option & PR_STEREO_ANAGLYPH_RC) current = 1;
745 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Green-Magenta"));
746 if (option & PR_STEREO_ANAGLYPH_GM) current = 2;
747 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Yellow-Blue"));
748 if (option & PR_STEREO_ANAGLYPH_YB) current = 3;
749 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Red-Cyan"));
750 if (option & PR_STEREO_ANAGLYPH_GRAY_RC) current = 4;
751 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Green-Magenta"));
752 if (option & PR_STEREO_ANAGLYPH_GRAY_GM) current = 5;
753 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Yellow-Blue"));
754 if (option & PR_STEREO_ANAGLYPH_GRAY_YB) current = 6;
755 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Red-Cyan"));
756 if (option & PR_STEREO_ANAGLYPH_DB_RC) current = 7;
757 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Green-Magenta"));
758 if (option & PR_STEREO_ANAGLYPH_DB_GM) current = 8;
759 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Yellow-Blue"));
760 if (option & PR_STEREO_ANAGLYPH_DB_YB) current = 9;
762 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side"));
763 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side Half size"));
764 if (option & PR_STEREO_HORIZ)
767 if (option & PR_STEREO_HALF) current = 11;
770 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom"));
771 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom Half size"));
772 if (option & PR_STEREO_VERT)
775 if (option & PR_STEREO_HALF) current = 13;
780 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Fixed position"));
781 if (option & PR_STEREO_FIXED) current = 14;
784 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
786 g_signal_connect(G_OBJECT(combo), "changed",
787 G_CALLBACK(stereo_mode_menu_cb), option_c);
789 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
790 GTK_EXPAND | GTK_FILL, 0, 0, 0);
791 gtk_widget_show(combo);
794 static void video_menu_cb(GtkWidget *combo, gpointer data)
796 gchar **option = data;
798 EditorDescription *ed = g_list_nth_data(editor_list_get(), gtk_combo_box_get_active(GTK_COMBO_BOX(combo)));
802 static void video_menu_populate(gpointer data, gpointer user_data)
804 GtkWidget *combo = user_data;
805 EditorDescription *ed = data;
807 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), ed->name);
810 static void add_video_menu(GtkWidget *table, gint column, gint row, const gchar *text,
811 gchar *option, gchar **option_c)
815 /* use lists since they are sorted */
816 GList *eds = editor_list_get();
820 pref_table_label(table, column, row, text, 0.0);
822 combo = gtk_combo_box_text_new();
823 g_list_foreach(eds,video_menu_populate,(gpointer)combo);
824 current = option ? g_list_index(eds,g_hash_table_lookup(editors,option)): -1;
826 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
828 g_signal_connect(G_OBJECT(combo), "changed",
829 G_CALLBACK(video_menu_cb), option_c);
831 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
832 GTK_EXPAND | GTK_FILL, 0, 0, 0);
833 gtk_widget_show(combo);
836 static void filter_store_populate(void)
840 if (!filter_store) return;
842 gtk_list_store_clear(filter_store);
844 work = filter_get_list();
853 gtk_list_store_append(filter_store, &iter);
854 gtk_list_store_set(filter_store, &iter, 0, fe, -1);
858 static void filter_store_ext_edit_cb(GtkCellRendererText *cell, gchar *path_str,
859 gchar *new_text, gpointer data)
861 GtkWidget *model = data;
862 FilterEntry *fe = data;
866 if (!new_text || strlen(new_text) < 1) return;
868 tpath = gtk_tree_path_new_from_string(path_str);
869 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
870 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
872 g_free(fe->extensions);
873 fe->extensions = g_strdup(new_text);
875 gtk_tree_path_free(tpath);
879 static void filter_store_class_edit_cb(GtkCellRendererText *cell, gchar *path_str,
880 gchar *new_text, gpointer data)
882 GtkWidget *model = data;
883 FilterEntry *fe = data;
888 if (!new_text || !new_text[0]) return;
890 tpath = gtk_tree_path_new_from_string(path_str);
891 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
892 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
894 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
896 if (strcmp(new_text, _(format_class_list[i])) == 0)
903 gtk_tree_path_free(tpath);
907 static void filter_store_desc_edit_cb(GtkCellRendererText *cell, gchar *path_str,
908 gchar *new_text, gpointer data)
910 GtkWidget *model = data;
915 if (!new_text || !new_text[0]) return;
917 tpath = gtk_tree_path_new_from_string(path_str);
918 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
919 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
921 g_free(fe->description);
922 fe->description = g_strdup(new_text);
924 gtk_tree_path_free(tpath);
927 static void filter_store_enable_cb(GtkCellRendererToggle *renderer,
928 gchar *path_str, gpointer data)
930 GtkWidget *model = data;
935 tpath = gtk_tree_path_new_from_string(path_str);
936 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
937 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
939 fe->enabled = !fe->enabled;
941 gtk_tree_path_free(tpath);
945 static void filter_store_writable_cb(GtkCellRendererToggle *renderer,
946 gchar *path_str, gpointer data)
948 GtkWidget *model = data;
953 tpath = gtk_tree_path_new_from_string(path_str);
954 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
955 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
957 fe->writable = !fe->writable;
958 if (fe->writable) fe->allow_sidecar = FALSE;
960 gtk_tree_path_free(tpath);
964 static void filter_store_sidecar_cb(GtkCellRendererToggle *renderer,
965 gchar *path_str, gpointer data)
967 GtkWidget *model = data;
972 tpath = gtk_tree_path_new_from_string(path_str);
973 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
974 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
976 fe->allow_sidecar = !fe->allow_sidecar;
977 if (fe->allow_sidecar) fe->writable = FALSE;
979 gtk_tree_path_free(tpath);
983 static void filter_set_func(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
984 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
988 gtk_tree_model_get(tree_model, iter, 0, &fe, -1);
990 switch (GPOINTER_TO_INT(data))
993 g_object_set(GTK_CELL_RENDERER(cell),
994 "active", fe->enabled, NULL);
997 g_object_set(GTK_CELL_RENDERER(cell),
998 "text", fe->extensions, NULL);
1000 case FE_DESCRIPTION:
1001 g_object_set(GTK_CELL_RENDERER(cell),
1002 "text", fe->description, NULL);
1005 g_object_set(GTK_CELL_RENDERER(cell),
1006 "text", _(format_class_list[fe->file_class]), NULL);
1009 g_object_set(GTK_CELL_RENDERER(cell),
1010 "active", fe->writable, NULL);
1012 case FE_ALLOW_SIDECAR:
1013 g_object_set(GTK_CELL_RENDERER(cell),
1014 "active", fe->allow_sidecar, NULL);
1019 static gboolean filter_add_scroll(gpointer data)
1023 GtkCellRenderer *cell;
1024 GtkTreeViewColumn *column;
1025 GList *list_columns;
1030 rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(filter_store), NULL);
1031 path = gtk_tree_path_new_from_indices(rows-1, -1);
1033 list_columns = gtk_tree_view_get_columns(GTK_TREE_VIEW(data));
1035 column = g_list_nth(list_columns,i)->data;
1036 title = gtk_tree_view_column_get_title(GTK_TREE_VIEW_COLUMN(column));
1038 } while (strcmp(title, "Filter") !=0 );
1040 list_cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column));
1041 cell = g_list_last(list_cells)->data;
1043 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1044 path, column, FALSE, 0.0, 0.0 );
1045 gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(data),
1046 path, column, cell, TRUE);
1048 gtk_tree_path_free(path);
1049 g_list_free(list_cells);
1050 g_list_free(list_columns);
1055 static void filter_add_cb(GtkWidget *widget, gpointer data)
1057 filter_add_unique("description", ".new", FORMAT_CLASS_IMAGE, TRUE, FALSE, TRUE);
1058 filter_store_populate();
1060 g_idle_add((GSourceFunc)filter_add_scroll, data);
1063 static void filter_remove_cb(GtkWidget *widget, gpointer data)
1065 GtkWidget *filter_view = data;
1066 GtkTreeSelection *selection;
1070 if (!filter_store) return;
1071 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1072 if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) return;
1073 gtk_tree_model_get(GTK_TREE_MODEL(filter_store), &iter, 0, &fe, -1);
1076 filter_remove_entry(fe);
1078 filter_store_populate();
1081 static gboolean filter_default_ok_scroll(GtkTreeView *data)
1085 GtkTreeViewColumn *column;
1087 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(filter_store), &iter);
1088 path = gtk_tree_model_get_path(GTK_TREE_MODEL(filter_store), &iter);
1089 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1091 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1095 gtk_tree_path_free(path);
1100 static void filter_default_ok_cb(GenericDialog *gd, gpointer data)
1103 filter_add_defaults();
1105 filter_store_populate();
1107 g_idle_add((GSourceFunc)filter_default_ok_scroll, gd->data);
1110 static void dummy_cancel_cb(GenericDialog *gd, gpointer data)
1112 /* no op, only so cancel button appears */
1115 static void filter_default_cb(GtkWidget *widget, gpointer data)
1119 gd = generic_dialog_new(_("Reset filters"),
1120 "reset_filter", widget, TRUE,
1121 dummy_cancel_cb, data);
1122 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset filters"),
1123 _("This will reset the file filters to the defaults.\nContinue?"), TRUE);
1124 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, filter_default_ok_cb, TRUE);
1125 gtk_widget_show(gd->dialog);
1128 static void filter_disable_cb(GtkWidget *widget, gpointer data)
1130 GtkWidget *frame = data;
1132 gtk_widget_set_sensitive(frame,
1133 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
1136 static void safe_delete_view_cb(GtkWidget *widget, gpointer data)
1138 layout_set_path(NULL, gtk_entry_get_text(GTK_ENTRY(safe_delete_path_entry)));
1141 static void safe_delete_clear_ok_cb(GenericDialog *gd, gpointer data)
1143 file_util_trash_clear();
1146 static void safe_delete_clear_cb(GtkWidget *widget, gpointer data)
1150 gd = generic_dialog_new(_("Clear trash"),
1151 "clear_trash", widget, TRUE,
1152 dummy_cancel_cb, NULL);
1153 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear trash"),
1154 _("This will remove the trash contents."), FALSE);
1155 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, safe_delete_clear_ok_cb, TRUE);
1156 entry = gtk_entry_new();
1157 gtk_widget_set_can_focus(entry, FALSE);
1158 gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE);
1159 if (options->file_ops.safe_delete_path) gtk_entry_set_text(GTK_ENTRY(entry), options->file_ops.safe_delete_path);
1160 gtk_box_pack_start(GTK_BOX(gd->vbox), entry, FALSE, FALSE, 0);
1161 gtk_widget_show(entry);
1162 gtk_widget_show(gd->dialog);
1165 static void image_overlay_template_view_changed_cb(GtkWidget *widget, gpointer data)
1167 GtkWidget *pTextView;
1168 GtkTextBuffer *pTextBuffer;
1172 pTextView = GTK_WIDGET(data);
1174 pTextBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pTextView));
1175 gtk_text_buffer_get_start_iter(pTextBuffer, &iStart);
1176 gtk_text_buffer_get_end_iter(pTextBuffer, &iEnd);
1178 set_image_overlay_template_string(&c_options->image_overlay.template_string,
1179 gtk_text_buffer_get_text(pTextBuffer, &iStart, &iEnd, TRUE));
1182 static void image_overlay_default_template_ok_cb(GenericDialog *gd, gpointer data)
1184 GtkTextView *text_view = data;
1185 GtkTextBuffer *buffer;
1187 set_default_image_overlay_template_string(&options->image_overlay.template_string);
1188 if (!configwindow) return;
1190 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
1191 gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1194 static void image_overlay_default_template_cb(GtkWidget *widget, gpointer data)
1198 gd = generic_dialog_new(_("Reset image overlay template string"),
1199 "reset_image_overlay_template_string", widget, TRUE,
1200 dummy_cancel_cb, data);
1201 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset image overlay template string"),
1202 _("This will reset the image overlay template string to the default.\nContinue?"), TRUE);
1203 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, image_overlay_default_template_ok_cb, TRUE);
1204 gtk_widget_show(gd->dialog);
1207 static void image_overlay_help_cb(GtkWidget *widget, gpointer data)
1209 help_window_show("GuideOptionsWindow.html#OverlayScreenDisplay");
1212 static void image_overlay_set_font_cb(GtkWidget *widget, gpointer data)
1214 #if GTK_CHECK_VERSION(3,4,0)
1217 PangoFontDescription *font_desc;
1219 dialog = gtk_font_chooser_dialog_new("Image Overlay Font", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1220 gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), options->image_overlay.font);
1222 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1224 font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
1225 font = pango_font_description_to_string(font_desc);
1226 g_free(c_options->image_overlay.font);
1227 c_options->image_overlay.font = g_strdup(font);
1231 gtk_widget_destroy(dialog);
1235 font = gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget));
1236 c_options->image_overlay.font = g_strdup(font);
1240 static void image_overlay_set_text_colour_cb(GtkWidget *widget, gpointer data)
1243 #if GTK_CHECK_VERSION(3,4,0)
1246 dialog = gtk_color_chooser_dialog_new("Image Overlay Text Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1247 colour.red = options->image_overlay.text_red;
1248 colour.green = options->image_overlay.text_green;
1249 colour.blue = options->image_overlay.text_blue;
1250 colour.alpha = options->image_overlay.text_alpha;
1251 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1252 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1254 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1256 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1257 c_options->image_overlay.text_red = colour.red*255;
1258 c_options->image_overlay.text_green = colour.green*255;
1259 c_options->image_overlay.text_blue = colour.blue*255;
1260 c_options->image_overlay.text_alpha = colour.alpha*255;
1262 gtk_widget_destroy(dialog);
1265 GtkColorSelection *colorsel;
1267 dialog = gtk_color_selection_dialog_new("Image Overlay Text Colour");
1268 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1269 colour.red = options->image_overlay.text_red*257;
1270 colour.green = options->image_overlay.text_green*257;
1271 colour.blue = options->image_overlay.text_blue*257;
1272 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1273 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1274 gtk_color_selection_set_current_color(colorsel, &colour);
1275 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.text_alpha*257);
1277 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1279 gtk_color_selection_get_current_color(colorsel, &colour);
1280 c_options->image_overlay.text_red = colour.red/257;
1281 c_options->image_overlay.text_green = colour.green/257;
1282 c_options->image_overlay.text_blue = colour.blue/257;
1283 c_options->image_overlay.text_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1285 gtk_widget_destroy (dialog);
1290 static void image_overlay_set_background_colour_cb(GtkWidget *widget, gpointer data)
1293 #if GTK_CHECK_VERSION(3,4,0)
1296 dialog = gtk_color_chooser_dialog_new("Image Overlay Background Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1297 colour.red = options->image_overlay.background_red;
1298 colour.green = options->image_overlay.background_green;
1299 colour.blue = options->image_overlay.background_blue;
1300 colour.alpha = options->image_overlay.background_alpha;
1301 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1302 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1304 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1306 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1307 c_options->image_overlay.background_red = colour.red*255;
1308 c_options->image_overlay.background_green = colour.green*255;
1309 c_options->image_overlay.background_blue = colour.blue*255;
1310 c_options->image_overlay.background_alpha = colour.alpha*255;
1312 gtk_widget_destroy(dialog);
1315 GtkColorSelection *colorsel;
1317 dialog = gtk_color_selection_dialog_new("Image Overlay Background Colour");
1318 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1319 colour.red = options->image_overlay.background_red*257;
1320 colour.green = options->image_overlay.background_green*257;
1321 colour.blue = options->image_overlay.background_blue*257;
1322 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1323 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1324 gtk_color_selection_set_current_color(colorsel, &colour);
1325 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.background_alpha*257);
1327 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1329 gtk_color_selection_get_current_color(colorsel, &colour);
1330 c_options->image_overlay.background_red = colour.red/257;
1331 c_options->image_overlay.background_green = colour.green/257;
1332 c_options->image_overlay.background_blue = colour.blue/257;
1333 c_options->image_overlay.background_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1335 gtk_widget_destroy(dialog);
1339 static void accel_store_populate(void)
1342 GList *groups, *actions;
1344 const gchar *accel_path;
1348 if (!accel_store || !layout_window_list || !layout_window_list->data) return;
1350 gtk_tree_store_clear(accel_store);
1351 lw = layout_window_list->data; /* get the actions from the first window, it should not matter, they should be the same in all windows */
1353 g_assert(lw && lw->ui_manager);
1354 groups = gtk_ui_manager_get_action_groups(lw->ui_manager);
1357 actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
1360 action = GTK_ACTION(actions->data);
1361 accel_path = gtk_action_get_accel_path(action);
1362 if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
1364 gchar *label, *label2, *tooltip, *accel;
1365 g_object_get(action,
1366 "tooltip", &tooltip,
1370 if (pango_parse_markup(label, -1, '_', NULL, &label2, NULL, NULL) && label2)
1376 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1380 gtk_tree_store_append(accel_store, &iter, NULL);
1381 gtk_tree_store_set(accel_store, &iter,
1384 AE_TOOLTIP, tooltip ? tooltip : "",
1385 AE_ACCEL, accel_path,
1393 actions = actions->next;
1396 groups = groups->next;
1400 static void accel_store_cleared_cb(GtkCellRendererAccel *accel, gchar *path_string, gpointer user_data)
1405 static gboolean accel_remove_key_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1407 gchar *accel1 = data;
1412 gtk_tree_model_get(model, iter, AE_KEY, &accel2, -1);
1414 gtk_accelerator_parse(accel1, &key1.accel_key, &key1.accel_mods);
1415 gtk_accelerator_parse(accel2, &key2.accel_key, &key2.accel_mods);
1417 if (key1.accel_key == key2.accel_key && key1.accel_mods == key2.accel_mods)
1419 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1420 DEBUG_1("accelerator key '%s' is already used, removing.", accel1);
1429 static void accel_store_edited_cb(GtkCellRendererAccel *accel, gchar *path_string, guint accel_key, GdkModifierType accel_mods, guint hardware_keycode, gpointer user_data)
1431 GtkTreeModel *model = (GtkTreeModel *)accel_store;
1435 GtkAccelKey old_key, key;
1436 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
1438 gtk_tree_model_get_iter(model, &iter, path);
1439 gtk_tree_model_get(model, &iter, AE_ACCEL, &accel_path, -1);
1441 /* test if the accelerator can be stored without conflicts*/
1442 gtk_accel_map_lookup_entry(accel_path, &old_key);
1444 /* change the key and read it back (change may fail on keys hardcoded in gtk)*/
1445 gtk_accel_map_change_entry(accel_path, accel_key, accel_mods, TRUE);
1446 gtk_accel_map_lookup_entry(accel_path, &key);
1448 /* restore the original for now, the key will be really changed when the changes are confirmed */
1449 gtk_accel_map_change_entry(accel_path, old_key.accel_key, old_key.accel_mods, TRUE);
1451 acc = gtk_accelerator_name(key.accel_key, key.accel_mods);
1452 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, acc);
1454 gtk_tree_store_set(accel_store, &iter, AE_KEY, acc, -1);
1455 gtk_tree_path_free(path);
1459 static gboolean accel_default_scroll(GtkTreeView *data)
1463 GtkTreeViewColumn *column;
1465 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(accel_store), &iter);
1466 path = gtk_tree_model_get_path(GTK_TREE_MODEL(accel_store), &iter);
1467 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1469 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1473 gtk_tree_path_free(path);
1478 static void accel_default_cb(GtkWidget *widget, gpointer data)
1480 accel_store_populate();
1482 g_idle_add((GSourceFunc)accel_default_scroll, data);
1485 void accel_remove_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1487 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1490 void accel_reset_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1493 gchar *accel_path, *accel;
1495 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, -1);
1496 gtk_accel_map_lookup_entry(accel_path, &key);
1497 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1499 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, accel);
1501 gtk_tree_store_set(accel_store, iter, AE_KEY, accel, -1);
1506 static void accel_reset_cb(GtkWidget *widget, gpointer data)
1508 GtkTreeSelection *selection;
1510 if (!accel_store) return;
1511 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data));
1512 gtk_tree_selection_selected_foreach(selection, &accel_reset_selection, NULL);
1517 static GtkWidget *scrolled_notebook_page(GtkWidget *notebook, const gchar *title)
1521 GtkWidget *scrolled;
1522 GtkWidget *viewport;
1524 scrolled = gtk_scrolled_window_new(NULL, NULL);
1525 gtk_container_set_border_width(GTK_CONTAINER(scrolled), PREF_PAD_BORDER);
1526 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1527 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1528 label = gtk_label_new(title);
1529 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, label);
1530 gtk_widget_show(scrolled);
1532 viewport = gtk_viewport_new(NULL, NULL);
1533 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1534 gtk_container_add(GTK_CONTAINER(scrolled), viewport);
1535 gtk_widget_show(viewport);
1537 vbox = gtk_vbox_new(FALSE, 0);
1538 gtk_container_add(GTK_CONTAINER(viewport), vbox);
1539 gtk_widget_show(vbox);
1544 static void cache_standard_cb(GtkWidget *widget, gpointer data)
1546 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1548 c_options->thumbnails.spec_standard =TRUE;
1549 c_options->thumbnails.cache_into_dirs = FALSE;
1553 c_options->thumbnails.spec_standard =FALSE;
1557 static void cache_geeqie_cb(GtkWidget *widget, gpointer data)
1559 if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1561 c_options->thumbnails.spec_standard =TRUE;
1562 c_options->thumbnails.cache_into_dirs = FALSE;
1566 c_options->thumbnails.spec_standard =FALSE;
1570 static void cache_local_cb(GtkWidget *widget, gpointer data)
1572 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1574 c_options->thumbnails.cache_into_dirs = TRUE;
1575 c_options->thumbnails.spec_standard =FALSE;
1579 c_options->thumbnails.cache_into_dirs = FALSE;
1583 /* general options tab */
1584 static void config_tab_general(GtkWidget *notebook)
1589 GtkWidget *group_frame;
1590 GtkWidget *subgroup;
1592 GtkWidget *ct_button;
1595 gint hours, minutes, remainder;
1598 vbox = scrolled_notebook_page(notebook, _("General"));
1600 group = pref_group_new(vbox, FALSE, _("Thumbnails"), GTK_ORIENTATION_VERTICAL);
1602 table = pref_table_new(group, 2, 2, FALSE, FALSE);
1603 add_thumb_size_menu(table, 0, 0, _("Size:"));
1604 add_quality_menu(table, 0, 1, _("Quality:"), options->thumbnails.quality, &c_options->thumbnails.quality);
1606 ct_button = pref_checkbox_new_int(group, _("Cache thumbnails"),
1607 options->thumbnails.enable_caching, &c_options->thumbnails.enable_caching);
1609 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1610 pref_checkbox_link_sensitivity(ct_button, subgroup);
1612 group_frame = pref_frame_new(subgroup, TRUE, _("Use Geeqie thumbnail style and cache"),
1613 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1614 button = pref_radiobutton_new(group_frame, NULL, get_thumbnails_cache_dir(),
1615 !options->thumbnails.spec_standard,
1616 G_CALLBACK(cache_geeqie_cb), NULL);
1618 group_frame = pref_frame_new(subgroup, TRUE,
1619 _("Store thumbnails local to image folder (non-standard)"),
1620 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1621 pref_radiobutton_new(group_frame, button, "*/.thumbnails",
1622 options->thumbnails.cache_into_dirs,
1623 G_CALLBACK(cache_local_cb), NULL);
1625 group_frame = pref_frame_new(subgroup, TRUE,
1626 _("Use standard thumbnail style and cache, shared with other applications"),
1627 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1628 pref_radiobutton_new(group_frame, button, get_thumbnails_standard_cache_dir(),
1629 options->thumbnails.spec_standard,
1630 G_CALLBACK(cache_standard_cb), NULL);
1632 pref_checkbox_new_int(group, _("Use EXIF thumbnails when available (EXIF thumbnails may be outdated)"),
1633 options->thumbnails.use_exif, &c_options->thumbnails.use_exif);
1635 #ifdef HAVE_FFMPEGTHUMBNAILER_METADATA
1636 pref_checkbox_new_int(group, _("Use embedded metadata in video files as thumbnails when available"),
1637 options->thumbnails.use_ft_metadata, &c_options->thumbnails.use_ft_metadata);
1639 // pref_checkbox_new_int(group, _("Ignore embedded metadata if size is too small"),
1640 // options->thumbnails.use_ft_metadata_small, &c_options->thumbnails.use_ft_metadata_small);
1643 group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
1645 c_options->slideshow.delay = options->slideshow.delay;
1646 hours = options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
1647 remainder = options->slideshow.delay % (3600 * SLIDESHOW_SUBSECOND_PRECISION);
1648 minutes = remainder / (60 * SLIDESHOW_SUBSECOND_PRECISION);
1649 seconds = (gdouble)(remainder % (60 * SLIDESHOW_SUBSECOND_PRECISION)) /
1650 SLIDESHOW_SUBSECOND_PRECISION;
1652 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1654 spin = pref_spin_new(hbox, _("Delay between image change hrs:mins:secs.dec"), NULL,
1656 options->slideshow.delay ? hours : 0.0,
1657 G_CALLBACK(slideshow_delay_hours_cb), NULL);
1658 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1659 spin = pref_spin_new(hbox, ":" , NULL,
1661 options->slideshow.delay ? minutes: 0.0,
1662 G_CALLBACK(slideshow_delay_minutes_cb), NULL);
1663 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1664 spin = pref_spin_new(hbox, ":", NULL,
1665 SLIDESHOW_MIN_SECONDS, 59, 1.0, 1,
1666 options->slideshow.delay ? seconds : 10.0,
1667 G_CALLBACK(slideshow_delay_seconds_cb), NULL);
1668 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1670 pref_checkbox_new_int(group, _("Random"), options->slideshow.random, &c_options->slideshow.random);
1671 pref_checkbox_new_int(group, _("Repeat"), options->slideshow.repeat, &c_options->slideshow.repeat);
1673 group = pref_group_new(vbox, FALSE, _("Image loading and caching"), GTK_ORIENTATION_VERTICAL);
1675 pref_spin_new_int(group, _("Decoded image cache size (Mb):"), NULL,
1676 0, 99999, 1, options->image.image_cache_max, &c_options->image.image_cache_max);
1677 pref_checkbox_new_int(group, _("Preload next image"),
1678 options->image.enable_read_ahead, &c_options->image.enable_read_ahead);
1680 pref_checkbox_new_int(group, _("Refresh on file change"),
1681 options->update_on_time_change, &c_options->update_on_time_change);
1683 group = pref_group_new(vbox, FALSE, _("Info sidebar heights"), GTK_ORIENTATION_VERTICAL);
1684 pref_label_new(group, _("NOTE! Geeqie must be restarted for changes to take effect"));
1685 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1686 pref_spin_new_int(hbox, _("Keywords:"), NULL,
1688 options->info_keywords.height, &c_options->info_keywords.height);
1689 pref_spin_new_int(hbox, _("Title:"), NULL,
1691 options->info_title.height, &c_options->info_title.height);
1692 pref_spin_new_int(hbox, _("Comment:"), NULL,
1694 options->info_comment.height, &c_options->info_comment.height);
1695 pref_spin_new_int(hbox, _("Rating:"), NULL,
1697 options->info_rating.height, &c_options->info_rating.height);
1701 static void config_tab_image(GtkWidget *notebook)
1706 GtkWidget *ct_button;
1707 GtkWidget *enlargement_button;
1711 vbox = scrolled_notebook_page(notebook, _("Image"));
1713 group = pref_group_new(vbox, FALSE, _("Zoom"), GTK_ORIENTATION_VERTICAL);
1715 table = pref_table_new(group, 2, 1, FALSE, FALSE);
1716 add_quality_menu(table, 0, 0, _("Quality:"), options->image.zoom_quality, &c_options->image.zoom_quality);
1719 pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library"),
1720 options->image.use_clutter_renderer, &c_options->image.use_clutter_renderer);
1723 pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"),
1724 options->image.zoom_2pass, &c_options->image.zoom_2pass);
1726 c_options->image.zoom_increment = options->image.zoom_increment;
1727 spin = pref_spin_new(group, _("Zoom increment:"), NULL,
1728 0.01, 4.0, 0.01, 2, (gdouble)options->image.zoom_increment / 100.0,
1729 G_CALLBACK(zoom_increment_cb), NULL);
1730 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1732 group = pref_group_new(vbox, FALSE, _("Fit image to window"), GTK_ORIENTATION_VERTICAL);
1734 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1735 enlargement_button = pref_checkbox_new_int(hbox, _("Allow enlargement of image (max. size in %)"),
1736 options->image.zoom_to_fit_allow_expand, &c_options->image.zoom_to_fit_allow_expand);
1737 spin = pref_spin_new_int(hbox, NULL, NULL,
1739 options->image.max_enlargement_size, &c_options->image.max_enlargement_size);
1740 pref_checkbox_link_sensitivity(enlargement_button, spin);
1741 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."));
1743 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1744 ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (% of actual window):"),
1745 options->image.limit_autofit_size, &c_options->image.limit_autofit_size);
1746 spin = pref_spin_new_int(hbox, NULL, NULL,
1748 options->image.max_autofit_size, &c_options->image.max_autofit_size);
1749 pref_checkbox_link_sensitivity(ct_button, spin);
1750 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."));
1752 group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
1754 pref_checkbox_new_int(group, _("Use custom border color in window mode"),
1755 options->image.use_custom_border_color, &c_options->image.use_custom_border_color);
1757 pref_checkbox_new_int(group, _("Use custom border color in fullscreen mode"),
1758 options->image.use_custom_border_color_in_fullscreen, &c_options->image.use_custom_border_color_in_fullscreen);
1760 pref_color_button_new(group, _("Border color"), &options->image.border_color,
1761 G_CALLBACK(pref_color_button_set_cb), &c_options->image.border_color);
1763 c_options->image.border_color = options->image.border_color;
1765 pref_color_button_new(group, _("Alpha channel color 1"), &options->image.alpha_color_1,
1766 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_1);
1768 pref_color_button_new(group, _("Alpha channel color 2"), &options->image.alpha_color_2,
1769 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_2);
1771 c_options->image.alpha_color_1 = options->image.alpha_color_1;
1772 c_options->image.alpha_color_2 = options->image.alpha_color_2;
1774 group = pref_group_new(vbox, FALSE, _("Convenience"), GTK_ORIENTATION_VERTICAL);
1776 pref_checkbox_new_int(group, _("Auto rotate proofs using Exif information"),
1777 options->image.exif_proof_rotate_enable, &c_options->image.exif_proof_rotate_enable);
1781 static void config_tab_windows(GtkWidget *notebook)
1787 GtkWidget *ct_button;
1789 GtkWidget *image_overlay_template_view;
1790 GtkWidget *scrolled;
1791 GtkTextBuffer *buffer;
1793 vbox = scrolled_notebook_page(notebook, _("Windows"));
1795 group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
1797 ct_button = pref_checkbox_new_int(group, _("Remember window positions"),
1798 options->save_window_positions, &c_options->save_window_positions);
1800 button = pref_checkbox_new_int(group, _("Use saved window positions also for new windows"),
1801 options->use_saved_window_positions_for_new_windows, &c_options->use_saved_window_positions_for_new_windows);
1802 pref_checkbox_link_sensitivity(ct_button, button);
1804 pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
1805 options->tools_restore_state, &c_options->tools_restore_state);
1807 pref_checkbox_new_int(group, _("Remember dialog window positions"),
1808 options->save_dialog_window_positions, &c_options->save_dialog_window_positions);
1810 pref_checkbox_new_int(group, _("Show window IDs"),
1811 options->show_window_ids, &c_options->show_window_ids);
1813 group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
1815 pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
1816 options->image.fit_window_to_image, &c_options->image.fit_window_to_image);
1818 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1819 ct_button = pref_checkbox_new_int(hbox, _("Limit size when auto-sizing window (%):"),
1820 options->image.limit_window_size, &c_options->image.limit_window_size);
1821 spin = pref_spin_new_int(hbox, NULL, NULL,
1823 options->image.max_window_size, &c_options->image.max_window_size);
1824 pref_checkbox_link_sensitivity(ct_button, spin);
1826 group = pref_group_new(vbox, FALSE, _("Full screen"), GTK_ORIENTATION_VERTICAL);
1828 c_options->fullscreen.screen = options->fullscreen.screen;
1829 c_options->fullscreen.above = options->fullscreen.above;
1830 hbox = fullscreen_prefs_selection_new(_("Location:"), &c_options->fullscreen.screen, &c_options->fullscreen.above);
1831 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
1832 gtk_widget_show(hbox);
1834 pref_checkbox_new_int(group, _("Smooth image flip"),
1835 options->fullscreen.clean_flip, &c_options->fullscreen.clean_flip);
1836 pref_checkbox_new_int(group, _("Disable screen saver"),
1837 options->fullscreen.disable_saver, &c_options->fullscreen.disable_saver);
1840 group = pref_group_new(vbox, FALSE, _("Overlay Screen Display"), GTK_ORIENTATION_VERTICAL);
1842 pref_label_new(group, _("Image overlay template"));
1844 scrolled = gtk_scrolled_window_new(NULL, NULL);
1845 gtk_widget_set_size_request(scrolled, 200, 150);
1846 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
1847 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1848 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1849 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 5);
1850 gtk_widget_show(scrolled);
1852 image_overlay_template_view = gtk_text_view_new();
1854 gtk_widget_set_tooltip_markup(image_overlay_template_view,
1855 _("<i>%name%</i> results in the filename of the picture.\n"
1856 "Also available: <i>%collection%</i>, <i>%number%</i>, <i>%total%</i>, <i>%date%</i>,\n"
1857 "<i>%size%</i> (filesize), <i>%width%</i>, <i>%height%</i>, <i>%res%</i> (resolution),\n"
1858 "<i>%rating%</i>, <i>%keywords%</i>, <i>%comment%</i> (XMP), <i>%imagecomment%</i> (JPEG)\n"
1859 "To access exif data use the exif name, e. g. <i>%formatted.Camera%</i> is the formatted camera name,\n"
1860 "<i>%Exif.Photo.DateTimeOriginal%</i> the date of the original shot.\n"
1861 "<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"
1862 "If two or more variables are connected with the |-sign, it prints available variables with a separator.\n"
1863 "<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"
1864 "if there's no ISO information in the Exif data.\n"
1865 "If a line is empty, it is removed. This allows one to add lines that totally disappear when no data is available.\n"
1867 gtk_container_add(GTK_CONTAINER(scrolled), image_overlay_template_view);
1868 gtk_widget_show(image_overlay_template_view);
1870 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
1872 #if GTK_CHECK_VERSION(3,4,0)
1873 button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
1874 G_CALLBACK(image_overlay_set_font_cb), notebook);
1876 button = gtk_font_button_new();
1877 gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Image Overlay Font");
1878 gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->image_overlay.font);
1879 g_signal_connect(G_OBJECT(button), "font-set",
1880 G_CALLBACK(image_overlay_set_font_cb),NULL);
1882 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1883 gtk_widget_show(button);
1885 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Text"), FALSE,
1886 G_CALLBACK(image_overlay_set_text_colour_cb), NULL);
1887 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1888 gtk_widget_show(button);
1890 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Background"), FALSE,
1891 G_CALLBACK(image_overlay_set_background_colour_cb), NULL);
1892 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1893 gtk_widget_show(button);
1894 image_overlay_set_text_colours();
1896 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
1897 G_CALLBACK(image_overlay_default_template_cb), image_overlay_template_view);
1898 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1899 gtk_widget_show(button);
1901 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
1902 G_CALLBACK(image_overlay_help_cb), NULL);
1903 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1904 gtk_widget_show(button);
1906 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_overlay_template_view));
1907 if (options->image_overlay.template_string) gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1908 g_signal_connect(G_OBJECT(buffer), "changed",
1909 G_CALLBACK(image_overlay_template_view_changed_cb), image_overlay_template_view);
1914 static GtkTreeModel *create_class_model(void)
1916 GtkListStore *model;
1920 /* create list store */
1921 model = gtk_list_store_new(1, G_TYPE_STRING);
1922 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
1924 gtk_list_store_append(model, &iter);
1925 gtk_list_store_set(model, &iter, 0, _(format_class_list[i]), -1);
1927 return GTK_TREE_MODEL (model);
1932 static void config_tab_files(GtkWidget *notebook)
1939 GtkWidget *ct_button;
1940 GtkWidget *scrolled;
1941 GtkWidget *filter_view;
1942 GtkCellRenderer *renderer;
1943 GtkTreeSelection *selection;
1944 GtkTreeViewColumn *column;
1946 vbox = scrolled_notebook_page(notebook, _("Files"));
1948 group = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1950 pref_checkbox_new_int(group, _("Show hidden files or folders"),
1951 options->file_filter.show_hidden_files, &c_options->file_filter.show_hidden_files);
1952 pref_checkbox_new_int(group, _("Show parent folder (..)"),
1953 options->file_filter.show_parent_directory, &c_options->file_filter.show_parent_directory);
1954 pref_checkbox_new_int(group, _("Case sensitive sort"),
1955 options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
1956 pref_checkbox_new_int(group, _("Natural sort order"),
1957 options->file_sort.natural, &c_options->file_sort.natural);
1958 pref_checkbox_new_int(group, _("Disable file extension checks"),
1959 options->file_filter.disable_file_extension_checks, &c_options->file_filter.disable_file_extension_checks);
1961 ct_button = pref_checkbox_new_int(group, _("Disable File Filtering"),
1962 options->file_filter.disable, &c_options->file_filter.disable);
1965 group = pref_group_new(vbox, FALSE, _("Grouping sidecar extensions"), GTK_ORIENTATION_VERTICAL);
1967 sidecar_ext_entry = gtk_entry_new();
1968 gtk_entry_set_text(GTK_ENTRY(sidecar_ext_entry), options->sidecar.ext);
1969 gtk_box_pack_start(GTK_BOX(group), sidecar_ext_entry, FALSE, FALSE, 0);
1970 gtk_widget_show(sidecar_ext_entry);
1972 group = pref_group_new(vbox, TRUE, _("File types"), GTK_ORIENTATION_VERTICAL);
1974 frame = pref_group_parent(group);
1975 g_signal_connect(G_OBJECT(ct_button), "toggled",
1976 G_CALLBACK(filter_disable_cb), frame);
1977 gtk_widget_set_sensitive(frame, !options->file_filter.disable);
1979 scrolled = gtk_scrolled_window_new(NULL, NULL);
1980 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
1981 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
1982 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
1983 gtk_widget_show(scrolled);
1985 filter_store = gtk_list_store_new(1, G_TYPE_POINTER);
1986 filter_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(filter_store));
1987 g_object_unref(filter_store);
1988 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1989 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
1991 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), FALSE);
1993 column = gtk_tree_view_column_new();
1994 gtk_tree_view_column_set_title(column, _("Filter"));
1995 gtk_tree_view_column_set_resizable(column, TRUE);
1997 renderer = gtk_cell_renderer_toggle_new();
1998 g_signal_connect(G_OBJECT(renderer), "toggled",
1999 G_CALLBACK(filter_store_enable_cb), filter_store);
2000 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2001 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2002 GINT_TO_POINTER(FE_ENABLE), NULL);
2004 renderer = gtk_cell_renderer_text_new();
2005 g_signal_connect(G_OBJECT(renderer), "edited",
2006 G_CALLBACK(filter_store_ext_edit_cb), filter_store);
2007 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2008 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2009 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2010 GINT_TO_POINTER(FE_EXTENSION), NULL);
2011 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2013 column = gtk_tree_view_column_new();
2014 gtk_tree_view_column_set_title(column, _("Description"));
2015 gtk_tree_view_column_set_resizable(column, TRUE);
2016 gtk_tree_view_column_set_fixed_width(column, 200);
2017 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
2019 renderer = gtk_cell_renderer_text_new();
2020 g_signal_connect(G_OBJECT(renderer), "edited",
2021 G_CALLBACK(filter_store_desc_edit_cb), filter_store);
2022 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2023 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2024 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2025 GINT_TO_POINTER(FE_DESCRIPTION), NULL);
2026 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2028 column = gtk_tree_view_column_new();
2029 gtk_tree_view_column_set_title(column, _("Class"));
2030 gtk_tree_view_column_set_resizable(column, TRUE);
2031 renderer = gtk_cell_renderer_combo_new();
2032 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE,
2033 "model", create_class_model(),
2038 g_signal_connect(G_OBJECT(renderer), "edited",
2039 G_CALLBACK(filter_store_class_edit_cb), filter_store);
2040 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2041 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2042 GINT_TO_POINTER(FE_CLASS), NULL);
2043 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2045 column = gtk_tree_view_column_new();
2046 gtk_tree_view_column_set_title(column, _("Writable"));
2047 gtk_tree_view_column_set_resizable(column, FALSE);
2048 renderer = gtk_cell_renderer_toggle_new();
2049 g_signal_connect(G_OBJECT(renderer), "toggled",
2050 G_CALLBACK(filter_store_writable_cb), filter_store);
2051 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2052 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2053 GINT_TO_POINTER(FE_WRITABLE), NULL);
2054 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2056 column = gtk_tree_view_column_new();
2057 gtk_tree_view_column_set_title(column, _("Sidecar is allowed"));
2058 gtk_tree_view_column_set_resizable(column, FALSE);
2059 renderer = gtk_cell_renderer_toggle_new();
2060 g_signal_connect(G_OBJECT(renderer), "toggled",
2061 G_CALLBACK(filter_store_sidecar_cb), filter_store);
2062 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2063 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2064 GINT_TO_POINTER(FE_ALLOW_SIDECAR), NULL);
2065 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2068 filter_store_populate();
2069 gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
2070 gtk_widget_show(filter_view);
2072 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2074 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2075 G_CALLBACK(filter_default_cb), filter_view);
2076 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2077 gtk_widget_show(button);
2079 button = pref_button_new(NULL, GTK_STOCK_REMOVE, NULL, FALSE,
2080 G_CALLBACK(filter_remove_cb), filter_view);
2081 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2082 gtk_widget_show(button);
2084 button = pref_button_new(NULL, GTK_STOCK_ADD, NULL, FALSE,
2085 G_CALLBACK(filter_add_cb), filter_view);
2086 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2087 gtk_widget_show(button);
2091 static void config_tab_metadata(GtkWidget *notebook)
2096 GtkWidget *ct_button;
2100 vbox = scrolled_notebook_page(notebook, _("Metadata"));
2103 group = pref_group_new(vbox, FALSE, _("Metadata writing process"), GTK_ORIENTATION_VERTICAL);
2105 label = pref_label_new(group, _("Warning: Geeqie is built without Exiv2. Some options are disabled."));
2107 label = pref_label_new(group, _("Metadata are written in the following order. The process ends after first success."));
2108 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2110 ct_button = pref_checkbox_new_int(group, _("1) Save metadata in image files, or sidecar files, according to the XMP standard"),
2111 options->metadata.save_in_image_file, &c_options->metadata.save_in_image_file);
2113 gtk_widget_set_sensitive(ct_button, FALSE);
2116 pref_checkbox_new_int(group, _("2) Save metadata in '.metadata' folder, local to image folder (non-standard)"),
2117 options->metadata.enable_metadata_dirs, &c_options->metadata.enable_metadata_dirs);
2119 text = g_strdup_printf(_("3) Save metadata in Geeqie private directory '%s'"), get_metadata_cache_dir());
2120 label = pref_label_new(group, text);
2121 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2122 gtk_misc_set_padding(GTK_MISC(label), 22, 0);
2125 group = pref_group_new(vbox, FALSE, _("Step 1: Write to image files"), GTK_ORIENTATION_VERTICAL);
2127 gtk_widget_set_sensitive(group, FALSE);
2130 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2131 pref_checkbox_link_sensitivity(ct_button, hbox);
2133 pref_checkbox_new_int(hbox, _("Store metadata also in legacy IPTC tags (converted according to IPTC4XMP standard)"),
2134 options->metadata.save_legacy_IPTC, &c_options->metadata.save_legacy_IPTC);
2136 pref_checkbox_new_int(hbox, _("Warn if the image files are unwritable"),
2137 options->metadata.warn_on_write_problems, &c_options->metadata.warn_on_write_problems);
2139 pref_checkbox_new_int(hbox, _("Ask before writing to image files"),
2140 options->metadata.confirm_write, &c_options->metadata.confirm_write);
2142 pref_checkbox_new_int(hbox, _("Create sidecar files named image.ext.xmp (as opposed to image.xmp)"),
2143 options->metadata.sidecar_extended_name, &c_options->metadata.sidecar_extended_name);
2145 group = pref_group_new(vbox, FALSE, _("Step 2 and 3: write to Geeqie private files"), GTK_ORIENTATION_VERTICAL);
2147 gtk_widget_set_sensitive(group, FALSE);
2150 pref_checkbox_new_int(group, _("Use GQview legacy metadata format (supports only keywords and comments) instead of XMP"),
2151 options->metadata.save_legacy_format, &c_options->metadata.save_legacy_format);
2154 group = pref_group_new(vbox, FALSE, _("Miscellaneous"), GTK_ORIENTATION_VERTICAL);
2155 pref_checkbox_new_int(group, _("Write the same description tags (keywords, comment, etc.) to all grouped sidecars"),
2156 options->metadata.sync_grouped_files, &c_options->metadata.sync_grouped_files);
2158 pref_checkbox_new_int(group, _("Allow keywords to differ only in case"),
2159 options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
2161 ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"),
2162 options->metadata.write_orientation, &c_options->metadata.write_orientation);
2164 gtk_widget_set_sensitive(ct_button, FALSE);
2167 group = pref_group_new(vbox, FALSE, _("Auto-save options"), GTK_ORIENTATION_VERTICAL);
2169 ct_button = pref_checkbox_new_int(group, _("Write metadata after timeout"),
2170 options->metadata.confirm_after_timeout, &c_options->metadata.confirm_after_timeout);
2172 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2173 pref_checkbox_link_sensitivity(ct_button, hbox);
2175 pref_spin_new_int(hbox, _("Timeout (seconds):"), NULL, 0, 900, 1,
2176 options->metadata.confirm_timeout, &c_options->metadata.confirm_timeout);
2178 pref_checkbox_new_int(group, _("Write metadata on image change"),
2179 options->metadata.confirm_on_image_change, &c_options->metadata.confirm_on_image_change);
2181 pref_checkbox_new_int(group, _("Write metadata on directory change"),
2182 options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
2187 static void intent_menu_cb(GtkWidget *combo, gpointer data)
2189 gint *option = data;
2191 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
2195 *option = INTENT_PERCEPTUAL;
2198 *option = INTENT_RELATIVE_COLORIMETRIC;
2201 *option = INTENT_SATURATION;
2204 *option = INTENT_ABSOLUTE_COLORIMETRIC;
2209 static void add_intent_menu(GtkWidget *table, gint column, gint row, const gchar *text,
2210 gint option, gint *option_c)
2217 pref_table_label(table, column, row, text, 0.0);
2219 combo = gtk_combo_box_text_new();
2221 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Perceptual"));
2222 if (option == INTENT_PERCEPTUAL) current = 0;
2223 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Relative Colorimetric"));
2224 if (option == INTENT_RELATIVE_COLORIMETRIC) current = 1;
2225 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Saturation"));
2226 if (option == INTENT_SATURATION) current = 2;
2227 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Absolute Colorimetric"));
2228 if (option == INTENT_ABSOLUTE_COLORIMETRIC) current = 3;
2230 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
2232 gtk_widget_set_tooltip_text(combo,"Refer to the lcms documentation for the defaults used when the selected Intent is not available");
2234 g_signal_connect(G_OBJECT(combo), "changed",
2235 G_CALLBACK(intent_menu_cb), option_c);
2237 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
2238 GTK_EXPAND | GTK_FILL, 0, 0, 0);
2239 gtk_widget_show(combo);
2243 static void config_tab_color(GtkWidget *notebook)
2252 vbox = scrolled_notebook_page(notebook, _("Color management"));
2254 group = pref_group_new(vbox, FALSE, _("Input profiles"), GTK_ORIENTATION_VERTICAL);
2256 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
2259 table = pref_table_new(group, 3, COLOR_PROFILE_INPUTS + 1, FALSE, FALSE);
2260 gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
2262 label = pref_table_label(table, 0, 0, _("Type"), 0.0);
2263 pref_label_bold(label, TRUE, FALSE);
2265 label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
2266 pref_label_bold(label, TRUE, FALSE);
2268 label = pref_table_label(table, 2, 0, _("File"), 0.0);
2269 pref_label_bold(label, TRUE, FALSE);
2271 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
2276 buf = g_strdup_printf(_("Input %d:"), i + COLOR_PROFILE_FILE);
2277 pref_table_label(table, 0, i + 1, buf, 1.0);
2280 entry = gtk_entry_new();
2281 gtk_entry_set_max_length(GTK_ENTRY(entry), EDITOR_NAME_MAX_LENGTH);
2282 if (options->color_profile.input_name[i])
2284 gtk_entry_set_text(GTK_ENTRY(entry), options->color_profile.input_name[i]);
2286 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, i + 1, i + 2,
2287 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2288 gtk_widget_show(entry);
2289 color_profile_input_name_entry[i] = entry;
2291 tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, ".icc", "ICC Files", NULL);
2292 tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
2293 gtk_widget_set_size_request(entry, 160, -1);
2294 gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
2295 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2296 gtk_widget_show(tabcomp);
2297 color_profile_input_file_entry[i] = entry;
2300 group = pref_group_new(vbox, FALSE, _("Screen profile"), GTK_ORIENTATION_VERTICAL);
2302 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
2304 pref_checkbox_new_int(group, _("Use system screen profile if available"),
2305 options->color_profile.use_x11_screen_profile, &c_options->color_profile.use_x11_screen_profile);
2307 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2309 pref_table_label(table, 0, 0, _("Screen:"), 1.0);
2310 tabcomp = tab_completion_new(&color_profile_screen_file_entry,
2311 options->color_profile.screen_file, NULL, ".icc", "ICC Files", NULL);
2312 tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
2313 gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
2315 add_intent_menu(table, 0, 1, _("Render Intent:"), options->color_profile.render_intent, &c_options->color_profile.render_intent);
2317 gtk_table_attach(GTK_TABLE(table), tabcomp, 1, 2,
2319 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2321 gtk_widget_show(tabcomp);
2324 /* advanced entry tab */
2325 static void config_tab_behavior(GtkWidget *notebook)
2332 GtkWidget *ct_button;
2336 vbox = scrolled_notebook_page(notebook, _("Behavior"));
2338 group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
2340 pref_checkbox_new_int(group, _("Confirm file delete"),
2341 options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
2342 pref_checkbox_new_int(group, _("Enable Delete key"),
2343 options->file_ops.enable_delete_key, &c_options->file_ops.enable_delete_key);
2345 ct_button = pref_checkbox_new_int(group, _("Safe delete"),
2346 options->file_ops.safe_delete_enable, &c_options->file_ops.safe_delete_enable);
2348 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2349 pref_checkbox_link_sensitivity(ct_button, hbox);
2351 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
2352 pref_label_new(hbox, _("Folder:"));
2354 tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL, NULL, NULL);
2355 tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
2356 gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
2357 gtk_widget_show(tabcomp);
2359 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2360 pref_checkbox_link_sensitivity(ct_button, hbox);
2362 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
2363 spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MB"),
2364 0, 2048, 1, options->file_ops.safe_delete_folder_maxsize, &c_options->file_ops.safe_delete_folder_maxsize);
2365 gtk_widget_set_tooltip_markup(spin, _("Set to 0 for unlimited size"));
2366 button = pref_button_new(NULL, NULL, _("View"), FALSE,
2367 G_CALLBACK(safe_delete_view_cb), NULL);
2368 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2369 gtk_widget_show(button);
2371 button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
2372 G_CALLBACK(safe_delete_clear_cb), NULL);
2373 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2374 gtk_widget_show(button);
2377 group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
2379 pref_checkbox_new_int(group, _("Descend folders in tree view"),
2380 options->tree_descend_subdirs, &c_options->tree_descend_subdirs);
2382 pref_checkbox_new_int(group, _("In place renaming"),
2383 options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
2385 pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
2386 options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
2388 pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
2389 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
2391 pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
2392 16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
2394 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2395 add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
2397 group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
2399 pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
2400 options->progressive_key_scrolling, &c_options->progressive_key_scrolling);
2401 pref_spin_new_int(group, _("Keyboard scrolling step multiplier:"), NULL,
2402 1, 32, 1, options->keyboard_scroll_step, (int *)&c_options->keyboard_scroll_step);
2403 pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
2404 options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
2405 pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
2406 options->image_lm_click_nav, &c_options->image_lm_click_nav);
2407 pref_checkbox_new_int(group, _("Play video by left click on image"),
2408 options->image_l_click_video, &c_options->image_l_click_video);
2409 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2410 add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
2414 group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
2416 pref_spin_new_int(group, _("Debug level:"), NULL,
2417 DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
2419 pref_checkbox_new_int(group, _("Timer data"),
2420 options->log_window.timer_data, &c_options->log_window.timer_data);
2422 pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
2423 1, 99999, 1, options->log_window_lines, &options->log_window_lines);
2427 /* accelerators tab */
2428 static void config_tab_accelerators(GtkWidget *notebook)
2434 GtkWidget *scrolled;
2435 GtkWidget *accel_view;
2436 GtkCellRenderer *renderer;
2437 GtkTreeSelection *selection;
2438 GtkTreeViewColumn *column;
2440 vbox = scrolled_notebook_page(notebook, _("Keyboard"));
2442 group = pref_group_new(vbox, TRUE, _("Accelerators"), GTK_ORIENTATION_VERTICAL);
2444 scrolled = gtk_scrolled_window_new(NULL, NULL);
2445 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2446 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2447 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2448 gtk_widget_show(scrolled);
2450 accel_store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
2452 accel_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(accel_store));
2453 g_object_unref(accel_store);
2454 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(accel_view));
2455 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
2457 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(accel_view), FALSE);
2459 renderer = gtk_cell_renderer_text_new();
2461 column = gtk_tree_view_column_new_with_attributes(_("Action"),
2466 gtk_tree_view_column_set_sort_column_id(column, AE_ACTION);
2467 gtk_tree_view_column_set_resizable(column, TRUE);
2468 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
2471 renderer = gtk_cell_renderer_accel_new();
2472 g_signal_connect(G_OBJECT(renderer), "accel-cleared",
2473 G_CALLBACK(accel_store_cleared_cb), accel_store);
2474 g_signal_connect(G_OBJECT(renderer), "accel-edited",
2475 G_CALLBACK(accel_store_edited_cb), accel_store);
2478 g_object_set (renderer,
2480 "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
2483 column = gtk_tree_view_column_new_with_attributes(_("KEY"),
2488 gtk_tree_view_column_set_sort_column_id(column, AE_KEY);
2489 gtk_tree_view_column_set_resizable(column, TRUE);
2490 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
2492 renderer = gtk_cell_renderer_text_new();
2494 column = gtk_tree_view_column_new_with_attributes(_("Tooltip"),
2499 gtk_tree_view_column_set_sort_column_id(column, AE_TOOLTIP);
2500 gtk_tree_view_column_set_resizable(column, TRUE);
2501 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
2503 renderer = gtk_cell_renderer_text_new();
2505 column = gtk_tree_view_column_new_with_attributes("Accel",
2510 gtk_tree_view_column_set_sort_column_id(column, AE_ACCEL);
2511 gtk_tree_view_column_set_resizable(column, TRUE);
2512 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
2514 accel_store_populate();
2515 gtk_container_add(GTK_CONTAINER(scrolled), accel_view);
2516 gtk_widget_show(accel_view);
2518 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2520 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2521 G_CALLBACK(accel_default_cb), accel_view);
2522 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2523 gtk_widget_show(button);
2525 button = pref_button_new(NULL, NULL, _("Reset selected"), FALSE,
2526 G_CALLBACK(accel_reset_cb), accel_view);
2527 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2528 gtk_widget_show(button);
2532 static void config_tab_toolbar(GtkWidget *notebook)
2535 GtkWidget *toolbardata;
2538 lw = layout_window_list->data;
2540 vbox = scrolled_notebook_page(notebook, _("Toolbar"));
2542 toolbardata = toolbar_select_new(lw);
2543 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
2544 gtk_widget_show(vbox);
2548 static void config_tab_stereo(GtkWidget *notebook)
2556 GtkWidget *fs_button;
2557 vbox = scrolled_notebook_page(notebook, _("Stereo"));
2559 group = pref_group_new(vbox, FALSE, _("Windowed stereo mode"), GTK_ORIENTATION_VERTICAL);
2561 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2562 add_stereo_mode_menu(table, 0, 0, _("Windowed stereo mode"), options->stereo.mode, &c_options->stereo.mode, FALSE);
2564 table = pref_table_new(group, 2, 2, TRUE, FALSE);
2565 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
2566 pref_checkbox_new_int(box, _("Mirror left image"),
2567 options->stereo.mode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.mirror_left);
2568 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
2569 pref_checkbox_new_int(box, _("Flip left image"),
2570 options->stereo.mode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.flip_left);
2571 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
2572 pref_checkbox_new_int(box, _("Mirror right image"),
2573 options->stereo.mode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.mirror_right);
2574 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
2575 pref_checkbox_new_int(box, _("Flip right image"),
2576 options->stereo.mode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.flip_right);
2577 pref_checkbox_new_int(group, _("Swap left and right images"),
2578 options->stereo.mode & PR_STEREO_SWAP, &c_options->stereo.tmp.swap);
2579 pref_checkbox_new_int(group, _("Disable stereo mode on single image source"),
2580 options->stereo.mode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.temp_disable);
2582 group = pref_group_new(vbox, FALSE, _("Fullscreen stereo mode"), GTK_ORIENTATION_VERTICAL);
2583 fs_button = pref_checkbox_new_int(group, _("Use different settings for fullscreen"),
2584 options->stereo.enable_fsmode, &c_options->stereo.enable_fsmode);
2585 box2 = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2586 pref_checkbox_link_sensitivity(fs_button, box2);
2587 table = pref_table_new(box2, 2, 1, FALSE, FALSE);
2588 add_stereo_mode_menu(table, 0, 0, _("Fullscreen stereo mode"), options->stereo.fsmode, &c_options->stereo.fsmode, TRUE);
2589 table = pref_table_new(box2, 2, 2, TRUE, FALSE);
2590 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
2591 pref_checkbox_new_int(box, _("Mirror left image"),
2592 options->stereo.fsmode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.fs_mirror_left);
2593 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
2594 pref_checkbox_new_int(box, _("Flip left image"),
2595 options->stereo.fsmode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.fs_flip_left);
2596 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
2597 pref_checkbox_new_int(box, _("Mirror right image"),
2598 options->stereo.fsmode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.fs_mirror_right);
2599 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
2600 pref_checkbox_new_int(box, _("Flip right image"),
2601 options->stereo.fsmode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.fs_flip_right);
2602 pref_checkbox_new_int(box2, _("Swap left and right images"),
2603 options->stereo.fsmode & PR_STEREO_SWAP, &c_options->stereo.tmp.fs_swap);
2604 pref_checkbox_new_int(box2, _("Disable stereo mode on single image source"),
2605 options->stereo.fsmode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.fs_temp_disable);
2607 group2 = pref_group_new(box2, FALSE, _("Fixed position"), GTK_ORIENTATION_VERTICAL);
2608 table = pref_table_new(group2, 5, 3, FALSE, FALSE);
2609 pref_table_spin_new_int(table, 0, 0, _("Width"), NULL,
2610 1, 5000, 1, options->stereo.fixed_w, &c_options->stereo.fixed_w);
2611 pref_table_spin_new_int(table, 3, 0, _("Height"), NULL,
2612 1, 5000, 1, options->stereo.fixed_h, &c_options->stereo.fixed_h);
2613 pref_table_spin_new_int(table, 0, 1, _("Left X"), NULL,
2614 0, 5000, 1, options->stereo.fixed_x1, &c_options->stereo.fixed_x1);
2615 pref_table_spin_new_int(table, 3, 1, _("Left Y"), NULL,
2616 0, 5000, 1, options->stereo.fixed_y1, &c_options->stereo.fixed_y1);
2617 pref_table_spin_new_int(table, 0, 2, _("Right X"), NULL,
2618 0, 5000, 1, options->stereo.fixed_x2, &c_options->stereo.fixed_x2);
2619 pref_table_spin_new_int(table, 3, 2, _("Right Y"), NULL,
2620 0, 5000, 1, options->stereo.fixed_y2, &c_options->stereo.fixed_y2);
2624 /* Main preferences window */
2625 static void config_window_create(void)
2627 GtkWidget *win_vbox;
2629 GtkWidget *notebook;
2631 GtkWidget *ct_button;
2633 if (!c_options) c_options = init_options(NULL);
2635 configwindow = window_new(GTK_WINDOW_TOPLEVEL, "preferences", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Preferences"));
2636 gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
2637 g_signal_connect(G_OBJECT(configwindow), "delete_event",
2638 G_CALLBACK(config_window_delete), NULL);
2639 gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
2640 gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
2641 gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
2643 win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
2644 gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
2645 gtk_widget_show(win_vbox);
2647 notebook = gtk_notebook_new();
2648 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP);
2649 gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
2651 config_tab_general(notebook);
2652 config_tab_image(notebook);
2653 config_tab_windows(notebook);
2654 config_tab_accelerators(notebook);
2655 config_tab_files(notebook);
2656 config_tab_metadata(notebook);
2657 config_tab_color(notebook);
2658 config_tab_stereo(notebook);
2659 config_tab_behavior(notebook);
2660 config_tab_toolbar(notebook);
2662 hbox = gtk_hbutton_box_new();
2663 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
2664 gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
2665 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
2666 gtk_widget_show(hbox);
2668 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
2669 G_CALLBACK(config_window_help_cb), notebook);
2670 gtk_container_add(GTK_CONTAINER(hbox), button);
2671 gtk_widget_set_can_default(button, TRUE);
2672 gtk_widget_show(button);
2674 button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
2675 G_CALLBACK(config_window_ok_cb), NULL);
2676 gtk_container_add(GTK_CONTAINER(hbox), button);
2677 gtk_widget_set_can_default(button, TRUE);
2678 gtk_widget_grab_default(button);
2679 gtk_widget_show(button);
2683 button = pref_button_new(NULL, GTK_STOCK_SAVE, NULL, FALSE,
2684 G_CALLBACK(config_window_save_cb), NULL);
2685 gtk_container_add(GTK_CONTAINER(hbox), button);
2686 gtk_widget_set_can_default(button, TRUE);
2687 gtk_widget_show(button);
2689 button = pref_button_new(NULL, GTK_STOCK_APPLY, NULL, FALSE,
2690 G_CALLBACK(config_window_apply_cb), NULL);
2691 gtk_container_add(GTK_CONTAINER(hbox), button);
2692 gtk_widget_set_can_default(button, TRUE);
2693 gtk_widget_show(button);
2695 button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
2696 G_CALLBACK(config_window_close_cb), NULL);
2697 gtk_container_add(GTK_CONTAINER(hbox), button);
2698 gtk_widget_set_can_default(button, TRUE);
2699 gtk_widget_show(button);
2701 if (!generic_dialog_get_alternative_button_order(configwindow))
2703 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
2706 gtk_widget_show(notebook);
2708 gtk_widget_show(configwindow);
2712 *-----------------------------------------------------------------------------
2713 * config window show (public)
2714 *-----------------------------------------------------------------------------
2717 void show_config_window(void)
2721 gtk_window_present(GTK_WINDOW(configwindow));
2725 config_window_create();
2734 void show_about_window(LayoutWindow *lw)
2736 GdkPixbuf *pixbuf_logo;
2737 GdkPixbuf *pixbuf_icon;
2738 gchar *authors[1000];
2743 #define LINE_LENGTH 1000
2744 gchar line[LINE_LENGTH];
2746 #if !GTK_CHECK_VERSION(3,0,0)
2749 copyright = g_string_new(NULL);
2750 path = g_build_filename(GQ_HELPDIR, "COPYING", NULL);
2751 fp = fopen(path, "r");
2754 while(fgets(line, LINE_LENGTH, fp))
2756 copyright = g_string_append(copyright, line);
2764 path = g_build_filename(GQ_HELPDIR, "AUTHORS", NULL);
2765 fp = fopen(path, "r");
2768 while(fgets(line, LINE_LENGTH, fp))
2770 /* get rid of ending \n from fgets */
2771 line[strlen(line) - 1] = '\0';
2772 authors[i_authors] = g_strdup(line);
2775 authors[i_authors] = NULL;
2780 comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
2781 "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
2783 pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
2784 pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
2785 gtk_show_about_dialog(GTK_WINDOW(lw->window),
2786 "title", _("About Geeqie"),
2788 "program-name", GQ_APPNAME,
2790 "logo", pixbuf_logo,
2791 "icon", pixbuf_icon,
2792 "website", GQ_WEBSITE,
2793 "website-label", "Website",
2794 "comments", comment,
2796 "translator-credits", _("translator-credits"),
2797 #if GTK_CHECK_VERSION(3,0,0)
2798 "license-type", GTK_LICENSE_GPL_2_0,
2800 "license", copyright->str,
2804 #if !GTK_CHECK_VERSION(3,0,0)
2805 g_string_free(copyright, TRUE);
2808 while(n < i_authors)
2818 static void image_overlay_set_text_colours()
2820 c_options->image_overlay.text_red = options->image_overlay.text_red;
2821 c_options->image_overlay.text_green = options->image_overlay.text_green;
2822 c_options->image_overlay.text_blue = options->image_overlay.text_blue;
2823 c_options->image_overlay.text_alpha = options->image_overlay.text_alpha;
2824 c_options->image_overlay.background_red = options->image_overlay.background_red;
2825 c_options->image_overlay.background_green = options->image_overlay.background_green;
2826 c_options->image_overlay.background_blue = options->image_overlay.background_blue;
2827 c_options->image_overlay.background_alpha = options->image_overlay.background_alpha;
2829 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */