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->image.scroll_reset_method = c_options->image.scroll_reset_method;
259 options->image.zoom_2pass = c_options->image.zoom_2pass;
260 options->image.fit_window_to_image = c_options->image.fit_window_to_image;
261 options->image.limit_window_size = c_options->image.limit_window_size;
262 options->image.zoom_to_fit_allow_expand = c_options->image.zoom_to_fit_allow_expand;
263 options->image.max_window_size = c_options->image.max_window_size;
264 options->image.limit_autofit_size = c_options->image.limit_autofit_size;
265 options->image.max_autofit_size = c_options->image.max_autofit_size;
266 options->image.max_enlargement_size = c_options->image.max_enlargement_size;
267 options->image.use_clutter_renderer = c_options->image.use_clutter_renderer;
268 options->progressive_key_scrolling = c_options->progressive_key_scrolling;
269 options->keyboard_scroll_step = c_options->keyboard_scroll_step;
271 if (options->thumbnails.max_width != c_options->thumbnails.max_width
272 || options->thumbnails.max_height != c_options->thumbnails.max_height
273 || options->thumbnails.quality != c_options->thumbnails.quality)
275 thumb_format_changed = TRUE;
277 options->thumbnails.max_width = c_options->thumbnails.max_width;
278 options->thumbnails.max_height = c_options->thumbnails.max_height;
279 options->thumbnails.quality = c_options->thumbnails.quality;
281 options->thumbnails.enable_caching = c_options->thumbnails.enable_caching;
282 options->thumbnails.cache_into_dirs = c_options->thumbnails.cache_into_dirs;
283 options->thumbnails.use_exif = c_options->thumbnails.use_exif;
284 options->thumbnails.spec_standard = c_options->thumbnails.spec_standard;
285 options->metadata.enable_metadata_dirs = c_options->metadata.enable_metadata_dirs;
286 options->file_filter.show_hidden_files = c_options->file_filter.show_hidden_files;
287 options->file_filter.show_parent_directory = c_options->file_filter.show_parent_directory;
288 options->file_filter.show_dot_directory = c_options->file_filter.show_dot_directory;
289 options->file_filter.disable_file_extension_checks = c_options->file_filter.disable_file_extension_checks;
291 options->file_sort.case_sensitive = c_options->file_sort.case_sensitive;
292 options->file_sort.natural = c_options->file_sort.natural;
293 options->file_filter.disable = c_options->file_filter.disable;
295 config_entry_to_option(sidecar_ext_entry, &options->sidecar.ext, NULL);
296 sidecar_ext_parse(options->sidecar.ext);
298 options->slideshow.random = c_options->slideshow.random;
299 options->slideshow.repeat = c_options->slideshow.repeat;
300 options->slideshow.delay = c_options->slideshow.delay;
302 options->mousewheel_scrolls = c_options->mousewheel_scrolls;
303 options->image_lm_click_nav = c_options->image_lm_click_nav;
304 options->image_l_click_video = c_options->image_l_click_video;
305 options->image_l_click_video_editor = c_options->image_l_click_video_editor;
307 options->file_ops.enable_in_place_rename = c_options->file_ops.enable_in_place_rename;
309 options->image.tile_cache_max = c_options->image.tile_cache_max;
310 options->image.image_cache_max = c_options->image.image_cache_max;
312 options->image.zoom_quality = c_options->image.zoom_quality;
314 options->image.zoom_increment = c_options->image.zoom_increment;
316 options->image.enable_read_ahead = c_options->image.enable_read_ahead;
319 if (options->image.use_custom_border_color != c_options->image.use_custom_border_color
320 || options->image.use_custom_border_color_in_fullscreen != c_options->image.use_custom_border_color_in_fullscreen
321 || !gdk_color_equal(&options->image.border_color, &c_options->image.border_color))
323 options->image.use_custom_border_color_in_fullscreen = c_options->image.use_custom_border_color_in_fullscreen;
324 options->image.use_custom_border_color = c_options->image.use_custom_border_color;
325 options->image.border_color = c_options->image.border_color;
326 layout_colors_update();
327 view_window_colors_update();
330 options->image.alpha_color_1 = c_options->image.alpha_color_1;
331 options->image.alpha_color_2 = c_options->image.alpha_color_2;
333 options->fullscreen.screen = c_options->fullscreen.screen;
334 options->fullscreen.clean_flip = c_options->fullscreen.clean_flip;
335 options->fullscreen.disable_saver = c_options->fullscreen.disable_saver;
336 options->fullscreen.above = c_options->fullscreen.above;
337 if (c_options->image_overlay.template_string)
338 set_image_overlay_template_string(&options->image_overlay.template_string,
339 c_options->image_overlay.template_string);
340 if (c_options->image_overlay.font)
341 set_image_overlay_font_string(&options->image_overlay.font,
342 c_options->image_overlay.font);
343 options->image_overlay.text_red = c_options->image_overlay.text_red;
344 options->image_overlay.text_green = c_options->image_overlay.text_green;
345 options->image_overlay.text_blue = c_options->image_overlay.text_blue;
346 options->image_overlay.text_alpha = c_options->image_overlay.text_alpha;
347 options->image_overlay.background_red = c_options->image_overlay.background_red;
348 options->image_overlay.background_green = c_options->image_overlay.background_green;
349 options->image_overlay.background_blue = c_options->image_overlay.background_blue;
350 options->image_overlay.background_alpha = c_options->image_overlay.background_alpha;
351 options->update_on_time_change = c_options->update_on_time_change;
352 options->image.exif_proof_rotate_enable = c_options->image.exif_proof_rotate_enable;
354 options->duplicates_similarity_threshold = c_options->duplicates_similarity_threshold;
355 options->rot_invariant_sim = c_options->rot_invariant_sim;
357 options->tree_descend_subdirs = c_options->tree_descend_subdirs;
359 options->view_dir_list_single_click_enter = c_options->view_dir_list_single_click_enter;
361 options->open_recent_list_maxsize = c_options->open_recent_list_maxsize;
362 options->dnd_icon_size = c_options->dnd_icon_size;
363 options->clipboard_selection = c_options->clipboard_selection;
365 options->metadata.save_in_image_file = c_options->metadata.save_in_image_file;
366 options->metadata.save_legacy_IPTC = c_options->metadata.save_legacy_IPTC;
367 options->metadata.warn_on_write_problems = c_options->metadata.warn_on_write_problems;
368 options->metadata.save_legacy_format = c_options->metadata.save_legacy_format;
369 options->metadata.sync_grouped_files = c_options->metadata.sync_grouped_files;
370 options->metadata.confirm_write = c_options->metadata.confirm_write;
371 options->metadata.sidecar_extended_name = c_options->metadata.sidecar_extended_name;
372 options->metadata.confirm_timeout = c_options->metadata.confirm_timeout;
373 options->metadata.confirm_after_timeout = c_options->metadata.confirm_after_timeout;
374 options->metadata.confirm_on_image_change = c_options->metadata.confirm_on_image_change;
375 options->metadata.confirm_on_dir_change = c_options->metadata.confirm_on_dir_change;
376 options->metadata.keywords_case_sensitive = c_options->metadata.keywords_case_sensitive;
377 options->metadata.write_orientation = c_options->metadata.write_orientation;
378 options->stereo.mode = (c_options->stereo.mode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
379 (c_options->stereo.tmp.mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
380 (c_options->stereo.tmp.flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
381 (c_options->stereo.tmp.mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
382 (c_options->stereo.tmp.flip_left ? PR_STEREO_FLIP_LEFT : 0) |
383 (c_options->stereo.tmp.swap ? PR_STEREO_SWAP : 0) |
384 (c_options->stereo.tmp.temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
385 options->stereo.fsmode = (c_options->stereo.fsmode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
386 (c_options->stereo.tmp.fs_mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
387 (c_options->stereo.tmp.fs_flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
388 (c_options->stereo.tmp.fs_mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
389 (c_options->stereo.tmp.fs_flip_left ? PR_STEREO_FLIP_LEFT : 0) |
390 (c_options->stereo.tmp.fs_swap ? PR_STEREO_SWAP : 0) |
391 (c_options->stereo.tmp.fs_temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
392 options->stereo.enable_fsmode = c_options->stereo.enable_fsmode;
393 options->stereo.fixed_w = c_options->stereo.fixed_w;
394 options->stereo.fixed_h = c_options->stereo.fixed_h;
395 options->stereo.fixed_x1 = c_options->stereo.fixed_x1;
396 options->stereo.fixed_y1 = c_options->stereo.fixed_y1;
397 options->stereo.fixed_x2 = c_options->stereo.fixed_x2;
398 options->stereo.fixed_y2 = c_options->stereo.fixed_y2;
400 options->info_keywords.height = c_options->info_keywords.height;
401 options->info_title.height = c_options->info_title.height;
402 options->info_comment.height = c_options->info_comment.height;
403 options->info_rating.height = c_options->info_rating.height;
406 set_debug_level(debug_c);
410 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
412 config_entry_to_option(color_profile_input_name_entry[i], &options->color_profile.input_name[i], NULL);
413 config_entry_to_option(color_profile_input_file_entry[i], &options->color_profile.input_file[i], NULL);
415 config_entry_to_option(color_profile_screen_file_entry, &options->color_profile.screen_file, NULL);
416 options->color_profile.use_x11_screen_profile = c_options->color_profile.use_x11_screen_profile;
417 if (options->color_profile.render_intent != c_options->color_profile.render_intent)
419 options->color_profile.render_intent = c_options->color_profile.render_intent;
424 image_options_sync();
429 layout_refresh(NULL);
432 if (accel_store) gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_apply_cb, NULL);
438 *-----------------------------------------------------------------------------
439 * config window main button callbacks (private)
440 *-----------------------------------------------------------------------------
443 static void config_window_close_cb(GtkWidget *widget, gpointer data)
445 gtk_widget_destroy(configwindow);
450 static void config_window_help_cb(GtkWidget *widget, gpointer data)
452 GtkWidget *notebook = data;
455 static gchar *html_section[] =
457 "GuideOptionsGeneral.html",
458 "GuideOptionsImage.html",
459 "GuideOptionsWindow.html",
460 "GuideOptionsKeyboard.html",
461 "GuideOptionsFiltering.html",
462 "GuideOptionsMetadata.html",
463 "GuideOptionsColor.html",
464 "GuideOptionsStereo.html",
465 "GuideOptionsBehavior.html",
466 "GuideOptionsToolbar.html"
469 i = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
470 help_window_show(html_section[i]);
473 static gboolean config_window_delete(GtkWidget *widget, GdkEventAny *event, gpointer data)
475 config_window_close_cb(NULL, NULL);
479 static void config_window_ok_cb(GtkWidget *widget, gpointer data)
481 config_window_apply();
482 config_window_close_cb(NULL, NULL);
485 static void config_window_apply_cb(GtkWidget *widget, gpointer data)
488 lw = layout_window_list->data;
490 config_window_apply();
491 layout_util_sync(lw);
494 static void config_window_save_cb(GtkWidget *widget, gpointer data)
496 config_window_apply();
497 save_options(options);
501 *-----------------------------------------------------------------------------
502 * config window setup (private)
503 *-----------------------------------------------------------------------------
506 static void quality_menu_cb(GtkWidget *combo, gpointer data)
510 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
514 *option = GDK_INTERP_NEAREST;
517 *option = GDK_INTERP_TILES;
520 *option = GDK_INTERP_BILINEAR;
523 *option = GDK_INTERP_HYPER;
528 static void clipboard_selection_menu_cb(GtkWidget *combo, gpointer data)
532 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
544 static void add_quality_menu(GtkWidget *table, gint column, gint row, const gchar *text,
545 guint option, guint *option_c)
552 pref_table_label(table, column, row, text, 0.0);
554 combo = gtk_combo_box_text_new();
556 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Nearest (worst, but fastest)"));
557 if (option == GDK_INTERP_NEAREST) current = 0;
558 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Tiles"));
559 if (option == GDK_INTERP_TILES) current = 1;
560 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Bilinear"));
561 if (option == GDK_INTERP_BILINEAR) current = 2;
562 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Hyper (best, but slowest)"));
563 if (option == GDK_INTERP_HYPER) current = 3;
565 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
567 g_signal_connect(G_OBJECT(combo), "changed",
568 G_CALLBACK(quality_menu_cb), option_c);
570 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
571 GTK_EXPAND | GTK_FILL, 0, 0, 0);
572 gtk_widget_show(combo);
575 static void add_clipboard_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
576 gint option, gint *option_c)
583 pref_table_label(table, column, row, text, 0.0);
585 combo = gtk_combo_box_text_new();
587 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("PRIMARY"));
588 if (option == PRIMARY) current = 0;
589 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("CLIPBOARD"));
590 if (option == CLIPBOARD) current = 1;
592 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
594 g_signal_connect(G_OBJECT(combo), "changed",
595 G_CALLBACK(clipboard_selection_menu_cb), option_c);
597 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
598 GTK_EXPAND | GTK_FILL, 0, 0, 0);
599 gtk_widget_show(combo);
602 static void thumb_size_menu_cb(GtkWidget *combo, gpointer data)
606 n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
609 if ((guint) n < sizeof(thumb_size_list) / sizeof(ThumbSize))
611 c_options->thumbnails.max_width = thumb_size_list[n].w;
612 c_options->thumbnails.max_height = thumb_size_list[n].h;
616 c_options->thumbnails.max_width = options->thumbnails.max_width;
617 c_options->thumbnails.max_height = options->thumbnails.max_height;
621 static void add_thumb_size_menu(GtkWidget *table, gint column, gint row, gchar *text)
627 c_options->thumbnails.max_width = options->thumbnails.max_width;
628 c_options->thumbnails.max_height = options->thumbnails.max_height;
630 pref_table_label(table, column, row, text, 0.0);
632 combo = gtk_combo_box_text_new();
635 for (i = 0; (guint) i < sizeof(thumb_size_list) / sizeof(ThumbSize); i++)
640 w = thumb_size_list[i].w;
641 h = thumb_size_list[i].h;
643 buf = g_strdup_printf("%d x %d", w, h);
644 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
647 if (w == options->thumbnails.max_width && h == options->thumbnails.max_height) current = i;
654 buf = g_strdup_printf("%s %d x %d", _("Custom"), options->thumbnails.max_width, options->thumbnails.max_height);
655 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
661 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
662 g_signal_connect(G_OBJECT(combo), "changed",
663 G_CALLBACK(thumb_size_menu_cb), NULL);
665 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
666 GTK_EXPAND | GTK_FILL, 0, 0, 0);
667 gtk_widget_show(combo);
670 static void stereo_mode_menu_cb(GtkWidget *combo, gpointer data)
674 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
678 *option = PR_STEREO_NONE;
681 *option = PR_STEREO_ANAGLYPH_RC;
684 *option = PR_STEREO_ANAGLYPH_GM;
687 *option = PR_STEREO_ANAGLYPH_YB;
690 *option = PR_STEREO_ANAGLYPH_GRAY_RC;
693 *option = PR_STEREO_ANAGLYPH_GRAY_GM;
696 *option = PR_STEREO_ANAGLYPH_GRAY_YB;
699 *option = PR_STEREO_ANAGLYPH_DB_RC;
702 *option = PR_STEREO_ANAGLYPH_DB_GM;
705 *option = PR_STEREO_ANAGLYPH_DB_YB;
708 *option = PR_STEREO_HORIZ;
711 *option = PR_STEREO_HORIZ | PR_STEREO_HALF;
714 *option = PR_STEREO_VERT;
717 *option = PR_STEREO_VERT | PR_STEREO_HALF;
720 *option = PR_STEREO_FIXED;
725 static void add_stereo_mode_menu(GtkWidget *table, gint column, gint row, const gchar *text,
726 gint option, gint *option_c, gboolean add_fixed)
733 pref_table_label(table, column, row, text, 0.0);
735 combo = gtk_combo_box_text_new();
737 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Single image"));
739 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Red-Cyan"));
740 if (option & PR_STEREO_ANAGLYPH_RC) current = 1;
741 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Green-Magenta"));
742 if (option & PR_STEREO_ANAGLYPH_GM) current = 2;
743 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Yellow-Blue"));
744 if (option & PR_STEREO_ANAGLYPH_YB) current = 3;
745 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Red-Cyan"));
746 if (option & PR_STEREO_ANAGLYPH_GRAY_RC) current = 4;
747 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Green-Magenta"));
748 if (option & PR_STEREO_ANAGLYPH_GRAY_GM) current = 5;
749 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Yellow-Blue"));
750 if (option & PR_STEREO_ANAGLYPH_GRAY_YB) current = 6;
751 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Red-Cyan"));
752 if (option & PR_STEREO_ANAGLYPH_DB_RC) current = 7;
753 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Green-Magenta"));
754 if (option & PR_STEREO_ANAGLYPH_DB_GM) current = 8;
755 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Yellow-Blue"));
756 if (option & PR_STEREO_ANAGLYPH_DB_YB) current = 9;
758 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side"));
759 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side Half size"));
760 if (option & PR_STEREO_HORIZ)
763 if (option & PR_STEREO_HALF) current = 11;
766 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom"));
767 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom Half size"));
768 if (option & PR_STEREO_VERT)
771 if (option & PR_STEREO_HALF) current = 13;
776 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Fixed position"));
777 if (option & PR_STEREO_FIXED) current = 14;
780 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
782 g_signal_connect(G_OBJECT(combo), "changed",
783 G_CALLBACK(stereo_mode_menu_cb), option_c);
785 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
786 GTK_EXPAND | GTK_FILL, 0, 0, 0);
787 gtk_widget_show(combo);
790 static void video_menu_cb(GtkWidget *combo, gpointer data)
792 gchar **option = data;
794 EditorDescription *ed = g_list_nth_data(editor_list_get(), gtk_combo_box_get_active(GTK_COMBO_BOX(combo)));
798 static void video_menu_populate(gpointer data, gpointer user_data)
800 GtkWidget *combo = user_data;
801 EditorDescription *ed = data;
803 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), ed->name);
806 static void add_video_menu(GtkWidget *table, gint column, gint row, const gchar *text,
807 gchar *option, gchar **option_c)
811 /* use lists since they are sorted */
812 GList *eds = editor_list_get();
816 pref_table_label(table, column, row, text, 0.0);
818 combo = gtk_combo_box_text_new();
819 g_list_foreach(eds,video_menu_populate,(gpointer)combo);
820 current = option ? g_list_index(eds,g_hash_table_lookup(editors,option)): -1;
822 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
824 g_signal_connect(G_OBJECT(combo), "changed",
825 G_CALLBACK(video_menu_cb), option_c);
827 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
828 GTK_EXPAND | GTK_FILL, 0, 0, 0);
829 gtk_widget_show(combo);
832 static void filter_store_populate(void)
836 if (!filter_store) return;
838 gtk_list_store_clear(filter_store);
840 work = filter_get_list();
849 gtk_list_store_append(filter_store, &iter);
850 gtk_list_store_set(filter_store, &iter, 0, fe, -1);
854 static void filter_store_ext_edit_cb(GtkCellRendererText *cell, gchar *path_str,
855 gchar *new_text, gpointer data)
857 GtkWidget *model = data;
858 FilterEntry *fe = data;
862 if (!new_text || strlen(new_text) < 1) return;
864 tpath = gtk_tree_path_new_from_string(path_str);
865 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
866 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
868 g_free(fe->extensions);
869 fe->extensions = g_strdup(new_text);
871 gtk_tree_path_free(tpath);
875 static void filter_store_class_edit_cb(GtkCellRendererText *cell, gchar *path_str,
876 gchar *new_text, gpointer data)
878 GtkWidget *model = data;
879 FilterEntry *fe = data;
884 if (!new_text || !new_text[0]) return;
886 tpath = gtk_tree_path_new_from_string(path_str);
887 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
888 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
890 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
892 if (strcmp(new_text, _(format_class_list[i])) == 0)
899 gtk_tree_path_free(tpath);
903 static void filter_store_desc_edit_cb(GtkCellRendererText *cell, gchar *path_str,
904 gchar *new_text, gpointer data)
906 GtkWidget *model = data;
911 if (!new_text || !new_text[0]) return;
913 tpath = gtk_tree_path_new_from_string(path_str);
914 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
915 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
917 g_free(fe->description);
918 fe->description = g_strdup(new_text);
920 gtk_tree_path_free(tpath);
923 static void filter_store_enable_cb(GtkCellRendererToggle *renderer,
924 gchar *path_str, gpointer data)
926 GtkWidget *model = data;
931 tpath = gtk_tree_path_new_from_string(path_str);
932 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
933 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
935 fe->enabled = !fe->enabled;
937 gtk_tree_path_free(tpath);
941 static void filter_store_writable_cb(GtkCellRendererToggle *renderer,
942 gchar *path_str, gpointer data)
944 GtkWidget *model = data;
949 tpath = gtk_tree_path_new_from_string(path_str);
950 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
951 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
953 fe->writable = !fe->writable;
954 if (fe->writable) fe->allow_sidecar = FALSE;
956 gtk_tree_path_free(tpath);
960 static void filter_store_sidecar_cb(GtkCellRendererToggle *renderer,
961 gchar *path_str, gpointer data)
963 GtkWidget *model = data;
968 tpath = gtk_tree_path_new_from_string(path_str);
969 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
970 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
972 fe->allow_sidecar = !fe->allow_sidecar;
973 if (fe->allow_sidecar) fe->writable = FALSE;
975 gtk_tree_path_free(tpath);
979 static void filter_set_func(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
980 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
984 gtk_tree_model_get(tree_model, iter, 0, &fe, -1);
986 switch (GPOINTER_TO_INT(data))
989 g_object_set(GTK_CELL_RENDERER(cell),
990 "active", fe->enabled, NULL);
993 g_object_set(GTK_CELL_RENDERER(cell),
994 "text", fe->extensions, NULL);
997 g_object_set(GTK_CELL_RENDERER(cell),
998 "text", fe->description, NULL);
1001 g_object_set(GTK_CELL_RENDERER(cell),
1002 "text", _(format_class_list[fe->file_class]), NULL);
1005 g_object_set(GTK_CELL_RENDERER(cell),
1006 "active", fe->writable, NULL);
1008 case FE_ALLOW_SIDECAR:
1009 g_object_set(GTK_CELL_RENDERER(cell),
1010 "active", fe->allow_sidecar, NULL);
1015 static gboolean filter_add_scroll(gpointer data)
1019 GtkCellRenderer *cell;
1020 GtkTreeViewColumn *column;
1021 GList *list_columns;
1026 rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(filter_store), NULL);
1027 path = gtk_tree_path_new_from_indices(rows-1, -1);
1029 list_columns = gtk_tree_view_get_columns(GTK_TREE_VIEW(data));
1031 column = g_list_nth(list_columns,i)->data;
1032 title = gtk_tree_view_column_get_title(GTK_TREE_VIEW_COLUMN(column));
1034 } while (strcmp(title, "Filter") !=0 );
1036 list_cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column));
1037 cell = g_list_last(list_cells)->data;
1039 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1040 path, column, FALSE, 0.0, 0.0 );
1041 gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(data),
1042 path, column, cell, TRUE);
1044 gtk_tree_path_free(path);
1045 g_list_free(list_cells);
1046 g_list_free(list_columns);
1051 static void filter_add_cb(GtkWidget *widget, gpointer data)
1053 filter_add_unique("description", ".new", FORMAT_CLASS_IMAGE, TRUE, FALSE, TRUE);
1054 filter_store_populate();
1056 g_idle_add((GSourceFunc)filter_add_scroll, data);
1059 static void filter_remove_cb(GtkWidget *widget, gpointer data)
1061 GtkWidget *filter_view = data;
1062 GtkTreeSelection *selection;
1066 if (!filter_store) return;
1067 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1068 if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) return;
1069 gtk_tree_model_get(GTK_TREE_MODEL(filter_store), &iter, 0, &fe, -1);
1072 filter_remove_entry(fe);
1074 filter_store_populate();
1077 static gboolean filter_default_ok_scroll(GtkTreeView *data)
1081 GtkTreeViewColumn *column;
1083 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(filter_store), &iter);
1084 path = gtk_tree_model_get_path(GTK_TREE_MODEL(filter_store), &iter);
1085 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1087 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1091 gtk_tree_path_free(path);
1096 static void filter_default_ok_cb(GenericDialog *gd, gpointer data)
1099 filter_add_defaults();
1101 filter_store_populate();
1103 g_idle_add((GSourceFunc)filter_default_ok_scroll, gd->data);
1106 static void dummy_cancel_cb(GenericDialog *gd, gpointer data)
1108 /* no op, only so cancel button appears */
1111 static void filter_default_cb(GtkWidget *widget, gpointer data)
1115 gd = generic_dialog_new(_("Reset filters"),
1116 "reset_filter", widget, TRUE,
1117 dummy_cancel_cb, data);
1118 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset filters"),
1119 _("This will reset the file filters to the defaults.\nContinue?"), TRUE);
1120 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, filter_default_ok_cb, TRUE);
1121 gtk_widget_show(gd->dialog);
1124 static void filter_disable_cb(GtkWidget *widget, gpointer data)
1126 GtkWidget *frame = data;
1128 gtk_widget_set_sensitive(frame,
1129 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
1132 static void safe_delete_view_cb(GtkWidget *widget, gpointer data)
1134 layout_set_path(NULL, gtk_entry_get_text(GTK_ENTRY(safe_delete_path_entry)));
1137 static void safe_delete_clear_ok_cb(GenericDialog *gd, gpointer data)
1139 file_util_trash_clear();
1142 static void safe_delete_clear_cb(GtkWidget *widget, gpointer data)
1146 gd = generic_dialog_new(_("Clear trash"),
1147 "clear_trash", widget, TRUE,
1148 dummy_cancel_cb, NULL);
1149 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear trash"),
1150 _("This will remove the trash contents."), FALSE);
1151 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, safe_delete_clear_ok_cb, TRUE);
1152 entry = gtk_entry_new();
1153 gtk_widget_set_can_focus(entry, FALSE);
1154 gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE);
1155 if (options->file_ops.safe_delete_path) gtk_entry_set_text(GTK_ENTRY(entry), options->file_ops.safe_delete_path);
1156 gtk_box_pack_start(GTK_BOX(gd->vbox), entry, FALSE, FALSE, 0);
1157 gtk_widget_show(entry);
1158 gtk_widget_show(gd->dialog);
1161 static void image_overlay_template_view_changed_cb(GtkWidget *widget, gpointer data)
1163 GtkWidget *pTextView;
1164 GtkTextBuffer *pTextBuffer;
1168 pTextView = GTK_WIDGET(data);
1170 pTextBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pTextView));
1171 gtk_text_buffer_get_start_iter(pTextBuffer, &iStart);
1172 gtk_text_buffer_get_end_iter(pTextBuffer, &iEnd);
1174 set_image_overlay_template_string(&c_options->image_overlay.template_string,
1175 gtk_text_buffer_get_text(pTextBuffer, &iStart, &iEnd, TRUE));
1178 static void image_overlay_default_template_ok_cb(GenericDialog *gd, gpointer data)
1180 GtkTextView *text_view = data;
1181 GtkTextBuffer *buffer;
1183 set_default_image_overlay_template_string(&options->image_overlay.template_string);
1184 if (!configwindow) return;
1186 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
1187 gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1190 static void image_overlay_default_template_cb(GtkWidget *widget, gpointer data)
1194 gd = generic_dialog_new(_("Reset image overlay template string"),
1195 "reset_image_overlay_template_string", widget, TRUE,
1196 dummy_cancel_cb, data);
1197 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset image overlay template string"),
1198 _("This will reset the image overlay template string to the default.\nContinue?"), TRUE);
1199 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, image_overlay_default_template_ok_cb, TRUE);
1200 gtk_widget_show(gd->dialog);
1203 static void image_overlay_help_cb(GtkWidget *widget, gpointer data)
1205 help_window_show("GuideOptionsWindow.html#OverlayScreenDisplay");
1208 static void image_overlay_set_font_cb(GtkWidget *widget, gpointer data)
1210 #if GTK_CHECK_VERSION(3,4,0)
1213 PangoFontDescription *font_desc;
1215 dialog = gtk_font_chooser_dialog_new("Image Overlay Font", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1216 gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), options->image_overlay.font);
1218 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1220 font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
1221 font = pango_font_description_to_string(font_desc);
1222 g_free(c_options->image_overlay.font);
1223 c_options->image_overlay.font = g_strdup(font);
1227 gtk_widget_destroy(dialog);
1231 font = gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget));
1232 c_options->image_overlay.font = g_strdup(font);
1236 static void image_overlay_set_text_colour_cb(GtkWidget *widget, gpointer data)
1239 #if GTK_CHECK_VERSION(3,4,0)
1242 dialog = gtk_color_chooser_dialog_new("Image Overlay Text Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1243 colour.red = options->image_overlay.text_red;
1244 colour.green = options->image_overlay.text_green;
1245 colour.blue = options->image_overlay.text_blue;
1246 colour.alpha = options->image_overlay.text_alpha;
1247 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1248 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1250 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1252 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1253 c_options->image_overlay.text_red = colour.red*255;
1254 c_options->image_overlay.text_green = colour.green*255;
1255 c_options->image_overlay.text_blue = colour.blue*255;
1256 c_options->image_overlay.text_alpha = colour.alpha*255;
1258 gtk_widget_destroy(dialog);
1261 GtkColorSelection *colorsel;
1263 dialog = gtk_color_selection_dialog_new("Image Overlay Text Colour");
1264 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1265 colour.red = options->image_overlay.text_red*257;
1266 colour.green = options->image_overlay.text_green*257;
1267 colour.blue = options->image_overlay.text_blue*257;
1268 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1269 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1270 gtk_color_selection_set_current_color(colorsel, &colour);
1271 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.text_alpha*257);
1273 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1275 gtk_color_selection_get_current_color(colorsel, &colour);
1276 c_options->image_overlay.text_red = colour.red/257;
1277 c_options->image_overlay.text_green = colour.green/257;
1278 c_options->image_overlay.text_blue = colour.blue/257;
1279 c_options->image_overlay.text_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1281 gtk_widget_destroy (dialog);
1286 static void image_overlay_set_background_colour_cb(GtkWidget *widget, gpointer data)
1289 #if GTK_CHECK_VERSION(3,4,0)
1292 dialog = gtk_color_chooser_dialog_new("Image Overlay Background Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1293 colour.red = options->image_overlay.background_red;
1294 colour.green = options->image_overlay.background_green;
1295 colour.blue = options->image_overlay.background_blue;
1296 colour.alpha = options->image_overlay.background_alpha;
1297 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1298 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1300 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1302 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1303 c_options->image_overlay.background_red = colour.red*255;
1304 c_options->image_overlay.background_green = colour.green*255;
1305 c_options->image_overlay.background_blue = colour.blue*255;
1306 c_options->image_overlay.background_alpha = colour.alpha*255;
1308 gtk_widget_destroy(dialog);
1311 GtkColorSelection *colorsel;
1313 dialog = gtk_color_selection_dialog_new("Image Overlay Background Colour");
1314 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1315 colour.red = options->image_overlay.background_red*257;
1316 colour.green = options->image_overlay.background_green*257;
1317 colour.blue = options->image_overlay.background_blue*257;
1318 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1319 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1320 gtk_color_selection_set_current_color(colorsel, &colour);
1321 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.background_alpha*257);
1323 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1325 gtk_color_selection_get_current_color(colorsel, &colour);
1326 c_options->image_overlay.background_red = colour.red/257;
1327 c_options->image_overlay.background_green = colour.green/257;
1328 c_options->image_overlay.background_blue = colour.blue/257;
1329 c_options->image_overlay.background_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1331 gtk_widget_destroy(dialog);
1335 static void accel_store_populate(void)
1338 GList *groups, *actions;
1340 const gchar *accel_path;
1344 if (!accel_store || !layout_window_list || !layout_window_list->data) return;
1346 gtk_tree_store_clear(accel_store);
1347 lw = layout_window_list->data; /* get the actions from the first window, it should not matter, they should be the same in all windows */
1349 g_assert(lw && lw->ui_manager);
1350 groups = gtk_ui_manager_get_action_groups(lw->ui_manager);
1353 actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
1356 action = GTK_ACTION(actions->data);
1357 accel_path = gtk_action_get_accel_path(action);
1358 if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
1360 gchar *label, *label2, *tooltip, *accel;
1361 g_object_get(action,
1362 "tooltip", &tooltip,
1366 if (pango_parse_markup(label, -1, '_', NULL, &label2, NULL, NULL) && label2)
1372 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1376 gtk_tree_store_append(accel_store, &iter, NULL);
1377 gtk_tree_store_set(accel_store, &iter,
1380 AE_TOOLTIP, tooltip ? tooltip : "",
1381 AE_ACCEL, accel_path,
1389 actions = actions->next;
1392 groups = groups->next;
1396 static void accel_store_cleared_cb(GtkCellRendererAccel *accel, gchar *path_string, gpointer user_data)
1401 static gboolean accel_remove_key_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1403 gchar *accel1 = data;
1408 gtk_tree_model_get(model, iter, AE_KEY, &accel2, -1);
1410 gtk_accelerator_parse(accel1, &key1.accel_key, &key1.accel_mods);
1411 gtk_accelerator_parse(accel2, &key2.accel_key, &key2.accel_mods);
1413 if (key1.accel_key == key2.accel_key && key1.accel_mods == key2.accel_mods)
1415 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1416 DEBUG_1("accelerator key '%s' is already used, removing.", accel1);
1425 static void accel_store_edited_cb(GtkCellRendererAccel *accel, gchar *path_string, guint accel_key, GdkModifierType accel_mods, guint hardware_keycode, gpointer user_data)
1427 GtkTreeModel *model = (GtkTreeModel *)accel_store;
1431 GtkAccelKey old_key, key;
1432 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
1434 gtk_tree_model_get_iter(model, &iter, path);
1435 gtk_tree_model_get(model, &iter, AE_ACCEL, &accel_path, -1);
1437 /* test if the accelerator can be stored without conflicts*/
1438 gtk_accel_map_lookup_entry(accel_path, &old_key);
1440 /* change the key and read it back (change may fail on keys hardcoded in gtk)*/
1441 gtk_accel_map_change_entry(accel_path, accel_key, accel_mods, TRUE);
1442 gtk_accel_map_lookup_entry(accel_path, &key);
1444 /* restore the original for now, the key will be really changed when the changes are confirmed */
1445 gtk_accel_map_change_entry(accel_path, old_key.accel_key, old_key.accel_mods, TRUE);
1447 acc = gtk_accelerator_name(key.accel_key, key.accel_mods);
1448 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, acc);
1450 gtk_tree_store_set(accel_store, &iter, AE_KEY, acc, -1);
1451 gtk_tree_path_free(path);
1455 static gboolean accel_default_scroll(GtkTreeView *data)
1459 GtkTreeViewColumn *column;
1461 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(accel_store), &iter);
1462 path = gtk_tree_model_get_path(GTK_TREE_MODEL(accel_store), &iter);
1463 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1465 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1469 gtk_tree_path_free(path);
1474 static void accel_default_cb(GtkWidget *widget, gpointer data)
1476 accel_store_populate();
1478 g_idle_add((GSourceFunc)accel_default_scroll, data);
1481 void accel_remove_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1483 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1486 void accel_reset_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1489 gchar *accel_path, *accel;
1491 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, -1);
1492 gtk_accel_map_lookup_entry(accel_path, &key);
1493 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1495 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, accel);
1497 gtk_tree_store_set(accel_store, iter, AE_KEY, accel, -1);
1502 static void accel_reset_cb(GtkWidget *widget, gpointer data)
1504 GtkTreeSelection *selection;
1506 if (!accel_store) return;
1507 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data));
1508 gtk_tree_selection_selected_foreach(selection, &accel_reset_selection, NULL);
1513 static GtkWidget *scrolled_notebook_page(GtkWidget *notebook, const gchar *title)
1517 GtkWidget *scrolled;
1518 GtkWidget *viewport;
1520 scrolled = gtk_scrolled_window_new(NULL, NULL);
1521 gtk_container_set_border_width(GTK_CONTAINER(scrolled), PREF_PAD_BORDER);
1522 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1523 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1524 label = gtk_label_new(title);
1525 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, label);
1526 gtk_widget_show(scrolled);
1528 viewport = gtk_viewport_new(NULL, NULL);
1529 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1530 gtk_container_add(GTK_CONTAINER(scrolled), viewport);
1531 gtk_widget_show(viewport);
1533 vbox = gtk_vbox_new(FALSE, 0);
1534 gtk_container_add(GTK_CONTAINER(viewport), vbox);
1535 gtk_widget_show(vbox);
1540 static void cache_standard_cb(GtkWidget *widget, gpointer data)
1542 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1544 c_options->thumbnails.spec_standard =TRUE;
1545 c_options->thumbnails.cache_into_dirs = FALSE;
1549 c_options->thumbnails.spec_standard =FALSE;
1553 static void cache_geeqie_cb(GtkWidget *widget, gpointer data)
1555 if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1557 c_options->thumbnails.spec_standard =TRUE;
1558 c_options->thumbnails.cache_into_dirs = FALSE;
1562 c_options->thumbnails.spec_standard =FALSE;
1566 static void cache_local_cb(GtkWidget *widget, gpointer data)
1568 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1570 c_options->thumbnails.cache_into_dirs = TRUE;
1571 c_options->thumbnails.spec_standard =FALSE;
1575 c_options->thumbnails.cache_into_dirs = FALSE;
1579 /* general options tab */
1580 static void config_tab_general(GtkWidget *notebook)
1585 GtkWidget *group_frame;
1586 GtkWidget *subgroup;
1588 GtkWidget *ct_button;
1591 gint hours, minutes, remainder;
1594 vbox = scrolled_notebook_page(notebook, _("General"));
1596 group = pref_group_new(vbox, FALSE, _("Thumbnails"), GTK_ORIENTATION_VERTICAL);
1598 table = pref_table_new(group, 2, 2, FALSE, FALSE);
1599 add_thumb_size_menu(table, 0, 0, _("Size:"));
1600 add_quality_menu(table, 0, 1, _("Quality:"), options->thumbnails.quality, &c_options->thumbnails.quality);
1602 ct_button = pref_checkbox_new_int(group, _("Cache thumbnails"),
1603 options->thumbnails.enable_caching, &c_options->thumbnails.enable_caching);
1605 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1606 pref_checkbox_link_sensitivity(ct_button, subgroup);
1608 group_frame = pref_frame_new(subgroup, TRUE, _("Use Geeqie thumbnail style and cache"),
1609 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1610 button = pref_radiobutton_new(group_frame, NULL, get_thumbnails_cache_dir(),
1611 !options->thumbnails.spec_standard,
1612 G_CALLBACK(cache_geeqie_cb), NULL);
1614 group_frame = pref_frame_new(subgroup, TRUE,
1615 _("Store thumbnails local to image folder (non-standard)"),
1616 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1617 pref_radiobutton_new(group_frame, button, "*/.thumbnails",
1618 options->thumbnails.cache_into_dirs,
1619 G_CALLBACK(cache_local_cb), NULL);
1621 group_frame = pref_frame_new(subgroup, TRUE,
1622 _("Use standard thumbnail style and cache, shared with other applications"),
1623 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1624 pref_radiobutton_new(group_frame, button, get_thumbnails_standard_cache_dir(),
1625 options->thumbnails.spec_standard,
1626 G_CALLBACK(cache_standard_cb), NULL);
1628 pref_checkbox_new_int(group, _("Use EXIF thumbnails when available (EXIF thumbnails may be outdated)"),
1629 options->thumbnails.use_exif, &c_options->thumbnails.use_exif);
1631 group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
1633 c_options->slideshow.delay = options->slideshow.delay;
1634 hours = options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
1635 remainder = options->slideshow.delay % (3600 * SLIDESHOW_SUBSECOND_PRECISION);
1636 minutes = remainder / (60 * SLIDESHOW_SUBSECOND_PRECISION);
1637 seconds = (gdouble)(remainder % (60 * SLIDESHOW_SUBSECOND_PRECISION)) /
1638 SLIDESHOW_SUBSECOND_PRECISION;
1640 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1642 spin = pref_spin_new(hbox, _("Delay between image change hrs:mins:secs.dec"), NULL,
1644 options->slideshow.delay ? hours : 0.0,
1645 G_CALLBACK(slideshow_delay_hours_cb), NULL);
1646 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1647 spin = pref_spin_new(hbox, ":" , NULL,
1649 options->slideshow.delay ? minutes: 0.0,
1650 G_CALLBACK(slideshow_delay_minutes_cb), NULL);
1651 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1652 spin = pref_spin_new(hbox, ":", NULL,
1653 SLIDESHOW_MIN_SECONDS, 59, 1.0, 1,
1654 options->slideshow.delay ? seconds : 10.0,
1655 G_CALLBACK(slideshow_delay_seconds_cb), NULL);
1656 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1658 pref_checkbox_new_int(group, _("Random"), options->slideshow.random, &c_options->slideshow.random);
1659 pref_checkbox_new_int(group, _("Repeat"), options->slideshow.repeat, &c_options->slideshow.repeat);
1661 group = pref_group_new(vbox, FALSE, _("Image loading and caching"), GTK_ORIENTATION_VERTICAL);
1663 pref_spin_new_int(group, _("Decoded image cache size (Mb):"), NULL,
1664 0, 99999, 1, options->image.image_cache_max, &c_options->image.image_cache_max);
1665 pref_checkbox_new_int(group, _("Preload next image"),
1666 options->image.enable_read_ahead, &c_options->image.enable_read_ahead);
1668 pref_checkbox_new_int(group, _("Refresh on file change"),
1669 options->update_on_time_change, &c_options->update_on_time_change);
1671 group = pref_group_new(vbox, FALSE, _("Info sidebar heights"), GTK_ORIENTATION_VERTICAL);
1672 pref_label_new(group, _("NOTE! Geeqie must be restarted for changes to take effect"));
1673 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1674 pref_spin_new_int(hbox, _("Keywords:"), NULL,
1676 options->info_keywords.height, &c_options->info_keywords.height);
1677 pref_spin_new_int(hbox, _("Title:"), NULL,
1679 options->info_title.height, &c_options->info_title.height);
1680 pref_spin_new_int(hbox, _("Comment:"), NULL,
1682 options->info_comment.height, &c_options->info_comment.height);
1683 pref_spin_new_int(hbox, _("Rating:"), NULL,
1685 options->info_rating.height, &c_options->info_rating.height);
1689 static void config_tab_image(GtkWidget *notebook)
1694 GtkWidget *ct_button;
1695 GtkWidget *enlargement_button;
1699 vbox = scrolled_notebook_page(notebook, _("Image"));
1701 group = pref_group_new(vbox, FALSE, _("Zoom"), GTK_ORIENTATION_VERTICAL);
1703 table = pref_table_new(group, 2, 1, FALSE, FALSE);
1704 add_quality_menu(table, 0, 0, _("Quality:"), options->image.zoom_quality, &c_options->image.zoom_quality);
1707 pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library"),
1708 options->image.use_clutter_renderer, &c_options->image.use_clutter_renderer);
1711 pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"),
1712 options->image.zoom_2pass, &c_options->image.zoom_2pass);
1714 c_options->image.zoom_increment = options->image.zoom_increment;
1715 spin = pref_spin_new(group, _("Zoom increment:"), NULL,
1716 0.01, 4.0, 0.01, 2, (gdouble)options->image.zoom_increment / 100.0,
1717 G_CALLBACK(zoom_increment_cb), NULL);
1718 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1720 group = pref_group_new(vbox, FALSE, _("Fit image to window"), GTK_ORIENTATION_VERTICAL);
1722 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1723 enlargement_button = pref_checkbox_new_int(hbox, _("Allow enlargement of image (max. size in %)"),
1724 options->image.zoom_to_fit_allow_expand, &c_options->image.zoom_to_fit_allow_expand);
1725 spin = pref_spin_new_int(hbox, NULL, NULL,
1727 options->image.max_enlargement_size, &c_options->image.max_enlargement_size);
1728 pref_checkbox_link_sensitivity(enlargement_button, spin);
1729 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."));
1731 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1732 ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (% of actual window):"),
1733 options->image.limit_autofit_size, &c_options->image.limit_autofit_size);
1734 spin = pref_spin_new_int(hbox, NULL, NULL,
1736 options->image.max_autofit_size, &c_options->image.max_autofit_size);
1737 pref_checkbox_link_sensitivity(ct_button, spin);
1738 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."));
1740 group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
1742 pref_checkbox_new_int(group, _("Use custom border color in window mode"),
1743 options->image.use_custom_border_color, &c_options->image.use_custom_border_color);
1745 pref_checkbox_new_int(group, _("Use custom border color in fullscreen mode"),
1746 options->image.use_custom_border_color_in_fullscreen, &c_options->image.use_custom_border_color_in_fullscreen);
1748 pref_color_button_new(group, _("Border color"), &options->image.border_color,
1749 G_CALLBACK(pref_color_button_set_cb), &c_options->image.border_color);
1751 c_options->image.border_color = options->image.border_color;
1753 pref_color_button_new(group, _("Alpha channel color 1"), &options->image.alpha_color_1,
1754 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_1);
1756 pref_color_button_new(group, _("Alpha channel color 2"), &options->image.alpha_color_2,
1757 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_2);
1759 c_options->image.alpha_color_1 = options->image.alpha_color_1;
1760 c_options->image.alpha_color_2 = options->image.alpha_color_2;
1762 group = pref_group_new(vbox, FALSE, _("Convenience"), GTK_ORIENTATION_VERTICAL);
1764 pref_checkbox_new_int(group, _("Auto rotate proofs using Exif information"),
1765 options->image.exif_proof_rotate_enable, &c_options->image.exif_proof_rotate_enable);
1769 static void config_tab_windows(GtkWidget *notebook)
1775 GtkWidget *ct_button;
1777 GtkWidget *image_overlay_template_view;
1778 GtkWidget *scrolled;
1779 GtkTextBuffer *buffer;
1781 vbox = scrolled_notebook_page(notebook, _("Windows"));
1783 group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
1785 ct_button = pref_checkbox_new_int(group, _("Remember window positions"),
1786 options->save_window_positions, &c_options->save_window_positions);
1788 button = pref_checkbox_new_int(group, _("Use saved window positions also for new windows"),
1789 options->use_saved_window_positions_for_new_windows, &c_options->use_saved_window_positions_for_new_windows);
1790 pref_checkbox_link_sensitivity(ct_button, button);
1792 pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
1793 options->tools_restore_state, &c_options->tools_restore_state);
1795 group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
1797 pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
1798 options->image.fit_window_to_image, &c_options->image.fit_window_to_image);
1800 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1801 ct_button = pref_checkbox_new_int(hbox, _("Limit size when auto-sizing window (%):"),
1802 options->image.limit_window_size, &c_options->image.limit_window_size);
1803 spin = pref_spin_new_int(hbox, NULL, NULL,
1805 options->image.max_window_size, &c_options->image.max_window_size);
1806 pref_checkbox_link_sensitivity(ct_button, spin);
1808 group = pref_group_new(vbox, FALSE, _("Full screen"), GTK_ORIENTATION_VERTICAL);
1810 c_options->fullscreen.screen = options->fullscreen.screen;
1811 c_options->fullscreen.above = options->fullscreen.above;
1812 hbox = fullscreen_prefs_selection_new(_("Location:"), &c_options->fullscreen.screen, &c_options->fullscreen.above);
1813 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
1814 gtk_widget_show(hbox);
1816 pref_checkbox_new_int(group, _("Smooth image flip"),
1817 options->fullscreen.clean_flip, &c_options->fullscreen.clean_flip);
1818 pref_checkbox_new_int(group, _("Disable screen saver"),
1819 options->fullscreen.disable_saver, &c_options->fullscreen.disable_saver);
1822 group = pref_group_new(vbox, FALSE, _("Overlay Screen Display"), GTK_ORIENTATION_VERTICAL);
1824 pref_label_new(group, _("Image overlay template"));
1826 scrolled = gtk_scrolled_window_new(NULL, NULL);
1827 gtk_widget_set_size_request(scrolled, 200, 150);
1828 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
1829 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1830 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1831 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 5);
1832 gtk_widget_show(scrolled);
1834 image_overlay_template_view = gtk_text_view_new();
1836 gtk_widget_set_tooltip_markup(image_overlay_template_view,
1837 _("<i>%name%</i> results in the filename of the picture.\n"
1838 "Also available: <i>%collection%</i>, <i>%number%</i>, <i>%total%</i>, <i>%date%</i>,\n"
1839 "<i>%size%</i> (filesize), <i>%width%</i>, <i>%height%</i>, <i>%res%</i> (resolution)\n"
1840 "To access exif data use the exif name, e. g. <i>%formatted.Camera%</i> is the formatted camera name,\n"
1841 "<i>%Exif.Photo.DateTimeOriginal%</i> the date of the original shot.\n"
1842 "<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"
1843 "If two or more variables are connected with the |-sign, it prints available variables with a separator.\n"
1844 "<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"
1845 "if there's no ISO information in the Exif data.\n"
1846 "If a line is empty, it is removed. This allows one to add lines that totally disappear when no data is available.\n"
1848 gtk_container_add(GTK_CONTAINER(scrolled), image_overlay_template_view);
1849 gtk_widget_show(image_overlay_template_view);
1851 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
1853 #if GTK_CHECK_VERSION(3,4,0)
1854 button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
1855 G_CALLBACK(image_overlay_set_font_cb), notebook);
1857 button = gtk_font_button_new();
1858 gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Image Overlay Font");
1859 gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->image_overlay.font);
1860 g_signal_connect(G_OBJECT(button), "font-set",
1861 G_CALLBACK(image_overlay_set_font_cb),NULL);
1863 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1864 gtk_widget_show(button);
1866 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Text"), FALSE,
1867 G_CALLBACK(image_overlay_set_text_colour_cb), NULL);
1868 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1869 gtk_widget_show(button);
1871 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Background"), FALSE,
1872 G_CALLBACK(image_overlay_set_background_colour_cb), NULL);
1873 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1874 gtk_widget_show(button);
1875 image_overlay_set_text_colours();
1877 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
1878 G_CALLBACK(image_overlay_default_template_cb), image_overlay_template_view);
1879 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1880 gtk_widget_show(button);
1882 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
1883 G_CALLBACK(image_overlay_help_cb), NULL);
1884 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1885 gtk_widget_show(button);
1887 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_overlay_template_view));
1888 if (options->image_overlay.template_string) gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1889 g_signal_connect(G_OBJECT(buffer), "changed",
1890 G_CALLBACK(image_overlay_template_view_changed_cb), image_overlay_template_view);
1895 static GtkTreeModel *create_class_model(void)
1897 GtkListStore *model;
1901 /* create list store */
1902 model = gtk_list_store_new(1, G_TYPE_STRING);
1903 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
1905 gtk_list_store_append(model, &iter);
1906 gtk_list_store_set(model, &iter, 0, _(format_class_list[i]), -1);
1908 return GTK_TREE_MODEL (model);
1913 static void config_tab_files(GtkWidget *notebook)
1920 GtkWidget *ct_button;
1921 GtkWidget *scrolled;
1922 GtkWidget *filter_view;
1923 GtkCellRenderer *renderer;
1924 GtkTreeSelection *selection;
1925 GtkTreeViewColumn *column;
1927 vbox = scrolled_notebook_page(notebook, _("Files"));
1929 group = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1931 pref_checkbox_new_int(group, _("Show hidden files or folders"),
1932 options->file_filter.show_hidden_files, &c_options->file_filter.show_hidden_files);
1933 pref_checkbox_new_int(group, _("Show parent folder (..)"),
1934 options->file_filter.show_parent_directory, &c_options->file_filter.show_parent_directory);
1935 pref_checkbox_new_int(group, _("Case sensitive sort"),
1936 options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
1937 pref_checkbox_new_int(group, _("Natural sort order"),
1938 options->file_sort.natural, &c_options->file_sort.natural);
1939 pref_checkbox_new_int(group, _("Disable file extension checks"),
1940 options->file_filter.disable_file_extension_checks, &c_options->file_filter.disable_file_extension_checks);
1942 ct_button = pref_checkbox_new_int(group, _("Disable File Filtering"),
1943 options->file_filter.disable, &c_options->file_filter.disable);
1946 group = pref_group_new(vbox, FALSE, _("Grouping sidecar extensions"), GTK_ORIENTATION_VERTICAL);
1948 sidecar_ext_entry = gtk_entry_new();
1949 gtk_entry_set_text(GTK_ENTRY(sidecar_ext_entry), options->sidecar.ext);
1950 gtk_box_pack_start(GTK_BOX(group), sidecar_ext_entry, FALSE, FALSE, 0);
1951 gtk_widget_show(sidecar_ext_entry);
1953 group = pref_group_new(vbox, TRUE, _("File types"), GTK_ORIENTATION_VERTICAL);
1955 frame = pref_group_parent(group);
1956 g_signal_connect(G_OBJECT(ct_button), "toggled",
1957 G_CALLBACK(filter_disable_cb), frame);
1958 gtk_widget_set_sensitive(frame, !options->file_filter.disable);
1960 scrolled = gtk_scrolled_window_new(NULL, NULL);
1961 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
1962 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
1963 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
1964 gtk_widget_show(scrolled);
1966 filter_store = gtk_list_store_new(1, G_TYPE_POINTER);
1967 filter_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(filter_store));
1968 g_object_unref(filter_store);
1969 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1970 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
1972 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), FALSE);
1974 column = gtk_tree_view_column_new();
1975 gtk_tree_view_column_set_title(column, _("Filter"));
1976 gtk_tree_view_column_set_resizable(column, TRUE);
1978 renderer = gtk_cell_renderer_toggle_new();
1979 g_signal_connect(G_OBJECT(renderer), "toggled",
1980 G_CALLBACK(filter_store_enable_cb), filter_store);
1981 gtk_tree_view_column_pack_start(column, renderer, FALSE);
1982 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
1983 GINT_TO_POINTER(FE_ENABLE), NULL);
1985 renderer = gtk_cell_renderer_text_new();
1986 g_signal_connect(G_OBJECT(renderer), "edited",
1987 G_CALLBACK(filter_store_ext_edit_cb), filter_store);
1988 gtk_tree_view_column_pack_start(column, renderer, TRUE);
1989 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
1990 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
1991 GINT_TO_POINTER(FE_EXTENSION), NULL);
1992 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
1994 column = gtk_tree_view_column_new();
1995 gtk_tree_view_column_set_title(column, _("Description"));
1996 gtk_tree_view_column_set_resizable(column, TRUE);
1997 gtk_tree_view_column_set_fixed_width(column, 200);
1998 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
2000 renderer = gtk_cell_renderer_text_new();
2001 g_signal_connect(G_OBJECT(renderer), "edited",
2002 G_CALLBACK(filter_store_desc_edit_cb), filter_store);
2003 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2004 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2005 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2006 GINT_TO_POINTER(FE_DESCRIPTION), NULL);
2007 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2009 column = gtk_tree_view_column_new();
2010 gtk_tree_view_column_set_title(column, _("Class"));
2011 gtk_tree_view_column_set_resizable(column, TRUE);
2012 renderer = gtk_cell_renderer_combo_new();
2013 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE,
2014 "model", create_class_model(),
2019 g_signal_connect(G_OBJECT(renderer), "edited",
2020 G_CALLBACK(filter_store_class_edit_cb), filter_store);
2021 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2022 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2023 GINT_TO_POINTER(FE_CLASS), NULL);
2024 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2026 column = gtk_tree_view_column_new();
2027 gtk_tree_view_column_set_title(column, _("Writable"));
2028 gtk_tree_view_column_set_resizable(column, FALSE);
2029 renderer = gtk_cell_renderer_toggle_new();
2030 g_signal_connect(G_OBJECT(renderer), "toggled",
2031 G_CALLBACK(filter_store_writable_cb), filter_store);
2032 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2033 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2034 GINT_TO_POINTER(FE_WRITABLE), NULL);
2035 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2037 column = gtk_tree_view_column_new();
2038 gtk_tree_view_column_set_title(column, _("Sidecar is allowed"));
2039 gtk_tree_view_column_set_resizable(column, FALSE);
2040 renderer = gtk_cell_renderer_toggle_new();
2041 g_signal_connect(G_OBJECT(renderer), "toggled",
2042 G_CALLBACK(filter_store_sidecar_cb), filter_store);
2043 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2044 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2045 GINT_TO_POINTER(FE_ALLOW_SIDECAR), NULL);
2046 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2049 filter_store_populate();
2050 gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
2051 gtk_widget_show(filter_view);
2053 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2055 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2056 G_CALLBACK(filter_default_cb), filter_view);
2057 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2058 gtk_widget_show(button);
2060 button = pref_button_new(NULL, GTK_STOCK_REMOVE, NULL, FALSE,
2061 G_CALLBACK(filter_remove_cb), filter_view);
2062 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2063 gtk_widget_show(button);
2065 button = pref_button_new(NULL, GTK_STOCK_ADD, NULL, FALSE,
2066 G_CALLBACK(filter_add_cb), filter_view);
2067 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2068 gtk_widget_show(button);
2072 static void config_tab_metadata(GtkWidget *notebook)
2077 GtkWidget *ct_button;
2081 vbox = scrolled_notebook_page(notebook, _("Metadata"));
2084 group = pref_group_new(vbox, FALSE, _("Metadata writing process"), GTK_ORIENTATION_VERTICAL);
2086 label = pref_label_new(group, _("Warning: Geeqie is built without Exiv2. Some options are disabled."));
2088 label = pref_label_new(group, _("Metadata are written in the following order. The process ends after first success."));
2089 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2091 ct_button = pref_checkbox_new_int(group, _("1) Save metadata in image files, or sidecar files, according to the XMP standard"),
2092 options->metadata.save_in_image_file, &c_options->metadata.save_in_image_file);
2094 gtk_widget_set_sensitive(ct_button, FALSE);
2097 pref_checkbox_new_int(group, _("2) Save metadata in '.metadata' folder, local to image folder (non-standard)"),
2098 options->metadata.enable_metadata_dirs, &c_options->metadata.enable_metadata_dirs);
2100 text = g_strdup_printf(_("3) Save metadata in Geeqie private directory '%s'"), get_metadata_cache_dir());
2101 label = pref_label_new(group, text);
2102 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2103 gtk_misc_set_padding(GTK_MISC(label), 22, 0);
2106 group = pref_group_new(vbox, FALSE, _("Step 1: Write to image files"), GTK_ORIENTATION_VERTICAL);
2108 gtk_widget_set_sensitive(group, FALSE);
2111 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2112 pref_checkbox_link_sensitivity(ct_button, hbox);
2114 pref_checkbox_new_int(hbox, _("Store metadata also in legacy IPTC tags (converted according to IPTC4XMP standard)"),
2115 options->metadata.save_legacy_IPTC, &c_options->metadata.save_legacy_IPTC);
2117 pref_checkbox_new_int(hbox, _("Warn if the image files are unwritable"),
2118 options->metadata.warn_on_write_problems, &c_options->metadata.warn_on_write_problems);
2120 pref_checkbox_new_int(hbox, _("Ask before writing to image files"),
2121 options->metadata.confirm_write, &c_options->metadata.confirm_write);
2123 pref_checkbox_new_int(hbox, _("Create sidecar files named image.ext.xmp (as opposed to image.xmp)"),
2124 options->metadata.sidecar_extended_name, &c_options->metadata.sidecar_extended_name);
2126 group = pref_group_new(vbox, FALSE, _("Step 2 and 3: write to Geeqie private files"), GTK_ORIENTATION_VERTICAL);
2128 gtk_widget_set_sensitive(group, FALSE);
2131 pref_checkbox_new_int(group, _("Use GQview legacy metadata format (supports only keywords and comments) instead of XMP"),
2132 options->metadata.save_legacy_format, &c_options->metadata.save_legacy_format);
2135 group = pref_group_new(vbox, FALSE, _("Miscellaneous"), GTK_ORIENTATION_VERTICAL);
2136 pref_checkbox_new_int(group, _("Write the same description tags (keywords, comment, etc.) to all grouped sidecars"),
2137 options->metadata.sync_grouped_files, &c_options->metadata.sync_grouped_files);
2139 pref_checkbox_new_int(group, _("Allow keywords to differ only in case"),
2140 options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
2142 ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"),
2143 options->metadata.write_orientation, &c_options->metadata.write_orientation);
2145 gtk_widget_set_sensitive(ct_button, FALSE);
2148 group = pref_group_new(vbox, FALSE, _("Auto-save options"), GTK_ORIENTATION_VERTICAL);
2150 ct_button = pref_checkbox_new_int(group, _("Write metadata after timeout"),
2151 options->metadata.confirm_after_timeout, &c_options->metadata.confirm_after_timeout);
2153 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2154 pref_checkbox_link_sensitivity(ct_button, hbox);
2156 pref_spin_new_int(hbox, _("Timeout (seconds):"), NULL, 0, 900, 1,
2157 options->metadata.confirm_timeout, &c_options->metadata.confirm_timeout);
2159 pref_checkbox_new_int(group, _("Write metadata on image change"),
2160 options->metadata.confirm_on_image_change, &c_options->metadata.confirm_on_image_change);
2162 pref_checkbox_new_int(group, _("Write metadata on directory change"),
2163 options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
2168 static void intent_menu_cb(GtkWidget *combo, gpointer data)
2170 gint *option = data;
2172 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
2176 *option = INTENT_PERCEPTUAL;
2179 *option = INTENT_RELATIVE_COLORIMETRIC;
2182 *option = INTENT_SATURATION;
2185 *option = INTENT_ABSOLUTE_COLORIMETRIC;
2190 static void add_intent_menu(GtkWidget *table, gint column, gint row, const gchar *text,
2191 gint option, gint *option_c)
2198 pref_table_label(table, column, row, text, 0.0);
2200 combo = gtk_combo_box_text_new();
2202 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Perceptual"));
2203 if (option == INTENT_PERCEPTUAL) current = 0;
2204 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Relative Colorimetric"));
2205 if (option == INTENT_RELATIVE_COLORIMETRIC) current = 1;
2206 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Saturation"));
2207 if (option == INTENT_SATURATION) current = 2;
2208 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Absolute Colorimetric"));
2209 if (option == INTENT_ABSOLUTE_COLORIMETRIC) current = 3;
2211 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
2213 gtk_widget_set_tooltip_text(combo,"Refer to the lcms documentation for the defaults used when the selected Intent is not available");
2215 g_signal_connect(G_OBJECT(combo), "changed",
2216 G_CALLBACK(intent_menu_cb), option_c);
2218 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
2219 GTK_EXPAND | GTK_FILL, 0, 0, 0);
2220 gtk_widget_show(combo);
2224 static void config_tab_color(GtkWidget *notebook)
2233 vbox = scrolled_notebook_page(notebook, _("Color management"));
2235 group = pref_group_new(vbox, FALSE, _("Input profiles"), GTK_ORIENTATION_VERTICAL);
2237 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
2240 table = pref_table_new(group, 3, COLOR_PROFILE_INPUTS + 1, FALSE, FALSE);
2241 gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
2243 label = pref_table_label(table, 0, 0, _("Type"), 0.0);
2244 pref_label_bold(label, TRUE, FALSE);
2246 label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
2247 pref_label_bold(label, TRUE, FALSE);
2249 label = pref_table_label(table, 2, 0, _("File"), 0.0);
2250 pref_label_bold(label, TRUE, FALSE);
2252 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
2257 buf = g_strdup_printf(_("Input %d:"), i + COLOR_PROFILE_FILE);
2258 pref_table_label(table, 0, i + 1, buf, 1.0);
2261 entry = gtk_entry_new();
2262 gtk_entry_set_max_length(GTK_ENTRY(entry), EDITOR_NAME_MAX_LENGTH);
2263 if (options->color_profile.input_name[i])
2265 gtk_entry_set_text(GTK_ENTRY(entry), options->color_profile.input_name[i]);
2267 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, i + 1, i + 2,
2268 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2269 gtk_widget_show(entry);
2270 color_profile_input_name_entry[i] = entry;
2272 tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, NULL);
2273 tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
2274 gtk_widget_set_size_request(entry, 160, -1);
2275 gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
2276 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2277 gtk_widget_show(tabcomp);
2278 color_profile_input_file_entry[i] = entry;
2281 group = pref_group_new(vbox, FALSE, _("Screen profile"), GTK_ORIENTATION_VERTICAL);
2283 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
2285 pref_checkbox_new_int(group, _("Use system screen profile if available"),
2286 options->color_profile.use_x11_screen_profile, &c_options->color_profile.use_x11_screen_profile);
2288 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2290 pref_table_label(table, 0, 0, _("Screen:"), 1.0);
2291 tabcomp = tab_completion_new(&color_profile_screen_file_entry,
2292 options->color_profile.screen_file, NULL, NULL);
2293 tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
2294 gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
2296 add_intent_menu(table, 0, 1, _("Render Intent:"), options->color_profile.render_intent, &c_options->color_profile.render_intent);
2298 gtk_table_attach(GTK_TABLE(table), tabcomp, 1, 2,
2300 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2302 gtk_widget_show(tabcomp);
2305 /* advanced entry tab */
2306 static void config_tab_behavior(GtkWidget *notebook)
2313 GtkWidget *ct_button;
2317 vbox = scrolled_notebook_page(notebook, _("Behavior"));
2319 group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
2321 pref_checkbox_new_int(group, _("Confirm file delete"),
2322 options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
2323 pref_checkbox_new_int(group, _("Enable Delete key"),
2324 options->file_ops.enable_delete_key, &c_options->file_ops.enable_delete_key);
2326 ct_button = pref_checkbox_new_int(group, _("Safe delete"),
2327 options->file_ops.safe_delete_enable, &c_options->file_ops.safe_delete_enable);
2329 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2330 pref_checkbox_link_sensitivity(ct_button, hbox);
2332 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
2333 pref_label_new(hbox, _("Folder:"));
2335 tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL);
2336 tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
2337 gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
2338 gtk_widget_show(tabcomp);
2340 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2341 pref_checkbox_link_sensitivity(ct_button, hbox);
2343 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
2344 spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MB"),
2345 0, 2048, 1, options->file_ops.safe_delete_folder_maxsize, &c_options->file_ops.safe_delete_folder_maxsize);
2346 gtk_widget_set_tooltip_markup(spin, _("Set to 0 for unlimited size"));
2347 button = pref_button_new(NULL, NULL, _("View"), FALSE,
2348 G_CALLBACK(safe_delete_view_cb), NULL);
2349 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2350 gtk_widget_show(button);
2352 button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
2353 G_CALLBACK(safe_delete_clear_cb), NULL);
2354 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2355 gtk_widget_show(button);
2358 group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
2360 pref_checkbox_new_int(group, _("Descend folders in tree view"),
2361 options->tree_descend_subdirs, &c_options->tree_descend_subdirs);
2363 pref_checkbox_new_int(group, _("In place renaming"),
2364 options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
2366 pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
2367 options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
2369 pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
2370 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
2372 pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
2373 16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
2375 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2376 add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
2378 group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
2380 pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
2381 options->progressive_key_scrolling, &c_options->progressive_key_scrolling);
2382 pref_spin_new_int(group, _("Keyboard scrolling step multiplier:"), NULL,
2383 1, 32, 1, options->keyboard_scroll_step, (int *)&c_options->keyboard_scroll_step);
2384 pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
2385 options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
2386 pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
2387 options->image_lm_click_nav, &c_options->image_lm_click_nav);
2388 pref_checkbox_new_int(group, _("Play video by left click on image"),
2389 options->image_l_click_video, &c_options->image_l_click_video);
2390 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2391 add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
2395 group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
2397 pref_spin_new_int(group, _("Debug level:"), NULL,
2398 DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
2400 pref_checkbox_new_int(group, _("Timer data"),
2401 options->log_window.timer_data, &c_options->log_window.timer_data);
2403 pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
2404 1, 99999, 1, options->log_window_lines, &options->log_window_lines);
2408 /* accelerators tab */
2409 static void config_tab_accelerators(GtkWidget *notebook)
2415 GtkWidget *scrolled;
2416 GtkWidget *accel_view;
2417 GtkCellRenderer *renderer;
2418 GtkTreeSelection *selection;
2419 GtkTreeViewColumn *column;
2421 vbox = scrolled_notebook_page(notebook, _("Keyboard"));
2423 group = pref_group_new(vbox, TRUE, _("Accelerators"), GTK_ORIENTATION_VERTICAL);
2425 scrolled = gtk_scrolled_window_new(NULL, NULL);
2426 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2427 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2428 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2429 gtk_widget_show(scrolled);
2431 accel_store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
2433 accel_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(accel_store));
2434 g_object_unref(accel_store);
2435 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(accel_view));
2436 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
2438 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(accel_view), FALSE);
2440 renderer = gtk_cell_renderer_text_new();
2442 column = gtk_tree_view_column_new_with_attributes(_("Action"),
2447 gtk_tree_view_column_set_sort_column_id(column, AE_ACTION);
2448 gtk_tree_view_column_set_resizable(column, TRUE);
2449 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
2452 renderer = gtk_cell_renderer_accel_new();
2453 g_signal_connect(G_OBJECT(renderer), "accel-cleared",
2454 G_CALLBACK(accel_store_cleared_cb), accel_store);
2455 g_signal_connect(G_OBJECT(renderer), "accel-edited",
2456 G_CALLBACK(accel_store_edited_cb), accel_store);
2459 g_object_set (renderer,
2461 "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
2464 column = gtk_tree_view_column_new_with_attributes(_("KEY"),
2469 gtk_tree_view_column_set_sort_column_id(column, AE_KEY);
2470 gtk_tree_view_column_set_resizable(column, TRUE);
2471 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
2473 renderer = gtk_cell_renderer_text_new();
2475 column = gtk_tree_view_column_new_with_attributes(_("Tooltip"),
2480 gtk_tree_view_column_set_sort_column_id(column, AE_TOOLTIP);
2481 gtk_tree_view_column_set_resizable(column, TRUE);
2482 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
2484 renderer = gtk_cell_renderer_text_new();
2486 column = gtk_tree_view_column_new_with_attributes("Accel",
2491 gtk_tree_view_column_set_sort_column_id(column, AE_ACCEL);
2492 gtk_tree_view_column_set_resizable(column, TRUE);
2493 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
2495 accel_store_populate();
2496 gtk_container_add(GTK_CONTAINER(scrolled), accel_view);
2497 gtk_widget_show(accel_view);
2499 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2501 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2502 G_CALLBACK(accel_default_cb), accel_view);
2503 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2504 gtk_widget_show(button);
2506 button = pref_button_new(NULL, NULL, _("Reset selected"), FALSE,
2507 G_CALLBACK(accel_reset_cb), accel_view);
2508 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2509 gtk_widget_show(button);
2513 static void config_tab_toolbar(GtkWidget *notebook)
2516 GtkWidget *toolbardata;
2519 lw = layout_window_list->data;
2521 vbox = scrolled_notebook_page(notebook, _("Toolbar"));
2523 toolbardata = toolbar_select_new(lw);
2524 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
2525 gtk_widget_show(vbox);
2529 static void config_tab_stereo(GtkWidget *notebook)
2537 GtkWidget *fs_button;
2538 vbox = scrolled_notebook_page(notebook, _("Stereo"));
2540 group = pref_group_new(vbox, FALSE, _("Windowed stereo mode"), GTK_ORIENTATION_VERTICAL);
2542 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2543 add_stereo_mode_menu(table, 0, 0, _("Windowed stereo mode"), options->stereo.mode, &c_options->stereo.mode, FALSE);
2545 table = pref_table_new(group, 2, 2, TRUE, FALSE);
2546 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
2547 pref_checkbox_new_int(box, _("Mirror left image"),
2548 options->stereo.mode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.mirror_left);
2549 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
2550 pref_checkbox_new_int(box, _("Flip left image"),
2551 options->stereo.mode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.flip_left);
2552 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
2553 pref_checkbox_new_int(box, _("Mirror right image"),
2554 options->stereo.mode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.mirror_right);
2555 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
2556 pref_checkbox_new_int(box, _("Flip right image"),
2557 options->stereo.mode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.flip_right);
2558 pref_checkbox_new_int(group, _("Swap left and right images"),
2559 options->stereo.mode & PR_STEREO_SWAP, &c_options->stereo.tmp.swap);
2560 pref_checkbox_new_int(group, _("Disable stereo mode on single image source"),
2561 options->stereo.mode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.temp_disable);
2563 group = pref_group_new(vbox, FALSE, _("Fullscreen stereo mode"), GTK_ORIENTATION_VERTICAL);
2564 fs_button = pref_checkbox_new_int(group, _("Use different settings for fullscreen"),
2565 options->stereo.enable_fsmode, &c_options->stereo.enable_fsmode);
2566 box2 = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2567 pref_checkbox_link_sensitivity(fs_button, box2);
2568 table = pref_table_new(box2, 2, 1, FALSE, FALSE);
2569 add_stereo_mode_menu(table, 0, 0, _("Fullscreen stereo mode"), options->stereo.fsmode, &c_options->stereo.fsmode, TRUE);
2570 table = pref_table_new(box2, 2, 2, TRUE, FALSE);
2571 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
2572 pref_checkbox_new_int(box, _("Mirror left image"),
2573 options->stereo.fsmode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.fs_mirror_left);
2574 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
2575 pref_checkbox_new_int(box, _("Flip left image"),
2576 options->stereo.fsmode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.fs_flip_left);
2577 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
2578 pref_checkbox_new_int(box, _("Mirror right image"),
2579 options->stereo.fsmode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.fs_mirror_right);
2580 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
2581 pref_checkbox_new_int(box, _("Flip right image"),
2582 options->stereo.fsmode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.fs_flip_right);
2583 pref_checkbox_new_int(box2, _("Swap left and right images"),
2584 options->stereo.fsmode & PR_STEREO_SWAP, &c_options->stereo.tmp.fs_swap);
2585 pref_checkbox_new_int(box2, _("Disable stereo mode on single image source"),
2586 options->stereo.fsmode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.fs_temp_disable);
2588 group2 = pref_group_new(box2, FALSE, _("Fixed position"), GTK_ORIENTATION_VERTICAL);
2589 table = pref_table_new(group2, 5, 3, FALSE, FALSE);
2590 pref_table_spin_new_int(table, 0, 0, _("Width"), NULL,
2591 1, 5000, 1, options->stereo.fixed_w, &c_options->stereo.fixed_w);
2592 pref_table_spin_new_int(table, 3, 0, _("Height"), NULL,
2593 1, 5000, 1, options->stereo.fixed_h, &c_options->stereo.fixed_h);
2594 pref_table_spin_new_int(table, 0, 1, _("Left X"), NULL,
2595 0, 5000, 1, options->stereo.fixed_x1, &c_options->stereo.fixed_x1);
2596 pref_table_spin_new_int(table, 3, 1, _("Left Y"), NULL,
2597 0, 5000, 1, options->stereo.fixed_y1, &c_options->stereo.fixed_y1);
2598 pref_table_spin_new_int(table, 0, 2, _("Right X"), NULL,
2599 0, 5000, 1, options->stereo.fixed_x2, &c_options->stereo.fixed_x2);
2600 pref_table_spin_new_int(table, 3, 2, _("Right Y"), NULL,
2601 0, 5000, 1, options->stereo.fixed_y2, &c_options->stereo.fixed_y2);
2605 /* Main preferences window */
2606 static void config_window_create(void)
2608 GtkWidget *win_vbox;
2610 GtkWidget *notebook;
2612 GtkWidget *ct_button;
2614 if (!c_options) c_options = init_options(NULL);
2616 configwindow = window_new(GTK_WINDOW_TOPLEVEL, "preferences", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Preferences"));
2617 gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
2618 g_signal_connect(G_OBJECT(configwindow), "delete_event",
2619 G_CALLBACK(config_window_delete), NULL);
2620 gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
2621 gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
2622 gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
2624 win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
2625 gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
2626 gtk_widget_show(win_vbox);
2628 notebook = gtk_notebook_new();
2629 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP);
2630 gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
2632 config_tab_general(notebook);
2633 config_tab_image(notebook);
2634 config_tab_windows(notebook);
2635 config_tab_accelerators(notebook);
2636 config_tab_files(notebook);
2637 config_tab_metadata(notebook);
2638 config_tab_color(notebook);
2639 config_tab_stereo(notebook);
2640 config_tab_behavior(notebook);
2641 config_tab_toolbar(notebook);
2643 hbox = gtk_hbutton_box_new();
2644 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
2645 gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
2646 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
2647 gtk_widget_show(hbox);
2649 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
2650 G_CALLBACK(config_window_help_cb), notebook);
2651 gtk_container_add(GTK_CONTAINER(hbox), button);
2652 gtk_widget_set_can_default(button, TRUE);
2653 gtk_widget_show(button);
2655 button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
2656 G_CALLBACK(config_window_ok_cb), NULL);
2657 gtk_container_add(GTK_CONTAINER(hbox), button);
2658 gtk_widget_set_can_default(button, TRUE);
2659 gtk_widget_grab_default(button);
2660 gtk_widget_show(button);
2664 button = pref_button_new(NULL, GTK_STOCK_SAVE, NULL, FALSE,
2665 G_CALLBACK(config_window_save_cb), NULL);
2666 gtk_container_add(GTK_CONTAINER(hbox), button);
2667 gtk_widget_set_can_default(button, TRUE);
2668 gtk_widget_show(button);
2670 button = pref_button_new(NULL, GTK_STOCK_APPLY, NULL, FALSE,
2671 G_CALLBACK(config_window_apply_cb), NULL);
2672 gtk_container_add(GTK_CONTAINER(hbox), button);
2673 gtk_widget_set_can_default(button, TRUE);
2674 gtk_widget_show(button);
2676 button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
2677 G_CALLBACK(config_window_close_cb), NULL);
2678 gtk_container_add(GTK_CONTAINER(hbox), button);
2679 gtk_widget_set_can_default(button, TRUE);
2680 gtk_widget_show(button);
2682 if (!generic_dialog_get_alternative_button_order(configwindow))
2684 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
2687 gtk_widget_show(notebook);
2689 gtk_widget_show(configwindow);
2693 *-----------------------------------------------------------------------------
2694 * config window show (public)
2695 *-----------------------------------------------------------------------------
2698 void show_config_window(void)
2702 gtk_window_present(GTK_WINDOW(configwindow));
2706 config_window_create();
2715 void show_about_window(LayoutWindow *lw)
2717 GdkPixbuf *pixbuf_logo;
2718 GdkPixbuf *pixbuf_icon;
2719 gchar *authors[1000];
2724 #define LINE_LENGTH 1000
2725 gchar line[LINE_LENGTH];
2727 #if !GTK_CHECK_VERSION(3,0,0)
2730 copyright = g_string_new(NULL);
2731 path = g_build_filename(GQ_HELPDIR, "COPYING", NULL);
2732 fp = fopen(path, "r");
2735 while(fgets(line, LINE_LENGTH, fp))
2737 copyright = g_string_append(copyright, line);
2745 path = g_build_filename(GQ_HELPDIR, "AUTHORS", NULL);
2746 fp = fopen(path, "r");
2749 while(fgets(line, LINE_LENGTH, fp))
2751 /* get rid of ending \n from fgets */
2752 line[strlen(line) - 1] = '\0';
2753 authors[i_authors] = g_strdup(line);
2756 authors[i_authors] = NULL;
2761 comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
2762 "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
2764 pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
2765 pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
2766 gtk_show_about_dialog(GTK_WINDOW(lw->window),
2767 "title", _("About Geeqie"),
2769 "program-name", GQ_APPNAME,
2771 "logo", pixbuf_logo,
2772 "icon", pixbuf_icon,
2773 "website", GQ_WEBSITE,
2774 "website-label", "Website",
2775 "comments", comment,
2777 "translator-credits", _("translator-credits"),
2778 #if GTK_CHECK_VERSION(3,0,0)
2779 "license-type", GTK_LICENSE_GPL_2_0,
2781 "license", copyright->str,
2785 #if !GTK_CHECK_VERSION(3,0,0)
2786 g_string_free(copyright, TRUE);
2789 while(n < i_authors)
2799 static void image_overlay_set_text_colours()
2801 c_options->image_overlay.text_red = options->image_overlay.text_red;
2802 c_options->image_overlay.text_green = options->image_overlay.text_green;
2803 c_options->image_overlay.text_blue = options->image_overlay.text_blue;
2804 c_options->image_overlay.text_alpha = options->image_overlay.text_alpha;
2805 c_options->image_overlay.background_red = options->image_overlay.background_red;
2806 c_options->image_overlay.background_green = options->image_overlay.background_green;
2807 c_options->image_overlay.background_blue = options->image_overlay.background_blue;
2808 c_options->image_overlay.background_alpha = options->image_overlay.background_alpha;
2810 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */