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"
26 #include "bar_keywords.h"
28 #include "cache_maint.h"
33 #include "filefilter.h"
34 #include "fullscreen.h"
36 #include "image-overlay.h"
37 #include "color-man.h"
39 #include "layout_config.h"
40 #include "layout_util.h"
43 #include "pixbuf_util.h"
44 #include "slideshow.h"
48 #include "ui_fileops.h"
50 #include "ui_spinner.h"
51 #include "ui_tabcomp.h"
52 #include "ui_utildlg.h"
54 #include "zonedetect.h"
64 #define EDITOR_NAME_MAX_LENGTH 32
65 #define EDITOR_COMMAND_MAX_LENGTH 1024
67 static void image_overlay_set_text_colours();
69 GtkWidget *keyword_text;
70 static void config_tab_keywords_save();
72 typedef struct _ThumbSize ThumbSize;
79 static ThumbSize thumb_size_list[] =
113 gchar *format_class_list[] = {
123 /* config memory values */
124 static ConfOptions *c_options = NULL;
131 static GtkWidget *configwindow = NULL;
132 static GtkListStore *filter_store = NULL;
133 static GtkTreeStore *accel_store = NULL;
135 static GtkWidget *safe_delete_path_entry;
137 static GtkWidget *color_profile_input_file_entry[COLOR_PROFILE_INPUTS];
138 static GtkWidget *color_profile_input_name_entry[COLOR_PROFILE_INPUTS];
139 static GtkWidget *color_profile_screen_file_entry;
141 static GtkWidget *sidecar_ext_entry;
142 static GtkWidget *help_search_engine_entry;
145 #define CONFIG_WINDOW_DEF_WIDTH 700
146 #define CONFIG_WINDOW_DEF_HEIGHT 600
149 *-----------------------------------------------------------------------------
150 * option widget callbacks (private)
151 *-----------------------------------------------------------------------------
154 static void zoom_increment_cb(GtkWidget *spin, gpointer data)
156 c_options->image.zoom_increment = (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) * 100.0 + 0.01);
159 static void slideshow_delay_hours_cb(GtkWidget *spin, gpointer data)
161 gint mins_secs_tenths, delay;
163 mins_secs_tenths = c_options->slideshow.delay %
164 (3600 * SLIDESHOW_SUBSECOND_PRECISION);
166 delay = (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
167 (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
170 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
171 SLIDESHOW_SUBSECOND_PRECISION;
174 static void slideshow_delay_minutes_cb(GtkWidget *spin, gpointer data)
176 gint hours, secs_tenths, delay;
178 hours = c_options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
179 secs_tenths = c_options->slideshow.delay % (60 * SLIDESHOW_SUBSECOND_PRECISION);
181 delay = hours * (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
182 (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
183 (60 * SLIDESHOW_SUBSECOND_PRECISION) + secs_tenths);
185 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
186 SLIDESHOW_SUBSECOND_PRECISION;
189 static void slideshow_delay_seconds_cb(GtkWidget *spin, gpointer data)
191 gint hours_mins, delay;
193 hours_mins = c_options->slideshow.delay / (60 * SLIDESHOW_SUBSECOND_PRECISION);
195 delay = (hours_mins * (60 * SLIDESHOW_SUBSECOND_PRECISION)) +
196 (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
197 (gdouble)(SLIDESHOW_SUBSECOND_PRECISION) + 0.01);
199 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
200 SLIDESHOW_SUBSECOND_PRECISION;
204 *-----------------------------------------------------------------------------
205 * sync progam to config window routine (private)
206 *-----------------------------------------------------------------------------
209 void config_entry_to_option(GtkWidget *entry, gchar **option, gchar *(*func)(const gchar *))
215 buf = gtk_entry_get_text(GTK_ENTRY(entry));
216 if (buf && strlen(buf) > 0)
221 *option = g_strdup(buf);
226 static gboolean accel_apply_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
228 gchar *accel_path, *accel;
230 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, AE_KEY, &accel, -1);
232 if (accel_path && accel_path[0])
235 gtk_accelerator_parse(accel, &key.accel_key, &key.accel_mods);
236 gtk_accel_map_change_entry(accel_path, key.accel_key, key.accel_mods, TRUE);
246 static void config_window_apply(void)
249 gboolean refresh = FALSE;
251 config_entry_to_option(safe_delete_path_entry, &options->file_ops.safe_delete_path, remove_trailing_slash);
253 if (options->file_filter.show_hidden_files != c_options->file_filter.show_hidden_files) refresh = TRUE;
254 if (options->file_filter.show_parent_directory != c_options->file_filter.show_parent_directory) refresh = TRUE;
255 if (options->file_filter.show_dot_directory != c_options->file_filter.show_dot_directory) refresh = TRUE;
256 if (options->file_sort.case_sensitive != c_options->file_sort.case_sensitive) refresh = TRUE;
257 if (options->file_sort.natural != c_options->file_sort.natural) refresh = TRUE;
258 if (options->file_filter.disable_file_extension_checks != c_options->file_filter.disable_file_extension_checks) refresh = TRUE;
259 if (options->file_filter.disable != c_options->file_filter.disable) refresh = TRUE;
261 options->file_ops.confirm_delete = c_options->file_ops.confirm_delete;
262 options->file_ops.enable_delete_key = c_options->file_ops.enable_delete_key;
263 options->file_ops.confirm_move_to_trash = c_options->file_ops.confirm_move_to_trash;
264 options->file_ops.use_system_trash = c_options->file_ops.use_system_trash;
265 options->file_ops.no_trash = c_options->file_ops.no_trash;
266 options->file_ops.safe_delete_folder_maxsize = c_options->file_ops.safe_delete_folder_maxsize;
267 options->tools_restore_state = c_options->tools_restore_state;
268 options->save_window_positions = c_options->save_window_positions;
269 options->use_saved_window_positions_for_new_windows = c_options->use_saved_window_positions_for_new_windows;
270 options->save_dialog_window_positions = c_options->save_dialog_window_positions;
271 options->show_window_ids = c_options->show_window_ids;
272 options->image.scroll_reset_method = c_options->image.scroll_reset_method;
273 options->image.zoom_2pass = c_options->image.zoom_2pass;
274 options->image.fit_window_to_image = c_options->image.fit_window_to_image;
275 options->image.limit_window_size = c_options->image.limit_window_size;
276 options->image.zoom_to_fit_allow_expand = c_options->image.zoom_to_fit_allow_expand;
277 options->image.max_window_size = c_options->image.max_window_size;
278 options->image.limit_autofit_size = c_options->image.limit_autofit_size;
279 options->image.max_autofit_size = c_options->image.max_autofit_size;
280 options->image.max_enlargement_size = c_options->image.max_enlargement_size;
281 options->image.use_clutter_renderer = c_options->image.use_clutter_renderer;
282 options->progressive_key_scrolling = c_options->progressive_key_scrolling;
283 options->keyboard_scroll_step = c_options->keyboard_scroll_step;
285 if (options->thumbnails.max_width != c_options->thumbnails.max_width
286 || options->thumbnails.max_height != c_options->thumbnails.max_height
287 || options->thumbnails.quality != c_options->thumbnails.quality)
289 thumb_format_changed = TRUE;
291 options->thumbnails.max_width = c_options->thumbnails.max_width;
292 options->thumbnails.max_height = c_options->thumbnails.max_height;
293 options->thumbnails.quality = c_options->thumbnails.quality;
295 options->thumbnails.enable_caching = c_options->thumbnails.enable_caching;
296 options->thumbnails.cache_into_dirs = c_options->thumbnails.cache_into_dirs;
297 options->thumbnails.use_exif = c_options->thumbnails.use_exif;
298 options->thumbnails.collection_preview = c_options->thumbnails.collection_preview;
299 options->thumbnails.use_ft_metadata = c_options->thumbnails.use_ft_metadata;
300 // options->thumbnails.use_ft_metadata_small = c_options->thumbnails.use_ft_metadata_small;
301 options->thumbnails.spec_standard = c_options->thumbnails.spec_standard;
302 options->metadata.enable_metadata_dirs = c_options->metadata.enable_metadata_dirs;
303 options->file_filter.show_hidden_files = c_options->file_filter.show_hidden_files;
304 options->file_filter.show_parent_directory = c_options->file_filter.show_parent_directory;
305 options->file_filter.show_dot_directory = c_options->file_filter.show_dot_directory;
306 options->file_filter.disable_file_extension_checks = c_options->file_filter.disable_file_extension_checks;
308 options->file_sort.case_sensitive = c_options->file_sort.case_sensitive;
309 options->file_sort.natural = c_options->file_sort.natural;
310 options->file_filter.disable = c_options->file_filter.disable;
312 config_entry_to_option(sidecar_ext_entry, &options->sidecar.ext, NULL);
313 sidecar_ext_parse(options->sidecar.ext);
315 options->slideshow.random = c_options->slideshow.random;
316 options->slideshow.repeat = c_options->slideshow.repeat;
317 options->slideshow.delay = c_options->slideshow.delay;
319 options->mousewheel_scrolls = c_options->mousewheel_scrolls;
320 options->image_lm_click_nav = c_options->image_lm_click_nav;
321 options->image_l_click_video = c_options->image_l_click_video;
322 options->image_l_click_video_editor = c_options->image_l_click_video_editor;
324 options->file_ops.enable_in_place_rename = c_options->file_ops.enable_in_place_rename;
326 options->image.tile_cache_max = c_options->image.tile_cache_max;
327 options->image.image_cache_max = c_options->image.image_cache_max;
329 options->image.zoom_quality = c_options->image.zoom_quality;
331 options->image.zoom_increment = c_options->image.zoom_increment;
333 options->image.enable_read_ahead = c_options->image.enable_read_ahead;
336 if (options->image.use_custom_border_color != c_options->image.use_custom_border_color
337 || options->image.use_custom_border_color_in_fullscreen != c_options->image.use_custom_border_color_in_fullscreen
338 || !gdk_color_equal(&options->image.border_color, &c_options->image.border_color))
340 options->image.use_custom_border_color_in_fullscreen = c_options->image.use_custom_border_color_in_fullscreen;
341 options->image.use_custom_border_color = c_options->image.use_custom_border_color;
342 options->image.border_color = c_options->image.border_color;
343 layout_colors_update();
344 view_window_colors_update();
347 options->image.alpha_color_1 = c_options->image.alpha_color_1;
348 options->image.alpha_color_2 = c_options->image.alpha_color_2;
350 options->fullscreen.screen = c_options->fullscreen.screen;
351 options->fullscreen.clean_flip = c_options->fullscreen.clean_flip;
352 options->fullscreen.disable_saver = c_options->fullscreen.disable_saver;
353 options->fullscreen.above = c_options->fullscreen.above;
354 if (c_options->image_overlay.template_string)
355 set_image_overlay_template_string(&options->image_overlay.template_string,
356 c_options->image_overlay.template_string);
357 if (c_options->image_overlay.font)
358 set_image_overlay_font_string(&options->image_overlay.font,
359 c_options->image_overlay.font);
360 options->image_overlay.text_red = c_options->image_overlay.text_red;
361 options->image_overlay.text_green = c_options->image_overlay.text_green;
362 options->image_overlay.text_blue = c_options->image_overlay.text_blue;
363 options->image_overlay.text_alpha = c_options->image_overlay.text_alpha;
364 options->image_overlay.background_red = c_options->image_overlay.background_red;
365 options->image_overlay.background_green = c_options->image_overlay.background_green;
366 options->image_overlay.background_blue = c_options->image_overlay.background_blue;
367 options->image_overlay.background_alpha = c_options->image_overlay.background_alpha;
368 options->update_on_time_change = c_options->update_on_time_change;
369 options->image.exif_proof_rotate_enable = c_options->image.exif_proof_rotate_enable;
371 options->duplicates_similarity_threshold = c_options->duplicates_similarity_threshold;
372 options->rot_invariant_sim = c_options->rot_invariant_sim;
374 options->tree_descend_subdirs = c_options->tree_descend_subdirs;
376 options->view_dir_list_single_click_enter = c_options->view_dir_list_single_click_enter;
378 options->open_recent_list_maxsize = c_options->open_recent_list_maxsize;
379 options->dnd_icon_size = c_options->dnd_icon_size;
380 options->clipboard_selection = c_options->clipboard_selection;
382 options->metadata.save_in_image_file = c_options->metadata.save_in_image_file;
383 options->metadata.save_legacy_IPTC = c_options->metadata.save_legacy_IPTC;
384 options->metadata.warn_on_write_problems = c_options->metadata.warn_on_write_problems;
385 options->metadata.save_legacy_format = c_options->metadata.save_legacy_format;
386 options->metadata.sync_grouped_files = c_options->metadata.sync_grouped_files;
387 options->metadata.confirm_write = c_options->metadata.confirm_write;
388 options->metadata.sidecar_extended_name = c_options->metadata.sidecar_extended_name;
389 options->metadata.confirm_timeout = c_options->metadata.confirm_timeout;
390 options->metadata.confirm_after_timeout = c_options->metadata.confirm_after_timeout;
391 options->metadata.confirm_on_image_change = c_options->metadata.confirm_on_image_change;
392 options->metadata.confirm_on_dir_change = c_options->metadata.confirm_on_dir_change;
393 options->metadata.keywords_case_sensitive = c_options->metadata.keywords_case_sensitive;
394 options->metadata.write_orientation = c_options->metadata.write_orientation;
395 options->stereo.mode = (c_options->stereo.mode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
396 (c_options->stereo.tmp.mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
397 (c_options->stereo.tmp.flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
398 (c_options->stereo.tmp.mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
399 (c_options->stereo.tmp.flip_left ? PR_STEREO_FLIP_LEFT : 0) |
400 (c_options->stereo.tmp.swap ? PR_STEREO_SWAP : 0) |
401 (c_options->stereo.tmp.temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
402 options->stereo.fsmode = (c_options->stereo.fsmode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
403 (c_options->stereo.tmp.fs_mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
404 (c_options->stereo.tmp.fs_flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
405 (c_options->stereo.tmp.fs_mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
406 (c_options->stereo.tmp.fs_flip_left ? PR_STEREO_FLIP_LEFT : 0) |
407 (c_options->stereo.tmp.fs_swap ? PR_STEREO_SWAP : 0) |
408 (c_options->stereo.tmp.fs_temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
409 options->stereo.enable_fsmode = c_options->stereo.enable_fsmode;
410 options->stereo.fixed_w = c_options->stereo.fixed_w;
411 options->stereo.fixed_h = c_options->stereo.fixed_h;
412 options->stereo.fixed_x1 = c_options->stereo.fixed_x1;
413 options->stereo.fixed_y1 = c_options->stereo.fixed_y1;
414 options->stereo.fixed_x2 = c_options->stereo.fixed_x2;
415 options->stereo.fixed_y2 = c_options->stereo.fixed_y2;
417 options->info_keywords.height = c_options->info_keywords.height;
418 options->info_title.height = c_options->info_title.height;
419 options->info_comment.height = c_options->info_comment.height;
420 options->info_rating.height = c_options->info_rating.height;
422 options->show_predefined_keyword_tree = c_options->show_predefined_keyword_tree;
424 options->marks_save = c_options->marks_save;
425 options->with_rename = c_options->with_rename;
426 options->collections_on_top = c_options->collections_on_top;
427 config_entry_to_option(help_search_engine_entry, &options->help_search_engine, NULL);
429 options->read_metadata_in_idle = c_options->read_metadata_in_idle;
431 options->star_rating.star = c_options->star_rating.star;
432 options->star_rating.rejected = c_options->star_rating.rejected;
434 set_debug_level(debug_c);
438 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
440 config_entry_to_option(color_profile_input_name_entry[i], &options->color_profile.input_name[i], NULL);
441 config_entry_to_option(color_profile_input_file_entry[i], &options->color_profile.input_file[i], NULL);
443 config_entry_to_option(color_profile_screen_file_entry, &options->color_profile.screen_file, NULL);
444 options->color_profile.use_x11_screen_profile = c_options->color_profile.use_x11_screen_profile;
445 if (options->color_profile.render_intent != c_options->color_profile.render_intent)
447 options->color_profile.render_intent = c_options->color_profile.render_intent;
452 config_tab_keywords_save();
454 image_options_sync();
459 layout_refresh(NULL);
462 if (accel_store) gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_apply_cb, NULL);
468 *-----------------------------------------------------------------------------
469 * config window main button callbacks (private)
470 *-----------------------------------------------------------------------------
473 static void config_window_close_cb(GtkWidget *widget, gpointer data)
475 gtk_widget_destroy(configwindow);
480 static void config_window_help_cb(GtkWidget *widget, gpointer data)
482 GtkWidget *notebook = data;
485 static gchar *html_section[] =
487 "GuideOptionsGeneral.html",
488 "GuideOptionsImage.html",
489 "GuideOptionsOSD.html",
490 "GuideOptionsWindow.html",
491 "GuideOptionsKeyboard.html",
492 "GuideOptionsFiltering.html",
493 "GuideOptionsMetadata.html",
494 "GuideOptionsKeywords.html",
495 "GuideOptionsColor.html",
496 "GuideOptionsStereo.html",
497 "GuideOptionsBehavior.html",
498 "GuideOptionsToolbar.html"
501 i = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
502 help_window_show(html_section[i]);
505 static gboolean config_window_delete(GtkWidget *widget, GdkEventAny *event, gpointer data)
507 config_window_close_cb(NULL, NULL);
511 static void config_window_ok_cb(GtkWidget *widget, gpointer data)
513 config_window_apply();
514 config_window_close_cb(NULL, NULL);
517 static void config_window_apply_cb(GtkWidget *widget, gpointer data)
520 lw = layout_window_list->data;
522 config_window_apply();
523 layout_util_sync(lw);
526 static void config_window_save_cb(GtkWidget *widget, gpointer data)
528 config_window_apply();
529 save_options(options);
533 *-----------------------------------------------------------------------------
534 * config window setup (private)
535 *-----------------------------------------------------------------------------
538 static void quality_menu_cb(GtkWidget *combo, gpointer data)
542 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
546 *option = GDK_INTERP_NEAREST;
549 *option = GDK_INTERP_TILES;
552 *option = GDK_INTERP_BILINEAR;
555 *option = GDK_INTERP_HYPER;
560 static void clipboard_selection_menu_cb(GtkWidget *combo, gpointer data)
564 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
576 static void add_quality_menu(GtkWidget *table, gint column, gint row, const gchar *text,
577 guint option, guint *option_c)
584 pref_table_label(table, column, row, text, 0.0);
586 combo = gtk_combo_box_text_new();
588 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Nearest (worst, but fastest)"));
589 if (option == GDK_INTERP_NEAREST) current = 0;
590 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Tiles"));
591 if (option == GDK_INTERP_TILES) current = 1;
592 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Bilinear"));
593 if (option == GDK_INTERP_BILINEAR) current = 2;
594 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Hyper (best, but slowest)"));
595 if (option == GDK_INTERP_HYPER) current = 3;
597 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
599 g_signal_connect(G_OBJECT(combo), "changed",
600 G_CALLBACK(quality_menu_cb), option_c);
602 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
603 GTK_EXPAND | GTK_FILL, 0, 0, 0);
604 gtk_widget_show(combo);
607 static void add_clipboard_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
608 gint option, gint *option_c)
615 pref_table_label(table, column, row, text, 0.0);
617 combo = gtk_combo_box_text_new();
619 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("PRIMARY"));
620 if (option == PRIMARY) current = 0;
621 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("CLIPBOARD"));
622 if (option == CLIPBOARD) current = 1;
624 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
626 g_signal_connect(G_OBJECT(combo), "changed",
627 G_CALLBACK(clipboard_selection_menu_cb), option_c);
629 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
630 GTK_EXPAND | GTK_FILL, 0, 0, 0);
631 gtk_widget_show(combo);
634 static void thumb_size_menu_cb(GtkWidget *combo, gpointer data)
638 n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
641 if ((guint) n < sizeof(thumb_size_list) / sizeof(ThumbSize))
643 c_options->thumbnails.max_width = thumb_size_list[n].w;
644 c_options->thumbnails.max_height = thumb_size_list[n].h;
648 c_options->thumbnails.max_width = options->thumbnails.max_width;
649 c_options->thumbnails.max_height = options->thumbnails.max_height;
653 static void add_thumb_size_menu(GtkWidget *table, gint column, gint row, gchar *text)
659 c_options->thumbnails.max_width = options->thumbnails.max_width;
660 c_options->thumbnails.max_height = options->thumbnails.max_height;
662 pref_table_label(table, column, row, text, 0.0);
664 combo = gtk_combo_box_text_new();
667 for (i = 0; (guint) i < sizeof(thumb_size_list) / sizeof(ThumbSize); i++)
672 w = thumb_size_list[i].w;
673 h = thumb_size_list[i].h;
675 buf = g_strdup_printf("%d x %d", w, h);
676 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
679 if (w == options->thumbnails.max_width && h == options->thumbnails.max_height) current = i;
686 buf = g_strdup_printf("%s %d x %d", _("Custom"), options->thumbnails.max_width, options->thumbnails.max_height);
687 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
693 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
694 g_signal_connect(G_OBJECT(combo), "changed",
695 G_CALLBACK(thumb_size_menu_cb), NULL);
697 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
698 GTK_EXPAND | GTK_FILL, 0, 0, 0);
699 gtk_widget_show(combo);
702 static void stereo_mode_menu_cb(GtkWidget *combo, gpointer data)
706 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
710 *option = PR_STEREO_NONE;
713 *option = PR_STEREO_ANAGLYPH_RC;
716 *option = PR_STEREO_ANAGLYPH_GM;
719 *option = PR_STEREO_ANAGLYPH_YB;
722 *option = PR_STEREO_ANAGLYPH_GRAY_RC;
725 *option = PR_STEREO_ANAGLYPH_GRAY_GM;
728 *option = PR_STEREO_ANAGLYPH_GRAY_YB;
731 *option = PR_STEREO_ANAGLYPH_DB_RC;
734 *option = PR_STEREO_ANAGLYPH_DB_GM;
737 *option = PR_STEREO_ANAGLYPH_DB_YB;
740 *option = PR_STEREO_HORIZ;
743 *option = PR_STEREO_HORIZ | PR_STEREO_HALF;
746 *option = PR_STEREO_VERT;
749 *option = PR_STEREO_VERT | PR_STEREO_HALF;
752 *option = PR_STEREO_FIXED;
757 static void add_stereo_mode_menu(GtkWidget *table, gint column, gint row, const gchar *text,
758 gint option, gint *option_c, gboolean add_fixed)
765 pref_table_label(table, column, row, text, 0.0);
767 combo = gtk_combo_box_text_new();
769 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Single image"));
771 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Red-Cyan"));
772 if (option & PR_STEREO_ANAGLYPH_RC) current = 1;
773 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Green-Magenta"));
774 if (option & PR_STEREO_ANAGLYPH_GM) current = 2;
775 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Yellow-Blue"));
776 if (option & PR_STEREO_ANAGLYPH_YB) current = 3;
777 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Red-Cyan"));
778 if (option & PR_STEREO_ANAGLYPH_GRAY_RC) current = 4;
779 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Green-Magenta"));
780 if (option & PR_STEREO_ANAGLYPH_GRAY_GM) current = 5;
781 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Yellow-Blue"));
782 if (option & PR_STEREO_ANAGLYPH_GRAY_YB) current = 6;
783 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Red-Cyan"));
784 if (option & PR_STEREO_ANAGLYPH_DB_RC) current = 7;
785 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Green-Magenta"));
786 if (option & PR_STEREO_ANAGLYPH_DB_GM) current = 8;
787 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Yellow-Blue"));
788 if (option & PR_STEREO_ANAGLYPH_DB_YB) current = 9;
790 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side"));
791 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side Half size"));
792 if (option & PR_STEREO_HORIZ)
795 if (option & PR_STEREO_HALF) current = 11;
798 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom"));
799 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom Half size"));
800 if (option & PR_STEREO_VERT)
803 if (option & PR_STEREO_HALF) current = 13;
808 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Fixed position"));
809 if (option & PR_STEREO_FIXED) current = 14;
812 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
814 g_signal_connect(G_OBJECT(combo), "changed",
815 G_CALLBACK(stereo_mode_menu_cb), option_c);
817 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
818 GTK_EXPAND | GTK_FILL, 0, 0, 0);
819 gtk_widget_show(combo);
822 static void video_menu_cb(GtkWidget *combo, gpointer data)
824 gchar **option = data;
826 EditorDescription *ed = g_list_nth_data(editor_list_get(), gtk_combo_box_get_active(GTK_COMBO_BOX(combo)));
830 static void video_menu_populate(gpointer data, gpointer user_data)
832 GtkWidget *combo = user_data;
833 EditorDescription *ed = data;
835 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), ed->name);
838 static void add_video_menu(GtkWidget *table, gint column, gint row, const gchar *text,
839 gchar *option, gchar **option_c)
843 /* use lists since they are sorted */
844 GList *eds = editor_list_get();
848 pref_table_label(table, column, row, text, 0.0);
850 combo = gtk_combo_box_text_new();
851 g_list_foreach(eds,video_menu_populate,(gpointer)combo);
852 current = option ? g_list_index(eds,g_hash_table_lookup(editors,option)): -1;
854 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
856 g_signal_connect(G_OBJECT(combo), "changed",
857 G_CALLBACK(video_menu_cb), option_c);
859 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
860 GTK_EXPAND | GTK_FILL, 0, 0, 0);
861 gtk_widget_show(combo);
864 static void filter_store_populate(void)
868 if (!filter_store) return;
870 gtk_list_store_clear(filter_store);
872 work = filter_get_list();
881 gtk_list_store_append(filter_store, &iter);
882 gtk_list_store_set(filter_store, &iter, 0, fe, -1);
886 static void filter_store_ext_edit_cb(GtkCellRendererText *cell, gchar *path_str,
887 gchar *new_text, gpointer data)
889 GtkWidget *model = data;
890 FilterEntry *fe = data;
894 if (!new_text || strlen(new_text) < 1) return;
896 tpath = gtk_tree_path_new_from_string(path_str);
897 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
898 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
900 g_free(fe->extensions);
901 fe->extensions = g_strdup(new_text);
903 gtk_tree_path_free(tpath);
907 static void filter_store_class_edit_cb(GtkCellRendererText *cell, gchar *path_str,
908 gchar *new_text, gpointer data)
910 GtkWidget *model = data;
911 FilterEntry *fe = data;
916 if (!new_text || !new_text[0]) return;
918 tpath = gtk_tree_path_new_from_string(path_str);
919 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
920 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
922 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
924 if (strcmp(new_text, _(format_class_list[i])) == 0)
931 gtk_tree_path_free(tpath);
935 static void filter_store_desc_edit_cb(GtkCellRendererText *cell, gchar *path_str,
936 gchar *new_text, gpointer data)
938 GtkWidget *model = data;
943 if (!new_text || !new_text[0]) return;
945 tpath = gtk_tree_path_new_from_string(path_str);
946 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
947 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
949 g_free(fe->description);
950 fe->description = g_strdup(new_text);
952 gtk_tree_path_free(tpath);
955 static void filter_store_enable_cb(GtkCellRendererToggle *renderer,
956 gchar *path_str, gpointer data)
958 GtkWidget *model = data;
963 tpath = gtk_tree_path_new_from_string(path_str);
964 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
965 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
967 fe->enabled = !fe->enabled;
969 gtk_tree_path_free(tpath);
973 static void filter_store_writable_cb(GtkCellRendererToggle *renderer,
974 gchar *path_str, gpointer data)
976 GtkWidget *model = data;
981 tpath = gtk_tree_path_new_from_string(path_str);
982 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
983 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
985 fe->writable = !fe->writable;
986 if (fe->writable) fe->allow_sidecar = FALSE;
988 gtk_tree_path_free(tpath);
992 static void filter_store_sidecar_cb(GtkCellRendererToggle *renderer,
993 gchar *path_str, gpointer data)
995 GtkWidget *model = data;
1000 tpath = gtk_tree_path_new_from_string(path_str);
1001 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1002 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1004 fe->allow_sidecar = !fe->allow_sidecar;
1005 if (fe->allow_sidecar) fe->writable = FALSE;
1007 gtk_tree_path_free(tpath);
1011 static void filter_set_func(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
1012 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
1016 gtk_tree_model_get(tree_model, iter, 0, &fe, -1);
1018 switch (GPOINTER_TO_INT(data))
1021 g_object_set(GTK_CELL_RENDERER(cell),
1022 "active", fe->enabled, NULL);
1025 g_object_set(GTK_CELL_RENDERER(cell),
1026 "text", fe->extensions, NULL);
1028 case FE_DESCRIPTION:
1029 g_object_set(GTK_CELL_RENDERER(cell),
1030 "text", fe->description, NULL);
1033 g_object_set(GTK_CELL_RENDERER(cell),
1034 "text", _(format_class_list[fe->file_class]), NULL);
1037 g_object_set(GTK_CELL_RENDERER(cell),
1038 "active", fe->writable, NULL);
1040 case FE_ALLOW_SIDECAR:
1041 g_object_set(GTK_CELL_RENDERER(cell),
1042 "active", fe->allow_sidecar, NULL);
1047 static gboolean filter_add_scroll(gpointer data)
1051 GtkCellRenderer *cell;
1052 GtkTreeViewColumn *column;
1057 rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(filter_store), NULL);
1058 path = gtk_tree_path_new_from_indices(rows-1, -1);
1060 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data), 0);
1062 list_cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column));
1063 cell = g_list_last(list_cells)->data;
1065 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1066 path, column, FALSE, 0.0, 0.0 );
1067 gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(data),
1068 path, column, cell, TRUE);
1070 gtk_tree_path_free(path);
1071 g_list_free(list_cells);
1076 static void filter_add_cb(GtkWidget *widget, gpointer data)
1078 filter_add_unique("description", ".new", FORMAT_CLASS_IMAGE, TRUE, FALSE, TRUE);
1079 filter_store_populate();
1081 g_idle_add((GSourceFunc)filter_add_scroll, data);
1084 static void filter_remove_cb(GtkWidget *widget, gpointer data)
1086 GtkWidget *filter_view = data;
1087 GtkTreeSelection *selection;
1091 if (!filter_store) return;
1092 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1093 if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) return;
1094 gtk_tree_model_get(GTK_TREE_MODEL(filter_store), &iter, 0, &fe, -1);
1097 filter_remove_entry(fe);
1099 filter_store_populate();
1102 static gboolean filter_default_ok_scroll(GtkTreeView *data)
1106 GtkTreeViewColumn *column;
1108 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(filter_store), &iter);
1109 path = gtk_tree_model_get_path(GTK_TREE_MODEL(filter_store), &iter);
1110 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1112 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1116 gtk_tree_path_free(path);
1121 static void filter_default_ok_cb(GenericDialog *gd, gpointer data)
1124 filter_add_defaults();
1126 filter_store_populate();
1128 g_idle_add((GSourceFunc)filter_default_ok_scroll, gd->data);
1131 static void dummy_cancel_cb(GenericDialog *gd, gpointer data)
1133 /* no op, only so cancel button appears */
1136 static void filter_default_cb(GtkWidget *widget, gpointer data)
1140 gd = generic_dialog_new(_("Reset filters"),
1141 "reset_filter", widget, TRUE,
1142 dummy_cancel_cb, data);
1143 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset filters"),
1144 _("This will reset the file filters to the defaults.\nContinue?"), TRUE);
1145 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, filter_default_ok_cb, TRUE);
1146 gtk_widget_show(gd->dialog);
1149 static void filter_disable_cb(GtkWidget *widget, gpointer data)
1151 GtkWidget *frame = data;
1153 gtk_widget_set_sensitive(frame,
1154 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
1157 static void safe_delete_view_cb(GtkWidget *widget, gpointer data)
1159 layout_set_path(NULL, gtk_entry_get_text(GTK_ENTRY(safe_delete_path_entry)));
1162 static void safe_delete_clear_ok_cb(GenericDialog *gd, gpointer data)
1164 file_util_trash_clear();
1167 static void safe_delete_clear_cb(GtkWidget *widget, gpointer data)
1171 gd = generic_dialog_new(_("Clear trash"),
1172 "clear_trash", widget, TRUE,
1173 dummy_cancel_cb, NULL);
1174 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear trash"),
1175 _("This will remove the trash contents."), FALSE);
1176 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, safe_delete_clear_ok_cb, TRUE);
1177 entry = gtk_entry_new();
1178 gtk_widget_set_can_focus(entry, FALSE);
1179 gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE);
1180 if (options->file_ops.safe_delete_path) gtk_entry_set_text(GTK_ENTRY(entry), options->file_ops.safe_delete_path);
1181 gtk_box_pack_start(GTK_BOX(gd->vbox), entry, FALSE, FALSE, 0);
1182 gtk_widget_show(entry);
1183 gtk_widget_show(gd->dialog);
1186 static void image_overlay_template_view_changed_cb(GtkWidget *widget, gpointer data)
1188 GtkWidget *pTextView;
1189 GtkTextBuffer *pTextBuffer;
1193 pTextView = GTK_WIDGET(data);
1195 pTextBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pTextView));
1196 gtk_text_buffer_get_start_iter(pTextBuffer, &iStart);
1197 gtk_text_buffer_get_end_iter(pTextBuffer, &iEnd);
1199 set_image_overlay_template_string(&c_options->image_overlay.template_string,
1200 gtk_text_buffer_get_text(pTextBuffer, &iStart, &iEnd, TRUE));
1203 static void image_overlay_default_template_ok_cb(GenericDialog *gd, gpointer data)
1205 GtkTextView *text_view = data;
1206 GtkTextBuffer *buffer;
1208 set_default_image_overlay_template_string(&options->image_overlay.template_string);
1209 if (!configwindow) return;
1211 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
1212 gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1215 static void image_overlay_default_template_cb(GtkWidget *widget, gpointer data)
1219 gd = generic_dialog_new(_("Reset image overlay template string"),
1220 "reset_image_overlay_template_string", widget, TRUE,
1221 dummy_cancel_cb, data);
1222 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset image overlay template string"),
1223 _("This will reset the image overlay template string to the default.\nContinue?"), TRUE);
1224 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, image_overlay_default_template_ok_cb, TRUE);
1225 gtk_widget_show(gd->dialog);
1228 static void image_overlay_help_cb(GtkWidget *widget, gpointer data)
1230 help_window_show("GuideOptionsOSD.html");
1233 static void image_overlay_set_font_cb(GtkWidget *widget, gpointer data)
1235 #if GTK_CHECK_VERSION(3,4,0)
1238 PangoFontDescription *font_desc;
1240 dialog = gtk_font_chooser_dialog_new("Image Overlay Font", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1241 gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), options->image_overlay.font);
1243 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1245 font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
1246 font = pango_font_description_to_string(font_desc);
1247 g_free(c_options->image_overlay.font);
1248 c_options->image_overlay.font = g_strdup(font);
1252 gtk_widget_destroy(dialog);
1256 font = gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget));
1257 c_options->image_overlay.font = g_strdup(font);
1261 static void image_overlay_set_text_colour_cb(GtkWidget *widget, gpointer data)
1264 #if GTK_CHECK_VERSION(3,4,0)
1267 dialog = gtk_color_chooser_dialog_new("Image Overlay Text Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1268 colour.red = options->image_overlay.text_red;
1269 colour.green = options->image_overlay.text_green;
1270 colour.blue = options->image_overlay.text_blue;
1271 colour.alpha = options->image_overlay.text_alpha;
1272 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1273 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1275 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1277 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1278 c_options->image_overlay.text_red = colour.red*255;
1279 c_options->image_overlay.text_green = colour.green*255;
1280 c_options->image_overlay.text_blue = colour.blue*255;
1281 c_options->image_overlay.text_alpha = colour.alpha*255;
1283 gtk_widget_destroy(dialog);
1286 GtkColorSelection *colorsel;
1288 dialog = gtk_color_selection_dialog_new("Image Overlay Text Colour");
1289 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1290 colour.red = options->image_overlay.text_red*257;
1291 colour.green = options->image_overlay.text_green*257;
1292 colour.blue = options->image_overlay.text_blue*257;
1293 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1294 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1295 gtk_color_selection_set_current_color(colorsel, &colour);
1296 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.text_alpha*257);
1298 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1300 gtk_color_selection_get_current_color(colorsel, &colour);
1301 c_options->image_overlay.text_red = colour.red/257;
1302 c_options->image_overlay.text_green = colour.green/257;
1303 c_options->image_overlay.text_blue = colour.blue/257;
1304 c_options->image_overlay.text_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1306 gtk_widget_destroy (dialog);
1311 static void image_overlay_set_background_colour_cb(GtkWidget *widget, gpointer data)
1314 #if GTK_CHECK_VERSION(3,4,0)
1317 dialog = gtk_color_chooser_dialog_new("Image Overlay Background Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1318 colour.red = options->image_overlay.background_red;
1319 colour.green = options->image_overlay.background_green;
1320 colour.blue = options->image_overlay.background_blue;
1321 colour.alpha = options->image_overlay.background_alpha;
1322 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1323 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1325 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1327 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1328 c_options->image_overlay.background_red = colour.red*255;
1329 c_options->image_overlay.background_green = colour.green*255;
1330 c_options->image_overlay.background_blue = colour.blue*255;
1331 c_options->image_overlay.background_alpha = colour.alpha*255;
1333 gtk_widget_destroy(dialog);
1336 GtkColorSelection *colorsel;
1338 dialog = gtk_color_selection_dialog_new("Image Overlay Background Colour");
1339 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1340 colour.red = options->image_overlay.background_red*257;
1341 colour.green = options->image_overlay.background_green*257;
1342 colour.blue = options->image_overlay.background_blue*257;
1343 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1344 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1345 gtk_color_selection_set_current_color(colorsel, &colour);
1346 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.background_alpha*257);
1348 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1350 gtk_color_selection_get_current_color(colorsel, &colour);
1351 c_options->image_overlay.background_red = colour.red/257;
1352 c_options->image_overlay.background_green = colour.green/257;
1353 c_options->image_overlay.background_blue = colour.blue/257;
1354 c_options->image_overlay.background_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1356 gtk_widget_destroy(dialog);
1360 static void accel_store_populate(void)
1363 GList *groups, *actions;
1365 const gchar *accel_path;
1369 if (!accel_store || !layout_window_list || !layout_window_list->data) return;
1371 gtk_tree_store_clear(accel_store);
1372 lw = layout_window_list->data; /* get the actions from the first window, it should not matter, they should be the same in all windows */
1374 g_assert(lw && lw->ui_manager);
1375 groups = gtk_ui_manager_get_action_groups(lw->ui_manager);
1378 actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
1381 action = GTK_ACTION(actions->data);
1382 accel_path = gtk_action_get_accel_path(action);
1383 if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
1385 gchar *label, *label2, *tooltip, *accel;
1386 g_object_get(action,
1387 "tooltip", &tooltip,
1391 if (pango_parse_markup(label, -1, '_', NULL, &label2, NULL, NULL) && label2)
1397 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1401 gtk_tree_store_append(accel_store, &iter, NULL);
1402 gtk_tree_store_set(accel_store, &iter,
1405 AE_TOOLTIP, tooltip ? tooltip : "",
1406 AE_ACCEL, accel_path,
1414 actions = actions->next;
1417 groups = groups->next;
1421 static void accel_store_cleared_cb(GtkCellRendererAccel *accel, gchar *path_string, gpointer user_data)
1426 static gboolean accel_remove_key_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1428 gchar *accel1 = data;
1433 gtk_tree_model_get(model, iter, AE_KEY, &accel2, -1);
1435 gtk_accelerator_parse(accel1, &key1.accel_key, &key1.accel_mods);
1436 gtk_accelerator_parse(accel2, &key2.accel_key, &key2.accel_mods);
1438 if (key1.accel_key == key2.accel_key && key1.accel_mods == key2.accel_mods)
1440 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1441 DEBUG_1("accelerator key '%s' is already used, removing.", accel1);
1450 static void accel_store_edited_cb(GtkCellRendererAccel *accel, gchar *path_string, guint accel_key, GdkModifierType accel_mods, guint hardware_keycode, gpointer user_data)
1452 GtkTreeModel *model = (GtkTreeModel *)accel_store;
1456 GtkAccelKey old_key, key;
1457 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
1459 gtk_tree_model_get_iter(model, &iter, path);
1460 gtk_tree_model_get(model, &iter, AE_ACCEL, &accel_path, -1);
1462 /* test if the accelerator can be stored without conflicts*/
1463 gtk_accel_map_lookup_entry(accel_path, &old_key);
1465 /* change the key and read it back (change may fail on keys hardcoded in gtk)*/
1466 gtk_accel_map_change_entry(accel_path, accel_key, accel_mods, TRUE);
1467 gtk_accel_map_lookup_entry(accel_path, &key);
1469 /* restore the original for now, the key will be really changed when the changes are confirmed */
1470 gtk_accel_map_change_entry(accel_path, old_key.accel_key, old_key.accel_mods, TRUE);
1472 acc = gtk_accelerator_name(key.accel_key, key.accel_mods);
1473 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, acc);
1475 gtk_tree_store_set(accel_store, &iter, AE_KEY, acc, -1);
1476 gtk_tree_path_free(path);
1480 static gboolean accel_default_scroll(GtkTreeView *data)
1484 GtkTreeViewColumn *column;
1486 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(accel_store), &iter);
1487 path = gtk_tree_model_get_path(GTK_TREE_MODEL(accel_store), &iter);
1488 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1490 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1494 gtk_tree_path_free(path);
1499 static void accel_default_cb(GtkWidget *widget, gpointer data)
1501 accel_store_populate();
1503 g_idle_add((GSourceFunc)accel_default_scroll, data);
1506 void accel_remove_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1508 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1511 void accel_reset_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1514 gchar *accel_path, *accel;
1516 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, -1);
1517 gtk_accel_map_lookup_entry(accel_path, &key);
1518 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1520 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, accel);
1522 gtk_tree_store_set(accel_store, iter, AE_KEY, accel, -1);
1527 static void accel_reset_cb(GtkWidget *widget, gpointer data)
1529 GtkTreeSelection *selection;
1531 if (!accel_store) return;
1532 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data));
1533 gtk_tree_selection_selected_foreach(selection, &accel_reset_selection, NULL);
1538 static GtkWidget *scrolled_notebook_page(GtkWidget *notebook, const gchar *title)
1542 GtkWidget *scrolled;
1543 GtkWidget *viewport;
1545 scrolled = gtk_scrolled_window_new(NULL, NULL);
1546 gtk_container_set_border_width(GTK_CONTAINER(scrolled), PREF_PAD_BORDER);
1547 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1548 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1549 label = gtk_label_new(title);
1550 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, label);
1551 gtk_widget_show(scrolled);
1553 viewport = gtk_viewport_new(NULL, NULL);
1554 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1555 gtk_container_add(GTK_CONTAINER(scrolled), viewport);
1556 gtk_widget_show(viewport);
1558 vbox = gtk_vbox_new(FALSE, 0);
1559 gtk_container_add(GTK_CONTAINER(viewport), vbox);
1560 gtk_widget_show(vbox);
1565 static void cache_standard_cb(GtkWidget *widget, gpointer data)
1567 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1569 c_options->thumbnails.spec_standard =TRUE;
1570 c_options->thumbnails.cache_into_dirs = FALSE;
1574 static void cache_geeqie_cb(GtkWidget *widget, gpointer data)
1576 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1578 c_options->thumbnails.spec_standard =FALSE;
1579 c_options->thumbnails.cache_into_dirs = FALSE;
1583 static void cache_local_cb(GtkWidget *widget, gpointer data)
1585 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1587 c_options->thumbnails.cache_into_dirs = TRUE;
1588 c_options->thumbnails.spec_standard =FALSE;
1592 static void help_search_engine_entry_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1593 GdkEvent *event, gpointer userdata)
1595 if (pos == GTK_ENTRY_ICON_PRIMARY)
1597 gtk_entry_set_text(GTK_ENTRY(userdata), HELP_SEARCH_ENGINE);
1601 gtk_entry_set_text(GTK_ENTRY(userdata), "");
1605 static void star_rating_star_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1606 GdkEvent *event, gpointer userdata)
1608 gchar *rating_symbol;
1610 if (pos == GTK_ENTRY_ICON_PRIMARY)
1612 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_STAR);
1613 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1614 g_free(rating_symbol);
1618 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1619 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1620 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1624 static void star_rating_rejected_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1625 GdkEvent *event, gpointer userdata)
1627 gchar *rating_symbol;
1629 if (pos == GTK_ENTRY_ICON_PRIMARY)
1631 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_REJECTED);
1632 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1633 g_free(rating_symbol);
1637 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1638 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1639 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1643 static guint star_rating_symbol_test(GtkWidget *widget, gpointer data)
1645 GtkContainer *hbox = data;
1646 GString *str = g_string_new(NULL);
1647 GtkEntry *hex_code_entry;
1648 gchar *hex_code_full;
1651 guint64 hex_value = 0;
1653 list = gtk_container_get_children(hbox);
1655 hex_code_entry = g_list_nth_data(list, 2);
1656 hex_code_full = g_strdup(gtk_entry_get_text(hex_code_entry));
1658 hex_code = g_strsplit(hex_code_full, "+", 2);
1659 if (hex_code[0] && hex_code[1])
1661 hex_value = strtoull(hex_code[1], NULL, 16);
1663 if (!hex_value || hex_value > 0x10FFFF)
1665 hex_value = 0x003F; // Unicode 'Question Mark'
1667 str = g_string_append_unichar(str, (gunichar)hex_value);
1668 gtk_label_set_text(g_list_nth_data(list, 1), str->str);
1670 g_strfreev(hex_code);
1671 g_string_free(str, TRUE);
1672 g_free(hex_code_full);
1677 static void star_rating_star_test_cb(GtkWidget *widget, gpointer data)
1679 guint64 star_symbol;
1681 star_symbol = star_rating_symbol_test(widget, data);
1682 c_options->star_rating.star = star_symbol;
1685 static void star_rating_rejected_test_cb(GtkWidget *widget, gpointer data)
1687 guint64 rejected_symbol;
1689 rejected_symbol = star_rating_symbol_test(widget, data);
1690 c_options->star_rating.rejected = rejected_symbol;
1693 /* general options tab */
1694 static void config_tab_general(GtkWidget *notebook)
1699 GtkWidget *group_frame;
1700 GtkWidget *subgroup;
1702 GtkWidget *ct_button;
1705 gint hours, minutes, remainder;
1707 GtkWidget *star_rating_entry;
1709 gchar *rating_symbol;
1711 vbox = scrolled_notebook_page(notebook, _("General"));
1713 group = pref_group_new(vbox, FALSE, _("Thumbnails"), GTK_ORIENTATION_VERTICAL);
1715 table = pref_table_new(group, 2, 2, FALSE, FALSE);
1716 add_thumb_size_menu(table, 0, 0, _("Size:"));
1717 add_quality_menu(table, 0, 1, _("Quality:"), options->thumbnails.quality, &c_options->thumbnails.quality);
1719 ct_button = pref_checkbox_new_int(group, _("Cache thumbnails"),
1720 options->thumbnails.enable_caching, &c_options->thumbnails.enable_caching);
1722 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1723 pref_checkbox_link_sensitivity(ct_button, subgroup);
1725 c_options->thumbnails.spec_standard = options->thumbnails.spec_standard;
1726 c_options->thumbnails.cache_into_dirs = options->thumbnails.cache_into_dirs;
1727 group_frame = pref_frame_new(subgroup, TRUE, _("Use Geeqie thumbnail style and cache"),
1728 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1729 button = pref_radiobutton_new(group_frame, NULL, get_thumbnails_cache_dir(),
1730 !options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1731 G_CALLBACK(cache_geeqie_cb), NULL);
1733 group_frame = pref_frame_new(subgroup, TRUE,
1734 _("Store thumbnails local to image folder (non-standard)"),
1735 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1736 pref_radiobutton_new(group_frame, button, "*/.thumbnails",
1737 !options->thumbnails.spec_standard && options->thumbnails.cache_into_dirs,
1738 G_CALLBACK(cache_local_cb), NULL);
1740 group_frame = pref_frame_new(subgroup, TRUE,
1741 _("Use standard thumbnail style and cache, shared with other applications"),
1742 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1743 pref_radiobutton_new(group_frame, button, get_thumbnails_standard_cache_dir(),
1744 options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1745 G_CALLBACK(cache_standard_cb), NULL);
1747 pref_checkbox_new_int(group, _("Use EXIF thumbnails when available (EXIF thumbnails may be outdated)"),
1748 options->thumbnails.use_exif, &c_options->thumbnails.use_exif);
1750 spin = pref_spin_new_int(group, _("Collection preview:"), NULL,
1752 options->thumbnails.collection_preview, &c_options->thumbnails.collection_preview);
1753 gtk_widget_set_tooltip_text(spin, _("The maximum number of thumbnails shown in a Collection preview montage"));
1755 #ifdef HAVE_FFMPEGTHUMBNAILER_METADATA
1756 pref_checkbox_new_int(group, _("Use embedded metadata in video files as thumbnails when available"),
1757 options->thumbnails.use_ft_metadata, &c_options->thumbnails.use_ft_metadata);
1759 // pref_checkbox_new_int(group, _("Ignore embedded metadata if size is too small"),
1760 // options->thumbnails.use_ft_metadata_small, &c_options->thumbnails.use_ft_metadata_small);
1763 group = pref_group_new(vbox, FALSE, _("Star Rating"), GTK_ORIENTATION_VERTICAL);
1765 c_options->star_rating.star = options->star_rating.star;
1766 c_options->star_rating.rejected = options->star_rating.rejected;
1768 str = g_string_new(NULL);
1769 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1770 pref_label_new(hbox, "Star character: ");
1771 str = g_string_append_unichar(str, options->star_rating.star);
1772 pref_label_new(hbox, g_strdup(str->str));
1773 rating_symbol = g_strdup_printf("U+%X", options->star_rating.star);
1774 star_rating_entry = gtk_entry_new();
1775 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
1776 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
1777 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
1778 gtk_widget_show(star_rating_entry);
1779 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
1780 G_CALLBACK(star_rating_star_test_cb), hbox);
1781 gtk_widget_set_tooltip_text(button, _("Display selected character"));
1782 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1783 gtk_widget_show(button);
1784 gtk_widget_set_tooltip_text(star_rating_entry, _("Hexadecimal representation of a Unicode character. A list of all Unicode characters may be found on the Internet."));
1785 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1786 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
1787 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1788 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
1789 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1790 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
1791 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1792 GTK_ENTRY_ICON_PRIMARY, _("Default"));
1793 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
1794 G_CALLBACK(star_rating_star_icon_cb),
1797 g_string_free(str, TRUE);
1798 g_free(rating_symbol);
1800 str = g_string_new(NULL);
1801 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1802 pref_label_new(hbox, "Rejected character: ");
1803 str = g_string_append_unichar(str, options->star_rating.rejected);
1804 pref_label_new(hbox, g_strdup(str->str));
1805 rating_symbol = g_strdup_printf("U+%X", options->star_rating.rejected);
1806 star_rating_entry = gtk_entry_new();
1807 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
1808 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
1809 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
1810 gtk_widget_show(star_rating_entry);
1811 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
1812 G_CALLBACK(star_rating_rejected_test_cb), hbox);
1813 gtk_widget_set_tooltip_text(button, _("Display selected character"));
1814 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1815 gtk_widget_show(button);
1816 gtk_widget_set_tooltip_text(star_rating_entry, _("Hexadecimal representation of a Unicode character. A list of all Unicode characters may be found on the Internet."));
1817 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1818 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
1819 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1820 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
1821 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1822 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
1823 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1824 GTK_ENTRY_ICON_PRIMARY, _("Default"));
1825 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
1826 G_CALLBACK(star_rating_rejected_icon_cb),
1829 g_string_free(str, TRUE);
1830 g_free(rating_symbol);
1832 group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
1834 c_options->slideshow.delay = options->slideshow.delay;
1835 hours = options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
1836 remainder = options->slideshow.delay % (3600 * SLIDESHOW_SUBSECOND_PRECISION);
1837 minutes = remainder / (60 * SLIDESHOW_SUBSECOND_PRECISION);
1838 seconds = (gdouble)(remainder % (60 * SLIDESHOW_SUBSECOND_PRECISION)) /
1839 SLIDESHOW_SUBSECOND_PRECISION;
1841 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1843 spin = pref_spin_new(hbox, _("Delay between image change hrs:mins:secs.dec"), NULL,
1845 options->slideshow.delay ? hours : 0.0,
1846 G_CALLBACK(slideshow_delay_hours_cb), NULL);
1847 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1848 spin = pref_spin_new(hbox, ":" , NULL,
1850 options->slideshow.delay ? minutes: 0.0,
1851 G_CALLBACK(slideshow_delay_minutes_cb), NULL);
1852 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1853 spin = pref_spin_new(hbox, ":", NULL,
1854 SLIDESHOW_MIN_SECONDS, 59, 1.0, 1,
1855 options->slideshow.delay ? seconds : 10.0,
1856 G_CALLBACK(slideshow_delay_seconds_cb), NULL);
1857 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1859 pref_checkbox_new_int(group, _("Random"), options->slideshow.random, &c_options->slideshow.random);
1860 pref_checkbox_new_int(group, _("Repeat"), options->slideshow.repeat, &c_options->slideshow.repeat);
1862 group = pref_group_new(vbox, FALSE, _("Image loading and caching"), GTK_ORIENTATION_VERTICAL);
1864 pref_spin_new_int(group, _("Decoded image cache size (Mb):"), NULL,
1865 0, 99999, 1, options->image.image_cache_max, &c_options->image.image_cache_max);
1866 pref_checkbox_new_int(group, _("Preload next image"),
1867 options->image.enable_read_ahead, &c_options->image.enable_read_ahead);
1869 pref_checkbox_new_int(group, _("Refresh on file change"),
1870 options->update_on_time_change, &c_options->update_on_time_change);
1872 group = pref_group_new(vbox, FALSE, _("Info sidebar heights"), GTK_ORIENTATION_VERTICAL);
1873 pref_label_new(group, _("NOTE! Geeqie must be restarted for changes to take effect"));
1874 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1875 pref_spin_new_int(hbox, _("Keywords:"), NULL,
1877 options->info_keywords.height, &c_options->info_keywords.height);
1878 pref_spin_new_int(hbox, _("Title:"), NULL,
1880 options->info_title.height, &c_options->info_title.height);
1881 pref_spin_new_int(hbox, _("Comment:"), NULL,
1883 options->info_comment.height, &c_options->info_comment.height);
1884 pref_spin_new_int(hbox, _("Rating:"), NULL,
1886 options->info_rating.height, &c_options->info_rating.height);
1888 group = pref_group_new(vbox, FALSE, _("Show predefined keyword tree"), GTK_ORIENTATION_VERTICAL);
1890 pref_checkbox_new_int(group, _("Show predefined keyword tree (NOTE! Geeqie must be restarted for change to take effect)"),
1891 options->show_predefined_keyword_tree, &c_options->show_predefined_keyword_tree);
1893 group = pref_group_new(vbox, FALSE, _("On-line help search engine"), GTK_ORIENTATION_VERTICAL);
1895 help_search_engine_entry = gtk_entry_new();
1896 gtk_entry_set_text(GTK_ENTRY(help_search_engine_entry), options->help_search_engine);
1897 gtk_box_pack_start(GTK_BOX(group), help_search_engine_entry, FALSE, FALSE, 0);
1898 gtk_widget_show(help_search_engine_entry);
1900 gtk_widget_set_tooltip_text(help_search_engine_entry, _("The format varies between search engines, e.g the format may be:\nhttps://www.search_engine.com/search?q=site:geeqie.org/help\nhttps://www.search_engine.com/?q=site:geeqie.org/help"));
1902 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
1903 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
1904 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
1905 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
1906 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
1907 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
1908 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
1909 GTK_ENTRY_ICON_PRIMARY, _("Default"));
1910 g_signal_connect(GTK_ENTRY(help_search_engine_entry), "icon-press",
1911 G_CALLBACK(help_search_engine_entry_icon_cb),
1912 help_search_engine_entry);
1916 static void config_tab_image(GtkWidget *notebook)
1921 GtkWidget *ct_button;
1922 GtkWidget *enlargement_button;
1926 vbox = scrolled_notebook_page(notebook, _("Image"));
1928 group = pref_group_new(vbox, FALSE, _("Zoom"), GTK_ORIENTATION_VERTICAL);
1930 table = pref_table_new(group, 2, 1, FALSE, FALSE);
1931 add_quality_menu(table, 0, 0, _("Quality:"), options->image.zoom_quality, &c_options->image.zoom_quality);
1934 pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library"),
1935 options->image.use_clutter_renderer, &c_options->image.use_clutter_renderer);
1938 pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"),
1939 options->image.zoom_2pass, &c_options->image.zoom_2pass);
1941 c_options->image.zoom_increment = options->image.zoom_increment;
1942 spin = pref_spin_new(group, _("Zoom increment:"), NULL,
1943 0.01, 4.0, 0.01, 2, (gdouble)options->image.zoom_increment / 100.0,
1944 G_CALLBACK(zoom_increment_cb), NULL);
1945 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1947 group = pref_group_new(vbox, FALSE, _("Fit image to window"), GTK_ORIENTATION_VERTICAL);
1949 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1950 enlargement_button = pref_checkbox_new_int(hbox, _("Allow enlargement of image (max. size in %)"),
1951 options->image.zoom_to_fit_allow_expand, &c_options->image.zoom_to_fit_allow_expand);
1952 spin = pref_spin_new_int(hbox, NULL, NULL,
1954 options->image.max_enlargement_size, &c_options->image.max_enlargement_size);
1955 pref_checkbox_link_sensitivity(enlargement_button, spin);
1956 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."));
1958 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1959 ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (% of actual window):"),
1960 options->image.limit_autofit_size, &c_options->image.limit_autofit_size);
1961 spin = pref_spin_new_int(hbox, NULL, NULL,
1963 options->image.max_autofit_size, &c_options->image.max_autofit_size);
1964 pref_checkbox_link_sensitivity(ct_button, spin);
1965 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."));
1967 group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
1969 pref_checkbox_new_int(group, _("Use custom border color in window mode"),
1970 options->image.use_custom_border_color, &c_options->image.use_custom_border_color);
1972 pref_checkbox_new_int(group, _("Use custom border color in fullscreen mode"),
1973 options->image.use_custom_border_color_in_fullscreen, &c_options->image.use_custom_border_color_in_fullscreen);
1975 pref_color_button_new(group, _("Border color"), &options->image.border_color,
1976 G_CALLBACK(pref_color_button_set_cb), &c_options->image.border_color);
1978 c_options->image.border_color = options->image.border_color;
1980 pref_color_button_new(group, _("Alpha channel color 1"), &options->image.alpha_color_1,
1981 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_1);
1983 pref_color_button_new(group, _("Alpha channel color 2"), &options->image.alpha_color_2,
1984 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_2);
1986 c_options->image.alpha_color_1 = options->image.alpha_color_1;
1987 c_options->image.alpha_color_2 = options->image.alpha_color_2;
1989 group = pref_group_new(vbox, FALSE, _("Convenience"), GTK_ORIENTATION_VERTICAL);
1991 pref_checkbox_new_int(group, _("Auto rotate proofs using Exif information"),
1992 options->image.exif_proof_rotate_enable, &c_options->image.exif_proof_rotate_enable);
1996 static void config_tab_windows(GtkWidget *notebook)
2002 GtkWidget *ct_button;
2005 vbox = scrolled_notebook_page(notebook, _("Windows"));
2007 group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
2009 ct_button = pref_checkbox_new_int(group, _("Remember window positions"),
2010 options->save_window_positions, &c_options->save_window_positions);
2012 button = pref_checkbox_new_int(group, _("Use saved window positions also for new windows"),
2013 options->use_saved_window_positions_for_new_windows, &c_options->use_saved_window_positions_for_new_windows);
2014 pref_checkbox_link_sensitivity(ct_button, button);
2016 pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
2017 options->tools_restore_state, &c_options->tools_restore_state);
2019 pref_checkbox_new_int(group, _("Remember dialog window positions"),
2020 options->save_dialog_window_positions, &c_options->save_dialog_window_positions);
2022 pref_checkbox_new_int(group, _("Show window IDs"),
2023 options->show_window_ids, &c_options->show_window_ids);
2025 group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
2027 pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
2028 options->image.fit_window_to_image, &c_options->image.fit_window_to_image);
2030 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2031 ct_button = pref_checkbox_new_int(hbox, _("Limit size when auto-sizing window (%):"),
2032 options->image.limit_window_size, &c_options->image.limit_window_size);
2033 spin = pref_spin_new_int(hbox, NULL, NULL,
2035 options->image.max_window_size, &c_options->image.max_window_size);
2036 pref_checkbox_link_sensitivity(ct_button, spin);
2038 group = pref_group_new(vbox, FALSE, _("Full screen"), GTK_ORIENTATION_VERTICAL);
2040 c_options->fullscreen.screen = options->fullscreen.screen;
2041 c_options->fullscreen.above = options->fullscreen.above;
2042 hbox = fullscreen_prefs_selection_new(_("Location:"), &c_options->fullscreen.screen, &c_options->fullscreen.above);
2043 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2044 gtk_widget_show(hbox);
2046 pref_checkbox_new_int(group, _("Smooth image flip"),
2047 options->fullscreen.clean_flip, &c_options->fullscreen.clean_flip);
2048 pref_checkbox_new_int(group, _("Disable screen saver"),
2049 options->fullscreen.disable_saver, &c_options->fullscreen.disable_saver);
2052 #define PRE_FORMATTED_COLUMNS 5
2053 static void config_tab_osd(GtkWidget *notebook)
2057 GtkWidget *vbox_buttons;
2060 GtkWidget *image_overlay_template_view;
2061 GtkWidget *scrolled;
2062 GtkWidget *scrolled_pre_formatted;
2063 GtkTextBuffer *buffer;
2065 GtkWidget * subgroup;
2070 vbox = scrolled_notebook_page(notebook, _("OSD"));
2072 image_overlay_template_view = gtk_text_view_new();
2074 group = pref_group_new(vbox, FALSE, _("Overlay Screen Display"), GTK_ORIENTATION_VERTICAL);
2076 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2078 scrolled_pre_formatted = osd_new(PRE_FORMATTED_COLUMNS, image_overlay_template_view);
2079 gtk_widget_set_size_request(scrolled_pre_formatted, 200, 150);
2080 gtk_box_pack_start(GTK_BOX(subgroup), scrolled_pre_formatted, FALSE, FALSE, 0);
2081 gtk_widget_show(scrolled_pre_formatted);
2082 gtk_widget_show(subgroup);
2084 pref_line(group, PREF_PAD_GAP);
2086 pref_label_new(group, _("Image overlay template"));
2088 scrolled = gtk_scrolled_window_new(NULL, NULL);
2089 gtk_widget_set_size_request(scrolled, 200, 150);
2090 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2091 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
2092 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2093 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 5);
2094 gtk_widget_show(scrolled);
2096 gtk_widget_set_tooltip_markup(image_overlay_template_view,
2097 _("Extensive formatting options are shown in the Help file"));
2099 gtk_container_add(GTK_CONTAINER(scrolled), image_overlay_template_view);
2100 gtk_widget_show(image_overlay_template_view);
2102 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2104 #if GTK_CHECK_VERSION(3,4,0)
2105 button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
2106 G_CALLBACK(image_overlay_set_font_cb), notebook);
2108 button = gtk_font_button_new();
2109 gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Image Overlay Font");
2110 gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->image_overlay.font);
2111 g_signal_connect(G_OBJECT(button), "font-set",
2112 G_CALLBACK(image_overlay_set_font_cb),NULL);
2114 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2115 gtk_widget_show(button);
2117 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Text"), FALSE,
2118 G_CALLBACK(image_overlay_set_text_colour_cb), NULL);
2119 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2120 gtk_widget_show(button);
2122 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Background"), FALSE,
2123 G_CALLBACK(image_overlay_set_background_colour_cb), NULL);
2124 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2125 gtk_widget_show(button);
2126 image_overlay_set_text_colours();
2128 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2129 G_CALLBACK(image_overlay_default_template_cb), image_overlay_template_view);
2130 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2131 gtk_widget_show(button);
2133 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
2134 G_CALLBACK(image_overlay_help_cb), NULL);
2135 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2136 gtk_widget_show(button);
2138 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_overlay_template_view));
2139 if (options->image_overlay.template_string) gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
2140 g_signal_connect(G_OBJECT(buffer), "changed",
2141 G_CALLBACK(image_overlay_template_view_changed_cb), image_overlay_template_view);
2143 pref_line(group, PREF_PAD_GAP);
2145 group = pref_group_new(vbox, FALSE, _("Exif, XMP or IPTC tags"), GTK_ORIENTATION_VERTICAL);
2146 hbox = gtk_hbox_new(FALSE, 0);
2147 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2148 gtk_widget_show(hbox);
2149 label = gtk_label_new(_("%Exif.Image.Orientation%"));
2150 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2151 gtk_widget_show(label);
2152 pref_spacer(group,TRUE);
2154 group = pref_group_new(vbox, FALSE, _("Field separators"), GTK_ORIENTATION_VERTICAL);
2155 hbox = gtk_hbox_new(FALSE, 0);
2156 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2157 gtk_widget_show(hbox);
2158 label = gtk_label_new(_("Separator shown only if both fields are non-null:\n%formatted.ShutterSpeed%|%formatted.ISOSpeedRating%"));
2159 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2160 gtk_widget_show(label);
2161 pref_spacer(group,TRUE);
2163 group = pref_group_new(vbox, FALSE, _("Field maximum length"), GTK_ORIENTATION_VERTICAL);
2164 hbox = gtk_hbox_new(FALSE, 0);
2165 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2166 gtk_widget_show(hbox);
2167 label = gtk_label_new(_("%path:39%"));
2168 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2169 gtk_widget_show(label);
2170 pref_spacer(group,TRUE);
2172 group = pref_group_new(vbox, FALSE, _("Pre- and post- text"), GTK_ORIENTATION_VERTICAL);
2173 hbox = gtk_hbox_new(FALSE, 0);
2174 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2175 gtk_widget_show(hbox);
2176 label = gtk_label_new(_("Text shown only if the field is non-null:\n%formatted.Aperture:F no. * setting%\n %formatted.Aperture:10:F no. * setting%"));
2177 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2178 gtk_widget_show(label);
2179 pref_spacer(group,TRUE);
2181 group = pref_group_new(vbox, FALSE, _("Pango markup"), GTK_ORIENTATION_VERTICAL);
2182 hbox = gtk_hbox_new(FALSE, 0);
2183 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2184 gtk_widget_show(hbox);
2185 label = gtk_label_new(_("<b>bold</b>\n<u>underline</u>\n<i>italic</i>\n<s>strikethrough</s>"));
2186 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2187 gtk_widget_show(label);
2190 static GtkTreeModel *create_class_model(void)
2192 GtkListStore *model;
2196 /* create list store */
2197 model = gtk_list_store_new(1, G_TYPE_STRING);
2198 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
2200 gtk_list_store_append(model, &iter);
2201 gtk_list_store_set(model, &iter, 0, _(format_class_list[i]), -1);
2203 return GTK_TREE_MODEL (model);
2208 static void config_tab_files(GtkWidget *notebook)
2215 GtkWidget *ct_button;
2216 GtkWidget *scrolled;
2217 GtkWidget *filter_view;
2218 GtkCellRenderer *renderer;
2219 GtkTreeSelection *selection;
2220 GtkTreeViewColumn *column;
2222 vbox = scrolled_notebook_page(notebook, _("Files"));
2224 group = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2226 pref_checkbox_new_int(group, _("Show hidden files or folders"),
2227 options->file_filter.show_hidden_files, &c_options->file_filter.show_hidden_files);
2228 pref_checkbox_new_int(group, _("Show parent folder (..)"),
2229 options->file_filter.show_parent_directory, &c_options->file_filter.show_parent_directory);
2230 pref_checkbox_new_int(group, _("Case sensitive sort"),
2231 options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
2232 pref_checkbox_new_int(group, _("Natural sort order"),
2233 options->file_sort.natural, &c_options->file_sort.natural);
2234 pref_checkbox_new_int(group, _("Disable file extension checks"),
2235 options->file_filter.disable_file_extension_checks, &c_options->file_filter.disable_file_extension_checks);
2237 ct_button = pref_checkbox_new_int(group, _("Disable File Filtering"),
2238 options->file_filter.disable, &c_options->file_filter.disable);
2241 group = pref_group_new(vbox, FALSE, _("Grouping sidecar extensions"), GTK_ORIENTATION_VERTICAL);
2243 sidecar_ext_entry = gtk_entry_new();
2244 gtk_entry_set_text(GTK_ENTRY(sidecar_ext_entry), options->sidecar.ext);
2245 gtk_box_pack_start(GTK_BOX(group), sidecar_ext_entry, FALSE, FALSE, 0);
2246 gtk_widget_show(sidecar_ext_entry);
2248 group = pref_group_new(vbox, TRUE, _("File types"), GTK_ORIENTATION_VERTICAL);
2250 frame = pref_group_parent(group);
2251 g_signal_connect(G_OBJECT(ct_button), "toggled",
2252 G_CALLBACK(filter_disable_cb), frame);
2253 gtk_widget_set_sensitive(frame, !options->file_filter.disable);
2255 scrolled = gtk_scrolled_window_new(NULL, NULL);
2256 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2257 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2258 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2259 gtk_widget_show(scrolled);
2261 filter_store = gtk_list_store_new(1, G_TYPE_POINTER);
2262 filter_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(filter_store));
2263 g_object_unref(filter_store);
2264 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
2265 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
2267 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), FALSE);
2269 column = gtk_tree_view_column_new();
2270 gtk_tree_view_column_set_title(column, _("Filter"));
2271 gtk_tree_view_column_set_resizable(column, TRUE);
2273 renderer = gtk_cell_renderer_toggle_new();
2274 g_signal_connect(G_OBJECT(renderer), "toggled",
2275 G_CALLBACK(filter_store_enable_cb), filter_store);
2276 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2277 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2278 GINT_TO_POINTER(FE_ENABLE), NULL);
2280 renderer = gtk_cell_renderer_text_new();
2281 g_signal_connect(G_OBJECT(renderer), "edited",
2282 G_CALLBACK(filter_store_ext_edit_cb), filter_store);
2283 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2284 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2285 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2286 GINT_TO_POINTER(FE_EXTENSION), NULL);
2287 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2289 column = gtk_tree_view_column_new();
2290 gtk_tree_view_column_set_title(column, _("Description"));
2291 gtk_tree_view_column_set_resizable(column, TRUE);
2292 gtk_tree_view_column_set_fixed_width(column, 200);
2293 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
2295 renderer = gtk_cell_renderer_text_new();
2296 g_signal_connect(G_OBJECT(renderer), "edited",
2297 G_CALLBACK(filter_store_desc_edit_cb), filter_store);
2298 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2299 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2300 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2301 GINT_TO_POINTER(FE_DESCRIPTION), NULL);
2302 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2304 column = gtk_tree_view_column_new();
2305 gtk_tree_view_column_set_title(column, _("Class"));
2306 gtk_tree_view_column_set_resizable(column, TRUE);
2307 renderer = gtk_cell_renderer_combo_new();
2308 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE,
2309 "model", create_class_model(),
2314 g_signal_connect(G_OBJECT(renderer), "edited",
2315 G_CALLBACK(filter_store_class_edit_cb), filter_store);
2316 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2317 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2318 GINT_TO_POINTER(FE_CLASS), NULL);
2319 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2321 column = gtk_tree_view_column_new();
2322 gtk_tree_view_column_set_title(column, _("Writable"));
2323 gtk_tree_view_column_set_resizable(column, FALSE);
2324 renderer = gtk_cell_renderer_toggle_new();
2325 g_signal_connect(G_OBJECT(renderer), "toggled",
2326 G_CALLBACK(filter_store_writable_cb), filter_store);
2327 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2328 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2329 GINT_TO_POINTER(FE_WRITABLE), NULL);
2330 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2332 column = gtk_tree_view_column_new();
2333 gtk_tree_view_column_set_title(column, _("Sidecar is allowed"));
2334 gtk_tree_view_column_set_resizable(column, FALSE);
2335 renderer = gtk_cell_renderer_toggle_new();
2336 g_signal_connect(G_OBJECT(renderer), "toggled",
2337 G_CALLBACK(filter_store_sidecar_cb), filter_store);
2338 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2339 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2340 GINT_TO_POINTER(FE_ALLOW_SIDECAR), NULL);
2341 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2344 filter_store_populate();
2345 gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
2346 gtk_widget_show(filter_view);
2348 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2350 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2351 G_CALLBACK(filter_default_cb), filter_view);
2352 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2353 gtk_widget_show(button);
2355 button = pref_button_new(NULL, GTK_STOCK_REMOVE, NULL, FALSE,
2356 G_CALLBACK(filter_remove_cb), filter_view);
2357 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2358 gtk_widget_show(button);
2360 button = pref_button_new(NULL, GTK_STOCK_ADD, NULL, FALSE,
2361 G_CALLBACK(filter_add_cb), filter_view);
2362 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2363 gtk_widget_show(button);
2367 static void config_tab_metadata(GtkWidget *notebook)
2372 GtkWidget *ct_button;
2376 vbox = scrolled_notebook_page(notebook, _("Metadata"));
2379 group = pref_group_new(vbox, FALSE, _("Metadata writing process"), GTK_ORIENTATION_VERTICAL);
2381 label = pref_label_new(group, _("Warning: Geeqie is built without Exiv2. Some options are disabled."));
2383 label = pref_label_new(group, _("Metadata are written in the following order. The process ends after first success."));
2384 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2386 ct_button = pref_checkbox_new_int(group, _("1) Save metadata in image files, or sidecar files, according to the XMP standard"),
2387 options->metadata.save_in_image_file, &c_options->metadata.save_in_image_file);
2389 gtk_widget_set_sensitive(ct_button, FALSE);
2392 pref_checkbox_new_int(group, _("2) Save metadata in '.metadata' folder, local to image folder (non-standard)"),
2393 options->metadata.enable_metadata_dirs, &c_options->metadata.enable_metadata_dirs);
2395 text = g_strdup_printf(_("3) Save metadata in Geeqie private directory '%s'"), get_metadata_cache_dir());
2396 label = pref_label_new(group, text);
2397 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2398 gtk_misc_set_padding(GTK_MISC(label), 22, 0);
2401 group = pref_group_new(vbox, FALSE, _("Step 1: Write to image files"), GTK_ORIENTATION_VERTICAL);
2403 gtk_widget_set_sensitive(group, FALSE);
2406 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2407 pref_checkbox_link_sensitivity(ct_button, hbox);
2409 pref_checkbox_new_int(hbox, _("Store metadata also in legacy IPTC tags (converted according to IPTC4XMP standard)"),
2410 options->metadata.save_legacy_IPTC, &c_options->metadata.save_legacy_IPTC);
2412 pref_checkbox_new_int(hbox, _("Warn if the image files are unwritable"),
2413 options->metadata.warn_on_write_problems, &c_options->metadata.warn_on_write_problems);
2415 pref_checkbox_new_int(hbox, _("Ask before writing to image files"),
2416 options->metadata.confirm_write, &c_options->metadata.confirm_write);
2418 pref_checkbox_new_int(hbox, _("Create sidecar files named image.ext.xmp (as opposed to image.xmp)"),
2419 options->metadata.sidecar_extended_name, &c_options->metadata.sidecar_extended_name);
2421 group = pref_group_new(vbox, FALSE, _("Step 2 and 3: write to Geeqie private files"), GTK_ORIENTATION_VERTICAL);
2423 gtk_widget_set_sensitive(group, FALSE);
2426 pref_checkbox_new_int(group, _("Use GQview legacy metadata format (supports only keywords and comments) instead of XMP"),
2427 options->metadata.save_legacy_format, &c_options->metadata.save_legacy_format);
2430 group = pref_group_new(vbox, FALSE, _("Miscellaneous"), GTK_ORIENTATION_VERTICAL);
2431 pref_checkbox_new_int(group, _("Write the same description tags (keywords, comment, etc.) to all grouped sidecars"),
2432 options->metadata.sync_grouped_files, &c_options->metadata.sync_grouped_files);
2434 pref_checkbox_new_int(group, _("Allow keywords to differ only in case"),
2435 options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
2437 ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"),
2438 options->metadata.write_orientation, &c_options->metadata.write_orientation);
2440 gtk_widget_set_sensitive(ct_button, FALSE);
2443 group = pref_group_new(vbox, FALSE, _("Auto-save options"), GTK_ORIENTATION_VERTICAL);
2445 ct_button = pref_checkbox_new_int(group, _("Write metadata after timeout"),
2446 options->metadata.confirm_after_timeout, &c_options->metadata.confirm_after_timeout);
2448 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2449 pref_checkbox_link_sensitivity(ct_button, hbox);
2451 pref_spin_new_int(hbox, _("Timeout (seconds):"), NULL, 0, 900, 1,
2452 options->metadata.confirm_timeout, &c_options->metadata.confirm_timeout);
2454 pref_checkbox_new_int(group, _("Write metadata on image change"),
2455 options->metadata.confirm_on_image_change, &c_options->metadata.confirm_on_image_change);
2457 pref_checkbox_new_int(group, _("Write metadata on directory change"),
2458 options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
2460 group = pref_group_new(vbox, FALSE, _("Pre-load metadata"), GTK_ORIENTATION_VERTICAL);
2462 ct_button = pref_checkbox_new_int(group, _("Read metadata in background"),
2463 options->read_metadata_in_idle, &c_options->read_metadata_in_idle);
2464 gtk_widget_set_tooltip_text(ct_button,"On folder change, read DateTimeOriginal, DateTimeDigitized and Star Rating in the idle loop.\nIf this is not selected, initial loading of the folder will be faster but sorting on these items will be slower");
2469 typedef struct _KeywordFindData KeywordFindData;
2470 struct _KeywordFindData
2477 GtkWidget *button_close;
2478 GtkWidget *button_stop;
2479 GtkWidget *button_start;
2480 GtkWidget *progress;
2488 guint idle_id; /* event source id */
2491 #define KEYWORD_DIALOG_WIDTH 400
2493 static void keywords_find_folder(KeywordFindData *kfd, FileData *dir_fd)
2495 GList *list_d = NULL;
2496 GList *list_f = NULL;
2500 filelist_read(dir_fd, &list_f, &list_d);
2504 filelist_read(dir_fd, &list_f, NULL);
2507 list_f = filelist_filter(list_f, FALSE);
2508 list_d = filelist_filter(list_d, TRUE);
2510 kfd->list = g_list_concat(list_f, kfd->list);
2511 kfd->list_dir = g_list_concat(list_d, kfd->list_dir);
2514 static void keywords_find_reset(KeywordFindData *kfd)
2516 filelist_free(kfd->list);
2519 filelist_free(kfd->list_dir);
2520 kfd->list_dir = NULL;
2523 static void keywords_find_close_cb(GenericDialog *fd, gpointer data)
2525 KeywordFindData *kfd = data;
2527 if (!gtk_widget_get_sensitive(kfd->button_close)) return;
2529 keywords_find_reset(kfd);
2530 generic_dialog_close(kfd->gd);
2534 static void keywords_find_finish(KeywordFindData *kfd)
2536 keywords_find_reset(kfd);
2538 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("done"));
2539 spinner_set_interval(kfd->spinner, -1);
2541 gtk_widget_set_sensitive(kfd->group, TRUE);
2542 gtk_widget_set_sensitive(kfd->button_start, TRUE);
2543 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2544 gtk_widget_set_sensitive(kfd->button_close, TRUE);
2547 static void keywords_find_stop_cb(GenericDialog *fd, gpointer data)
2549 KeywordFindData *kfd = data;
2551 g_idle_remove_by_data(kfd);
2553 keywords_find_finish(kfd);
2556 static gboolean keywords_find_file(gpointer data)
2558 KeywordFindData *kfd = data;
2560 GtkTextBuffer *buffer;
2568 fd = kfd->list->data;
2569 kfd->list = g_list_remove(kfd->list, fd);
2571 keywords = metadata_read_list(fd, KEYWORD_KEY, METADATA_PLAIN);
2572 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2576 gtk_text_buffer_get_end_iter(buffer, &iter);
2577 tmp = g_strconcat(keywords->data, "\n", NULL);
2578 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
2580 keywords = keywords->next;
2583 gtk_entry_set_text(GTK_ENTRY(kfd->progress), fd->path);
2584 file_data_unref(fd);
2585 string_list_free(keywords);
2589 else if (kfd->list_dir)
2593 fd = kfd->list_dir->data;
2594 kfd->list_dir = g_list_remove(kfd->list_dir, fd);
2596 keywords_find_folder(kfd, fd);
2598 file_data_unref(fd);
2603 keywords_find_finish(kfd);
2608 static void keywords_find_start_cb(GenericDialog *fd, gpointer data)
2610 KeywordFindData *kfd = data;
2613 if (kfd->list || !gtk_widget_get_sensitive(kfd->button_start)) return;
2615 path = remove_trailing_slash((gtk_entry_get_text(GTK_ENTRY(kfd->entry))));
2616 parse_out_relatives(path);
2620 warning_dialog(_("Invalid folder"),
2621 _("The specified folder can not be found."),
2622 GTK_STOCK_DIALOG_WARNING, kfd->gd->dialog);
2628 gtk_widget_set_sensitive(kfd->group, FALSE);
2629 gtk_widget_set_sensitive(kfd->button_start, FALSE);
2630 gtk_widget_set_sensitive(kfd->button_stop, TRUE);
2631 gtk_widget_set_sensitive(kfd->button_close, FALSE);
2632 spinner_set_interval(kfd->spinner, SPINNER_SPEED);
2634 dir_fd = file_data_new_dir(path);
2635 keywords_find_folder(kfd, dir_fd);
2636 file_data_unref(dir_fd);
2637 kfd->idle_id = g_idle_add(keywords_find_file, kfd);
2643 static void keywords_find_dialog(GtkWidget *widget, const gchar *path)
2645 KeywordFindData *kfd;
2649 kfd = g_new0(KeywordFindData, 1);
2651 kfd->gd = generic_dialog_new(_("Search for keywords"),
2652 "search_for_keywords",
2655 gtk_window_set_default_size(GTK_WINDOW(kfd->gd->dialog), KEYWORD_DIALOG_WIDTH, -1);
2656 kfd->gd->cancel_cb = keywords_find_close_cb;
2657 kfd->button_close = generic_dialog_add_button(kfd->gd, GTK_STOCK_CLOSE, NULL,
2658 keywords_find_close_cb, FALSE);
2659 kfd->button_start = generic_dialog_add_button(kfd->gd, GTK_STOCK_OK, _("S_tart"),
2660 keywords_find_start_cb, FALSE);
2661 kfd->button_stop = generic_dialog_add_button(kfd->gd, GTK_STOCK_STOP, NULL,
2662 keywords_find_stop_cb, FALSE);
2663 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2665 generic_dialog_add_message(kfd->gd, NULL, _("Search for keywords"), NULL, FALSE);
2667 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0);
2668 pref_spacer(hbox, PREF_PAD_INDENT);
2669 kfd->group = pref_box_new(hbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2671 hbox = pref_box_new(kfd->group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2672 pref_label_new(hbox, _("Folder:"));
2674 label = tab_completion_new(&kfd->entry, path, NULL, NULL, NULL, NULL);
2675 tab_completion_add_select_button(kfd->entry,_("Select folder") , TRUE);
2676 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
2677 gtk_widget_show(label);
2679 pref_checkbox_new_int(kfd->group, _("Include subfolders"), FALSE, &kfd->recurse);
2681 pref_line(kfd->gd->vbox, PREF_PAD_SPACE);
2682 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2684 kfd->progress = gtk_entry_new();
2685 gtk_widget_set_can_focus(kfd->progress, FALSE);
2686 gtk_editable_set_editable(GTK_EDITABLE(kfd->progress), FALSE);
2687 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("click start to begin"));
2688 gtk_box_pack_start(GTK_BOX(hbox), kfd->progress, TRUE, TRUE, 0);
2689 gtk_widget_show(kfd->progress);
2691 kfd->spinner = spinner_new(NULL, -1);
2692 gtk_box_pack_start(GTK_BOX(hbox), kfd->spinner, FALSE, FALSE, 0);
2693 gtk_widget_show(kfd->spinner);
2697 gtk_widget_show(kfd->gd->dialog);
2700 static void keywords_find_cb(GtkWidget *widget, gpointer data)
2702 const gchar *path = layout_get_path(NULL);
2704 if (!path || !*path) path = homedir();
2705 keywords_find_dialog(widget, path);
2708 static void config_tab_keywords_save()
2710 GtkTextIter start, end;
2711 GtkTextBuffer *buffer;
2712 GList *kw_list = NULL;
2718 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2719 gtk_text_buffer_get_bounds(buffer, &start, &end);
2721 buffer_text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
2723 kw_split = strtok(buffer_text, "\n");
2724 while (kw_split != NULL)
2730 if (g_strcmp0(work->data, kw_split) == 0)
2739 kw_list = g_list_append(kw_list, g_strdup(kw_split));
2741 kw_split = strtok(NULL, "\n");
2744 keyword_list_set(kw_list);
2746 string_list_free(kw_list);
2747 g_free(buffer_text);
2750 static void config_tab_keywords(GtkWidget *notebook)
2756 GtkWidget *scrolled;
2758 GtkTextBuffer *buffer;
2761 vbox = scrolled_notebook_page(notebook, _("Keywords"));
2763 group = pref_group_new(vbox, TRUE, _("Edit keywords autocompletion list"), GTK_ORIENTATION_VERTICAL);
2765 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2767 button = pref_button_new(hbox, GTK_STOCK_EXECUTE, _("Search"), FALSE,
2768 G_CALLBACK(keywords_find_cb), keyword_text);
2769 gtk_widget_set_tooltip_text(button, "Search for existing keywords");
2772 keyword_text = gtk_text_view_new();
2773 gtk_widget_set_size_request(keyword_text, 20, 20);
2774 scrolled = gtk_scrolled_window_new(NULL, NULL);
2775 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2776 gtk_widget_show(scrolled);
2778 gtk_container_add(GTK_CONTAINER(scrolled), keyword_text);
2779 gtk_widget_show(keyword_text);
2781 gtk_text_view_set_editable(GTK_TEXT_VIEW(keyword_text), TRUE);
2783 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2784 gtk_text_buffer_create_tag(buffer, "monospace",
2785 "family", "monospace", NULL);
2787 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(keyword_text), GTK_WRAP_WORD);
2788 gtk_text_buffer_get_start_iter(buffer, &iter);
2789 gtk_text_buffer_create_mark(buffer, "end", &iter, FALSE);
2792 path = g_build_filename(get_rc_dir(), "keywords", NULL);
2794 GList *kwl = keyword_list_get();
2795 kwl = g_list_first(kwl);
2798 gtk_text_buffer_get_end_iter (buffer, &iter);
2799 tmp = g_strconcat(kwl->data, "\n", NULL);
2800 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
2805 gtk_text_buffer_set_modified(buffer, FALSE);
2812 static void intent_menu_cb(GtkWidget *combo, gpointer data)
2814 gint *option = data;
2816 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
2820 *option = INTENT_PERCEPTUAL;
2823 *option = INTENT_RELATIVE_COLORIMETRIC;
2826 *option = INTENT_SATURATION;
2829 *option = INTENT_ABSOLUTE_COLORIMETRIC;
2834 static void add_intent_menu(GtkWidget *table, gint column, gint row, const gchar *text,
2835 gint option, gint *option_c)
2842 pref_table_label(table, column, row, text, 0.0);
2844 combo = gtk_combo_box_text_new();
2846 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Perceptual"));
2847 if (option == INTENT_PERCEPTUAL) current = 0;
2848 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Relative Colorimetric"));
2849 if (option == INTENT_RELATIVE_COLORIMETRIC) current = 1;
2850 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Saturation"));
2851 if (option == INTENT_SATURATION) current = 2;
2852 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Absolute Colorimetric"));
2853 if (option == INTENT_ABSOLUTE_COLORIMETRIC) current = 3;
2855 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
2857 gtk_widget_set_tooltip_text(combo,"Refer to the lcms documentation for the defaults used when the selected Intent is not available");
2859 g_signal_connect(G_OBJECT(combo), "changed",
2860 G_CALLBACK(intent_menu_cb), option_c);
2862 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
2863 GTK_EXPAND | GTK_FILL, 0, 0, 0);
2864 gtk_widget_show(combo);
2868 static void config_tab_color(GtkWidget *notebook)
2877 vbox = scrolled_notebook_page(notebook, _("Color management"));
2879 group = pref_group_new(vbox, FALSE, _("Input profiles"), GTK_ORIENTATION_VERTICAL);
2881 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
2884 table = pref_table_new(group, 3, COLOR_PROFILE_INPUTS + 1, FALSE, FALSE);
2885 gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
2887 label = pref_table_label(table, 0, 0, _("Type"), 0.0);
2888 pref_label_bold(label, TRUE, FALSE);
2890 label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
2891 pref_label_bold(label, TRUE, FALSE);
2893 label = pref_table_label(table, 2, 0, _("File"), 0.0);
2894 pref_label_bold(label, TRUE, FALSE);
2896 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
2901 buf = g_strdup_printf(_("Input %d:"), i + COLOR_PROFILE_FILE);
2902 pref_table_label(table, 0, i + 1, buf, 1.0);
2905 entry = gtk_entry_new();
2906 gtk_entry_set_max_length(GTK_ENTRY(entry), EDITOR_NAME_MAX_LENGTH);
2907 if (options->color_profile.input_name[i])
2909 gtk_entry_set_text(GTK_ENTRY(entry), options->color_profile.input_name[i]);
2911 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, i + 1, i + 2,
2912 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2913 gtk_widget_show(entry);
2914 color_profile_input_name_entry[i] = entry;
2916 tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, ".icc", "ICC Files", NULL);
2917 tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
2918 gtk_widget_set_size_request(entry, 160, -1);
2919 gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
2920 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2921 gtk_widget_show(tabcomp);
2922 color_profile_input_file_entry[i] = entry;
2925 group = pref_group_new(vbox, FALSE, _("Screen profile"), GTK_ORIENTATION_VERTICAL);
2927 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
2929 pref_checkbox_new_int(group, _("Use system screen profile if available"),
2930 options->color_profile.use_x11_screen_profile, &c_options->color_profile.use_x11_screen_profile);
2932 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2934 pref_table_label(table, 0, 0, _("Screen:"), 1.0);
2935 tabcomp = tab_completion_new(&color_profile_screen_file_entry,
2936 options->color_profile.screen_file, NULL, ".icc", "ICC Files", NULL);
2937 tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
2938 gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
2940 add_intent_menu(table, 0, 1, _("Render Intent:"), options->color_profile.render_intent, &c_options->color_profile.render_intent);
2942 gtk_table_attach(GTK_TABLE(table), tabcomp, 1, 2,
2944 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2946 gtk_widget_show(tabcomp);
2949 /* advanced entry tab */
2950 static void use_geeqie_trash_cb(GtkWidget *widget, gpointer data)
2952 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
2954 c_options->file_ops.use_system_trash = FALSE;
2955 c_options->file_ops.no_trash = FALSE;
2959 static void use_system_trash_cb(GtkWidget *widget, gpointer data)
2961 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
2963 c_options->file_ops.use_system_trash = TRUE;
2964 c_options->file_ops.no_trash = FALSE;
2968 static void use_no_cache_cb(GtkWidget *widget, gpointer data)
2970 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
2972 c_options->file_ops.no_trash = TRUE;
2976 static void config_tab_behavior(GtkWidget *notebook)
2983 GtkWidget *ct_button;
2987 GtkWidget *with_rename;
2988 GtkWidget *collections_on_top;
2990 vbox = scrolled_notebook_page(notebook, _("Behavior"));
2992 group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
2994 pref_checkbox_new_int(group, _("Confirm permanent file delete"),
2995 options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
2996 pref_checkbox_new_int(group, _("Confirm move file to Trash"),
2997 options->file_ops.confirm_move_to_trash, &c_options->file_ops.confirm_move_to_trash);
2998 pref_checkbox_new_int(group, _("Enable Delete key"),
2999 options->file_ops.enable_delete_key, &c_options->file_ops.enable_delete_key);
3001 ct_button = pref_radiobutton_new(group, NULL, _("Use Geeqie trash location"),
3002 !options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_geeqie_trash_cb),NULL);
3004 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3005 pref_checkbox_link_sensitivity(ct_button, hbox);
3007 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
3008 pref_label_new(hbox, _("Folder:"));
3010 tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL, NULL, NULL);
3011 tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
3012 gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
3013 gtk_widget_show(tabcomp);
3015 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3016 pref_checkbox_link_sensitivity(ct_button, hbox);
3018 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
3019 spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MB"),
3020 0, 2048, 1, options->file_ops.safe_delete_folder_maxsize, &c_options->file_ops.safe_delete_folder_maxsize);
3021 gtk_widget_set_tooltip_markup(spin, _("Set to 0 for unlimited size"));
3022 button = pref_button_new(NULL, NULL, _("View"), FALSE,
3023 G_CALLBACK(safe_delete_view_cb), NULL);
3024 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3025 gtk_widget_show(button);
3027 button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
3028 G_CALLBACK(safe_delete_clear_cb), NULL);
3029 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3030 pref_radiobutton_new(group, ct_button, _("Use system Trash bin"),
3031 options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_system_trash_cb), NULL);
3033 pref_radiobutton_new(group, ct_button, _("Use no trash at all"),
3034 options->file_ops.no_trash, G_CALLBACK(use_no_cache_cb), NULL);
3036 gtk_widget_show(button);
3038 pref_spacer(group, PREF_PAD_GROUP);
3041 group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
3043 pref_checkbox_new_int(group, _("Descend folders in tree view"),
3044 options->tree_descend_subdirs, &c_options->tree_descend_subdirs);
3046 pref_checkbox_new_int(group, _("In place renaming"),
3047 options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
3049 pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
3050 options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
3052 marks = pref_checkbox_new_int(group, _("Save marks on exit"),
3053 options->marks_save, &c_options->marks_save);
3054 gtk_widget_set_tooltip_text(marks,"Note that marks linked to a keyword will be saved irrespective of this setting");
3056 with_rename = pref_checkbox_new_int(group, _("Use \"With Rename\" as default for Copy/Move dialogs"),
3057 options->with_rename, &c_options->with_rename);
3058 gtk_widget_set_tooltip_text(with_rename,"Change the default button for Copy/Move dialogs");
3060 collections_on_top = pref_checkbox_new_int(group, _("Open collections on top"),
3061 options->collections_on_top, &c_options->collections_on_top);
3062 gtk_widget_set_tooltip_text(collections_on_top,"Open collections window on top");
3064 pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
3065 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
3067 pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
3068 16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
3070 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3071 add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
3073 pref_spacer(group, PREF_PAD_GROUP);
3075 group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
3077 pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
3078 options->progressive_key_scrolling, &c_options->progressive_key_scrolling);
3079 pref_spin_new_int(group, _("Keyboard scrolling step multiplier:"), NULL,
3080 1, 32, 1, options->keyboard_scroll_step, (int *)&c_options->keyboard_scroll_step);
3081 pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
3082 options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
3083 pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
3084 options->image_lm_click_nav, &c_options->image_lm_click_nav);
3085 pref_checkbox_new_int(group, _("Play video by left click on image"),
3086 options->image_l_click_video, &c_options->image_l_click_video);
3087 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3088 add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
3092 pref_spacer(group, PREF_PAD_GROUP);
3094 group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
3096 pref_spin_new_int(group, _("Debug level:"), NULL,
3097 DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
3099 pref_checkbox_new_int(group, _("Timer data"),
3100 options->log_window.timer_data, &c_options->log_window.timer_data);
3102 pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
3103 1, 99999, 1, options->log_window_lines, &options->log_window_lines);
3107 /* accelerators tab */
3108 static void config_tab_accelerators(GtkWidget *notebook)
3114 GtkWidget *scrolled;
3115 GtkWidget *accel_view;
3116 GtkCellRenderer *renderer;
3117 GtkTreeSelection *selection;
3118 GtkTreeViewColumn *column;
3120 vbox = scrolled_notebook_page(notebook, _("Keyboard"));
3122 group = pref_group_new(vbox, TRUE, _("Accelerators"), GTK_ORIENTATION_VERTICAL);
3124 scrolled = gtk_scrolled_window_new(NULL, NULL);
3125 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
3126 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
3127 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3128 gtk_widget_show(scrolled);
3130 accel_store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
3132 accel_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(accel_store));
3133 g_object_unref(accel_store);
3134 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(accel_view));
3135 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
3137 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(accel_view), FALSE);
3139 renderer = gtk_cell_renderer_text_new();
3141 column = gtk_tree_view_column_new_with_attributes(_("Action"),
3146 gtk_tree_view_column_set_sort_column_id(column, AE_ACTION);
3147 gtk_tree_view_column_set_resizable(column, TRUE);
3148 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3151 renderer = gtk_cell_renderer_accel_new();
3152 g_signal_connect(G_OBJECT(renderer), "accel-cleared",
3153 G_CALLBACK(accel_store_cleared_cb), accel_store);
3154 g_signal_connect(G_OBJECT(renderer), "accel-edited",
3155 G_CALLBACK(accel_store_edited_cb), accel_store);
3158 g_object_set (renderer,
3160 "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
3163 column = gtk_tree_view_column_new_with_attributes(_("KEY"),
3168 gtk_tree_view_column_set_sort_column_id(column, AE_KEY);
3169 gtk_tree_view_column_set_resizable(column, TRUE);
3170 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3172 renderer = gtk_cell_renderer_text_new();
3174 column = gtk_tree_view_column_new_with_attributes(_("Tooltip"),
3179 gtk_tree_view_column_set_sort_column_id(column, AE_TOOLTIP);
3180 gtk_tree_view_column_set_resizable(column, TRUE);
3181 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3183 renderer = gtk_cell_renderer_text_new();
3185 column = gtk_tree_view_column_new_with_attributes("Accel",
3190 gtk_tree_view_column_set_sort_column_id(column, AE_ACCEL);
3191 gtk_tree_view_column_set_resizable(column, TRUE);
3192 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3194 accel_store_populate();
3195 gtk_container_add(GTK_CONTAINER(scrolled), accel_view);
3196 gtk_widget_show(accel_view);
3198 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3200 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
3201 G_CALLBACK(accel_default_cb), accel_view);
3202 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3203 gtk_widget_show(button);
3205 button = pref_button_new(NULL, NULL, _("Reset selected"), FALSE,
3206 G_CALLBACK(accel_reset_cb), accel_view);
3207 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3208 gtk_widget_show(button);
3212 static void config_tab_toolbar(GtkWidget *notebook)
3215 GtkWidget *toolbardata;
3218 lw = layout_window_list->data;
3220 vbox = scrolled_notebook_page(notebook, _("Toolbar"));
3222 toolbardata = toolbar_select_new(lw);
3223 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3224 gtk_widget_show(vbox);
3228 static void config_tab_stereo(GtkWidget *notebook)
3236 GtkWidget *fs_button;
3237 vbox = scrolled_notebook_page(notebook, _("Stereo"));
3239 group = pref_group_new(vbox, FALSE, _("Windowed stereo mode"), GTK_ORIENTATION_VERTICAL);
3241 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3242 add_stereo_mode_menu(table, 0, 0, _("Windowed stereo mode"), options->stereo.mode, &c_options->stereo.mode, FALSE);
3244 table = pref_table_new(group, 2, 2, TRUE, FALSE);
3245 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3246 pref_checkbox_new_int(box, _("Mirror left image"),
3247 options->stereo.mode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.mirror_left);
3248 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3249 pref_checkbox_new_int(box, _("Flip left image"),
3250 options->stereo.mode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.flip_left);
3251 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3252 pref_checkbox_new_int(box, _("Mirror right image"),
3253 options->stereo.mode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.mirror_right);
3254 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3255 pref_checkbox_new_int(box, _("Flip right image"),
3256 options->stereo.mode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.flip_right);
3257 pref_checkbox_new_int(group, _("Swap left and right images"),
3258 options->stereo.mode & PR_STEREO_SWAP, &c_options->stereo.tmp.swap);
3259 pref_checkbox_new_int(group, _("Disable stereo mode on single image source"),
3260 options->stereo.mode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.temp_disable);
3262 group = pref_group_new(vbox, FALSE, _("Fullscreen stereo mode"), GTK_ORIENTATION_VERTICAL);
3263 fs_button = pref_checkbox_new_int(group, _("Use different settings for fullscreen"),
3264 options->stereo.enable_fsmode, &c_options->stereo.enable_fsmode);
3265 box2 = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
3266 pref_checkbox_link_sensitivity(fs_button, box2);
3267 table = pref_table_new(box2, 2, 1, FALSE, FALSE);
3268 add_stereo_mode_menu(table, 0, 0, _("Fullscreen stereo mode"), options->stereo.fsmode, &c_options->stereo.fsmode, TRUE);
3269 table = pref_table_new(box2, 2, 2, TRUE, FALSE);
3270 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3271 pref_checkbox_new_int(box, _("Mirror left image"),
3272 options->stereo.fsmode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.fs_mirror_left);
3273 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3274 pref_checkbox_new_int(box, _("Flip left image"),
3275 options->stereo.fsmode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.fs_flip_left);
3276 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3277 pref_checkbox_new_int(box, _("Mirror right image"),
3278 options->stereo.fsmode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.fs_mirror_right);
3279 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3280 pref_checkbox_new_int(box, _("Flip right image"),
3281 options->stereo.fsmode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.fs_flip_right);
3282 pref_checkbox_new_int(box2, _("Swap left and right images"),
3283 options->stereo.fsmode & PR_STEREO_SWAP, &c_options->stereo.tmp.fs_swap);
3284 pref_checkbox_new_int(box2, _("Disable stereo mode on single image source"),
3285 options->stereo.fsmode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.fs_temp_disable);
3287 group2 = pref_group_new(box2, FALSE, _("Fixed position"), GTK_ORIENTATION_VERTICAL);
3288 table = pref_table_new(group2, 5, 3, FALSE, FALSE);
3289 pref_table_spin_new_int(table, 0, 0, _("Width"), NULL,
3290 1, 5000, 1, options->stereo.fixed_w, &c_options->stereo.fixed_w);
3291 pref_table_spin_new_int(table, 3, 0, _("Height"), NULL,
3292 1, 5000, 1, options->stereo.fixed_h, &c_options->stereo.fixed_h);
3293 pref_table_spin_new_int(table, 0, 1, _("Left X"), NULL,
3294 0, 5000, 1, options->stereo.fixed_x1, &c_options->stereo.fixed_x1);
3295 pref_table_spin_new_int(table, 3, 1, _("Left Y"), NULL,
3296 0, 5000, 1, options->stereo.fixed_y1, &c_options->stereo.fixed_y1);
3297 pref_table_spin_new_int(table, 0, 2, _("Right X"), NULL,
3298 0, 5000, 1, options->stereo.fixed_x2, &c_options->stereo.fixed_x2);
3299 pref_table_spin_new_int(table, 3, 2, _("Right Y"), NULL,
3300 0, 5000, 1, options->stereo.fixed_y2, &c_options->stereo.fixed_y2);
3304 /* Main preferences window */
3305 static void config_window_create(void)
3307 GtkWidget *win_vbox;
3309 GtkWidget *notebook;
3311 GtkWidget *ct_button;
3313 if (!c_options) c_options = init_options(NULL);
3315 configwindow = window_new(GTK_WINDOW_TOPLEVEL, "preferences", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Preferences"));
3316 DEBUG_NAME(configwindow);
3317 gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
3318 g_signal_connect(G_OBJECT(configwindow), "delete_event",
3319 G_CALLBACK(config_window_delete), NULL);
3320 gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
3321 gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
3322 gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
3324 win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
3325 gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
3326 gtk_widget_show(win_vbox);
3328 notebook = gtk_notebook_new();
3329 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_LEFT);
3330 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE);
3331 gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
3333 config_tab_general(notebook);
3334 config_tab_image(notebook);
3335 config_tab_osd(notebook);
3336 config_tab_windows(notebook);
3337 config_tab_accelerators(notebook);
3338 config_tab_files(notebook);
3339 config_tab_metadata(notebook);
3340 config_tab_keywords(notebook);
3341 config_tab_color(notebook);
3342 config_tab_stereo(notebook);
3343 config_tab_behavior(notebook);
3344 config_tab_toolbar(notebook);
3346 hbox = gtk_hbutton_box_new();
3347 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
3348 gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
3349 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
3350 gtk_widget_show(hbox);
3352 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
3353 G_CALLBACK(config_window_help_cb), notebook);
3354 gtk_container_add(GTK_CONTAINER(hbox), button);
3355 gtk_widget_set_can_default(button, TRUE);
3356 gtk_widget_show(button);
3358 button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
3359 G_CALLBACK(config_window_ok_cb), NULL);
3360 gtk_container_add(GTK_CONTAINER(hbox), button);
3361 gtk_widget_set_can_default(button, TRUE);
3362 gtk_widget_grab_default(button);
3363 gtk_widget_show(button);
3367 button = pref_button_new(NULL, GTK_STOCK_SAVE, NULL, FALSE,
3368 G_CALLBACK(config_window_save_cb), NULL);
3369 gtk_container_add(GTK_CONTAINER(hbox), button);
3370 gtk_widget_set_can_default(button, TRUE);
3371 gtk_widget_show(button);
3373 button = pref_button_new(NULL, GTK_STOCK_APPLY, NULL, FALSE,
3374 G_CALLBACK(config_window_apply_cb), NULL);
3375 gtk_container_add(GTK_CONTAINER(hbox), button);
3376 gtk_widget_set_can_default(button, TRUE);
3377 gtk_widget_show(button);
3379 button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
3380 G_CALLBACK(config_window_close_cb), NULL);
3381 gtk_container_add(GTK_CONTAINER(hbox), button);
3382 gtk_widget_set_can_default(button, TRUE);
3383 gtk_widget_show(button);
3385 if (!generic_dialog_get_alternative_button_order(configwindow))
3387 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
3390 gtk_widget_show(notebook);
3392 gtk_widget_show(configwindow);
3396 *-----------------------------------------------------------------------------
3397 * config window show (public)
3398 *-----------------------------------------------------------------------------
3401 void show_config_window(void)
3405 gtk_window_present(GTK_WINDOW(configwindow));
3409 config_window_create();
3418 void show_about_window(LayoutWindow *lw)
3420 GdkPixbuf *pixbuf_logo;
3421 GdkPixbuf *pixbuf_icon;
3422 gchar *authors[1000];
3430 #define LINE_LENGTH 1000
3431 gchar line[LINE_LENGTH];
3433 copyright = g_string_new(NULL);
3434 copyright = g_string_append(copyright, "This program comes with absolutely no warranty.\nGNU General Public License, version 2 or later.\nSee https://www.gnu.org/licenses/old-licenses/gpl-2.0.html\n\n");
3436 zd_path = g_build_filename(GQ_BIN_DIR, TIMEZONE_DATABASE, NULL);
3437 cd = ZDOpenDatabase(zd_path);
3440 copyright = g_string_append(copyright, ZDGetNotice(cd));
3442 ZDCloseDatabase(cd);
3446 path = g_build_filename(GQ_HELPDIR, "AUTHORS", NULL);
3447 fp = fopen(path, "r");
3450 while(fgets(line, LINE_LENGTH, fp))
3452 /* get rid of ending \n from fgets */
3453 line[strlen(line) - 1] = '\0';
3454 authors[i_authors] = g_strdup(line);
3457 authors[i_authors] = NULL;
3462 comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
3463 "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
3465 pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
3466 pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
3467 gtk_show_about_dialog(GTK_WINDOW(lw->window),
3468 "title", _("About Geeqie"),
3470 "program-name", GQ_APPNAME,
3472 "logo", pixbuf_logo,
3473 "icon", pixbuf_icon,
3474 "website", GQ_WEBSITE,
3475 "website-label", "Website",
3476 "comments", comment,
3478 "translator-credits", _("translator-credits"),
3479 "wrap-license", TRUE,
3480 "license", copyright->str,
3483 g_string_free(copyright, TRUE);
3486 while(n < i_authors)
3496 static void image_overlay_set_text_colours()
3498 c_options->image_overlay.text_red = options->image_overlay.text_red;
3499 c_options->image_overlay.text_green = options->image_overlay.text_green;
3500 c_options->image_overlay.text_blue = options->image_overlay.text_blue;
3501 c_options->image_overlay.text_alpha = options->image_overlay.text_alpha;
3502 c_options->image_overlay.background_red = options->image_overlay.background_red;
3503 c_options->image_overlay.background_green = options->image_overlay.background_green;
3504 c_options->image_overlay.background_blue = options->image_overlay.background_blue;
3505 c_options->image_overlay.background_alpha = options->image_overlay.background_alpha;
3507 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */