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->image.scroll_reset_method = c_options->image.scroll_reset_method;
260 options->image.zoom_2pass = c_options->image.zoom_2pass;
261 options->image.fit_window_to_image = c_options->image.fit_window_to_image;
262 options->image.limit_window_size = c_options->image.limit_window_size;
263 options->image.zoom_to_fit_allow_expand = c_options->image.zoom_to_fit_allow_expand;
264 options->image.max_window_size = c_options->image.max_window_size;
265 options->image.limit_autofit_size = c_options->image.limit_autofit_size;
266 options->image.max_autofit_size = c_options->image.max_autofit_size;
267 options->image.max_enlargement_size = c_options->image.max_enlargement_size;
268 options->image.use_clutter_renderer = c_options->image.use_clutter_renderer;
269 options->progressive_key_scrolling = c_options->progressive_key_scrolling;
270 options->keyboard_scroll_step = c_options->keyboard_scroll_step;
272 if (options->thumbnails.max_width != c_options->thumbnails.max_width
273 || options->thumbnails.max_height != c_options->thumbnails.max_height
274 || options->thumbnails.quality != c_options->thumbnails.quality)
276 thumb_format_changed = TRUE;
278 options->thumbnails.max_width = c_options->thumbnails.max_width;
279 options->thumbnails.max_height = c_options->thumbnails.max_height;
280 options->thumbnails.quality = c_options->thumbnails.quality;
282 options->thumbnails.enable_caching = c_options->thumbnails.enable_caching;
283 options->thumbnails.cache_into_dirs = c_options->thumbnails.cache_into_dirs;
284 options->thumbnails.use_exif = c_options->thumbnails.use_exif;
285 options->thumbnails.spec_standard = c_options->thumbnails.spec_standard;
286 options->metadata.enable_metadata_dirs = c_options->metadata.enable_metadata_dirs;
287 options->file_filter.show_hidden_files = c_options->file_filter.show_hidden_files;
288 options->file_filter.show_parent_directory = c_options->file_filter.show_parent_directory;
289 options->file_filter.show_dot_directory = c_options->file_filter.show_dot_directory;
290 options->file_filter.disable_file_extension_checks = c_options->file_filter.disable_file_extension_checks;
292 options->file_sort.case_sensitive = c_options->file_sort.case_sensitive;
293 options->file_sort.natural = c_options->file_sort.natural;
294 options->file_filter.disable = c_options->file_filter.disable;
296 config_entry_to_option(sidecar_ext_entry, &options->sidecar.ext, NULL);
297 sidecar_ext_parse(options->sidecar.ext);
299 options->slideshow.random = c_options->slideshow.random;
300 options->slideshow.repeat = c_options->slideshow.repeat;
301 options->slideshow.delay = c_options->slideshow.delay;
303 options->mousewheel_scrolls = c_options->mousewheel_scrolls;
304 options->image_lm_click_nav = c_options->image_lm_click_nav;
305 options->image_l_click_video = c_options->image_l_click_video;
306 options->image_l_click_video_editor = c_options->image_l_click_video_editor;
308 options->file_ops.enable_in_place_rename = c_options->file_ops.enable_in_place_rename;
310 options->image.tile_cache_max = c_options->image.tile_cache_max;
311 options->image.image_cache_max = c_options->image.image_cache_max;
313 options->image.zoom_quality = c_options->image.zoom_quality;
315 options->image.zoom_increment = c_options->image.zoom_increment;
317 options->image.enable_read_ahead = c_options->image.enable_read_ahead;
320 if (options->image.use_custom_border_color != c_options->image.use_custom_border_color
321 || options->image.use_custom_border_color_in_fullscreen != c_options->image.use_custom_border_color_in_fullscreen
322 || !gdk_color_equal(&options->image.border_color, &c_options->image.border_color))
324 options->image.use_custom_border_color_in_fullscreen = c_options->image.use_custom_border_color_in_fullscreen;
325 options->image.use_custom_border_color = c_options->image.use_custom_border_color;
326 options->image.border_color = c_options->image.border_color;
327 layout_colors_update();
328 view_window_colors_update();
331 options->image.alpha_color_1 = c_options->image.alpha_color_1;
332 options->image.alpha_color_2 = c_options->image.alpha_color_2;
334 options->fullscreen.screen = c_options->fullscreen.screen;
335 options->fullscreen.clean_flip = c_options->fullscreen.clean_flip;
336 options->fullscreen.disable_saver = c_options->fullscreen.disable_saver;
337 options->fullscreen.above = c_options->fullscreen.above;
338 if (c_options->image_overlay.template_string)
339 set_image_overlay_template_string(&options->image_overlay.template_string,
340 c_options->image_overlay.template_string);
341 if (c_options->image_overlay.font)
342 set_image_overlay_font_string(&options->image_overlay.font,
343 c_options->image_overlay.font);
344 options->image_overlay.text_red = c_options->image_overlay.text_red;
345 options->image_overlay.text_green = c_options->image_overlay.text_green;
346 options->image_overlay.text_blue = c_options->image_overlay.text_blue;
347 options->image_overlay.text_alpha = c_options->image_overlay.text_alpha;
348 options->image_overlay.background_red = c_options->image_overlay.background_red;
349 options->image_overlay.background_green = c_options->image_overlay.background_green;
350 options->image_overlay.background_blue = c_options->image_overlay.background_blue;
351 options->image_overlay.background_alpha = c_options->image_overlay.background_alpha;
352 options->update_on_time_change = c_options->update_on_time_change;
353 options->image.exif_proof_rotate_enable = c_options->image.exif_proof_rotate_enable;
355 options->duplicates_similarity_threshold = c_options->duplicates_similarity_threshold;
356 options->rot_invariant_sim = c_options->rot_invariant_sim;
358 options->tree_descend_subdirs = c_options->tree_descend_subdirs;
360 options->view_dir_list_single_click_enter = c_options->view_dir_list_single_click_enter;
362 options->open_recent_list_maxsize = c_options->open_recent_list_maxsize;
363 options->dnd_icon_size = c_options->dnd_icon_size;
364 options->clipboard_selection = c_options->clipboard_selection;
366 options->metadata.save_in_image_file = c_options->metadata.save_in_image_file;
367 options->metadata.save_legacy_IPTC = c_options->metadata.save_legacy_IPTC;
368 options->metadata.warn_on_write_problems = c_options->metadata.warn_on_write_problems;
369 options->metadata.save_legacy_format = c_options->metadata.save_legacy_format;
370 options->metadata.sync_grouped_files = c_options->metadata.sync_grouped_files;
371 options->metadata.confirm_write = c_options->metadata.confirm_write;
372 options->metadata.sidecar_extended_name = c_options->metadata.sidecar_extended_name;
373 options->metadata.confirm_timeout = c_options->metadata.confirm_timeout;
374 options->metadata.confirm_after_timeout = c_options->metadata.confirm_after_timeout;
375 options->metadata.confirm_on_image_change = c_options->metadata.confirm_on_image_change;
376 options->metadata.confirm_on_dir_change = c_options->metadata.confirm_on_dir_change;
377 options->metadata.keywords_case_sensitive = c_options->metadata.keywords_case_sensitive;
378 options->metadata.write_orientation = c_options->metadata.write_orientation;
379 options->stereo.mode = (c_options->stereo.mode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
380 (c_options->stereo.tmp.mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
381 (c_options->stereo.tmp.flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
382 (c_options->stereo.tmp.mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
383 (c_options->stereo.tmp.flip_left ? PR_STEREO_FLIP_LEFT : 0) |
384 (c_options->stereo.tmp.swap ? PR_STEREO_SWAP : 0) |
385 (c_options->stereo.tmp.temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
386 options->stereo.fsmode = (c_options->stereo.fsmode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
387 (c_options->stereo.tmp.fs_mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
388 (c_options->stereo.tmp.fs_flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
389 (c_options->stereo.tmp.fs_mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
390 (c_options->stereo.tmp.fs_flip_left ? PR_STEREO_FLIP_LEFT : 0) |
391 (c_options->stereo.tmp.fs_swap ? PR_STEREO_SWAP : 0) |
392 (c_options->stereo.tmp.fs_temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
393 options->stereo.enable_fsmode = c_options->stereo.enable_fsmode;
394 options->stereo.fixed_w = c_options->stereo.fixed_w;
395 options->stereo.fixed_h = c_options->stereo.fixed_h;
396 options->stereo.fixed_x1 = c_options->stereo.fixed_x1;
397 options->stereo.fixed_y1 = c_options->stereo.fixed_y1;
398 options->stereo.fixed_x2 = c_options->stereo.fixed_x2;
399 options->stereo.fixed_y2 = c_options->stereo.fixed_y2;
401 options->info_keywords.height = c_options->info_keywords.height;
402 options->info_title.height = c_options->info_title.height;
403 options->info_comment.height = c_options->info_comment.height;
404 options->info_rating.height = c_options->info_rating.height;
407 set_debug_level(debug_c);
411 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
413 config_entry_to_option(color_profile_input_name_entry[i], &options->color_profile.input_name[i], NULL);
414 config_entry_to_option(color_profile_input_file_entry[i], &options->color_profile.input_file[i], NULL);
416 config_entry_to_option(color_profile_screen_file_entry, &options->color_profile.screen_file, NULL);
417 options->color_profile.use_x11_screen_profile = c_options->color_profile.use_x11_screen_profile;
418 if (options->color_profile.render_intent != c_options->color_profile.render_intent)
420 options->color_profile.render_intent = c_options->color_profile.render_intent;
425 image_options_sync();
430 layout_refresh(NULL);
433 if (accel_store) gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_apply_cb, NULL);
439 *-----------------------------------------------------------------------------
440 * config window main button callbacks (private)
441 *-----------------------------------------------------------------------------
444 static void config_window_close_cb(GtkWidget *widget, gpointer data)
446 gtk_widget_destroy(configwindow);
451 static void config_window_help_cb(GtkWidget *widget, gpointer data)
453 GtkWidget *notebook = data;
456 static gchar *html_section[] =
458 "GuideOptionsGeneral.html",
459 "GuideOptionsImage.html",
460 "GuideOptionsWindow.html",
461 "GuideOptionsKeyboard.html",
462 "GuideOptionsFiltering.html",
463 "GuideOptionsMetadata.html",
464 "GuideOptionsColor.html",
465 "GuideOptionsStereo.html",
466 "GuideOptionsBehavior.html",
467 "GuideOptionsToolbar.html"
470 i = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
471 help_window_show(html_section[i]);
474 static gboolean config_window_delete(GtkWidget *widget, GdkEventAny *event, gpointer data)
476 config_window_close_cb(NULL, NULL);
480 static void config_window_ok_cb(GtkWidget *widget, gpointer data)
482 config_window_apply();
483 config_window_close_cb(NULL, NULL);
486 static void config_window_apply_cb(GtkWidget *widget, gpointer data)
489 lw = layout_window_list->data;
491 config_window_apply();
492 layout_util_sync(lw);
495 static void config_window_save_cb(GtkWidget *widget, gpointer data)
497 config_window_apply();
498 save_options(options);
502 *-----------------------------------------------------------------------------
503 * config window setup (private)
504 *-----------------------------------------------------------------------------
507 static void quality_menu_cb(GtkWidget *combo, gpointer data)
511 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
515 *option = GDK_INTERP_NEAREST;
518 *option = GDK_INTERP_TILES;
521 *option = GDK_INTERP_BILINEAR;
524 *option = GDK_INTERP_HYPER;
529 static void clipboard_selection_menu_cb(GtkWidget *combo, gpointer data)
533 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
545 static void add_quality_menu(GtkWidget *table, gint column, gint row, const gchar *text,
546 guint option, guint *option_c)
553 pref_table_label(table, column, row, text, 0.0);
555 combo = gtk_combo_box_text_new();
557 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Nearest (worst, but fastest)"));
558 if (option == GDK_INTERP_NEAREST) current = 0;
559 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Tiles"));
560 if (option == GDK_INTERP_TILES) current = 1;
561 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Bilinear"));
562 if (option == GDK_INTERP_BILINEAR) current = 2;
563 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Hyper (best, but slowest)"));
564 if (option == GDK_INTERP_HYPER) current = 3;
566 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
568 g_signal_connect(G_OBJECT(combo), "changed",
569 G_CALLBACK(quality_menu_cb), option_c);
571 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
572 GTK_EXPAND | GTK_FILL, 0, 0, 0);
573 gtk_widget_show(combo);
576 static void add_clipboard_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
577 gint option, gint *option_c)
584 pref_table_label(table, column, row, text, 0.0);
586 combo = gtk_combo_box_text_new();
588 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("PRIMARY"));
589 if (option == PRIMARY) current = 0;
590 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("CLIPBOARD"));
591 if (option == CLIPBOARD) current = 1;
593 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
595 g_signal_connect(G_OBJECT(combo), "changed",
596 G_CALLBACK(clipboard_selection_menu_cb), option_c);
598 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
599 GTK_EXPAND | GTK_FILL, 0, 0, 0);
600 gtk_widget_show(combo);
603 static void thumb_size_menu_cb(GtkWidget *combo, gpointer data)
607 n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
610 if ((guint) n < sizeof(thumb_size_list) / sizeof(ThumbSize))
612 c_options->thumbnails.max_width = thumb_size_list[n].w;
613 c_options->thumbnails.max_height = thumb_size_list[n].h;
617 c_options->thumbnails.max_width = options->thumbnails.max_width;
618 c_options->thumbnails.max_height = options->thumbnails.max_height;
622 static void add_thumb_size_menu(GtkWidget *table, gint column, gint row, gchar *text)
628 c_options->thumbnails.max_width = options->thumbnails.max_width;
629 c_options->thumbnails.max_height = options->thumbnails.max_height;
631 pref_table_label(table, column, row, text, 0.0);
633 combo = gtk_combo_box_text_new();
636 for (i = 0; (guint) i < sizeof(thumb_size_list) / sizeof(ThumbSize); i++)
641 w = thumb_size_list[i].w;
642 h = thumb_size_list[i].h;
644 buf = g_strdup_printf("%d x %d", w, h);
645 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
648 if (w == options->thumbnails.max_width && h == options->thumbnails.max_height) current = i;
655 buf = g_strdup_printf("%s %d x %d", _("Custom"), options->thumbnails.max_width, options->thumbnails.max_height);
656 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
662 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
663 g_signal_connect(G_OBJECT(combo), "changed",
664 G_CALLBACK(thumb_size_menu_cb), NULL);
666 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
667 GTK_EXPAND | GTK_FILL, 0, 0, 0);
668 gtk_widget_show(combo);
671 static void stereo_mode_menu_cb(GtkWidget *combo, gpointer data)
675 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
679 *option = PR_STEREO_NONE;
682 *option = PR_STEREO_ANAGLYPH_RC;
685 *option = PR_STEREO_ANAGLYPH_GM;
688 *option = PR_STEREO_ANAGLYPH_YB;
691 *option = PR_STEREO_ANAGLYPH_GRAY_RC;
694 *option = PR_STEREO_ANAGLYPH_GRAY_GM;
697 *option = PR_STEREO_ANAGLYPH_GRAY_YB;
700 *option = PR_STEREO_ANAGLYPH_DB_RC;
703 *option = PR_STEREO_ANAGLYPH_DB_GM;
706 *option = PR_STEREO_ANAGLYPH_DB_YB;
709 *option = PR_STEREO_HORIZ;
712 *option = PR_STEREO_HORIZ | PR_STEREO_HALF;
715 *option = PR_STEREO_VERT;
718 *option = PR_STEREO_VERT | PR_STEREO_HALF;
721 *option = PR_STEREO_FIXED;
726 static void add_stereo_mode_menu(GtkWidget *table, gint column, gint row, const gchar *text,
727 gint option, gint *option_c, gboolean add_fixed)
734 pref_table_label(table, column, row, text, 0.0);
736 combo = gtk_combo_box_text_new();
738 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Single image"));
740 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Red-Cyan"));
741 if (option & PR_STEREO_ANAGLYPH_RC) current = 1;
742 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Green-Magenta"));
743 if (option & PR_STEREO_ANAGLYPH_GM) current = 2;
744 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Yellow-Blue"));
745 if (option & PR_STEREO_ANAGLYPH_YB) current = 3;
746 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Red-Cyan"));
747 if (option & PR_STEREO_ANAGLYPH_GRAY_RC) current = 4;
748 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Green-Magenta"));
749 if (option & PR_STEREO_ANAGLYPH_GRAY_GM) current = 5;
750 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Yellow-Blue"));
751 if (option & PR_STEREO_ANAGLYPH_GRAY_YB) current = 6;
752 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Red-Cyan"));
753 if (option & PR_STEREO_ANAGLYPH_DB_RC) current = 7;
754 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Green-Magenta"));
755 if (option & PR_STEREO_ANAGLYPH_DB_GM) current = 8;
756 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Yellow-Blue"));
757 if (option & PR_STEREO_ANAGLYPH_DB_YB) current = 9;
759 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side"));
760 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side Half size"));
761 if (option & PR_STEREO_HORIZ)
764 if (option & PR_STEREO_HALF) current = 11;
767 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom"));
768 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom Half size"));
769 if (option & PR_STEREO_VERT)
772 if (option & PR_STEREO_HALF) current = 13;
777 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Fixed position"));
778 if (option & PR_STEREO_FIXED) current = 14;
781 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
783 g_signal_connect(G_OBJECT(combo), "changed",
784 G_CALLBACK(stereo_mode_menu_cb), option_c);
786 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
787 GTK_EXPAND | GTK_FILL, 0, 0, 0);
788 gtk_widget_show(combo);
791 static void video_menu_cb(GtkWidget *combo, gpointer data)
793 gchar **option = data;
795 EditorDescription *ed = g_list_nth_data(editor_list_get(), gtk_combo_box_get_active(GTK_COMBO_BOX(combo)));
799 static void video_menu_populate(gpointer data, gpointer user_data)
801 GtkWidget *combo = user_data;
802 EditorDescription *ed = data;
804 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), ed->name);
807 static void add_video_menu(GtkWidget *table, gint column, gint row, const gchar *text,
808 gchar *option, gchar **option_c)
812 /* use lists since they are sorted */
813 GList *eds = editor_list_get();
817 pref_table_label(table, column, row, text, 0.0);
819 combo = gtk_combo_box_text_new();
820 g_list_foreach(eds,video_menu_populate,(gpointer)combo);
821 current = option ? g_list_index(eds,g_hash_table_lookup(editors,option)): -1;
823 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
825 g_signal_connect(G_OBJECT(combo), "changed",
826 G_CALLBACK(video_menu_cb), option_c);
828 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
829 GTK_EXPAND | GTK_FILL, 0, 0, 0);
830 gtk_widget_show(combo);
833 static void filter_store_populate(void)
837 if (!filter_store) return;
839 gtk_list_store_clear(filter_store);
841 work = filter_get_list();
850 gtk_list_store_append(filter_store, &iter);
851 gtk_list_store_set(filter_store, &iter, 0, fe, -1);
855 static void filter_store_ext_edit_cb(GtkCellRendererText *cell, gchar *path_str,
856 gchar *new_text, gpointer data)
858 GtkWidget *model = data;
859 FilterEntry *fe = data;
863 if (!new_text || strlen(new_text) < 1) return;
865 tpath = gtk_tree_path_new_from_string(path_str);
866 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
867 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
869 g_free(fe->extensions);
870 fe->extensions = g_strdup(new_text);
872 gtk_tree_path_free(tpath);
876 static void filter_store_class_edit_cb(GtkCellRendererText *cell, gchar *path_str,
877 gchar *new_text, gpointer data)
879 GtkWidget *model = data;
880 FilterEntry *fe = data;
885 if (!new_text || !new_text[0]) return;
887 tpath = gtk_tree_path_new_from_string(path_str);
888 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
889 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
891 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
893 if (strcmp(new_text, _(format_class_list[i])) == 0)
900 gtk_tree_path_free(tpath);
904 static void filter_store_desc_edit_cb(GtkCellRendererText *cell, gchar *path_str,
905 gchar *new_text, gpointer data)
907 GtkWidget *model = data;
912 if (!new_text || !new_text[0]) return;
914 tpath = gtk_tree_path_new_from_string(path_str);
915 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
916 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
918 g_free(fe->description);
919 fe->description = g_strdup(new_text);
921 gtk_tree_path_free(tpath);
924 static void filter_store_enable_cb(GtkCellRendererToggle *renderer,
925 gchar *path_str, gpointer data)
927 GtkWidget *model = data;
932 tpath = gtk_tree_path_new_from_string(path_str);
933 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
934 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
936 fe->enabled = !fe->enabled;
938 gtk_tree_path_free(tpath);
942 static void filter_store_writable_cb(GtkCellRendererToggle *renderer,
943 gchar *path_str, gpointer data)
945 GtkWidget *model = data;
950 tpath = gtk_tree_path_new_from_string(path_str);
951 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
952 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
954 fe->writable = !fe->writable;
955 if (fe->writable) fe->allow_sidecar = FALSE;
957 gtk_tree_path_free(tpath);
961 static void filter_store_sidecar_cb(GtkCellRendererToggle *renderer,
962 gchar *path_str, gpointer data)
964 GtkWidget *model = data;
969 tpath = gtk_tree_path_new_from_string(path_str);
970 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
971 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
973 fe->allow_sidecar = !fe->allow_sidecar;
974 if (fe->allow_sidecar) fe->writable = FALSE;
976 gtk_tree_path_free(tpath);
980 static void filter_set_func(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
981 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
985 gtk_tree_model_get(tree_model, iter, 0, &fe, -1);
987 switch (GPOINTER_TO_INT(data))
990 g_object_set(GTK_CELL_RENDERER(cell),
991 "active", fe->enabled, NULL);
994 g_object_set(GTK_CELL_RENDERER(cell),
995 "text", fe->extensions, NULL);
998 g_object_set(GTK_CELL_RENDERER(cell),
999 "text", fe->description, NULL);
1002 g_object_set(GTK_CELL_RENDERER(cell),
1003 "text", _(format_class_list[fe->file_class]), NULL);
1006 g_object_set(GTK_CELL_RENDERER(cell),
1007 "active", fe->writable, NULL);
1009 case FE_ALLOW_SIDECAR:
1010 g_object_set(GTK_CELL_RENDERER(cell),
1011 "active", fe->allow_sidecar, NULL);
1016 static gboolean filter_add_scroll(gpointer data)
1020 GtkCellRenderer *cell;
1021 GtkTreeViewColumn *column;
1022 GList *list_columns;
1027 rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(filter_store), NULL);
1028 path = gtk_tree_path_new_from_indices(rows-1, -1);
1030 list_columns = gtk_tree_view_get_columns(GTK_TREE_VIEW(data));
1032 column = g_list_nth(list_columns,i)->data;
1033 title = gtk_tree_view_column_get_title(GTK_TREE_VIEW_COLUMN(column));
1035 } while (strcmp(title, "Filter") !=0 );
1037 list_cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column));
1038 cell = g_list_last(list_cells)->data;
1040 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1041 path, column, FALSE, 0.0, 0.0 );
1042 gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(data),
1043 path, column, cell, TRUE);
1045 gtk_tree_path_free(path);
1046 g_list_free(list_cells);
1047 g_list_free(list_columns);
1052 static void filter_add_cb(GtkWidget *widget, gpointer data)
1054 filter_add_unique("description", ".new", FORMAT_CLASS_IMAGE, TRUE, FALSE, TRUE);
1055 filter_store_populate();
1057 g_idle_add((GSourceFunc)filter_add_scroll, data);
1060 static void filter_remove_cb(GtkWidget *widget, gpointer data)
1062 GtkWidget *filter_view = data;
1063 GtkTreeSelection *selection;
1067 if (!filter_store) return;
1068 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1069 if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) return;
1070 gtk_tree_model_get(GTK_TREE_MODEL(filter_store), &iter, 0, &fe, -1);
1073 filter_remove_entry(fe);
1075 filter_store_populate();
1078 static gboolean filter_default_ok_scroll(GtkTreeView *data)
1082 GtkTreeViewColumn *column;
1084 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(filter_store), &iter);
1085 path = gtk_tree_model_get_path(GTK_TREE_MODEL(filter_store), &iter);
1086 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1088 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1092 gtk_tree_path_free(path);
1097 static void filter_default_ok_cb(GenericDialog *gd, gpointer data)
1100 filter_add_defaults();
1102 filter_store_populate();
1104 g_idle_add((GSourceFunc)filter_default_ok_scroll, gd->data);
1107 static void dummy_cancel_cb(GenericDialog *gd, gpointer data)
1109 /* no op, only so cancel button appears */
1112 static void filter_default_cb(GtkWidget *widget, gpointer data)
1116 gd = generic_dialog_new(_("Reset filters"),
1117 "reset_filter", widget, TRUE,
1118 dummy_cancel_cb, data);
1119 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset filters"),
1120 _("This will reset the file filters to the defaults.\nContinue?"), TRUE);
1121 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, filter_default_ok_cb, TRUE);
1122 gtk_widget_show(gd->dialog);
1125 static void filter_disable_cb(GtkWidget *widget, gpointer data)
1127 GtkWidget *frame = data;
1129 gtk_widget_set_sensitive(frame,
1130 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
1133 static void safe_delete_view_cb(GtkWidget *widget, gpointer data)
1135 layout_set_path(NULL, gtk_entry_get_text(GTK_ENTRY(safe_delete_path_entry)));
1138 static void safe_delete_clear_ok_cb(GenericDialog *gd, gpointer data)
1140 file_util_trash_clear();
1143 static void safe_delete_clear_cb(GtkWidget *widget, gpointer data)
1147 gd = generic_dialog_new(_("Clear trash"),
1148 "clear_trash", widget, TRUE,
1149 dummy_cancel_cb, NULL);
1150 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear trash"),
1151 _("This will remove the trash contents."), FALSE);
1152 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, safe_delete_clear_ok_cb, TRUE);
1153 entry = gtk_entry_new();
1154 gtk_widget_set_can_focus(entry, FALSE);
1155 gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE);
1156 if (options->file_ops.safe_delete_path) gtk_entry_set_text(GTK_ENTRY(entry), options->file_ops.safe_delete_path);
1157 gtk_box_pack_start(GTK_BOX(gd->vbox), entry, FALSE, FALSE, 0);
1158 gtk_widget_show(entry);
1159 gtk_widget_show(gd->dialog);
1162 static void image_overlay_template_view_changed_cb(GtkWidget *widget, gpointer data)
1164 GtkWidget *pTextView;
1165 GtkTextBuffer *pTextBuffer;
1169 pTextView = GTK_WIDGET(data);
1171 pTextBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pTextView));
1172 gtk_text_buffer_get_start_iter(pTextBuffer, &iStart);
1173 gtk_text_buffer_get_end_iter(pTextBuffer, &iEnd);
1175 set_image_overlay_template_string(&c_options->image_overlay.template_string,
1176 gtk_text_buffer_get_text(pTextBuffer, &iStart, &iEnd, TRUE));
1179 static void image_overlay_default_template_ok_cb(GenericDialog *gd, gpointer data)
1181 GtkTextView *text_view = data;
1182 GtkTextBuffer *buffer;
1184 set_default_image_overlay_template_string(&options->image_overlay.template_string);
1185 if (!configwindow) return;
1187 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
1188 gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1191 static void image_overlay_default_template_cb(GtkWidget *widget, gpointer data)
1195 gd = generic_dialog_new(_("Reset image overlay template string"),
1196 "reset_image_overlay_template_string", widget, TRUE,
1197 dummy_cancel_cb, data);
1198 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset image overlay template string"),
1199 _("This will reset the image overlay template string to the default.\nContinue?"), TRUE);
1200 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, image_overlay_default_template_ok_cb, TRUE);
1201 gtk_widget_show(gd->dialog);
1204 static void image_overlay_help_cb(GtkWidget *widget, gpointer data)
1206 help_window_show("GuideOptionsWindow.html#OverlayScreenDisplay");
1209 static void image_overlay_set_font_cb(GtkWidget *widget, gpointer data)
1211 #if GTK_CHECK_VERSION(3,4,0)
1214 PangoFontDescription *font_desc;
1216 dialog = gtk_font_chooser_dialog_new("Image Overlay Font", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1217 gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), options->image_overlay.font);
1219 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1221 font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
1222 font = pango_font_description_to_string(font_desc);
1223 g_free(c_options->image_overlay.font);
1224 c_options->image_overlay.font = g_strdup(font);
1228 gtk_widget_destroy(dialog);
1232 font = gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget));
1233 c_options->image_overlay.font = g_strdup(font);
1237 static void image_overlay_set_text_colour_cb(GtkWidget *widget, gpointer data)
1240 #if GTK_CHECK_VERSION(3,4,0)
1243 dialog = gtk_color_chooser_dialog_new("Image Overlay Text Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1244 colour.red = options->image_overlay.text_red;
1245 colour.green = options->image_overlay.text_green;
1246 colour.blue = options->image_overlay.text_blue;
1247 colour.alpha = options->image_overlay.text_alpha;
1248 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1249 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1251 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1253 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1254 c_options->image_overlay.text_red = colour.red*255;
1255 c_options->image_overlay.text_green = colour.green*255;
1256 c_options->image_overlay.text_blue = colour.blue*255;
1257 c_options->image_overlay.text_alpha = colour.alpha*255;
1259 gtk_widget_destroy(dialog);
1262 GtkColorSelection *colorsel;
1264 dialog = gtk_color_selection_dialog_new("Image Overlay Text Colour");
1265 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1266 colour.red = options->image_overlay.text_red*257;
1267 colour.green = options->image_overlay.text_green*257;
1268 colour.blue = options->image_overlay.text_blue*257;
1269 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1270 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1271 gtk_color_selection_set_current_color(colorsel, &colour);
1272 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.text_alpha*257);
1274 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1276 gtk_color_selection_get_current_color(colorsel, &colour);
1277 c_options->image_overlay.text_red = colour.red/257;
1278 c_options->image_overlay.text_green = colour.green/257;
1279 c_options->image_overlay.text_blue = colour.blue/257;
1280 c_options->image_overlay.text_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1282 gtk_widget_destroy (dialog);
1287 static void image_overlay_set_background_colour_cb(GtkWidget *widget, gpointer data)
1290 #if GTK_CHECK_VERSION(3,4,0)
1293 dialog = gtk_color_chooser_dialog_new("Image Overlay Background Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1294 colour.red = options->image_overlay.background_red;
1295 colour.green = options->image_overlay.background_green;
1296 colour.blue = options->image_overlay.background_blue;
1297 colour.alpha = options->image_overlay.background_alpha;
1298 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1299 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1301 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1303 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1304 c_options->image_overlay.background_red = colour.red*255;
1305 c_options->image_overlay.background_green = colour.green*255;
1306 c_options->image_overlay.background_blue = colour.blue*255;
1307 c_options->image_overlay.background_alpha = colour.alpha*255;
1309 gtk_widget_destroy(dialog);
1312 GtkColorSelection *colorsel;
1314 dialog = gtk_color_selection_dialog_new("Image Overlay Background Colour");
1315 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1316 colour.red = options->image_overlay.background_red*257;
1317 colour.green = options->image_overlay.background_green*257;
1318 colour.blue = options->image_overlay.background_blue*257;
1319 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1320 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1321 gtk_color_selection_set_current_color(colorsel, &colour);
1322 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.background_alpha*257);
1324 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1326 gtk_color_selection_get_current_color(colorsel, &colour);
1327 c_options->image_overlay.background_red = colour.red/257;
1328 c_options->image_overlay.background_green = colour.green/257;
1329 c_options->image_overlay.background_blue = colour.blue/257;
1330 c_options->image_overlay.background_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1332 gtk_widget_destroy(dialog);
1336 static void accel_store_populate(void)
1339 GList *groups, *actions;
1341 const gchar *accel_path;
1345 if (!accel_store || !layout_window_list || !layout_window_list->data) return;
1347 gtk_tree_store_clear(accel_store);
1348 lw = layout_window_list->data; /* get the actions from the first window, it should not matter, they should be the same in all windows */
1350 g_assert(lw && lw->ui_manager);
1351 groups = gtk_ui_manager_get_action_groups(lw->ui_manager);
1354 actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
1357 action = GTK_ACTION(actions->data);
1358 accel_path = gtk_action_get_accel_path(action);
1359 if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
1361 gchar *label, *label2, *tooltip, *accel;
1362 g_object_get(action,
1363 "tooltip", &tooltip,
1367 if (pango_parse_markup(label, -1, '_', NULL, &label2, NULL, NULL) && label2)
1373 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1377 gtk_tree_store_append(accel_store, &iter, NULL);
1378 gtk_tree_store_set(accel_store, &iter,
1381 AE_TOOLTIP, tooltip ? tooltip : "",
1382 AE_ACCEL, accel_path,
1390 actions = actions->next;
1393 groups = groups->next;
1397 static void accel_store_cleared_cb(GtkCellRendererAccel *accel, gchar *path_string, gpointer user_data)
1402 static gboolean accel_remove_key_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1404 gchar *accel1 = data;
1409 gtk_tree_model_get(model, iter, AE_KEY, &accel2, -1);
1411 gtk_accelerator_parse(accel1, &key1.accel_key, &key1.accel_mods);
1412 gtk_accelerator_parse(accel2, &key2.accel_key, &key2.accel_mods);
1414 if (key1.accel_key == key2.accel_key && key1.accel_mods == key2.accel_mods)
1416 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1417 DEBUG_1("accelerator key '%s' is already used, removing.", accel1);
1426 static void accel_store_edited_cb(GtkCellRendererAccel *accel, gchar *path_string, guint accel_key, GdkModifierType accel_mods, guint hardware_keycode, gpointer user_data)
1428 GtkTreeModel *model = (GtkTreeModel *)accel_store;
1432 GtkAccelKey old_key, key;
1433 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
1435 gtk_tree_model_get_iter(model, &iter, path);
1436 gtk_tree_model_get(model, &iter, AE_ACCEL, &accel_path, -1);
1438 /* test if the accelerator can be stored without conflicts*/
1439 gtk_accel_map_lookup_entry(accel_path, &old_key);
1441 /* change the key and read it back (change may fail on keys hardcoded in gtk)*/
1442 gtk_accel_map_change_entry(accel_path, accel_key, accel_mods, TRUE);
1443 gtk_accel_map_lookup_entry(accel_path, &key);
1445 /* restore the original for now, the key will be really changed when the changes are confirmed */
1446 gtk_accel_map_change_entry(accel_path, old_key.accel_key, old_key.accel_mods, TRUE);
1448 acc = gtk_accelerator_name(key.accel_key, key.accel_mods);
1449 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, acc);
1451 gtk_tree_store_set(accel_store, &iter, AE_KEY, acc, -1);
1452 gtk_tree_path_free(path);
1456 static gboolean accel_default_scroll(GtkTreeView *data)
1460 GtkTreeViewColumn *column;
1462 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(accel_store), &iter);
1463 path = gtk_tree_model_get_path(GTK_TREE_MODEL(accel_store), &iter);
1464 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1466 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1470 gtk_tree_path_free(path);
1475 static void accel_default_cb(GtkWidget *widget, gpointer data)
1477 accel_store_populate();
1479 g_idle_add((GSourceFunc)accel_default_scroll, data);
1482 void accel_remove_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1484 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1487 void accel_reset_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1490 gchar *accel_path, *accel;
1492 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, -1);
1493 gtk_accel_map_lookup_entry(accel_path, &key);
1494 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1496 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, accel);
1498 gtk_tree_store_set(accel_store, iter, AE_KEY, accel, -1);
1503 static void accel_reset_cb(GtkWidget *widget, gpointer data)
1505 GtkTreeSelection *selection;
1507 if (!accel_store) return;
1508 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data));
1509 gtk_tree_selection_selected_foreach(selection, &accel_reset_selection, NULL);
1514 static GtkWidget *scrolled_notebook_page(GtkWidget *notebook, const gchar *title)
1518 GtkWidget *scrolled;
1519 GtkWidget *viewport;
1521 scrolled = gtk_scrolled_window_new(NULL, NULL);
1522 gtk_container_set_border_width(GTK_CONTAINER(scrolled), PREF_PAD_BORDER);
1523 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1524 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1525 label = gtk_label_new(title);
1526 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, label);
1527 gtk_widget_show(scrolled);
1529 viewport = gtk_viewport_new(NULL, NULL);
1530 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1531 gtk_container_add(GTK_CONTAINER(scrolled), viewport);
1532 gtk_widget_show(viewport);
1534 vbox = gtk_vbox_new(FALSE, 0);
1535 gtk_container_add(GTK_CONTAINER(viewport), vbox);
1536 gtk_widget_show(vbox);
1541 static void cache_standard_cb(GtkWidget *widget, gpointer data)
1543 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1545 c_options->thumbnails.spec_standard =TRUE;
1546 c_options->thumbnails.cache_into_dirs = FALSE;
1550 c_options->thumbnails.spec_standard =FALSE;
1554 static void cache_geeqie_cb(GtkWidget *widget, gpointer data)
1556 if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1558 c_options->thumbnails.spec_standard =TRUE;
1559 c_options->thumbnails.cache_into_dirs = FALSE;
1563 c_options->thumbnails.spec_standard =FALSE;
1567 static void cache_local_cb(GtkWidget *widget, gpointer data)
1569 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1571 c_options->thumbnails.cache_into_dirs = TRUE;
1572 c_options->thumbnails.spec_standard =FALSE;
1576 c_options->thumbnails.cache_into_dirs = FALSE;
1580 /* general options tab */
1581 static void config_tab_general(GtkWidget *notebook)
1586 GtkWidget *group_frame;
1587 GtkWidget *subgroup;
1589 GtkWidget *ct_button;
1592 gint hours, minutes, remainder;
1595 vbox = scrolled_notebook_page(notebook, _("General"));
1597 group = pref_group_new(vbox, FALSE, _("Thumbnails"), GTK_ORIENTATION_VERTICAL);
1599 table = pref_table_new(group, 2, 2, FALSE, FALSE);
1600 add_thumb_size_menu(table, 0, 0, _("Size:"));
1601 add_quality_menu(table, 0, 1, _("Quality:"), options->thumbnails.quality, &c_options->thumbnails.quality);
1603 ct_button = pref_checkbox_new_int(group, _("Cache thumbnails"),
1604 options->thumbnails.enable_caching, &c_options->thumbnails.enable_caching);
1606 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1607 pref_checkbox_link_sensitivity(ct_button, subgroup);
1609 group_frame = pref_frame_new(subgroup, TRUE, _("Use Geeqie thumbnail style and cache"),
1610 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1611 button = pref_radiobutton_new(group_frame, NULL, get_thumbnails_cache_dir(),
1612 !options->thumbnails.spec_standard,
1613 G_CALLBACK(cache_geeqie_cb), NULL);
1615 group_frame = pref_frame_new(subgroup, TRUE,
1616 _("Store thumbnails local to image folder (non-standard)"),
1617 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1618 pref_radiobutton_new(group_frame, button, "*/.thumbnails",
1619 options->thumbnails.cache_into_dirs,
1620 G_CALLBACK(cache_local_cb), NULL);
1622 group_frame = pref_frame_new(subgroup, TRUE,
1623 _("Use standard thumbnail style and cache, shared with other applications"),
1624 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1625 pref_radiobutton_new(group_frame, button, get_thumbnails_standard_cache_dir(),
1626 options->thumbnails.spec_standard,
1627 G_CALLBACK(cache_standard_cb), NULL);
1629 pref_checkbox_new_int(group, _("Use EXIF thumbnails when available (EXIF thumbnails may be outdated)"),
1630 options->thumbnails.use_exif, &c_options->thumbnails.use_exif);
1632 group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
1634 c_options->slideshow.delay = options->slideshow.delay;
1635 hours = options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
1636 remainder = options->slideshow.delay % (3600 * SLIDESHOW_SUBSECOND_PRECISION);
1637 minutes = remainder / (60 * SLIDESHOW_SUBSECOND_PRECISION);
1638 seconds = (gdouble)(remainder % (60 * SLIDESHOW_SUBSECOND_PRECISION)) /
1639 SLIDESHOW_SUBSECOND_PRECISION;
1641 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1643 spin = pref_spin_new(hbox, _("Delay between image change hrs:mins:secs.dec"), NULL,
1645 options->slideshow.delay ? hours : 0.0,
1646 G_CALLBACK(slideshow_delay_hours_cb), NULL);
1647 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1648 spin = pref_spin_new(hbox, ":" , NULL,
1650 options->slideshow.delay ? minutes: 0.0,
1651 G_CALLBACK(slideshow_delay_minutes_cb), NULL);
1652 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1653 spin = pref_spin_new(hbox, ":", NULL,
1654 SLIDESHOW_MIN_SECONDS, 59, 1.0, 1,
1655 options->slideshow.delay ? seconds : 10.0,
1656 G_CALLBACK(slideshow_delay_seconds_cb), NULL);
1657 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1659 pref_checkbox_new_int(group, _("Random"), options->slideshow.random, &c_options->slideshow.random);
1660 pref_checkbox_new_int(group, _("Repeat"), options->slideshow.repeat, &c_options->slideshow.repeat);
1662 group = pref_group_new(vbox, FALSE, _("Image loading and caching"), GTK_ORIENTATION_VERTICAL);
1664 pref_spin_new_int(group, _("Decoded image cache size (Mb):"), NULL,
1665 0, 99999, 1, options->image.image_cache_max, &c_options->image.image_cache_max);
1666 pref_checkbox_new_int(group, _("Preload next image"),
1667 options->image.enable_read_ahead, &c_options->image.enable_read_ahead);
1669 pref_checkbox_new_int(group, _("Refresh on file change"),
1670 options->update_on_time_change, &c_options->update_on_time_change);
1672 group = pref_group_new(vbox, FALSE, _("Info sidebar heights"), GTK_ORIENTATION_VERTICAL);
1673 pref_label_new(group, _("NOTE! Geeqie must be restarted for changes to take effect"));
1674 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1675 pref_spin_new_int(hbox, _("Keywords:"), NULL,
1677 options->info_keywords.height, &c_options->info_keywords.height);
1678 pref_spin_new_int(hbox, _("Title:"), NULL,
1680 options->info_title.height, &c_options->info_title.height);
1681 pref_spin_new_int(hbox, _("Comment:"), NULL,
1683 options->info_comment.height, &c_options->info_comment.height);
1684 pref_spin_new_int(hbox, _("Rating:"), NULL,
1686 options->info_rating.height, &c_options->info_rating.height);
1690 static void config_tab_image(GtkWidget *notebook)
1695 GtkWidget *ct_button;
1696 GtkWidget *enlargement_button;
1700 vbox = scrolled_notebook_page(notebook, _("Image"));
1702 group = pref_group_new(vbox, FALSE, _("Zoom"), GTK_ORIENTATION_VERTICAL);
1704 table = pref_table_new(group, 2, 1, FALSE, FALSE);
1705 add_quality_menu(table, 0, 0, _("Quality:"), options->image.zoom_quality, &c_options->image.zoom_quality);
1708 pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library"),
1709 options->image.use_clutter_renderer, &c_options->image.use_clutter_renderer);
1712 pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"),
1713 options->image.zoom_2pass, &c_options->image.zoom_2pass);
1715 c_options->image.zoom_increment = options->image.zoom_increment;
1716 spin = pref_spin_new(group, _("Zoom increment:"), NULL,
1717 0.01, 4.0, 0.01, 2, (gdouble)options->image.zoom_increment / 100.0,
1718 G_CALLBACK(zoom_increment_cb), NULL);
1719 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1721 group = pref_group_new(vbox, FALSE, _("Fit image to window"), GTK_ORIENTATION_VERTICAL);
1723 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1724 enlargement_button = pref_checkbox_new_int(hbox, _("Allow enlargement of image (max. size in %)"),
1725 options->image.zoom_to_fit_allow_expand, &c_options->image.zoom_to_fit_allow_expand);
1726 spin = pref_spin_new_int(hbox, NULL, NULL,
1728 options->image.max_enlargement_size, &c_options->image.max_enlargement_size);
1729 pref_checkbox_link_sensitivity(enlargement_button, spin);
1730 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."));
1732 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1733 ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (% of actual window):"),
1734 options->image.limit_autofit_size, &c_options->image.limit_autofit_size);
1735 spin = pref_spin_new_int(hbox, NULL, NULL,
1737 options->image.max_autofit_size, &c_options->image.max_autofit_size);
1738 pref_checkbox_link_sensitivity(ct_button, spin);
1739 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."));
1741 group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
1743 pref_checkbox_new_int(group, _("Use custom border color in window mode"),
1744 options->image.use_custom_border_color, &c_options->image.use_custom_border_color);
1746 pref_checkbox_new_int(group, _("Use custom border color in fullscreen mode"),
1747 options->image.use_custom_border_color_in_fullscreen, &c_options->image.use_custom_border_color_in_fullscreen);
1749 pref_color_button_new(group, _("Border color"), &options->image.border_color,
1750 G_CALLBACK(pref_color_button_set_cb), &c_options->image.border_color);
1752 c_options->image.border_color = options->image.border_color;
1754 pref_color_button_new(group, _("Alpha channel color 1"), &options->image.alpha_color_1,
1755 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_1);
1757 pref_color_button_new(group, _("Alpha channel color 2"), &options->image.alpha_color_2,
1758 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_2);
1760 c_options->image.alpha_color_1 = options->image.alpha_color_1;
1761 c_options->image.alpha_color_2 = options->image.alpha_color_2;
1763 group = pref_group_new(vbox, FALSE, _("Convenience"), GTK_ORIENTATION_VERTICAL);
1765 pref_checkbox_new_int(group, _("Auto rotate proofs using Exif information"),
1766 options->image.exif_proof_rotate_enable, &c_options->image.exif_proof_rotate_enable);
1770 static void config_tab_windows(GtkWidget *notebook)
1776 GtkWidget *ct_button;
1778 GtkWidget *image_overlay_template_view;
1779 GtkWidget *scrolled;
1780 GtkTextBuffer *buffer;
1782 vbox = scrolled_notebook_page(notebook, _("Windows"));
1784 group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
1786 ct_button = pref_checkbox_new_int(group, _("Remember window positions"),
1787 options->save_window_positions, &c_options->save_window_positions);
1789 button = pref_checkbox_new_int(group, _("Use saved window positions also for new windows"),
1790 options->use_saved_window_positions_for_new_windows, &c_options->use_saved_window_positions_for_new_windows);
1791 pref_checkbox_link_sensitivity(ct_button, button);
1793 pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
1794 options->tools_restore_state, &c_options->tools_restore_state);
1796 pref_checkbox_new_int(group, _("Remember dialog window positions"),
1797 options->save_dialog_window_positions, &c_options->save_dialog_window_positions);
1799 group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
1801 pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
1802 options->image.fit_window_to_image, &c_options->image.fit_window_to_image);
1804 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1805 ct_button = pref_checkbox_new_int(hbox, _("Limit size when auto-sizing window (%):"),
1806 options->image.limit_window_size, &c_options->image.limit_window_size);
1807 spin = pref_spin_new_int(hbox, NULL, NULL,
1809 options->image.max_window_size, &c_options->image.max_window_size);
1810 pref_checkbox_link_sensitivity(ct_button, spin);
1812 group = pref_group_new(vbox, FALSE, _("Full screen"), GTK_ORIENTATION_VERTICAL);
1814 c_options->fullscreen.screen = options->fullscreen.screen;
1815 c_options->fullscreen.above = options->fullscreen.above;
1816 hbox = fullscreen_prefs_selection_new(_("Location:"), &c_options->fullscreen.screen, &c_options->fullscreen.above);
1817 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
1818 gtk_widget_show(hbox);
1820 pref_checkbox_new_int(group, _("Smooth image flip"),
1821 options->fullscreen.clean_flip, &c_options->fullscreen.clean_flip);
1822 pref_checkbox_new_int(group, _("Disable screen saver"),
1823 options->fullscreen.disable_saver, &c_options->fullscreen.disable_saver);
1826 group = pref_group_new(vbox, FALSE, _("Overlay Screen Display"), GTK_ORIENTATION_VERTICAL);
1828 pref_label_new(group, _("Image overlay template"));
1830 scrolled = gtk_scrolled_window_new(NULL, NULL);
1831 gtk_widget_set_size_request(scrolled, 200, 150);
1832 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
1833 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1834 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1835 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 5);
1836 gtk_widget_show(scrolled);
1838 image_overlay_template_view = gtk_text_view_new();
1840 gtk_widget_set_tooltip_markup(image_overlay_template_view,
1841 _("<i>%name%</i> results in the filename of the picture.\n"
1842 "Also available: <i>%collection%</i>, <i>%number%</i>, <i>%total%</i>, <i>%date%</i>,\n"
1843 "<i>%size%</i> (filesize), <i>%width%</i>, <i>%height%</i>, <i>%res%</i> (resolution)\n"
1844 "To access exif data use the exif name, e. g. <i>%formatted.Camera%</i> is the formatted camera name,\n"
1845 "<i>%Exif.Photo.DateTimeOriginal%</i> the date of the original shot.\n"
1846 "<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"
1847 "If two or more variables are connected with the |-sign, it prints available variables with a separator.\n"
1848 "<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"
1849 "if there's no ISO information in the Exif data.\n"
1850 "If a line is empty, it is removed. This allows one to add lines that totally disappear when no data is available.\n"
1852 gtk_container_add(GTK_CONTAINER(scrolled), image_overlay_template_view);
1853 gtk_widget_show(image_overlay_template_view);
1855 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
1857 #if GTK_CHECK_VERSION(3,4,0)
1858 button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
1859 G_CALLBACK(image_overlay_set_font_cb), notebook);
1861 button = gtk_font_button_new();
1862 gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Image Overlay Font");
1863 gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->image_overlay.font);
1864 g_signal_connect(G_OBJECT(button), "font-set",
1865 G_CALLBACK(image_overlay_set_font_cb),NULL);
1867 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1868 gtk_widget_show(button);
1870 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Text"), FALSE,
1871 G_CALLBACK(image_overlay_set_text_colour_cb), NULL);
1872 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1873 gtk_widget_show(button);
1875 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Background"), FALSE,
1876 G_CALLBACK(image_overlay_set_background_colour_cb), NULL);
1877 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1878 gtk_widget_show(button);
1879 image_overlay_set_text_colours();
1881 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
1882 G_CALLBACK(image_overlay_default_template_cb), image_overlay_template_view);
1883 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1884 gtk_widget_show(button);
1886 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
1887 G_CALLBACK(image_overlay_help_cb), NULL);
1888 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1889 gtk_widget_show(button);
1891 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_overlay_template_view));
1892 if (options->image_overlay.template_string) gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1893 g_signal_connect(G_OBJECT(buffer), "changed",
1894 G_CALLBACK(image_overlay_template_view_changed_cb), image_overlay_template_view);
1899 static GtkTreeModel *create_class_model(void)
1901 GtkListStore *model;
1905 /* create list store */
1906 model = gtk_list_store_new(1, G_TYPE_STRING);
1907 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
1909 gtk_list_store_append(model, &iter);
1910 gtk_list_store_set(model, &iter, 0, _(format_class_list[i]), -1);
1912 return GTK_TREE_MODEL (model);
1917 static void config_tab_files(GtkWidget *notebook)
1924 GtkWidget *ct_button;
1925 GtkWidget *scrolled;
1926 GtkWidget *filter_view;
1927 GtkCellRenderer *renderer;
1928 GtkTreeSelection *selection;
1929 GtkTreeViewColumn *column;
1931 vbox = scrolled_notebook_page(notebook, _("Files"));
1933 group = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1935 pref_checkbox_new_int(group, _("Show hidden files or folders"),
1936 options->file_filter.show_hidden_files, &c_options->file_filter.show_hidden_files);
1937 pref_checkbox_new_int(group, _("Show parent folder (..)"),
1938 options->file_filter.show_parent_directory, &c_options->file_filter.show_parent_directory);
1939 pref_checkbox_new_int(group, _("Case sensitive sort"),
1940 options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
1941 pref_checkbox_new_int(group, _("Natural sort order"),
1942 options->file_sort.natural, &c_options->file_sort.natural);
1943 pref_checkbox_new_int(group, _("Disable file extension checks"),
1944 options->file_filter.disable_file_extension_checks, &c_options->file_filter.disable_file_extension_checks);
1946 ct_button = pref_checkbox_new_int(group, _("Disable File Filtering"),
1947 options->file_filter.disable, &c_options->file_filter.disable);
1950 group = pref_group_new(vbox, FALSE, _("Grouping sidecar extensions"), GTK_ORIENTATION_VERTICAL);
1952 sidecar_ext_entry = gtk_entry_new();
1953 gtk_entry_set_text(GTK_ENTRY(sidecar_ext_entry), options->sidecar.ext);
1954 gtk_box_pack_start(GTK_BOX(group), sidecar_ext_entry, FALSE, FALSE, 0);
1955 gtk_widget_show(sidecar_ext_entry);
1957 group = pref_group_new(vbox, TRUE, _("File types"), GTK_ORIENTATION_VERTICAL);
1959 frame = pref_group_parent(group);
1960 g_signal_connect(G_OBJECT(ct_button), "toggled",
1961 G_CALLBACK(filter_disable_cb), frame);
1962 gtk_widget_set_sensitive(frame, !options->file_filter.disable);
1964 scrolled = gtk_scrolled_window_new(NULL, NULL);
1965 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
1966 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
1967 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
1968 gtk_widget_show(scrolled);
1970 filter_store = gtk_list_store_new(1, G_TYPE_POINTER);
1971 filter_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(filter_store));
1972 g_object_unref(filter_store);
1973 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1974 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
1976 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), FALSE);
1978 column = gtk_tree_view_column_new();
1979 gtk_tree_view_column_set_title(column, _("Filter"));
1980 gtk_tree_view_column_set_resizable(column, TRUE);
1982 renderer = gtk_cell_renderer_toggle_new();
1983 g_signal_connect(G_OBJECT(renderer), "toggled",
1984 G_CALLBACK(filter_store_enable_cb), filter_store);
1985 gtk_tree_view_column_pack_start(column, renderer, FALSE);
1986 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
1987 GINT_TO_POINTER(FE_ENABLE), NULL);
1989 renderer = gtk_cell_renderer_text_new();
1990 g_signal_connect(G_OBJECT(renderer), "edited",
1991 G_CALLBACK(filter_store_ext_edit_cb), filter_store);
1992 gtk_tree_view_column_pack_start(column, renderer, TRUE);
1993 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
1994 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
1995 GINT_TO_POINTER(FE_EXTENSION), NULL);
1996 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
1998 column = gtk_tree_view_column_new();
1999 gtk_tree_view_column_set_title(column, _("Description"));
2000 gtk_tree_view_column_set_resizable(column, TRUE);
2001 gtk_tree_view_column_set_fixed_width(column, 200);
2002 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
2004 renderer = gtk_cell_renderer_text_new();
2005 g_signal_connect(G_OBJECT(renderer), "edited",
2006 G_CALLBACK(filter_store_desc_edit_cb), filter_store);
2007 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2008 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2009 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2010 GINT_TO_POINTER(FE_DESCRIPTION), 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, _("Class"));
2015 gtk_tree_view_column_set_resizable(column, TRUE);
2016 renderer = gtk_cell_renderer_combo_new();
2017 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE,
2018 "model", create_class_model(),
2023 g_signal_connect(G_OBJECT(renderer), "edited",
2024 G_CALLBACK(filter_store_class_edit_cb), filter_store);
2025 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2026 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2027 GINT_TO_POINTER(FE_CLASS), NULL);
2028 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2030 column = gtk_tree_view_column_new();
2031 gtk_tree_view_column_set_title(column, _("Writable"));
2032 gtk_tree_view_column_set_resizable(column, FALSE);
2033 renderer = gtk_cell_renderer_toggle_new();
2034 g_signal_connect(G_OBJECT(renderer), "toggled",
2035 G_CALLBACK(filter_store_writable_cb), filter_store);
2036 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2037 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2038 GINT_TO_POINTER(FE_WRITABLE), NULL);
2039 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2041 column = gtk_tree_view_column_new();
2042 gtk_tree_view_column_set_title(column, _("Sidecar is allowed"));
2043 gtk_tree_view_column_set_resizable(column, FALSE);
2044 renderer = gtk_cell_renderer_toggle_new();
2045 g_signal_connect(G_OBJECT(renderer), "toggled",
2046 G_CALLBACK(filter_store_sidecar_cb), filter_store);
2047 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2048 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2049 GINT_TO_POINTER(FE_ALLOW_SIDECAR), NULL);
2050 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2053 filter_store_populate();
2054 gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
2055 gtk_widget_show(filter_view);
2057 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2059 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2060 G_CALLBACK(filter_default_cb), filter_view);
2061 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2062 gtk_widget_show(button);
2064 button = pref_button_new(NULL, GTK_STOCK_REMOVE, NULL, FALSE,
2065 G_CALLBACK(filter_remove_cb), filter_view);
2066 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2067 gtk_widget_show(button);
2069 button = pref_button_new(NULL, GTK_STOCK_ADD, NULL, FALSE,
2070 G_CALLBACK(filter_add_cb), filter_view);
2071 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2072 gtk_widget_show(button);
2076 static void config_tab_metadata(GtkWidget *notebook)
2081 GtkWidget *ct_button;
2085 vbox = scrolled_notebook_page(notebook, _("Metadata"));
2088 group = pref_group_new(vbox, FALSE, _("Metadata writing process"), GTK_ORIENTATION_VERTICAL);
2090 label = pref_label_new(group, _("Warning: Geeqie is built without Exiv2. Some options are disabled."));
2092 label = pref_label_new(group, _("Metadata are written in the following order. The process ends after first success."));
2093 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2095 ct_button = pref_checkbox_new_int(group, _("1) Save metadata in image files, or sidecar files, according to the XMP standard"),
2096 options->metadata.save_in_image_file, &c_options->metadata.save_in_image_file);
2098 gtk_widget_set_sensitive(ct_button, FALSE);
2101 pref_checkbox_new_int(group, _("2) Save metadata in '.metadata' folder, local to image folder (non-standard)"),
2102 options->metadata.enable_metadata_dirs, &c_options->metadata.enable_metadata_dirs);
2104 text = g_strdup_printf(_("3) Save metadata in Geeqie private directory '%s'"), get_metadata_cache_dir());
2105 label = pref_label_new(group, text);
2106 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2107 gtk_misc_set_padding(GTK_MISC(label), 22, 0);
2110 group = pref_group_new(vbox, FALSE, _("Step 1: Write to image files"), GTK_ORIENTATION_VERTICAL);
2112 gtk_widget_set_sensitive(group, FALSE);
2115 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2116 pref_checkbox_link_sensitivity(ct_button, hbox);
2118 pref_checkbox_new_int(hbox, _("Store metadata also in legacy IPTC tags (converted according to IPTC4XMP standard)"),
2119 options->metadata.save_legacy_IPTC, &c_options->metadata.save_legacy_IPTC);
2121 pref_checkbox_new_int(hbox, _("Warn if the image files are unwritable"),
2122 options->metadata.warn_on_write_problems, &c_options->metadata.warn_on_write_problems);
2124 pref_checkbox_new_int(hbox, _("Ask before writing to image files"),
2125 options->metadata.confirm_write, &c_options->metadata.confirm_write);
2127 pref_checkbox_new_int(hbox, _("Create sidecar files named image.ext.xmp (as opposed to image.xmp)"),
2128 options->metadata.sidecar_extended_name, &c_options->metadata.sidecar_extended_name);
2130 group = pref_group_new(vbox, FALSE, _("Step 2 and 3: write to Geeqie private files"), GTK_ORIENTATION_VERTICAL);
2132 gtk_widget_set_sensitive(group, FALSE);
2135 pref_checkbox_new_int(group, _("Use GQview legacy metadata format (supports only keywords and comments) instead of XMP"),
2136 options->metadata.save_legacy_format, &c_options->metadata.save_legacy_format);
2139 group = pref_group_new(vbox, FALSE, _("Miscellaneous"), GTK_ORIENTATION_VERTICAL);
2140 pref_checkbox_new_int(group, _("Write the same description tags (keywords, comment, etc.) to all grouped sidecars"),
2141 options->metadata.sync_grouped_files, &c_options->metadata.sync_grouped_files);
2143 pref_checkbox_new_int(group, _("Allow keywords to differ only in case"),
2144 options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
2146 ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"),
2147 options->metadata.write_orientation, &c_options->metadata.write_orientation);
2149 gtk_widget_set_sensitive(ct_button, FALSE);
2152 group = pref_group_new(vbox, FALSE, _("Auto-save options"), GTK_ORIENTATION_VERTICAL);
2154 ct_button = pref_checkbox_new_int(group, _("Write metadata after timeout"),
2155 options->metadata.confirm_after_timeout, &c_options->metadata.confirm_after_timeout);
2157 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2158 pref_checkbox_link_sensitivity(ct_button, hbox);
2160 pref_spin_new_int(hbox, _("Timeout (seconds):"), NULL, 0, 900, 1,
2161 options->metadata.confirm_timeout, &c_options->metadata.confirm_timeout);
2163 pref_checkbox_new_int(group, _("Write metadata on image change"),
2164 options->metadata.confirm_on_image_change, &c_options->metadata.confirm_on_image_change);
2166 pref_checkbox_new_int(group, _("Write metadata on directory change"),
2167 options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
2172 static void intent_menu_cb(GtkWidget *combo, gpointer data)
2174 gint *option = data;
2176 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
2180 *option = INTENT_PERCEPTUAL;
2183 *option = INTENT_RELATIVE_COLORIMETRIC;
2186 *option = INTENT_SATURATION;
2189 *option = INTENT_ABSOLUTE_COLORIMETRIC;
2194 static void add_intent_menu(GtkWidget *table, gint column, gint row, const gchar *text,
2195 gint option, gint *option_c)
2202 pref_table_label(table, column, row, text, 0.0);
2204 combo = gtk_combo_box_text_new();
2206 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Perceptual"));
2207 if (option == INTENT_PERCEPTUAL) current = 0;
2208 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Relative Colorimetric"));
2209 if (option == INTENT_RELATIVE_COLORIMETRIC) current = 1;
2210 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Saturation"));
2211 if (option == INTENT_SATURATION) current = 2;
2212 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Absolute Colorimetric"));
2213 if (option == INTENT_ABSOLUTE_COLORIMETRIC) current = 3;
2215 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
2217 gtk_widget_set_tooltip_text(combo,"Refer to the lcms documentation for the defaults used when the selected Intent is not available");
2219 g_signal_connect(G_OBJECT(combo), "changed",
2220 G_CALLBACK(intent_menu_cb), option_c);
2222 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
2223 GTK_EXPAND | GTK_FILL, 0, 0, 0);
2224 gtk_widget_show(combo);
2228 static void config_tab_color(GtkWidget *notebook)
2237 vbox = scrolled_notebook_page(notebook, _("Color management"));
2239 group = pref_group_new(vbox, FALSE, _("Input profiles"), GTK_ORIENTATION_VERTICAL);
2241 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
2244 table = pref_table_new(group, 3, COLOR_PROFILE_INPUTS + 1, FALSE, FALSE);
2245 gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
2247 label = pref_table_label(table, 0, 0, _("Type"), 0.0);
2248 pref_label_bold(label, TRUE, FALSE);
2250 label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
2251 pref_label_bold(label, TRUE, FALSE);
2253 label = pref_table_label(table, 2, 0, _("File"), 0.0);
2254 pref_label_bold(label, TRUE, FALSE);
2256 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
2261 buf = g_strdup_printf(_("Input %d:"), i + COLOR_PROFILE_FILE);
2262 pref_table_label(table, 0, i + 1, buf, 1.0);
2265 entry = gtk_entry_new();
2266 gtk_entry_set_max_length(GTK_ENTRY(entry), EDITOR_NAME_MAX_LENGTH);
2267 if (options->color_profile.input_name[i])
2269 gtk_entry_set_text(GTK_ENTRY(entry), options->color_profile.input_name[i]);
2271 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, i + 1, i + 2,
2272 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2273 gtk_widget_show(entry);
2274 color_profile_input_name_entry[i] = entry;
2276 tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, NULL);
2277 tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
2278 gtk_widget_set_size_request(entry, 160, -1);
2279 gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
2280 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2281 gtk_widget_show(tabcomp);
2282 color_profile_input_file_entry[i] = entry;
2285 group = pref_group_new(vbox, FALSE, _("Screen profile"), GTK_ORIENTATION_VERTICAL);
2287 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
2289 pref_checkbox_new_int(group, _("Use system screen profile if available"),
2290 options->color_profile.use_x11_screen_profile, &c_options->color_profile.use_x11_screen_profile);
2292 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2294 pref_table_label(table, 0, 0, _("Screen:"), 1.0);
2295 tabcomp = tab_completion_new(&color_profile_screen_file_entry,
2296 options->color_profile.screen_file, NULL, NULL);
2297 tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
2298 gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
2300 add_intent_menu(table, 0, 1, _("Render Intent:"), options->color_profile.render_intent, &c_options->color_profile.render_intent);
2302 gtk_table_attach(GTK_TABLE(table), tabcomp, 1, 2,
2304 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2306 gtk_widget_show(tabcomp);
2309 /* advanced entry tab */
2310 static void config_tab_behavior(GtkWidget *notebook)
2317 GtkWidget *ct_button;
2321 vbox = scrolled_notebook_page(notebook, _("Behavior"));
2323 group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
2325 pref_checkbox_new_int(group, _("Confirm file delete"),
2326 options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
2327 pref_checkbox_new_int(group, _("Enable Delete key"),
2328 options->file_ops.enable_delete_key, &c_options->file_ops.enable_delete_key);
2330 ct_button = pref_checkbox_new_int(group, _("Safe delete"),
2331 options->file_ops.safe_delete_enable, &c_options->file_ops.safe_delete_enable);
2333 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2334 pref_checkbox_link_sensitivity(ct_button, hbox);
2336 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
2337 pref_label_new(hbox, _("Folder:"));
2339 tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL);
2340 tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
2341 gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
2342 gtk_widget_show(tabcomp);
2344 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2345 pref_checkbox_link_sensitivity(ct_button, hbox);
2347 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
2348 spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MB"),
2349 0, 2048, 1, options->file_ops.safe_delete_folder_maxsize, &c_options->file_ops.safe_delete_folder_maxsize);
2350 gtk_widget_set_tooltip_markup(spin, _("Set to 0 for unlimited size"));
2351 button = pref_button_new(NULL, NULL, _("View"), FALSE,
2352 G_CALLBACK(safe_delete_view_cb), NULL);
2353 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2354 gtk_widget_show(button);
2356 button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
2357 G_CALLBACK(safe_delete_clear_cb), NULL);
2358 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2359 gtk_widget_show(button);
2362 group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
2364 pref_checkbox_new_int(group, _("Descend folders in tree view"),
2365 options->tree_descend_subdirs, &c_options->tree_descend_subdirs);
2367 pref_checkbox_new_int(group, _("In place renaming"),
2368 options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
2370 pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
2371 options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
2373 pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
2374 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
2376 pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
2377 16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
2379 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2380 add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
2382 group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
2384 pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
2385 options->progressive_key_scrolling, &c_options->progressive_key_scrolling);
2386 pref_spin_new_int(group, _("Keyboard scrolling step multiplier:"), NULL,
2387 1, 32, 1, options->keyboard_scroll_step, (int *)&c_options->keyboard_scroll_step);
2388 pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
2389 options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
2390 pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
2391 options->image_lm_click_nav, &c_options->image_lm_click_nav);
2392 pref_checkbox_new_int(group, _("Play video by left click on image"),
2393 options->image_l_click_video, &c_options->image_l_click_video);
2394 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2395 add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
2399 group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
2401 pref_spin_new_int(group, _("Debug level:"), NULL,
2402 DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
2404 pref_checkbox_new_int(group, _("Timer data"),
2405 options->log_window.timer_data, &c_options->log_window.timer_data);
2407 pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
2408 1, 99999, 1, options->log_window_lines, &options->log_window_lines);
2412 /* accelerators tab */
2413 static void config_tab_accelerators(GtkWidget *notebook)
2419 GtkWidget *scrolled;
2420 GtkWidget *accel_view;
2421 GtkCellRenderer *renderer;
2422 GtkTreeSelection *selection;
2423 GtkTreeViewColumn *column;
2425 vbox = scrolled_notebook_page(notebook, _("Keyboard"));
2427 group = pref_group_new(vbox, TRUE, _("Accelerators"), GTK_ORIENTATION_VERTICAL);
2429 scrolled = gtk_scrolled_window_new(NULL, NULL);
2430 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2431 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2432 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2433 gtk_widget_show(scrolled);
2435 accel_store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
2437 accel_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(accel_store));
2438 g_object_unref(accel_store);
2439 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(accel_view));
2440 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
2442 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(accel_view), FALSE);
2444 renderer = gtk_cell_renderer_text_new();
2446 column = gtk_tree_view_column_new_with_attributes(_("Action"),
2451 gtk_tree_view_column_set_sort_column_id(column, AE_ACTION);
2452 gtk_tree_view_column_set_resizable(column, TRUE);
2453 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
2456 renderer = gtk_cell_renderer_accel_new();
2457 g_signal_connect(G_OBJECT(renderer), "accel-cleared",
2458 G_CALLBACK(accel_store_cleared_cb), accel_store);
2459 g_signal_connect(G_OBJECT(renderer), "accel-edited",
2460 G_CALLBACK(accel_store_edited_cb), accel_store);
2463 g_object_set (renderer,
2465 "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
2468 column = gtk_tree_view_column_new_with_attributes(_("KEY"),
2473 gtk_tree_view_column_set_sort_column_id(column, AE_KEY);
2474 gtk_tree_view_column_set_resizable(column, TRUE);
2475 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
2477 renderer = gtk_cell_renderer_text_new();
2479 column = gtk_tree_view_column_new_with_attributes(_("Tooltip"),
2484 gtk_tree_view_column_set_sort_column_id(column, AE_TOOLTIP);
2485 gtk_tree_view_column_set_resizable(column, TRUE);
2486 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
2488 renderer = gtk_cell_renderer_text_new();
2490 column = gtk_tree_view_column_new_with_attributes("Accel",
2495 gtk_tree_view_column_set_sort_column_id(column, AE_ACCEL);
2496 gtk_tree_view_column_set_resizable(column, TRUE);
2497 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
2499 accel_store_populate();
2500 gtk_container_add(GTK_CONTAINER(scrolled), accel_view);
2501 gtk_widget_show(accel_view);
2503 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2505 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2506 G_CALLBACK(accel_default_cb), accel_view);
2507 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2508 gtk_widget_show(button);
2510 button = pref_button_new(NULL, NULL, _("Reset selected"), FALSE,
2511 G_CALLBACK(accel_reset_cb), accel_view);
2512 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2513 gtk_widget_show(button);
2517 static void config_tab_toolbar(GtkWidget *notebook)
2520 GtkWidget *toolbardata;
2523 lw = layout_window_list->data;
2525 vbox = scrolled_notebook_page(notebook, _("Toolbar"));
2527 toolbardata = toolbar_select_new(lw);
2528 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
2529 gtk_widget_show(vbox);
2533 static void config_tab_stereo(GtkWidget *notebook)
2541 GtkWidget *fs_button;
2542 vbox = scrolled_notebook_page(notebook, _("Stereo"));
2544 group = pref_group_new(vbox, FALSE, _("Windowed stereo mode"), GTK_ORIENTATION_VERTICAL);
2546 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2547 add_stereo_mode_menu(table, 0, 0, _("Windowed stereo mode"), options->stereo.mode, &c_options->stereo.mode, FALSE);
2549 table = pref_table_new(group, 2, 2, TRUE, FALSE);
2550 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
2551 pref_checkbox_new_int(box, _("Mirror left image"),
2552 options->stereo.mode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.mirror_left);
2553 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
2554 pref_checkbox_new_int(box, _("Flip left image"),
2555 options->stereo.mode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.flip_left);
2556 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
2557 pref_checkbox_new_int(box, _("Mirror right image"),
2558 options->stereo.mode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.mirror_right);
2559 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
2560 pref_checkbox_new_int(box, _("Flip right image"),
2561 options->stereo.mode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.flip_right);
2562 pref_checkbox_new_int(group, _("Swap left and right images"),
2563 options->stereo.mode & PR_STEREO_SWAP, &c_options->stereo.tmp.swap);
2564 pref_checkbox_new_int(group, _("Disable stereo mode on single image source"),
2565 options->stereo.mode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.temp_disable);
2567 group = pref_group_new(vbox, FALSE, _("Fullscreen stereo mode"), GTK_ORIENTATION_VERTICAL);
2568 fs_button = pref_checkbox_new_int(group, _("Use different settings for fullscreen"),
2569 options->stereo.enable_fsmode, &c_options->stereo.enable_fsmode);
2570 box2 = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2571 pref_checkbox_link_sensitivity(fs_button, box2);
2572 table = pref_table_new(box2, 2, 1, FALSE, FALSE);
2573 add_stereo_mode_menu(table, 0, 0, _("Fullscreen stereo mode"), options->stereo.fsmode, &c_options->stereo.fsmode, TRUE);
2574 table = pref_table_new(box2, 2, 2, TRUE, FALSE);
2575 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
2576 pref_checkbox_new_int(box, _("Mirror left image"),
2577 options->stereo.fsmode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.fs_mirror_left);
2578 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
2579 pref_checkbox_new_int(box, _("Flip left image"),
2580 options->stereo.fsmode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.fs_flip_left);
2581 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
2582 pref_checkbox_new_int(box, _("Mirror right image"),
2583 options->stereo.fsmode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.fs_mirror_right);
2584 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
2585 pref_checkbox_new_int(box, _("Flip right image"),
2586 options->stereo.fsmode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.fs_flip_right);
2587 pref_checkbox_new_int(box2, _("Swap left and right images"),
2588 options->stereo.fsmode & PR_STEREO_SWAP, &c_options->stereo.tmp.fs_swap);
2589 pref_checkbox_new_int(box2, _("Disable stereo mode on single image source"),
2590 options->stereo.fsmode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.fs_temp_disable);
2592 group2 = pref_group_new(box2, FALSE, _("Fixed position"), GTK_ORIENTATION_VERTICAL);
2593 table = pref_table_new(group2, 5, 3, FALSE, FALSE);
2594 pref_table_spin_new_int(table, 0, 0, _("Width"), NULL,
2595 1, 5000, 1, options->stereo.fixed_w, &c_options->stereo.fixed_w);
2596 pref_table_spin_new_int(table, 3, 0, _("Height"), NULL,
2597 1, 5000, 1, options->stereo.fixed_h, &c_options->stereo.fixed_h);
2598 pref_table_spin_new_int(table, 0, 1, _("Left X"), NULL,
2599 0, 5000, 1, options->stereo.fixed_x1, &c_options->stereo.fixed_x1);
2600 pref_table_spin_new_int(table, 3, 1, _("Left Y"), NULL,
2601 0, 5000, 1, options->stereo.fixed_y1, &c_options->stereo.fixed_y1);
2602 pref_table_spin_new_int(table, 0, 2, _("Right X"), NULL,
2603 0, 5000, 1, options->stereo.fixed_x2, &c_options->stereo.fixed_x2);
2604 pref_table_spin_new_int(table, 3, 2, _("Right Y"), NULL,
2605 0, 5000, 1, options->stereo.fixed_y2, &c_options->stereo.fixed_y2);
2609 /* Main preferences window */
2610 static void config_window_create(void)
2612 GtkWidget *win_vbox;
2614 GtkWidget *notebook;
2616 GtkWidget *ct_button;
2618 if (!c_options) c_options = init_options(NULL);
2620 configwindow = window_new(GTK_WINDOW_TOPLEVEL, "preferences", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Preferences"));
2621 gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
2622 g_signal_connect(G_OBJECT(configwindow), "delete_event",
2623 G_CALLBACK(config_window_delete), NULL);
2624 gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
2625 gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
2626 gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
2628 win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
2629 gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
2630 gtk_widget_show(win_vbox);
2632 notebook = gtk_notebook_new();
2633 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP);
2634 gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
2636 config_tab_general(notebook);
2637 config_tab_image(notebook);
2638 config_tab_windows(notebook);
2639 config_tab_accelerators(notebook);
2640 config_tab_files(notebook);
2641 config_tab_metadata(notebook);
2642 config_tab_color(notebook);
2643 config_tab_stereo(notebook);
2644 config_tab_behavior(notebook);
2645 config_tab_toolbar(notebook);
2647 hbox = gtk_hbutton_box_new();
2648 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
2649 gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
2650 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
2651 gtk_widget_show(hbox);
2653 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
2654 G_CALLBACK(config_window_help_cb), notebook);
2655 gtk_container_add(GTK_CONTAINER(hbox), button);
2656 gtk_widget_set_can_default(button, TRUE);
2657 gtk_widget_show(button);
2659 button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
2660 G_CALLBACK(config_window_ok_cb), NULL);
2661 gtk_container_add(GTK_CONTAINER(hbox), button);
2662 gtk_widget_set_can_default(button, TRUE);
2663 gtk_widget_grab_default(button);
2664 gtk_widget_show(button);
2668 button = pref_button_new(NULL, GTK_STOCK_SAVE, NULL, FALSE,
2669 G_CALLBACK(config_window_save_cb), NULL);
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_APPLY, NULL, FALSE,
2675 G_CALLBACK(config_window_apply_cb), NULL);
2676 gtk_container_add(GTK_CONTAINER(hbox), button);
2677 gtk_widget_set_can_default(button, TRUE);
2678 gtk_widget_show(button);
2680 button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
2681 G_CALLBACK(config_window_close_cb), NULL);
2682 gtk_container_add(GTK_CONTAINER(hbox), button);
2683 gtk_widget_set_can_default(button, TRUE);
2684 gtk_widget_show(button);
2686 if (!generic_dialog_get_alternative_button_order(configwindow))
2688 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
2691 gtk_widget_show(notebook);
2693 gtk_widget_show(configwindow);
2697 *-----------------------------------------------------------------------------
2698 * config window show (public)
2699 *-----------------------------------------------------------------------------
2702 void show_config_window(void)
2706 gtk_window_present(GTK_WINDOW(configwindow));
2710 config_window_create();
2719 void show_about_window(LayoutWindow *lw)
2721 GdkPixbuf *pixbuf_logo;
2722 GdkPixbuf *pixbuf_icon;
2723 gchar *authors[1000];
2728 #define LINE_LENGTH 1000
2729 gchar line[LINE_LENGTH];
2731 #if !GTK_CHECK_VERSION(3,0,0)
2734 copyright = g_string_new(NULL);
2735 path = g_build_filename(GQ_HELPDIR, "COPYING", NULL);
2736 fp = fopen(path, "r");
2739 while(fgets(line, LINE_LENGTH, fp))
2741 copyright = g_string_append(copyright, line);
2749 path = g_build_filename(GQ_HELPDIR, "AUTHORS", NULL);
2750 fp = fopen(path, "r");
2753 while(fgets(line, LINE_LENGTH, fp))
2755 /* get rid of ending \n from fgets */
2756 line[strlen(line) - 1] = '\0';
2757 authors[i_authors] = g_strdup(line);
2760 authors[i_authors] = NULL;
2765 comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
2766 "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
2768 pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
2769 pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
2770 gtk_show_about_dialog(GTK_WINDOW(lw->window),
2771 "title", _("About Geeqie"),
2773 "program-name", GQ_APPNAME,
2775 "logo", pixbuf_logo,
2776 "icon", pixbuf_icon,
2777 "website", GQ_WEBSITE,
2778 "website-label", "Website",
2779 "comments", comment,
2781 "translator-credits", _("translator-credits"),
2782 #if GTK_CHECK_VERSION(3,0,0)
2783 "license-type", GTK_LICENSE_GPL_2_0,
2785 "license", copyright->str,
2789 #if !GTK_CHECK_VERSION(3,0,0)
2790 g_string_free(copyright, TRUE);
2793 while(n < i_authors)
2803 static void image_overlay_set_text_colours()
2805 c_options->image_overlay.text_red = options->image_overlay.text_red;
2806 c_options->image_overlay.text_green = options->image_overlay.text_green;
2807 c_options->image_overlay.text_blue = options->image_overlay.text_blue;
2808 c_options->image_overlay.text_alpha = options->image_overlay.text_alpha;
2809 c_options->image_overlay.background_red = options->image_overlay.background_red;
2810 c_options->image_overlay.background_green = options->image_overlay.background_green;
2811 c_options->image_overlay.background_blue = options->image_overlay.background_blue;
2812 c_options->image_overlay.background_alpha = options->image_overlay.background_alpha;
2814 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */