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.safe_delete_folder_maxsize = c_options->file_ops.safe_delete_folder_maxsize;
266 options->tools_restore_state = c_options->tools_restore_state;
267 options->save_window_positions = c_options->save_window_positions;
268 options->use_saved_window_positions_for_new_windows = c_options->use_saved_window_positions_for_new_windows;
269 options->save_dialog_window_positions = c_options->save_dialog_window_positions;
270 options->show_window_ids = c_options->show_window_ids;
271 options->image.scroll_reset_method = c_options->image.scroll_reset_method;
272 options->image.zoom_2pass = c_options->image.zoom_2pass;
273 options->image.fit_window_to_image = c_options->image.fit_window_to_image;
274 options->image.limit_window_size = c_options->image.limit_window_size;
275 options->image.zoom_to_fit_allow_expand = c_options->image.zoom_to_fit_allow_expand;
276 options->image.max_window_size = c_options->image.max_window_size;
277 options->image.limit_autofit_size = c_options->image.limit_autofit_size;
278 options->image.max_autofit_size = c_options->image.max_autofit_size;
279 options->image.max_enlargement_size = c_options->image.max_enlargement_size;
280 options->image.use_clutter_renderer = c_options->image.use_clutter_renderer;
281 options->progressive_key_scrolling = c_options->progressive_key_scrolling;
282 options->keyboard_scroll_step = c_options->keyboard_scroll_step;
284 if (options->thumbnails.max_width != c_options->thumbnails.max_width
285 || options->thumbnails.max_height != c_options->thumbnails.max_height
286 || options->thumbnails.quality != c_options->thumbnails.quality)
288 thumb_format_changed = TRUE;
290 options->thumbnails.max_width = c_options->thumbnails.max_width;
291 options->thumbnails.max_height = c_options->thumbnails.max_height;
292 options->thumbnails.quality = c_options->thumbnails.quality;
294 options->thumbnails.enable_caching = c_options->thumbnails.enable_caching;
295 options->thumbnails.cache_into_dirs = c_options->thumbnails.cache_into_dirs;
296 options->thumbnails.use_exif = c_options->thumbnails.use_exif;
297 options->thumbnails.collection_preview = c_options->thumbnails.collection_preview;
298 options->thumbnails.use_ft_metadata = c_options->thumbnails.use_ft_metadata;
299 // options->thumbnails.use_ft_metadata_small = c_options->thumbnails.use_ft_metadata_small;
300 options->thumbnails.spec_standard = c_options->thumbnails.spec_standard;
301 options->metadata.enable_metadata_dirs = c_options->metadata.enable_metadata_dirs;
302 options->file_filter.show_hidden_files = c_options->file_filter.show_hidden_files;
303 options->file_filter.show_parent_directory = c_options->file_filter.show_parent_directory;
304 options->file_filter.show_dot_directory = c_options->file_filter.show_dot_directory;
305 options->file_filter.disable_file_extension_checks = c_options->file_filter.disable_file_extension_checks;
307 options->file_sort.case_sensitive = c_options->file_sort.case_sensitive;
308 options->file_sort.natural = c_options->file_sort.natural;
309 options->file_filter.disable = c_options->file_filter.disable;
311 config_entry_to_option(sidecar_ext_entry, &options->sidecar.ext, NULL);
312 sidecar_ext_parse(options->sidecar.ext);
314 options->slideshow.random = c_options->slideshow.random;
315 options->slideshow.repeat = c_options->slideshow.repeat;
316 options->slideshow.delay = c_options->slideshow.delay;
318 options->mousewheel_scrolls = c_options->mousewheel_scrolls;
319 options->image_lm_click_nav = c_options->image_lm_click_nav;
320 options->image_l_click_video = c_options->image_l_click_video;
321 options->image_l_click_video_editor = c_options->image_l_click_video_editor;
323 options->file_ops.enable_in_place_rename = c_options->file_ops.enable_in_place_rename;
325 options->image.tile_cache_max = c_options->image.tile_cache_max;
326 options->image.image_cache_max = c_options->image.image_cache_max;
328 options->image.zoom_quality = c_options->image.zoom_quality;
330 options->image.zoom_increment = c_options->image.zoom_increment;
332 options->image.enable_read_ahead = c_options->image.enable_read_ahead;
335 if (options->image.use_custom_border_color != c_options->image.use_custom_border_color
336 || options->image.use_custom_border_color_in_fullscreen != c_options->image.use_custom_border_color_in_fullscreen
337 || !gdk_color_equal(&options->image.border_color, &c_options->image.border_color))
339 options->image.use_custom_border_color_in_fullscreen = c_options->image.use_custom_border_color_in_fullscreen;
340 options->image.use_custom_border_color = c_options->image.use_custom_border_color;
341 options->image.border_color = c_options->image.border_color;
342 layout_colors_update();
343 view_window_colors_update();
346 options->image.alpha_color_1 = c_options->image.alpha_color_1;
347 options->image.alpha_color_2 = c_options->image.alpha_color_2;
349 options->fullscreen.screen = c_options->fullscreen.screen;
350 options->fullscreen.clean_flip = c_options->fullscreen.clean_flip;
351 options->fullscreen.disable_saver = c_options->fullscreen.disable_saver;
352 options->fullscreen.above = c_options->fullscreen.above;
353 if (c_options->image_overlay.template_string)
354 set_image_overlay_template_string(&options->image_overlay.template_string,
355 c_options->image_overlay.template_string);
356 if (c_options->image_overlay.font)
357 set_image_overlay_font_string(&options->image_overlay.font,
358 c_options->image_overlay.font);
359 options->image_overlay.text_red = c_options->image_overlay.text_red;
360 options->image_overlay.text_green = c_options->image_overlay.text_green;
361 options->image_overlay.text_blue = c_options->image_overlay.text_blue;
362 options->image_overlay.text_alpha = c_options->image_overlay.text_alpha;
363 options->image_overlay.background_red = c_options->image_overlay.background_red;
364 options->image_overlay.background_green = c_options->image_overlay.background_green;
365 options->image_overlay.background_blue = c_options->image_overlay.background_blue;
366 options->image_overlay.background_alpha = c_options->image_overlay.background_alpha;
367 options->update_on_time_change = c_options->update_on_time_change;
368 options->image.exif_proof_rotate_enable = c_options->image.exif_proof_rotate_enable;
370 options->duplicates_similarity_threshold = c_options->duplicates_similarity_threshold;
371 options->rot_invariant_sim = c_options->rot_invariant_sim;
373 options->tree_descend_subdirs = c_options->tree_descend_subdirs;
375 options->view_dir_list_single_click_enter = c_options->view_dir_list_single_click_enter;
377 options->open_recent_list_maxsize = c_options->open_recent_list_maxsize;
378 options->dnd_icon_size = c_options->dnd_icon_size;
379 options->clipboard_selection = c_options->clipboard_selection;
381 options->metadata.save_in_image_file = c_options->metadata.save_in_image_file;
382 options->metadata.save_legacy_IPTC = c_options->metadata.save_legacy_IPTC;
383 options->metadata.warn_on_write_problems = c_options->metadata.warn_on_write_problems;
384 options->metadata.save_legacy_format = c_options->metadata.save_legacy_format;
385 options->metadata.sync_grouped_files = c_options->metadata.sync_grouped_files;
386 options->metadata.confirm_write = c_options->metadata.confirm_write;
387 options->metadata.sidecar_extended_name = c_options->metadata.sidecar_extended_name;
388 options->metadata.confirm_timeout = c_options->metadata.confirm_timeout;
389 options->metadata.confirm_after_timeout = c_options->metadata.confirm_after_timeout;
390 options->metadata.confirm_on_image_change = c_options->metadata.confirm_on_image_change;
391 options->metadata.confirm_on_dir_change = c_options->metadata.confirm_on_dir_change;
392 options->metadata.keywords_case_sensitive = c_options->metadata.keywords_case_sensitive;
393 options->metadata.write_orientation = c_options->metadata.write_orientation;
394 options->stereo.mode = (c_options->stereo.mode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
395 (c_options->stereo.tmp.mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
396 (c_options->stereo.tmp.flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
397 (c_options->stereo.tmp.mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
398 (c_options->stereo.tmp.flip_left ? PR_STEREO_FLIP_LEFT : 0) |
399 (c_options->stereo.tmp.swap ? PR_STEREO_SWAP : 0) |
400 (c_options->stereo.tmp.temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
401 options->stereo.fsmode = (c_options->stereo.fsmode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
402 (c_options->stereo.tmp.fs_mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
403 (c_options->stereo.tmp.fs_flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
404 (c_options->stereo.tmp.fs_mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
405 (c_options->stereo.tmp.fs_flip_left ? PR_STEREO_FLIP_LEFT : 0) |
406 (c_options->stereo.tmp.fs_swap ? PR_STEREO_SWAP : 0) |
407 (c_options->stereo.tmp.fs_temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
408 options->stereo.enable_fsmode = c_options->stereo.enable_fsmode;
409 options->stereo.fixed_w = c_options->stereo.fixed_w;
410 options->stereo.fixed_h = c_options->stereo.fixed_h;
411 options->stereo.fixed_x1 = c_options->stereo.fixed_x1;
412 options->stereo.fixed_y1 = c_options->stereo.fixed_y1;
413 options->stereo.fixed_x2 = c_options->stereo.fixed_x2;
414 options->stereo.fixed_y2 = c_options->stereo.fixed_y2;
416 options->info_keywords.height = c_options->info_keywords.height;
417 options->info_title.height = c_options->info_title.height;
418 options->info_comment.height = c_options->info_comment.height;
419 options->info_rating.height = c_options->info_rating.height;
421 options->show_predefined_keyword_tree = c_options->show_predefined_keyword_tree;
423 options->marks_save = c_options->marks_save;
424 options->with_rename = c_options->with_rename;
425 options->collections_on_top = c_options->collections_on_top;
426 config_entry_to_option(help_search_engine_entry, &options->help_search_engine, NULL);
428 options->read_metadata_in_idle = c_options->read_metadata_in_idle;
430 options->star_rating.star = c_options->star_rating.star;
431 options->star_rating.rejected = c_options->star_rating.rejected;
433 set_debug_level(debug_c);
437 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
439 config_entry_to_option(color_profile_input_name_entry[i], &options->color_profile.input_name[i], NULL);
440 config_entry_to_option(color_profile_input_file_entry[i], &options->color_profile.input_file[i], NULL);
442 config_entry_to_option(color_profile_screen_file_entry, &options->color_profile.screen_file, NULL);
443 options->color_profile.use_x11_screen_profile = c_options->color_profile.use_x11_screen_profile;
444 if (options->color_profile.render_intent != c_options->color_profile.render_intent)
446 options->color_profile.render_intent = c_options->color_profile.render_intent;
451 config_tab_keywords_save();
453 image_options_sync();
458 layout_refresh(NULL);
461 if (accel_store) gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_apply_cb, NULL);
467 *-----------------------------------------------------------------------------
468 * config window main button callbacks (private)
469 *-----------------------------------------------------------------------------
472 static void config_window_close_cb(GtkWidget *widget, gpointer data)
474 gtk_widget_destroy(configwindow);
479 static void config_window_help_cb(GtkWidget *widget, gpointer data)
481 GtkWidget *notebook = data;
484 static gchar *html_section[] =
486 "GuideOptionsGeneral.html",
487 "GuideOptionsImage.html",
488 "GuideOptionsOSD.html",
489 "GuideOptionsWindow.html",
490 "GuideOptionsKeyboard.html",
491 "GuideOptionsFiltering.html",
492 "GuideOptionsMetadata.html",
493 "GuideOptionsKeywords.html",
494 "GuideOptionsColor.html",
495 "GuideOptionsStereo.html",
496 "GuideOptionsBehavior.html",
497 "GuideOptionsToolbar.html"
500 i = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
501 help_window_show(html_section[i]);
504 static gboolean config_window_delete(GtkWidget *widget, GdkEventAny *event, gpointer data)
506 config_window_close_cb(NULL, NULL);
510 static void config_window_ok_cb(GtkWidget *widget, gpointer data)
512 config_window_apply();
513 config_window_close_cb(NULL, NULL);
516 static void config_window_apply_cb(GtkWidget *widget, gpointer data)
519 lw = layout_window_list->data;
521 config_window_apply();
522 layout_util_sync(lw);
525 static void config_window_save_cb(GtkWidget *widget, gpointer data)
527 config_window_apply();
528 save_options(options);
532 *-----------------------------------------------------------------------------
533 * config window setup (private)
534 *-----------------------------------------------------------------------------
537 static void quality_menu_cb(GtkWidget *combo, gpointer data)
541 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
545 *option = GDK_INTERP_NEAREST;
548 *option = GDK_INTERP_TILES;
551 *option = GDK_INTERP_BILINEAR;
554 *option = GDK_INTERP_HYPER;
559 static void clipboard_selection_menu_cb(GtkWidget *combo, gpointer data)
563 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
575 static void add_quality_menu(GtkWidget *table, gint column, gint row, const gchar *text,
576 guint option, guint *option_c)
583 pref_table_label(table, column, row, text, 0.0);
585 combo = gtk_combo_box_text_new();
587 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Nearest (worst, but fastest)"));
588 if (option == GDK_INTERP_NEAREST) current = 0;
589 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Tiles"));
590 if (option == GDK_INTERP_TILES) current = 1;
591 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Bilinear"));
592 if (option == GDK_INTERP_BILINEAR) current = 2;
593 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Hyper (best, but slowest)"));
594 if (option == GDK_INTERP_HYPER) current = 3;
596 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
598 g_signal_connect(G_OBJECT(combo), "changed",
599 G_CALLBACK(quality_menu_cb), option_c);
601 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
602 GTK_EXPAND | GTK_FILL, 0, 0, 0);
603 gtk_widget_show(combo);
606 static void add_clipboard_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
607 gint option, gint *option_c)
614 pref_table_label(table, column, row, text, 0.0);
616 combo = gtk_combo_box_text_new();
618 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("PRIMARY"));
619 if (option == PRIMARY) current = 0;
620 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("CLIPBOARD"));
621 if (option == CLIPBOARD) current = 1;
623 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
625 g_signal_connect(G_OBJECT(combo), "changed",
626 G_CALLBACK(clipboard_selection_menu_cb), option_c);
628 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
629 GTK_EXPAND | GTK_FILL, 0, 0, 0);
630 gtk_widget_show(combo);
633 static void thumb_size_menu_cb(GtkWidget *combo, gpointer data)
637 n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
640 if ((guint) n < sizeof(thumb_size_list) / sizeof(ThumbSize))
642 c_options->thumbnails.max_width = thumb_size_list[n].w;
643 c_options->thumbnails.max_height = thumb_size_list[n].h;
647 c_options->thumbnails.max_width = options->thumbnails.max_width;
648 c_options->thumbnails.max_height = options->thumbnails.max_height;
652 static void add_thumb_size_menu(GtkWidget *table, gint column, gint row, gchar *text)
658 c_options->thumbnails.max_width = options->thumbnails.max_width;
659 c_options->thumbnails.max_height = options->thumbnails.max_height;
661 pref_table_label(table, column, row, text, 0.0);
663 combo = gtk_combo_box_text_new();
666 for (i = 0; (guint) i < sizeof(thumb_size_list) / sizeof(ThumbSize); i++)
671 w = thumb_size_list[i].w;
672 h = thumb_size_list[i].h;
674 buf = g_strdup_printf("%d x %d", w, h);
675 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
678 if (w == options->thumbnails.max_width && h == options->thumbnails.max_height) current = i;
685 buf = g_strdup_printf("%s %d x %d", _("Custom"), options->thumbnails.max_width, options->thumbnails.max_height);
686 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
692 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
693 g_signal_connect(G_OBJECT(combo), "changed",
694 G_CALLBACK(thumb_size_menu_cb), NULL);
696 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
697 GTK_EXPAND | GTK_FILL, 0, 0, 0);
698 gtk_widget_show(combo);
701 static void stereo_mode_menu_cb(GtkWidget *combo, gpointer data)
705 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
709 *option = PR_STEREO_NONE;
712 *option = PR_STEREO_ANAGLYPH_RC;
715 *option = PR_STEREO_ANAGLYPH_GM;
718 *option = PR_STEREO_ANAGLYPH_YB;
721 *option = PR_STEREO_ANAGLYPH_GRAY_RC;
724 *option = PR_STEREO_ANAGLYPH_GRAY_GM;
727 *option = PR_STEREO_ANAGLYPH_GRAY_YB;
730 *option = PR_STEREO_ANAGLYPH_DB_RC;
733 *option = PR_STEREO_ANAGLYPH_DB_GM;
736 *option = PR_STEREO_ANAGLYPH_DB_YB;
739 *option = PR_STEREO_HORIZ;
742 *option = PR_STEREO_HORIZ | PR_STEREO_HALF;
745 *option = PR_STEREO_VERT;
748 *option = PR_STEREO_VERT | PR_STEREO_HALF;
751 *option = PR_STEREO_FIXED;
756 static void add_stereo_mode_menu(GtkWidget *table, gint column, gint row, const gchar *text,
757 gint option, gint *option_c, gboolean add_fixed)
764 pref_table_label(table, column, row, text, 0.0);
766 combo = gtk_combo_box_text_new();
768 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Single image"));
770 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Red-Cyan"));
771 if (option & PR_STEREO_ANAGLYPH_RC) current = 1;
772 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Green-Magenta"));
773 if (option & PR_STEREO_ANAGLYPH_GM) current = 2;
774 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Yellow-Blue"));
775 if (option & PR_STEREO_ANAGLYPH_YB) current = 3;
776 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Red-Cyan"));
777 if (option & PR_STEREO_ANAGLYPH_GRAY_RC) current = 4;
778 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Green-Magenta"));
779 if (option & PR_STEREO_ANAGLYPH_GRAY_GM) current = 5;
780 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Yellow-Blue"));
781 if (option & PR_STEREO_ANAGLYPH_GRAY_YB) current = 6;
782 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Red-Cyan"));
783 if (option & PR_STEREO_ANAGLYPH_DB_RC) current = 7;
784 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Green-Magenta"));
785 if (option & PR_STEREO_ANAGLYPH_DB_GM) current = 8;
786 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Yellow-Blue"));
787 if (option & PR_STEREO_ANAGLYPH_DB_YB) current = 9;
789 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side"));
790 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side Half size"));
791 if (option & PR_STEREO_HORIZ)
794 if (option & PR_STEREO_HALF) current = 11;
797 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom"));
798 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom Half size"));
799 if (option & PR_STEREO_VERT)
802 if (option & PR_STEREO_HALF) current = 13;
807 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Fixed position"));
808 if (option & PR_STEREO_FIXED) current = 14;
811 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
813 g_signal_connect(G_OBJECT(combo), "changed",
814 G_CALLBACK(stereo_mode_menu_cb), option_c);
816 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
817 GTK_EXPAND | GTK_FILL, 0, 0, 0);
818 gtk_widget_show(combo);
821 static void video_menu_cb(GtkWidget *combo, gpointer data)
823 gchar **option = data;
825 EditorDescription *ed = g_list_nth_data(editor_list_get(), gtk_combo_box_get_active(GTK_COMBO_BOX(combo)));
829 static void video_menu_populate(gpointer data, gpointer user_data)
831 GtkWidget *combo = user_data;
832 EditorDescription *ed = data;
834 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), ed->name);
837 static void add_video_menu(GtkWidget *table, gint column, gint row, const gchar *text,
838 gchar *option, gchar **option_c)
842 /* use lists since they are sorted */
843 GList *eds = editor_list_get();
847 pref_table_label(table, column, row, text, 0.0);
849 combo = gtk_combo_box_text_new();
850 g_list_foreach(eds,video_menu_populate,(gpointer)combo);
851 current = option ? g_list_index(eds,g_hash_table_lookup(editors,option)): -1;
853 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
855 g_signal_connect(G_OBJECT(combo), "changed",
856 G_CALLBACK(video_menu_cb), option_c);
858 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
859 GTK_EXPAND | GTK_FILL, 0, 0, 0);
860 gtk_widget_show(combo);
863 static void filter_store_populate(void)
867 if (!filter_store) return;
869 gtk_list_store_clear(filter_store);
871 work = filter_get_list();
880 gtk_list_store_append(filter_store, &iter);
881 gtk_list_store_set(filter_store, &iter, 0, fe, -1);
885 static void filter_store_ext_edit_cb(GtkCellRendererText *cell, gchar *path_str,
886 gchar *new_text, gpointer data)
888 GtkWidget *model = data;
889 FilterEntry *fe = data;
893 if (!new_text || strlen(new_text) < 1) return;
895 tpath = gtk_tree_path_new_from_string(path_str);
896 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
897 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
899 g_free(fe->extensions);
900 fe->extensions = g_strdup(new_text);
902 gtk_tree_path_free(tpath);
906 static void filter_store_class_edit_cb(GtkCellRendererText *cell, gchar *path_str,
907 gchar *new_text, gpointer data)
909 GtkWidget *model = data;
910 FilterEntry *fe = data;
915 if (!new_text || !new_text[0]) return;
917 tpath = gtk_tree_path_new_from_string(path_str);
918 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
919 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
921 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
923 if (strcmp(new_text, _(format_class_list[i])) == 0)
930 gtk_tree_path_free(tpath);
934 static void filter_store_desc_edit_cb(GtkCellRendererText *cell, gchar *path_str,
935 gchar *new_text, gpointer data)
937 GtkWidget *model = data;
942 if (!new_text || !new_text[0]) return;
944 tpath = gtk_tree_path_new_from_string(path_str);
945 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
946 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
948 g_free(fe->description);
949 fe->description = g_strdup(new_text);
951 gtk_tree_path_free(tpath);
954 static void filter_store_enable_cb(GtkCellRendererToggle *renderer,
955 gchar *path_str, gpointer data)
957 GtkWidget *model = data;
962 tpath = gtk_tree_path_new_from_string(path_str);
963 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
964 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
966 fe->enabled = !fe->enabled;
968 gtk_tree_path_free(tpath);
972 static void filter_store_writable_cb(GtkCellRendererToggle *renderer,
973 gchar *path_str, gpointer data)
975 GtkWidget *model = data;
980 tpath = gtk_tree_path_new_from_string(path_str);
981 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
982 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
984 fe->writable = !fe->writable;
985 if (fe->writable) fe->allow_sidecar = FALSE;
987 gtk_tree_path_free(tpath);
991 static void filter_store_sidecar_cb(GtkCellRendererToggle *renderer,
992 gchar *path_str, gpointer data)
994 GtkWidget *model = data;
999 tpath = gtk_tree_path_new_from_string(path_str);
1000 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1001 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1003 fe->allow_sidecar = !fe->allow_sidecar;
1004 if (fe->allow_sidecar) fe->writable = FALSE;
1006 gtk_tree_path_free(tpath);
1010 static void filter_set_func(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
1011 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
1015 gtk_tree_model_get(tree_model, iter, 0, &fe, -1);
1017 switch (GPOINTER_TO_INT(data))
1020 g_object_set(GTK_CELL_RENDERER(cell),
1021 "active", fe->enabled, NULL);
1024 g_object_set(GTK_CELL_RENDERER(cell),
1025 "text", fe->extensions, NULL);
1027 case FE_DESCRIPTION:
1028 g_object_set(GTK_CELL_RENDERER(cell),
1029 "text", fe->description, NULL);
1032 g_object_set(GTK_CELL_RENDERER(cell),
1033 "text", _(format_class_list[fe->file_class]), NULL);
1036 g_object_set(GTK_CELL_RENDERER(cell),
1037 "active", fe->writable, NULL);
1039 case FE_ALLOW_SIDECAR:
1040 g_object_set(GTK_CELL_RENDERER(cell),
1041 "active", fe->allow_sidecar, NULL);
1046 static gboolean filter_add_scroll(gpointer data)
1050 GtkCellRenderer *cell;
1051 GtkTreeViewColumn *column;
1056 rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(filter_store), NULL);
1057 path = gtk_tree_path_new_from_indices(rows-1, -1);
1059 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data), 0);
1061 list_cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column));
1062 cell = g_list_last(list_cells)->data;
1064 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1065 path, column, FALSE, 0.0, 0.0 );
1066 gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(data),
1067 path, column, cell, TRUE);
1069 gtk_tree_path_free(path);
1070 g_list_free(list_cells);
1075 static void filter_add_cb(GtkWidget *widget, gpointer data)
1077 filter_add_unique("description", ".new", FORMAT_CLASS_IMAGE, TRUE, FALSE, TRUE);
1078 filter_store_populate();
1080 g_idle_add((GSourceFunc)filter_add_scroll, data);
1083 static void filter_remove_cb(GtkWidget *widget, gpointer data)
1085 GtkWidget *filter_view = data;
1086 GtkTreeSelection *selection;
1090 if (!filter_store) return;
1091 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1092 if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) return;
1093 gtk_tree_model_get(GTK_TREE_MODEL(filter_store), &iter, 0, &fe, -1);
1096 filter_remove_entry(fe);
1098 filter_store_populate();
1101 static gboolean filter_default_ok_scroll(GtkTreeView *data)
1105 GtkTreeViewColumn *column;
1107 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(filter_store), &iter);
1108 path = gtk_tree_model_get_path(GTK_TREE_MODEL(filter_store), &iter);
1109 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1111 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1115 gtk_tree_path_free(path);
1120 static void filter_default_ok_cb(GenericDialog *gd, gpointer data)
1123 filter_add_defaults();
1125 filter_store_populate();
1127 g_idle_add((GSourceFunc)filter_default_ok_scroll, gd->data);
1130 static void dummy_cancel_cb(GenericDialog *gd, gpointer data)
1132 /* no op, only so cancel button appears */
1135 static void filter_default_cb(GtkWidget *widget, gpointer data)
1139 gd = generic_dialog_new(_("Reset filters"),
1140 "reset_filter", widget, TRUE,
1141 dummy_cancel_cb, data);
1142 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset filters"),
1143 _("This will reset the file filters to the defaults.\nContinue?"), TRUE);
1144 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, filter_default_ok_cb, TRUE);
1145 gtk_widget_show(gd->dialog);
1148 static void filter_disable_cb(GtkWidget *widget, gpointer data)
1150 GtkWidget *frame = data;
1152 gtk_widget_set_sensitive(frame,
1153 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
1156 static void safe_delete_view_cb(GtkWidget *widget, gpointer data)
1158 layout_set_path(NULL, gtk_entry_get_text(GTK_ENTRY(safe_delete_path_entry)));
1161 static void safe_delete_clear_ok_cb(GenericDialog *gd, gpointer data)
1163 file_util_trash_clear();
1166 static void safe_delete_clear_cb(GtkWidget *widget, gpointer data)
1170 gd = generic_dialog_new(_("Clear trash"),
1171 "clear_trash", widget, TRUE,
1172 dummy_cancel_cb, NULL);
1173 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear trash"),
1174 _("This will remove the trash contents."), FALSE);
1175 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, safe_delete_clear_ok_cb, TRUE);
1176 entry = gtk_entry_new();
1177 gtk_widget_set_can_focus(entry, FALSE);
1178 gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE);
1179 if (options->file_ops.safe_delete_path) gtk_entry_set_text(GTK_ENTRY(entry), options->file_ops.safe_delete_path);
1180 gtk_box_pack_start(GTK_BOX(gd->vbox), entry, FALSE, FALSE, 0);
1181 gtk_widget_show(entry);
1182 gtk_widget_show(gd->dialog);
1185 static void image_overlay_template_view_changed_cb(GtkWidget *widget, gpointer data)
1187 GtkWidget *pTextView;
1188 GtkTextBuffer *pTextBuffer;
1192 pTextView = GTK_WIDGET(data);
1194 pTextBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pTextView));
1195 gtk_text_buffer_get_start_iter(pTextBuffer, &iStart);
1196 gtk_text_buffer_get_end_iter(pTextBuffer, &iEnd);
1198 set_image_overlay_template_string(&c_options->image_overlay.template_string,
1199 gtk_text_buffer_get_text(pTextBuffer, &iStart, &iEnd, TRUE));
1202 static void image_overlay_default_template_ok_cb(GenericDialog *gd, gpointer data)
1204 GtkTextView *text_view = data;
1205 GtkTextBuffer *buffer;
1207 set_default_image_overlay_template_string(&options->image_overlay.template_string);
1208 if (!configwindow) return;
1210 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
1211 gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1214 static void image_overlay_default_template_cb(GtkWidget *widget, gpointer data)
1218 gd = generic_dialog_new(_("Reset image overlay template string"),
1219 "reset_image_overlay_template_string", widget, TRUE,
1220 dummy_cancel_cb, data);
1221 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset image overlay template string"),
1222 _("This will reset the image overlay template string to the default.\nContinue?"), TRUE);
1223 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, image_overlay_default_template_ok_cb, TRUE);
1224 gtk_widget_show(gd->dialog);
1227 static void image_overlay_help_cb(GtkWidget *widget, gpointer data)
1229 help_window_show("GuideOptionsOSD.html");
1232 static void image_overlay_set_font_cb(GtkWidget *widget, gpointer data)
1234 #if GTK_CHECK_VERSION(3,4,0)
1237 PangoFontDescription *font_desc;
1239 dialog = gtk_font_chooser_dialog_new("Image Overlay Font", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1240 gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), options->image_overlay.font);
1242 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1244 font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
1245 font = pango_font_description_to_string(font_desc);
1246 g_free(c_options->image_overlay.font);
1247 c_options->image_overlay.font = g_strdup(font);
1251 gtk_widget_destroy(dialog);
1255 font = gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget));
1256 c_options->image_overlay.font = g_strdup(font);
1260 static void image_overlay_set_text_colour_cb(GtkWidget *widget, gpointer data)
1263 #if GTK_CHECK_VERSION(3,4,0)
1266 dialog = gtk_color_chooser_dialog_new("Image Overlay Text Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1267 colour.red = options->image_overlay.text_red;
1268 colour.green = options->image_overlay.text_green;
1269 colour.blue = options->image_overlay.text_blue;
1270 colour.alpha = options->image_overlay.text_alpha;
1271 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1272 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1274 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1276 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1277 c_options->image_overlay.text_red = colour.red*255;
1278 c_options->image_overlay.text_green = colour.green*255;
1279 c_options->image_overlay.text_blue = colour.blue*255;
1280 c_options->image_overlay.text_alpha = colour.alpha*255;
1282 gtk_widget_destroy(dialog);
1285 GtkColorSelection *colorsel;
1287 dialog = gtk_color_selection_dialog_new("Image Overlay Text Colour");
1288 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1289 colour.red = options->image_overlay.text_red*257;
1290 colour.green = options->image_overlay.text_green*257;
1291 colour.blue = options->image_overlay.text_blue*257;
1292 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1293 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1294 gtk_color_selection_set_current_color(colorsel, &colour);
1295 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.text_alpha*257);
1297 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1299 gtk_color_selection_get_current_color(colorsel, &colour);
1300 c_options->image_overlay.text_red = colour.red/257;
1301 c_options->image_overlay.text_green = colour.green/257;
1302 c_options->image_overlay.text_blue = colour.blue/257;
1303 c_options->image_overlay.text_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1305 gtk_widget_destroy (dialog);
1310 static void image_overlay_set_background_colour_cb(GtkWidget *widget, gpointer data)
1313 #if GTK_CHECK_VERSION(3,4,0)
1316 dialog = gtk_color_chooser_dialog_new("Image Overlay Background Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1317 colour.red = options->image_overlay.background_red;
1318 colour.green = options->image_overlay.background_green;
1319 colour.blue = options->image_overlay.background_blue;
1320 colour.alpha = options->image_overlay.background_alpha;
1321 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1322 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1324 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1326 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1327 c_options->image_overlay.background_red = colour.red*255;
1328 c_options->image_overlay.background_green = colour.green*255;
1329 c_options->image_overlay.background_blue = colour.blue*255;
1330 c_options->image_overlay.background_alpha = colour.alpha*255;
1332 gtk_widget_destroy(dialog);
1335 GtkColorSelection *colorsel;
1337 dialog = gtk_color_selection_dialog_new("Image Overlay Background Colour");
1338 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1339 colour.red = options->image_overlay.background_red*257;
1340 colour.green = options->image_overlay.background_green*257;
1341 colour.blue = options->image_overlay.background_blue*257;
1342 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1343 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1344 gtk_color_selection_set_current_color(colorsel, &colour);
1345 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.background_alpha*257);
1347 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1349 gtk_color_selection_get_current_color(colorsel, &colour);
1350 c_options->image_overlay.background_red = colour.red/257;
1351 c_options->image_overlay.background_green = colour.green/257;
1352 c_options->image_overlay.background_blue = colour.blue/257;
1353 c_options->image_overlay.background_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1355 gtk_widget_destroy(dialog);
1359 static void accel_store_populate(void)
1362 GList *groups, *actions;
1364 const gchar *accel_path;
1368 if (!accel_store || !layout_window_list || !layout_window_list->data) return;
1370 gtk_tree_store_clear(accel_store);
1371 lw = layout_window_list->data; /* get the actions from the first window, it should not matter, they should be the same in all windows */
1373 g_assert(lw && lw->ui_manager);
1374 groups = gtk_ui_manager_get_action_groups(lw->ui_manager);
1377 actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
1380 action = GTK_ACTION(actions->data);
1381 accel_path = gtk_action_get_accel_path(action);
1382 if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
1384 gchar *label, *label2, *tooltip, *accel;
1385 g_object_get(action,
1386 "tooltip", &tooltip,
1390 if (pango_parse_markup(label, -1, '_', NULL, &label2, NULL, NULL) && label2)
1396 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1400 gtk_tree_store_append(accel_store, &iter, NULL);
1401 gtk_tree_store_set(accel_store, &iter,
1404 AE_TOOLTIP, tooltip ? tooltip : "",
1405 AE_ACCEL, accel_path,
1413 actions = actions->next;
1416 groups = groups->next;
1420 static void accel_store_cleared_cb(GtkCellRendererAccel *accel, gchar *path_string, gpointer user_data)
1425 static gboolean accel_remove_key_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1427 gchar *accel1 = data;
1432 gtk_tree_model_get(model, iter, AE_KEY, &accel2, -1);
1434 gtk_accelerator_parse(accel1, &key1.accel_key, &key1.accel_mods);
1435 gtk_accelerator_parse(accel2, &key2.accel_key, &key2.accel_mods);
1437 if (key1.accel_key == key2.accel_key && key1.accel_mods == key2.accel_mods)
1439 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1440 DEBUG_1("accelerator key '%s' is already used, removing.", accel1);
1449 static void accel_store_edited_cb(GtkCellRendererAccel *accel, gchar *path_string, guint accel_key, GdkModifierType accel_mods, guint hardware_keycode, gpointer user_data)
1451 GtkTreeModel *model = (GtkTreeModel *)accel_store;
1455 GtkAccelKey old_key, key;
1456 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
1458 gtk_tree_model_get_iter(model, &iter, path);
1459 gtk_tree_model_get(model, &iter, AE_ACCEL, &accel_path, -1);
1461 /* test if the accelerator can be stored without conflicts*/
1462 gtk_accel_map_lookup_entry(accel_path, &old_key);
1464 /* change the key and read it back (change may fail on keys hardcoded in gtk)*/
1465 gtk_accel_map_change_entry(accel_path, accel_key, accel_mods, TRUE);
1466 gtk_accel_map_lookup_entry(accel_path, &key);
1468 /* restore the original for now, the key will be really changed when the changes are confirmed */
1469 gtk_accel_map_change_entry(accel_path, old_key.accel_key, old_key.accel_mods, TRUE);
1471 acc = gtk_accelerator_name(key.accel_key, key.accel_mods);
1472 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, acc);
1474 gtk_tree_store_set(accel_store, &iter, AE_KEY, acc, -1);
1475 gtk_tree_path_free(path);
1479 static gboolean accel_default_scroll(GtkTreeView *data)
1483 GtkTreeViewColumn *column;
1485 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(accel_store), &iter);
1486 path = gtk_tree_model_get_path(GTK_TREE_MODEL(accel_store), &iter);
1487 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1489 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1493 gtk_tree_path_free(path);
1498 static void accel_default_cb(GtkWidget *widget, gpointer data)
1500 accel_store_populate();
1502 g_idle_add((GSourceFunc)accel_default_scroll, data);
1505 void accel_remove_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1507 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1510 void accel_reset_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1513 gchar *accel_path, *accel;
1515 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, -1);
1516 gtk_accel_map_lookup_entry(accel_path, &key);
1517 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1519 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, accel);
1521 gtk_tree_store_set(accel_store, iter, AE_KEY, accel, -1);
1526 static void accel_reset_cb(GtkWidget *widget, gpointer data)
1528 GtkTreeSelection *selection;
1530 if (!accel_store) return;
1531 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data));
1532 gtk_tree_selection_selected_foreach(selection, &accel_reset_selection, NULL);
1537 static GtkWidget *scrolled_notebook_page(GtkWidget *notebook, const gchar *title)
1541 GtkWidget *scrolled;
1542 GtkWidget *viewport;
1544 scrolled = gtk_scrolled_window_new(NULL, NULL);
1545 gtk_container_set_border_width(GTK_CONTAINER(scrolled), PREF_PAD_BORDER);
1546 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1547 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1548 label = gtk_label_new(title);
1549 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, label);
1550 gtk_widget_show(scrolled);
1552 viewport = gtk_viewport_new(NULL, NULL);
1553 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1554 gtk_container_add(GTK_CONTAINER(scrolled), viewport);
1555 gtk_widget_show(viewport);
1557 vbox = gtk_vbox_new(FALSE, 0);
1558 gtk_container_add(GTK_CONTAINER(viewport), vbox);
1559 gtk_widget_show(vbox);
1564 static void cache_standard_cb(GtkWidget *widget, gpointer data)
1566 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1568 c_options->thumbnails.spec_standard =TRUE;
1569 c_options->thumbnails.cache_into_dirs = FALSE;
1573 static void cache_geeqie_cb(GtkWidget *widget, gpointer data)
1575 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1577 c_options->thumbnails.spec_standard =FALSE;
1578 c_options->thumbnails.cache_into_dirs = FALSE;
1582 static void cache_local_cb(GtkWidget *widget, gpointer data)
1584 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1586 c_options->thumbnails.cache_into_dirs = TRUE;
1587 c_options->thumbnails.spec_standard =FALSE;
1591 static void help_search_engine_entry_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1592 GdkEvent *event, gpointer userdata)
1594 if (pos == GTK_ENTRY_ICON_PRIMARY)
1596 gtk_entry_set_text(GTK_ENTRY(userdata), HELP_SEARCH_ENGINE);
1600 gtk_entry_set_text(GTK_ENTRY(userdata), "");
1604 static void star_rating_star_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1605 GdkEvent *event, gpointer userdata)
1607 gchar *rating_symbol;
1609 if (pos == GTK_ENTRY_ICON_PRIMARY)
1611 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_STAR);
1612 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1613 g_free(rating_symbol);
1617 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1618 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1619 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1623 static void star_rating_rejected_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1624 GdkEvent *event, gpointer userdata)
1626 gchar *rating_symbol;
1628 if (pos == GTK_ENTRY_ICON_PRIMARY)
1630 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_REJECTED);
1631 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1632 g_free(rating_symbol);
1636 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1637 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1638 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1642 static guint star_rating_symbol_test(GtkWidget *widget, gpointer data)
1644 GtkContainer *hbox = data;
1645 GString *str = g_string_new(NULL);
1646 GtkEntry *hex_code_entry;
1647 gchar *hex_code_full;
1650 guint64 hex_value = 0;
1652 list = gtk_container_get_children(hbox);
1654 hex_code_entry = g_list_nth_data(list, 2);
1655 hex_code_full = g_strdup(gtk_entry_get_text(hex_code_entry));
1657 hex_code = g_strsplit(hex_code_full, "+", 2);
1658 if (hex_code[0] && hex_code[1])
1660 hex_value = strtoull(hex_code[1], NULL, 16);
1662 if (!hex_value || hex_value > 0x10FFFF)
1664 hex_value = 0x003F; // Unicode 'Question Mark'
1666 str = g_string_append_unichar(str, (gunichar)hex_value);
1667 gtk_label_set_text(g_list_nth_data(list, 1), str->str);
1669 g_strfreev(hex_code);
1670 g_string_free(str, TRUE);
1671 g_free(hex_code_full);
1676 static void star_rating_star_test_cb(GtkWidget *widget, gpointer data)
1678 guint64 star_symbol;
1680 star_symbol = star_rating_symbol_test(widget, data);
1681 c_options->star_rating.star = star_symbol;
1684 static void star_rating_rejected_test_cb(GtkWidget *widget, gpointer data)
1686 guint64 rejected_symbol;
1688 rejected_symbol = star_rating_symbol_test(widget, data);
1689 c_options->star_rating.rejected = rejected_symbol;
1692 /* general options tab */
1693 static void config_tab_general(GtkWidget *notebook)
1698 GtkWidget *group_frame;
1699 GtkWidget *subgroup;
1701 GtkWidget *ct_button;
1704 gint hours, minutes, remainder;
1706 GtkWidget *star_rating_entry;
1708 gchar *rating_symbol;
1710 vbox = scrolled_notebook_page(notebook, _("General"));
1712 group = pref_group_new(vbox, FALSE, _("Thumbnails"), GTK_ORIENTATION_VERTICAL);
1714 table = pref_table_new(group, 2, 2, FALSE, FALSE);
1715 add_thumb_size_menu(table, 0, 0, _("Size:"));
1716 add_quality_menu(table, 0, 1, _("Quality:"), options->thumbnails.quality, &c_options->thumbnails.quality);
1718 ct_button = pref_checkbox_new_int(group, _("Cache thumbnails"),
1719 options->thumbnails.enable_caching, &c_options->thumbnails.enable_caching);
1721 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1722 pref_checkbox_link_sensitivity(ct_button, subgroup);
1724 c_options->thumbnails.spec_standard = options->thumbnails.spec_standard;
1725 c_options->thumbnails.cache_into_dirs = options->thumbnails.cache_into_dirs;
1726 group_frame = pref_frame_new(subgroup, TRUE, _("Use Geeqie thumbnail style and cache"),
1727 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1728 button = pref_radiobutton_new(group_frame, NULL, get_thumbnails_cache_dir(),
1729 !options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1730 G_CALLBACK(cache_geeqie_cb), NULL);
1732 group_frame = pref_frame_new(subgroup, TRUE,
1733 _("Store thumbnails local to image folder (non-standard)"),
1734 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1735 pref_radiobutton_new(group_frame, button, "*/.thumbnails",
1736 !options->thumbnails.spec_standard && options->thumbnails.cache_into_dirs,
1737 G_CALLBACK(cache_local_cb), NULL);
1739 group_frame = pref_frame_new(subgroup, TRUE,
1740 _("Use standard thumbnail style and cache, shared with other applications"),
1741 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1742 pref_radiobutton_new(group_frame, button, get_thumbnails_standard_cache_dir(),
1743 options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1744 G_CALLBACK(cache_standard_cb), NULL);
1746 pref_checkbox_new_int(group, _("Use EXIF thumbnails when available (EXIF thumbnails may be outdated)"),
1747 options->thumbnails.use_exif, &c_options->thumbnails.use_exif);
1749 spin = pref_spin_new_int(group, _("Collection preview:"), NULL,
1751 options->thumbnails.collection_preview, &c_options->thumbnails.collection_preview);
1752 gtk_widget_set_tooltip_text(spin, _("The maximum number of thumbnails shown in a Collection preview montage"));
1754 #ifdef HAVE_FFMPEGTHUMBNAILER_METADATA
1755 pref_checkbox_new_int(group, _("Use embedded metadata in video files as thumbnails when available"),
1756 options->thumbnails.use_ft_metadata, &c_options->thumbnails.use_ft_metadata);
1758 // pref_checkbox_new_int(group, _("Ignore embedded metadata if size is too small"),
1759 // options->thumbnails.use_ft_metadata_small, &c_options->thumbnails.use_ft_metadata_small);
1762 group = pref_group_new(vbox, FALSE, _("Star Rating"), GTK_ORIENTATION_VERTICAL);
1764 c_options->star_rating.star = options->star_rating.star;
1765 c_options->star_rating.rejected = options->star_rating.rejected;
1767 str = g_string_new(NULL);
1768 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1769 pref_label_new(hbox, "Star character: ");
1770 str = g_string_append_unichar(str, options->star_rating.star);
1771 pref_label_new(hbox, g_strdup(str->str));
1772 rating_symbol = g_strdup_printf("U+%X", options->star_rating.star);
1773 star_rating_entry = gtk_entry_new();
1774 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
1775 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
1776 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
1777 gtk_widget_show(star_rating_entry);
1778 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
1779 G_CALLBACK(star_rating_star_test_cb), hbox);
1780 gtk_widget_set_tooltip_text(button, _("Display selected character"));
1781 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1782 gtk_widget_show(button);
1783 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."));
1784 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1785 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
1786 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1787 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
1788 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1789 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
1790 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1791 GTK_ENTRY_ICON_PRIMARY, _("Default"));
1792 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
1793 G_CALLBACK(star_rating_star_icon_cb),
1796 g_string_free(str, TRUE);
1797 g_free(rating_symbol);
1799 str = g_string_new(NULL);
1800 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1801 pref_label_new(hbox, "Rejected character: ");
1802 str = g_string_append_unichar(str, options->star_rating.rejected);
1803 pref_label_new(hbox, g_strdup(str->str));
1804 rating_symbol = g_strdup_printf("U+%X", options->star_rating.rejected);
1805 star_rating_entry = gtk_entry_new();
1806 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
1807 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
1808 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
1809 gtk_widget_show(star_rating_entry);
1810 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
1811 G_CALLBACK(star_rating_rejected_test_cb), hbox);
1812 gtk_widget_set_tooltip_text(button, _("Display selected character"));
1813 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1814 gtk_widget_show(button);
1815 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."));
1816 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1817 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
1818 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1819 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
1820 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1821 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
1822 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1823 GTK_ENTRY_ICON_PRIMARY, _("Default"));
1824 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
1825 G_CALLBACK(star_rating_rejected_icon_cb),
1828 g_string_free(str, TRUE);
1829 g_free(rating_symbol);
1831 group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
1833 c_options->slideshow.delay = options->slideshow.delay;
1834 hours = options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
1835 remainder = options->slideshow.delay % (3600 * SLIDESHOW_SUBSECOND_PRECISION);
1836 minutes = remainder / (60 * SLIDESHOW_SUBSECOND_PRECISION);
1837 seconds = (gdouble)(remainder % (60 * SLIDESHOW_SUBSECOND_PRECISION)) /
1838 SLIDESHOW_SUBSECOND_PRECISION;
1840 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1842 spin = pref_spin_new(hbox, _("Delay between image change hrs:mins:secs.dec"), NULL,
1844 options->slideshow.delay ? hours : 0.0,
1845 G_CALLBACK(slideshow_delay_hours_cb), NULL);
1846 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1847 spin = pref_spin_new(hbox, ":" , NULL,
1849 options->slideshow.delay ? minutes: 0.0,
1850 G_CALLBACK(slideshow_delay_minutes_cb), NULL);
1851 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1852 spin = pref_spin_new(hbox, ":", NULL,
1853 SLIDESHOW_MIN_SECONDS, 59, 1.0, 1,
1854 options->slideshow.delay ? seconds : 10.0,
1855 G_CALLBACK(slideshow_delay_seconds_cb), NULL);
1856 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1858 pref_checkbox_new_int(group, _("Random"), options->slideshow.random, &c_options->slideshow.random);
1859 pref_checkbox_new_int(group, _("Repeat"), options->slideshow.repeat, &c_options->slideshow.repeat);
1861 group = pref_group_new(vbox, FALSE, _("Image loading and caching"), GTK_ORIENTATION_VERTICAL);
1863 pref_spin_new_int(group, _("Decoded image cache size (Mb):"), NULL,
1864 0, 99999, 1, options->image.image_cache_max, &c_options->image.image_cache_max);
1865 pref_checkbox_new_int(group, _("Preload next image"),
1866 options->image.enable_read_ahead, &c_options->image.enable_read_ahead);
1868 pref_checkbox_new_int(group, _("Refresh on file change"),
1869 options->update_on_time_change, &c_options->update_on_time_change);
1871 group = pref_group_new(vbox, FALSE, _("Info sidebar heights"), GTK_ORIENTATION_VERTICAL);
1872 pref_label_new(group, _("NOTE! Geeqie must be restarted for changes to take effect"));
1873 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1874 pref_spin_new_int(hbox, _("Keywords:"), NULL,
1876 options->info_keywords.height, &c_options->info_keywords.height);
1877 pref_spin_new_int(hbox, _("Title:"), NULL,
1879 options->info_title.height, &c_options->info_title.height);
1880 pref_spin_new_int(hbox, _("Comment:"), NULL,
1882 options->info_comment.height, &c_options->info_comment.height);
1883 pref_spin_new_int(hbox, _("Rating:"), NULL,
1885 options->info_rating.height, &c_options->info_rating.height);
1887 group = pref_group_new(vbox, FALSE, _("Show predefined keyword tree"), GTK_ORIENTATION_VERTICAL);
1889 pref_checkbox_new_int(group, _("Show predefined keyword tree (NOTE! Geeqie must be restarted for change to take effect)"),
1890 options->show_predefined_keyword_tree, &c_options->show_predefined_keyword_tree);
1892 group = pref_group_new(vbox, FALSE, _("On-line help search engine"), GTK_ORIENTATION_VERTICAL);
1894 help_search_engine_entry = gtk_entry_new();
1895 gtk_entry_set_text(GTK_ENTRY(help_search_engine_entry), options->help_search_engine);
1896 gtk_box_pack_start(GTK_BOX(group), help_search_engine_entry, FALSE, FALSE, 0);
1897 gtk_widget_show(help_search_engine_entry);
1899 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"));
1901 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
1902 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
1903 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
1904 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
1905 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
1906 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
1907 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
1908 GTK_ENTRY_ICON_PRIMARY, _("Default"));
1909 g_signal_connect(GTK_ENTRY(help_search_engine_entry), "icon-press",
1910 G_CALLBACK(help_search_engine_entry_icon_cb),
1911 help_search_engine_entry);
1915 static void config_tab_image(GtkWidget *notebook)
1920 GtkWidget *ct_button;
1921 GtkWidget *enlargement_button;
1925 vbox = scrolled_notebook_page(notebook, _("Image"));
1927 group = pref_group_new(vbox, FALSE, _("Zoom"), GTK_ORIENTATION_VERTICAL);
1929 table = pref_table_new(group, 2, 1, FALSE, FALSE);
1930 add_quality_menu(table, 0, 0, _("Quality:"), options->image.zoom_quality, &c_options->image.zoom_quality);
1933 pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library"),
1934 options->image.use_clutter_renderer, &c_options->image.use_clutter_renderer);
1937 pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"),
1938 options->image.zoom_2pass, &c_options->image.zoom_2pass);
1940 c_options->image.zoom_increment = options->image.zoom_increment;
1941 spin = pref_spin_new(group, _("Zoom increment:"), NULL,
1942 0.01, 4.0, 0.01, 2, (gdouble)options->image.zoom_increment / 100.0,
1943 G_CALLBACK(zoom_increment_cb), NULL);
1944 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1946 group = pref_group_new(vbox, FALSE, _("Fit image to window"), GTK_ORIENTATION_VERTICAL);
1948 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1949 enlargement_button = pref_checkbox_new_int(hbox, _("Allow enlargement of image (max. size in %)"),
1950 options->image.zoom_to_fit_allow_expand, &c_options->image.zoom_to_fit_allow_expand);
1951 spin = pref_spin_new_int(hbox, NULL, NULL,
1953 options->image.max_enlargement_size, &c_options->image.max_enlargement_size);
1954 pref_checkbox_link_sensitivity(enlargement_button, spin);
1955 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."));
1957 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1958 ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (% of actual window):"),
1959 options->image.limit_autofit_size, &c_options->image.limit_autofit_size);
1960 spin = pref_spin_new_int(hbox, NULL, NULL,
1962 options->image.max_autofit_size, &c_options->image.max_autofit_size);
1963 pref_checkbox_link_sensitivity(ct_button, spin);
1964 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."));
1966 group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
1968 pref_checkbox_new_int(group, _("Use custom border color in window mode"),
1969 options->image.use_custom_border_color, &c_options->image.use_custom_border_color);
1971 pref_checkbox_new_int(group, _("Use custom border color in fullscreen mode"),
1972 options->image.use_custom_border_color_in_fullscreen, &c_options->image.use_custom_border_color_in_fullscreen);
1974 pref_color_button_new(group, _("Border color"), &options->image.border_color,
1975 G_CALLBACK(pref_color_button_set_cb), &c_options->image.border_color);
1977 c_options->image.border_color = options->image.border_color;
1979 pref_color_button_new(group, _("Alpha channel color 1"), &options->image.alpha_color_1,
1980 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_1);
1982 pref_color_button_new(group, _("Alpha channel color 2"), &options->image.alpha_color_2,
1983 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_2);
1985 c_options->image.alpha_color_1 = options->image.alpha_color_1;
1986 c_options->image.alpha_color_2 = options->image.alpha_color_2;
1988 group = pref_group_new(vbox, FALSE, _("Convenience"), GTK_ORIENTATION_VERTICAL);
1990 pref_checkbox_new_int(group, _("Auto rotate proofs using Exif information"),
1991 options->image.exif_proof_rotate_enable, &c_options->image.exif_proof_rotate_enable);
1995 static void config_tab_windows(GtkWidget *notebook)
2001 GtkWidget *ct_button;
2004 vbox = scrolled_notebook_page(notebook, _("Windows"));
2006 group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
2008 ct_button = pref_checkbox_new_int(group, _("Remember window positions"),
2009 options->save_window_positions, &c_options->save_window_positions);
2011 button = pref_checkbox_new_int(group, _("Use saved window positions also for new windows"),
2012 options->use_saved_window_positions_for_new_windows, &c_options->use_saved_window_positions_for_new_windows);
2013 pref_checkbox_link_sensitivity(ct_button, button);
2015 pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
2016 options->tools_restore_state, &c_options->tools_restore_state);
2018 pref_checkbox_new_int(group, _("Remember dialog window positions"),
2019 options->save_dialog_window_positions, &c_options->save_dialog_window_positions);
2021 pref_checkbox_new_int(group, _("Show window IDs"),
2022 options->show_window_ids, &c_options->show_window_ids);
2024 group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
2026 pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
2027 options->image.fit_window_to_image, &c_options->image.fit_window_to_image);
2029 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2030 ct_button = pref_checkbox_new_int(hbox, _("Limit size when auto-sizing window (%):"),
2031 options->image.limit_window_size, &c_options->image.limit_window_size);
2032 spin = pref_spin_new_int(hbox, NULL, NULL,
2034 options->image.max_window_size, &c_options->image.max_window_size);
2035 pref_checkbox_link_sensitivity(ct_button, spin);
2037 group = pref_group_new(vbox, FALSE, _("Full screen"), GTK_ORIENTATION_VERTICAL);
2039 c_options->fullscreen.screen = options->fullscreen.screen;
2040 c_options->fullscreen.above = options->fullscreen.above;
2041 hbox = fullscreen_prefs_selection_new(_("Location:"), &c_options->fullscreen.screen, &c_options->fullscreen.above);
2042 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2043 gtk_widget_show(hbox);
2045 pref_checkbox_new_int(group, _("Smooth image flip"),
2046 options->fullscreen.clean_flip, &c_options->fullscreen.clean_flip);
2047 pref_checkbox_new_int(group, _("Disable screen saver"),
2048 options->fullscreen.disable_saver, &c_options->fullscreen.disable_saver);
2051 #define PRE_FORMATTED_COLUMNS 5
2052 static void config_tab_osd(GtkWidget *notebook)
2056 GtkWidget *vbox_buttons;
2059 GtkWidget *image_overlay_template_view;
2060 GtkWidget *scrolled;
2061 GtkWidget *scrolled_pre_formatted;
2062 GtkTextBuffer *buffer;
2064 GtkWidget * subgroup;
2069 vbox = scrolled_notebook_page(notebook, _("OSD"));
2071 image_overlay_template_view = gtk_text_view_new();
2073 group = pref_group_new(vbox, FALSE, _("Overlay Screen Display"), GTK_ORIENTATION_VERTICAL);
2075 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2077 scrolled_pre_formatted = osd_new(PRE_FORMATTED_COLUMNS, image_overlay_template_view);
2078 gtk_widget_set_size_request(scrolled_pre_formatted, 200, 150);
2079 gtk_box_pack_start(GTK_BOX(subgroup), scrolled_pre_formatted, FALSE, FALSE, 0);
2080 gtk_widget_show(scrolled_pre_formatted);
2081 gtk_widget_show(subgroup);
2083 pref_line(group, PREF_PAD_GAP);
2085 pref_label_new(group, _("Image overlay template"));
2087 scrolled = gtk_scrolled_window_new(NULL, NULL);
2088 gtk_widget_set_size_request(scrolled, 200, 150);
2089 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2090 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
2091 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2092 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 5);
2093 gtk_widget_show(scrolled);
2095 gtk_widget_set_tooltip_markup(image_overlay_template_view,
2096 _("Extensive formatting options are shown in the Help file"));
2098 gtk_container_add(GTK_CONTAINER(scrolled), image_overlay_template_view);
2099 gtk_widget_show(image_overlay_template_view);
2101 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2103 #if GTK_CHECK_VERSION(3,4,0)
2104 button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
2105 G_CALLBACK(image_overlay_set_font_cb), notebook);
2107 button = gtk_font_button_new();
2108 gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Image Overlay Font");
2109 gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->image_overlay.font);
2110 g_signal_connect(G_OBJECT(button), "font-set",
2111 G_CALLBACK(image_overlay_set_font_cb),NULL);
2113 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2114 gtk_widget_show(button);
2116 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Text"), FALSE,
2117 G_CALLBACK(image_overlay_set_text_colour_cb), NULL);
2118 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2119 gtk_widget_show(button);
2121 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Background"), FALSE,
2122 G_CALLBACK(image_overlay_set_background_colour_cb), NULL);
2123 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2124 gtk_widget_show(button);
2125 image_overlay_set_text_colours();
2127 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2128 G_CALLBACK(image_overlay_default_template_cb), image_overlay_template_view);
2129 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2130 gtk_widget_show(button);
2132 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
2133 G_CALLBACK(image_overlay_help_cb), NULL);
2134 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2135 gtk_widget_show(button);
2137 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_overlay_template_view));
2138 if (options->image_overlay.template_string) gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
2139 g_signal_connect(G_OBJECT(buffer), "changed",
2140 G_CALLBACK(image_overlay_template_view_changed_cb), image_overlay_template_view);
2142 pref_line(group, PREF_PAD_GAP);
2144 group = pref_group_new(vbox, FALSE, _("Exif, XMP or IPTC tags"), GTK_ORIENTATION_VERTICAL);
2145 hbox = gtk_hbox_new(FALSE, 0);
2146 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2147 gtk_widget_show(hbox);
2148 label = gtk_label_new(_("%Exif.Image.Orientation%"));
2149 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2150 gtk_widget_show(label);
2151 pref_spacer(group,TRUE);
2153 group = pref_group_new(vbox, FALSE, _("Field separators"), GTK_ORIENTATION_VERTICAL);
2154 hbox = gtk_hbox_new(FALSE, 0);
2155 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2156 gtk_widget_show(hbox);
2157 label = gtk_label_new(_("Separator shown only if both fields are non-null:\n%formatted.ShutterSpeed%|%formatted.ISOSpeedRating%"));
2158 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2159 gtk_widget_show(label);
2160 pref_spacer(group,TRUE);
2162 group = pref_group_new(vbox, FALSE, _("Field maximum length"), GTK_ORIENTATION_VERTICAL);
2163 hbox = gtk_hbox_new(FALSE, 0);
2164 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2165 gtk_widget_show(hbox);
2166 label = gtk_label_new(_("%path:39%"));
2167 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2168 gtk_widget_show(label);
2169 pref_spacer(group,TRUE);
2171 group = pref_group_new(vbox, FALSE, _("Pre- and post- text"), GTK_ORIENTATION_VERTICAL);
2172 hbox = gtk_hbox_new(FALSE, 0);
2173 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2174 gtk_widget_show(hbox);
2175 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%"));
2176 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2177 gtk_widget_show(label);
2178 pref_spacer(group,TRUE);
2180 group = pref_group_new(vbox, FALSE, _("Pango markup"), GTK_ORIENTATION_VERTICAL);
2181 hbox = gtk_hbox_new(FALSE, 0);
2182 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2183 gtk_widget_show(hbox);
2184 label = gtk_label_new(_("<b>bold</b>\n<u>underline</u>\n<i>italic</i>\n<s>strikethrough</s>"));
2185 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2186 gtk_widget_show(label);
2189 static GtkTreeModel *create_class_model(void)
2191 GtkListStore *model;
2195 /* create list store */
2196 model = gtk_list_store_new(1, G_TYPE_STRING);
2197 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
2199 gtk_list_store_append(model, &iter);
2200 gtk_list_store_set(model, &iter, 0, _(format_class_list[i]), -1);
2202 return GTK_TREE_MODEL (model);
2207 static void config_tab_files(GtkWidget *notebook)
2214 GtkWidget *ct_button;
2215 GtkWidget *scrolled;
2216 GtkWidget *filter_view;
2217 GtkCellRenderer *renderer;
2218 GtkTreeSelection *selection;
2219 GtkTreeViewColumn *column;
2221 vbox = scrolled_notebook_page(notebook, _("Files"));
2223 group = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2225 pref_checkbox_new_int(group, _("Show hidden files or folders"),
2226 options->file_filter.show_hidden_files, &c_options->file_filter.show_hidden_files);
2227 pref_checkbox_new_int(group, _("Show parent folder (..)"),
2228 options->file_filter.show_parent_directory, &c_options->file_filter.show_parent_directory);
2229 pref_checkbox_new_int(group, _("Case sensitive sort"),
2230 options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
2231 pref_checkbox_new_int(group, _("Natural sort order"),
2232 options->file_sort.natural, &c_options->file_sort.natural);
2233 pref_checkbox_new_int(group, _("Disable file extension checks"),
2234 options->file_filter.disable_file_extension_checks, &c_options->file_filter.disable_file_extension_checks);
2236 ct_button = pref_checkbox_new_int(group, _("Disable File Filtering"),
2237 options->file_filter.disable, &c_options->file_filter.disable);
2240 group = pref_group_new(vbox, FALSE, _("Grouping sidecar extensions"), GTK_ORIENTATION_VERTICAL);
2242 sidecar_ext_entry = gtk_entry_new();
2243 gtk_entry_set_text(GTK_ENTRY(sidecar_ext_entry), options->sidecar.ext);
2244 gtk_box_pack_start(GTK_BOX(group), sidecar_ext_entry, FALSE, FALSE, 0);
2245 gtk_widget_show(sidecar_ext_entry);
2247 group = pref_group_new(vbox, TRUE, _("File types"), GTK_ORIENTATION_VERTICAL);
2249 frame = pref_group_parent(group);
2250 g_signal_connect(G_OBJECT(ct_button), "toggled",
2251 G_CALLBACK(filter_disable_cb), frame);
2252 gtk_widget_set_sensitive(frame, !options->file_filter.disable);
2254 scrolled = gtk_scrolled_window_new(NULL, NULL);
2255 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2256 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2257 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2258 gtk_widget_show(scrolled);
2260 filter_store = gtk_list_store_new(1, G_TYPE_POINTER);
2261 filter_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(filter_store));
2262 g_object_unref(filter_store);
2263 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
2264 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
2266 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), FALSE);
2268 column = gtk_tree_view_column_new();
2269 gtk_tree_view_column_set_title(column, _("Filter"));
2270 gtk_tree_view_column_set_resizable(column, TRUE);
2272 renderer = gtk_cell_renderer_toggle_new();
2273 g_signal_connect(G_OBJECT(renderer), "toggled",
2274 G_CALLBACK(filter_store_enable_cb), filter_store);
2275 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2276 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2277 GINT_TO_POINTER(FE_ENABLE), NULL);
2279 renderer = gtk_cell_renderer_text_new();
2280 g_signal_connect(G_OBJECT(renderer), "edited",
2281 G_CALLBACK(filter_store_ext_edit_cb), filter_store);
2282 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2283 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2284 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2285 GINT_TO_POINTER(FE_EXTENSION), NULL);
2286 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2288 column = gtk_tree_view_column_new();
2289 gtk_tree_view_column_set_title(column, _("Description"));
2290 gtk_tree_view_column_set_resizable(column, TRUE);
2291 gtk_tree_view_column_set_fixed_width(column, 200);
2292 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
2294 renderer = gtk_cell_renderer_text_new();
2295 g_signal_connect(G_OBJECT(renderer), "edited",
2296 G_CALLBACK(filter_store_desc_edit_cb), filter_store);
2297 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2298 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2299 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2300 GINT_TO_POINTER(FE_DESCRIPTION), NULL);
2301 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2303 column = gtk_tree_view_column_new();
2304 gtk_tree_view_column_set_title(column, _("Class"));
2305 gtk_tree_view_column_set_resizable(column, TRUE);
2306 renderer = gtk_cell_renderer_combo_new();
2307 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE,
2308 "model", create_class_model(),
2313 g_signal_connect(G_OBJECT(renderer), "edited",
2314 G_CALLBACK(filter_store_class_edit_cb), filter_store);
2315 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2316 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2317 GINT_TO_POINTER(FE_CLASS), NULL);
2318 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2320 column = gtk_tree_view_column_new();
2321 gtk_tree_view_column_set_title(column, _("Writable"));
2322 gtk_tree_view_column_set_resizable(column, FALSE);
2323 renderer = gtk_cell_renderer_toggle_new();
2324 g_signal_connect(G_OBJECT(renderer), "toggled",
2325 G_CALLBACK(filter_store_writable_cb), filter_store);
2326 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2327 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2328 GINT_TO_POINTER(FE_WRITABLE), NULL);
2329 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2331 column = gtk_tree_view_column_new();
2332 gtk_tree_view_column_set_title(column, _("Sidecar is allowed"));
2333 gtk_tree_view_column_set_resizable(column, FALSE);
2334 renderer = gtk_cell_renderer_toggle_new();
2335 g_signal_connect(G_OBJECT(renderer), "toggled",
2336 G_CALLBACK(filter_store_sidecar_cb), filter_store);
2337 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2338 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2339 GINT_TO_POINTER(FE_ALLOW_SIDECAR), NULL);
2340 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2343 filter_store_populate();
2344 gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
2345 gtk_widget_show(filter_view);
2347 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2349 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2350 G_CALLBACK(filter_default_cb), filter_view);
2351 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2352 gtk_widget_show(button);
2354 button = pref_button_new(NULL, GTK_STOCK_REMOVE, NULL, FALSE,
2355 G_CALLBACK(filter_remove_cb), filter_view);
2356 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2357 gtk_widget_show(button);
2359 button = pref_button_new(NULL, GTK_STOCK_ADD, NULL, FALSE,
2360 G_CALLBACK(filter_add_cb), filter_view);
2361 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2362 gtk_widget_show(button);
2366 static void config_tab_metadata(GtkWidget *notebook)
2371 GtkWidget *ct_button;
2375 vbox = scrolled_notebook_page(notebook, _("Metadata"));
2378 group = pref_group_new(vbox, FALSE, _("Metadata writing process"), GTK_ORIENTATION_VERTICAL);
2380 label = pref_label_new(group, _("Warning: Geeqie is built without Exiv2. Some options are disabled."));
2382 label = pref_label_new(group, _("Metadata are written in the following order. The process ends after first success."));
2383 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2385 ct_button = pref_checkbox_new_int(group, _("1) Save metadata in image files, or sidecar files, according to the XMP standard"),
2386 options->metadata.save_in_image_file, &c_options->metadata.save_in_image_file);
2388 gtk_widget_set_sensitive(ct_button, FALSE);
2391 pref_checkbox_new_int(group, _("2) Save metadata in '.metadata' folder, local to image folder (non-standard)"),
2392 options->metadata.enable_metadata_dirs, &c_options->metadata.enable_metadata_dirs);
2394 text = g_strdup_printf(_("3) Save metadata in Geeqie private directory '%s'"), get_metadata_cache_dir());
2395 label = pref_label_new(group, text);
2396 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2397 gtk_misc_set_padding(GTK_MISC(label), 22, 0);
2400 group = pref_group_new(vbox, FALSE, _("Step 1: Write to image files"), GTK_ORIENTATION_VERTICAL);
2402 gtk_widget_set_sensitive(group, FALSE);
2405 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2406 pref_checkbox_link_sensitivity(ct_button, hbox);
2408 pref_checkbox_new_int(hbox, _("Store metadata also in legacy IPTC tags (converted according to IPTC4XMP standard)"),
2409 options->metadata.save_legacy_IPTC, &c_options->metadata.save_legacy_IPTC);
2411 pref_checkbox_new_int(hbox, _("Warn if the image files are unwritable"),
2412 options->metadata.warn_on_write_problems, &c_options->metadata.warn_on_write_problems);
2414 pref_checkbox_new_int(hbox, _("Ask before writing to image files"),
2415 options->metadata.confirm_write, &c_options->metadata.confirm_write);
2417 pref_checkbox_new_int(hbox, _("Create sidecar files named image.ext.xmp (as opposed to image.xmp)"),
2418 options->metadata.sidecar_extended_name, &c_options->metadata.sidecar_extended_name);
2420 group = pref_group_new(vbox, FALSE, _("Step 2 and 3: write to Geeqie private files"), GTK_ORIENTATION_VERTICAL);
2422 gtk_widget_set_sensitive(group, FALSE);
2425 pref_checkbox_new_int(group, _("Use GQview legacy metadata format (supports only keywords and comments) instead of XMP"),
2426 options->metadata.save_legacy_format, &c_options->metadata.save_legacy_format);
2429 group = pref_group_new(vbox, FALSE, _("Miscellaneous"), GTK_ORIENTATION_VERTICAL);
2430 pref_checkbox_new_int(group, _("Write the same description tags (keywords, comment, etc.) to all grouped sidecars"),
2431 options->metadata.sync_grouped_files, &c_options->metadata.sync_grouped_files);
2433 pref_checkbox_new_int(group, _("Allow keywords to differ only in case"),
2434 options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
2436 ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"),
2437 options->metadata.write_orientation, &c_options->metadata.write_orientation);
2439 gtk_widget_set_sensitive(ct_button, FALSE);
2442 group = pref_group_new(vbox, FALSE, _("Auto-save options"), GTK_ORIENTATION_VERTICAL);
2444 ct_button = pref_checkbox_new_int(group, _("Write metadata after timeout"),
2445 options->metadata.confirm_after_timeout, &c_options->metadata.confirm_after_timeout);
2447 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2448 pref_checkbox_link_sensitivity(ct_button, hbox);
2450 pref_spin_new_int(hbox, _("Timeout (seconds):"), NULL, 0, 900, 1,
2451 options->metadata.confirm_timeout, &c_options->metadata.confirm_timeout);
2453 pref_checkbox_new_int(group, _("Write metadata on image change"),
2454 options->metadata.confirm_on_image_change, &c_options->metadata.confirm_on_image_change);
2456 pref_checkbox_new_int(group, _("Write metadata on directory change"),
2457 options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
2459 group = pref_group_new(vbox, FALSE, _("Pre-load metadata"), GTK_ORIENTATION_VERTICAL);
2461 ct_button = pref_checkbox_new_int(group, _("Read metadata in background"),
2462 options->read_metadata_in_idle, &c_options->read_metadata_in_idle);
2463 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");
2468 typedef struct _KeywordFindData KeywordFindData;
2469 struct _KeywordFindData
2476 GtkWidget *button_close;
2477 GtkWidget *button_stop;
2478 GtkWidget *button_start;
2479 GtkWidget *progress;
2487 guint idle_id; /* event source id */
2490 #define KEYWORD_DIALOG_WIDTH 400
2492 static void keywords_find_folder(KeywordFindData *kfd, FileData *dir_fd)
2494 GList *list_d = NULL;
2495 GList *list_f = NULL;
2499 filelist_read(dir_fd, &list_f, &list_d);
2503 filelist_read(dir_fd, &list_f, NULL);
2506 list_f = filelist_filter(list_f, FALSE);
2507 list_d = filelist_filter(list_d, TRUE);
2509 kfd->list = g_list_concat(list_f, kfd->list);
2510 kfd->list_dir = g_list_concat(list_d, kfd->list_dir);
2513 static void keywords_find_reset(KeywordFindData *kfd)
2515 filelist_free(kfd->list);
2518 filelist_free(kfd->list_dir);
2519 kfd->list_dir = NULL;
2522 static void keywords_find_close_cb(GenericDialog *fd, gpointer data)
2524 KeywordFindData *kfd = data;
2526 if (!gtk_widget_get_sensitive(kfd->button_close)) return;
2528 keywords_find_reset(kfd);
2529 generic_dialog_close(kfd->gd);
2533 static void keywords_find_finish(KeywordFindData *kfd)
2535 keywords_find_reset(kfd);
2537 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("done"));
2538 spinner_set_interval(kfd->spinner, -1);
2540 gtk_widget_set_sensitive(kfd->group, TRUE);
2541 gtk_widget_set_sensitive(kfd->button_start, TRUE);
2542 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2543 gtk_widget_set_sensitive(kfd->button_close, TRUE);
2546 static void keywords_find_stop_cb(GenericDialog *fd, gpointer data)
2548 KeywordFindData *kfd = data;
2550 g_idle_remove_by_data(kfd);
2552 keywords_find_finish(kfd);
2555 static gboolean keywords_find_file(gpointer data)
2557 KeywordFindData *kfd = data;
2559 GtkTextBuffer *buffer;
2567 fd = kfd->list->data;
2568 kfd->list = g_list_remove(kfd->list, fd);
2570 keywords = metadata_read_list(fd, KEYWORD_KEY, METADATA_PLAIN);
2571 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2575 gtk_text_buffer_get_end_iter(buffer, &iter);
2576 tmp = g_strconcat(keywords->data, "\n", NULL);
2577 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
2579 keywords = keywords->next;
2582 gtk_entry_set_text(GTK_ENTRY(kfd->progress), fd->path);
2583 file_data_unref(fd);
2584 string_list_free(keywords);
2588 else if (kfd->list_dir)
2592 fd = kfd->list_dir->data;
2593 kfd->list_dir = g_list_remove(kfd->list_dir, fd);
2595 keywords_find_folder(kfd, fd);
2597 file_data_unref(fd);
2602 keywords_find_finish(kfd);
2607 static void keywords_find_start_cb(GenericDialog *fd, gpointer data)
2609 KeywordFindData *kfd = data;
2612 if (kfd->list || !gtk_widget_get_sensitive(kfd->button_start)) return;
2614 path = remove_trailing_slash((gtk_entry_get_text(GTK_ENTRY(kfd->entry))));
2615 parse_out_relatives(path);
2619 warning_dialog(_("Invalid folder"),
2620 _("The specified folder can not be found."),
2621 GTK_STOCK_DIALOG_WARNING, kfd->gd->dialog);
2627 gtk_widget_set_sensitive(kfd->group, FALSE);
2628 gtk_widget_set_sensitive(kfd->button_start, FALSE);
2629 gtk_widget_set_sensitive(kfd->button_stop, TRUE);
2630 gtk_widget_set_sensitive(kfd->button_close, FALSE);
2631 spinner_set_interval(kfd->spinner, SPINNER_SPEED);
2633 dir_fd = file_data_new_dir(path);
2634 keywords_find_folder(kfd, dir_fd);
2635 file_data_unref(dir_fd);
2636 kfd->idle_id = g_idle_add(keywords_find_file, kfd);
2642 static void keywords_find_dialog(GtkWidget *widget, const gchar *path)
2644 KeywordFindData *kfd;
2648 kfd = g_new0(KeywordFindData, 1);
2650 kfd->gd = generic_dialog_new(_("Search for keywords"),
2651 "search_for_keywords",
2654 gtk_window_set_default_size(GTK_WINDOW(kfd->gd->dialog), KEYWORD_DIALOG_WIDTH, -1);
2655 kfd->gd->cancel_cb = keywords_find_close_cb;
2656 kfd->button_close = generic_dialog_add_button(kfd->gd, GTK_STOCK_CLOSE, NULL,
2657 keywords_find_close_cb, FALSE);
2658 kfd->button_start = generic_dialog_add_button(kfd->gd, GTK_STOCK_OK, _("S_tart"),
2659 keywords_find_start_cb, FALSE);
2660 kfd->button_stop = generic_dialog_add_button(kfd->gd, GTK_STOCK_STOP, NULL,
2661 keywords_find_stop_cb, FALSE);
2662 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2664 generic_dialog_add_message(kfd->gd, NULL, _("Search for keywords"), NULL, FALSE);
2666 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0);
2667 pref_spacer(hbox, PREF_PAD_INDENT);
2668 kfd->group = pref_box_new(hbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2670 hbox = pref_box_new(kfd->group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2671 pref_label_new(hbox, _("Folder:"));
2673 label = tab_completion_new(&kfd->entry, path, NULL, NULL, NULL, NULL);
2674 tab_completion_add_select_button(kfd->entry,_("Select folder") , TRUE);
2675 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
2676 gtk_widget_show(label);
2678 pref_checkbox_new_int(kfd->group, _("Include subfolders"), FALSE, &kfd->recurse);
2680 pref_line(kfd->gd->vbox, PREF_PAD_SPACE);
2681 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2683 kfd->progress = gtk_entry_new();
2684 gtk_widget_set_can_focus(kfd->progress, FALSE);
2685 gtk_editable_set_editable(GTK_EDITABLE(kfd->progress), FALSE);
2686 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("click start to begin"));
2687 gtk_box_pack_start(GTK_BOX(hbox), kfd->progress, TRUE, TRUE, 0);
2688 gtk_widget_show(kfd->progress);
2690 kfd->spinner = spinner_new(NULL, -1);
2691 gtk_box_pack_start(GTK_BOX(hbox), kfd->spinner, FALSE, FALSE, 0);
2692 gtk_widget_show(kfd->spinner);
2696 gtk_widget_show(kfd->gd->dialog);
2699 static void keywords_find_cb(GtkWidget *widget, gpointer data)
2701 const gchar *path = layout_get_path(NULL);
2703 if (!path || !*path) path = homedir();
2704 keywords_find_dialog(widget, path);
2707 static void config_tab_keywords_save()
2709 GtkTextIter start, end;
2710 GtkTextBuffer *buffer;
2711 GList *kw_list = NULL;
2717 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2718 gtk_text_buffer_get_bounds(buffer, &start, &end);
2720 buffer_text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
2722 kw_split = strtok(buffer_text, "\n");
2723 while (kw_split != NULL)
2729 if (g_strcmp0(work->data, kw_split) == 0)
2738 kw_list = g_list_append(kw_list, g_strdup(kw_split));
2740 kw_split = strtok(NULL, "\n");
2743 keyword_list_set(kw_list);
2745 string_list_free(kw_list);
2746 g_free(buffer_text);
2749 static void config_tab_keywords(GtkWidget *notebook)
2755 GtkWidget *scrolled;
2757 GtkTextBuffer *buffer;
2760 vbox = scrolled_notebook_page(notebook, _("Keywords"));
2762 group = pref_group_new(vbox, TRUE, _("Edit keywords autocompletion list"), GTK_ORIENTATION_VERTICAL);
2764 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2766 button = pref_button_new(hbox, GTK_STOCK_EXECUTE, _("Search"), FALSE,
2767 G_CALLBACK(keywords_find_cb), keyword_text);
2768 gtk_widget_set_tooltip_text(button, "Search for existing keywords");
2771 keyword_text = gtk_text_view_new();
2772 gtk_widget_set_size_request(keyword_text, 20, 20);
2773 scrolled = gtk_scrolled_window_new(NULL, NULL);
2774 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2775 gtk_widget_show(scrolled);
2777 gtk_container_add(GTK_CONTAINER(scrolled), keyword_text);
2778 gtk_widget_show(keyword_text);
2780 gtk_text_view_set_editable(GTK_TEXT_VIEW(keyword_text), TRUE);
2782 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2783 gtk_text_buffer_create_tag(buffer, "monospace",
2784 "family", "monospace", NULL);
2786 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(keyword_text), GTK_WRAP_WORD);
2787 gtk_text_buffer_get_start_iter(buffer, &iter);
2788 gtk_text_buffer_create_mark(buffer, "end", &iter, FALSE);
2791 path = g_build_filename(get_rc_dir(), "keywords", NULL);
2793 GList *kwl = keyword_list_get();
2794 kwl = g_list_first(kwl);
2797 gtk_text_buffer_get_end_iter (buffer, &iter);
2798 tmp = g_strconcat(kwl->data, "\n", NULL);
2799 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
2804 gtk_text_buffer_set_modified(buffer, FALSE);
2811 static void intent_menu_cb(GtkWidget *combo, gpointer data)
2813 gint *option = data;
2815 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
2819 *option = INTENT_PERCEPTUAL;
2822 *option = INTENT_RELATIVE_COLORIMETRIC;
2825 *option = INTENT_SATURATION;
2828 *option = INTENT_ABSOLUTE_COLORIMETRIC;
2833 static void add_intent_menu(GtkWidget *table, gint column, gint row, const gchar *text,
2834 gint option, gint *option_c)
2841 pref_table_label(table, column, row, text, 0.0);
2843 combo = gtk_combo_box_text_new();
2845 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Perceptual"));
2846 if (option == INTENT_PERCEPTUAL) current = 0;
2847 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Relative Colorimetric"));
2848 if (option == INTENT_RELATIVE_COLORIMETRIC) current = 1;
2849 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Saturation"));
2850 if (option == INTENT_SATURATION) current = 2;
2851 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Absolute Colorimetric"));
2852 if (option == INTENT_ABSOLUTE_COLORIMETRIC) current = 3;
2854 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
2856 gtk_widget_set_tooltip_text(combo,"Refer to the lcms documentation for the defaults used when the selected Intent is not available");
2858 g_signal_connect(G_OBJECT(combo), "changed",
2859 G_CALLBACK(intent_menu_cb), option_c);
2861 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
2862 GTK_EXPAND | GTK_FILL, 0, 0, 0);
2863 gtk_widget_show(combo);
2867 static void config_tab_color(GtkWidget *notebook)
2876 vbox = scrolled_notebook_page(notebook, _("Color management"));
2878 group = pref_group_new(vbox, FALSE, _("Input profiles"), GTK_ORIENTATION_VERTICAL);
2880 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
2883 table = pref_table_new(group, 3, COLOR_PROFILE_INPUTS + 1, FALSE, FALSE);
2884 gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
2886 label = pref_table_label(table, 0, 0, _("Type"), 0.0);
2887 pref_label_bold(label, TRUE, FALSE);
2889 label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
2890 pref_label_bold(label, TRUE, FALSE);
2892 label = pref_table_label(table, 2, 0, _("File"), 0.0);
2893 pref_label_bold(label, TRUE, FALSE);
2895 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
2900 buf = g_strdup_printf(_("Input %d:"), i + COLOR_PROFILE_FILE);
2901 pref_table_label(table, 0, i + 1, buf, 1.0);
2904 entry = gtk_entry_new();
2905 gtk_entry_set_max_length(GTK_ENTRY(entry), EDITOR_NAME_MAX_LENGTH);
2906 if (options->color_profile.input_name[i])
2908 gtk_entry_set_text(GTK_ENTRY(entry), options->color_profile.input_name[i]);
2910 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, i + 1, i + 2,
2911 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2912 gtk_widget_show(entry);
2913 color_profile_input_name_entry[i] = entry;
2915 tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, ".icc", "ICC Files", NULL);
2916 tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
2917 gtk_widget_set_size_request(entry, 160, -1);
2918 gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
2919 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2920 gtk_widget_show(tabcomp);
2921 color_profile_input_file_entry[i] = entry;
2924 group = pref_group_new(vbox, FALSE, _("Screen profile"), GTK_ORIENTATION_VERTICAL);
2926 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
2928 pref_checkbox_new_int(group, _("Use system screen profile if available"),
2929 options->color_profile.use_x11_screen_profile, &c_options->color_profile.use_x11_screen_profile);
2931 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2933 pref_table_label(table, 0, 0, _("Screen:"), 1.0);
2934 tabcomp = tab_completion_new(&color_profile_screen_file_entry,
2935 options->color_profile.screen_file, NULL, ".icc", "ICC Files", NULL);
2936 tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
2937 gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
2939 add_intent_menu(table, 0, 1, _("Render Intent:"), options->color_profile.render_intent, &c_options->color_profile.render_intent);
2941 gtk_table_attach(GTK_TABLE(table), tabcomp, 1, 2,
2943 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2945 gtk_widget_show(tabcomp);
2948 /* advanced entry tab */
2949 static void use_geeqie_trash_cb(GtkWidget *widget, gpointer data)
2951 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
2953 c_options->file_ops.use_system_trash = FALSE;
2957 static void use_system_trash_cb(GtkWidget *widget, gpointer data)
2959 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
2961 c_options->file_ops.use_system_trash = TRUE;
2965 static void config_tab_behavior(GtkWidget *notebook)
2972 GtkWidget *ct_button;
2976 GtkWidget *with_rename;
2977 GtkWidget *collections_on_top;
2979 vbox = scrolled_notebook_page(notebook, _("Behavior"));
2981 group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
2983 pref_checkbox_new_int(group, _("Confirm permanent file delete"),
2984 options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
2985 pref_checkbox_new_int(group, _("Confirm move file to Trash"),
2986 options->file_ops.confirm_move_to_trash, &c_options->file_ops.confirm_move_to_trash);
2987 pref_checkbox_new_int(group, _("Enable Delete key"),
2988 options->file_ops.enable_delete_key, &c_options->file_ops.enable_delete_key);
2990 ct_button = pref_radiobutton_new(group, NULL, _("Use Geeqie trash location"),
2991 !options->file_ops.use_system_trash, G_CALLBACK(use_geeqie_trash_cb),NULL);
2993 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2994 pref_checkbox_link_sensitivity(ct_button, hbox);
2996 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
2997 pref_label_new(hbox, _("Folder:"));
2999 tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL, NULL, NULL);
3000 tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
3001 gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
3002 gtk_widget_show(tabcomp);
3004 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3005 pref_checkbox_link_sensitivity(ct_button, hbox);
3007 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
3008 spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MB"),
3009 0, 2048, 1, options->file_ops.safe_delete_folder_maxsize, &c_options->file_ops.safe_delete_folder_maxsize);
3010 gtk_widget_set_tooltip_markup(spin, _("Set to 0 for unlimited size"));
3011 button = pref_button_new(NULL, NULL, _("View"), FALSE,
3012 G_CALLBACK(safe_delete_view_cb), NULL);
3013 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3014 gtk_widget_show(button);
3016 button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
3017 G_CALLBACK(safe_delete_clear_cb), NULL);
3018 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3019 pref_radiobutton_new(group, ct_button, _("Use system Trash bin"),
3020 options->file_ops.use_system_trash, G_CALLBACK(use_system_trash_cb), NULL);
3021 gtk_widget_show(button);
3023 pref_spacer(group, PREF_PAD_GROUP);
3026 group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
3028 pref_checkbox_new_int(group, _("Descend folders in tree view"),
3029 options->tree_descend_subdirs, &c_options->tree_descend_subdirs);
3031 pref_checkbox_new_int(group, _("In place renaming"),
3032 options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
3034 pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
3035 options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
3037 marks = pref_checkbox_new_int(group, _("Save marks on exit"),
3038 options->marks_save, &c_options->marks_save);
3039 gtk_widget_set_tooltip_text(marks,"Note that marks linked to a keyword will be saved irrespective of this setting");
3041 with_rename = pref_checkbox_new_int(group, _("Use \"With Rename\" as default for Copy/Move dialogs"),
3042 options->with_rename, &c_options->with_rename);
3043 gtk_widget_set_tooltip_text(with_rename,"Change the default button for Copy/Move dialogs");
3045 collections_on_top = pref_checkbox_new_int(group, _("Open collections on top"),
3046 options->collections_on_top, &c_options->collections_on_top);
3047 gtk_widget_set_tooltip_text(collections_on_top,"Open collections window on top");
3049 pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
3050 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
3052 pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
3053 16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
3055 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3056 add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
3058 pref_spacer(group, PREF_PAD_GROUP);
3060 group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
3062 pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
3063 options->progressive_key_scrolling, &c_options->progressive_key_scrolling);
3064 pref_spin_new_int(group, _("Keyboard scrolling step multiplier:"), NULL,
3065 1, 32, 1, options->keyboard_scroll_step, (int *)&c_options->keyboard_scroll_step);
3066 pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
3067 options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
3068 pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
3069 options->image_lm_click_nav, &c_options->image_lm_click_nav);
3070 pref_checkbox_new_int(group, _("Play video by left click on image"),
3071 options->image_l_click_video, &c_options->image_l_click_video);
3072 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3073 add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
3077 pref_spacer(group, PREF_PAD_GROUP);
3079 group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
3081 pref_spin_new_int(group, _("Debug level:"), NULL,
3082 DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
3084 pref_checkbox_new_int(group, _("Timer data"),
3085 options->log_window.timer_data, &c_options->log_window.timer_data);
3087 pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
3088 1, 99999, 1, options->log_window_lines, &options->log_window_lines);
3092 /* accelerators tab */
3093 static void config_tab_accelerators(GtkWidget *notebook)
3099 GtkWidget *scrolled;
3100 GtkWidget *accel_view;
3101 GtkCellRenderer *renderer;
3102 GtkTreeSelection *selection;
3103 GtkTreeViewColumn *column;
3105 vbox = scrolled_notebook_page(notebook, _("Keyboard"));
3107 group = pref_group_new(vbox, TRUE, _("Accelerators"), GTK_ORIENTATION_VERTICAL);
3109 scrolled = gtk_scrolled_window_new(NULL, NULL);
3110 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
3111 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
3112 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3113 gtk_widget_show(scrolled);
3115 accel_store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
3117 accel_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(accel_store));
3118 g_object_unref(accel_store);
3119 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(accel_view));
3120 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
3122 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(accel_view), FALSE);
3124 renderer = gtk_cell_renderer_text_new();
3126 column = gtk_tree_view_column_new_with_attributes(_("Action"),
3131 gtk_tree_view_column_set_sort_column_id(column, AE_ACTION);
3132 gtk_tree_view_column_set_resizable(column, TRUE);
3133 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3136 renderer = gtk_cell_renderer_accel_new();
3137 g_signal_connect(G_OBJECT(renderer), "accel-cleared",
3138 G_CALLBACK(accel_store_cleared_cb), accel_store);
3139 g_signal_connect(G_OBJECT(renderer), "accel-edited",
3140 G_CALLBACK(accel_store_edited_cb), accel_store);
3143 g_object_set (renderer,
3145 "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
3148 column = gtk_tree_view_column_new_with_attributes(_("KEY"),
3153 gtk_tree_view_column_set_sort_column_id(column, AE_KEY);
3154 gtk_tree_view_column_set_resizable(column, TRUE);
3155 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3157 renderer = gtk_cell_renderer_text_new();
3159 column = gtk_tree_view_column_new_with_attributes(_("Tooltip"),
3164 gtk_tree_view_column_set_sort_column_id(column, AE_TOOLTIP);
3165 gtk_tree_view_column_set_resizable(column, TRUE);
3166 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3168 renderer = gtk_cell_renderer_text_new();
3170 column = gtk_tree_view_column_new_with_attributes("Accel",
3175 gtk_tree_view_column_set_sort_column_id(column, AE_ACCEL);
3176 gtk_tree_view_column_set_resizable(column, TRUE);
3177 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3179 accel_store_populate();
3180 gtk_container_add(GTK_CONTAINER(scrolled), accel_view);
3181 gtk_widget_show(accel_view);
3183 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3185 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
3186 G_CALLBACK(accel_default_cb), accel_view);
3187 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3188 gtk_widget_show(button);
3190 button = pref_button_new(NULL, NULL, _("Reset selected"), FALSE,
3191 G_CALLBACK(accel_reset_cb), accel_view);
3192 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3193 gtk_widget_show(button);
3197 static void config_tab_toolbar(GtkWidget *notebook)
3200 GtkWidget *toolbardata;
3203 lw = layout_window_list->data;
3205 vbox = scrolled_notebook_page(notebook, _("Toolbar"));
3207 toolbardata = toolbar_select_new(lw);
3208 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3209 gtk_widget_show(vbox);
3213 static void config_tab_stereo(GtkWidget *notebook)
3221 GtkWidget *fs_button;
3222 vbox = scrolled_notebook_page(notebook, _("Stereo"));
3224 group = pref_group_new(vbox, FALSE, _("Windowed stereo mode"), GTK_ORIENTATION_VERTICAL);
3226 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3227 add_stereo_mode_menu(table, 0, 0, _("Windowed stereo mode"), options->stereo.mode, &c_options->stereo.mode, FALSE);
3229 table = pref_table_new(group, 2, 2, TRUE, FALSE);
3230 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3231 pref_checkbox_new_int(box, _("Mirror left image"),
3232 options->stereo.mode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.mirror_left);
3233 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3234 pref_checkbox_new_int(box, _("Flip left image"),
3235 options->stereo.mode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.flip_left);
3236 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3237 pref_checkbox_new_int(box, _("Mirror right image"),
3238 options->stereo.mode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.mirror_right);
3239 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3240 pref_checkbox_new_int(box, _("Flip right image"),
3241 options->stereo.mode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.flip_right);
3242 pref_checkbox_new_int(group, _("Swap left and right images"),
3243 options->stereo.mode & PR_STEREO_SWAP, &c_options->stereo.tmp.swap);
3244 pref_checkbox_new_int(group, _("Disable stereo mode on single image source"),
3245 options->stereo.mode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.temp_disable);
3247 group = pref_group_new(vbox, FALSE, _("Fullscreen stereo mode"), GTK_ORIENTATION_VERTICAL);
3248 fs_button = pref_checkbox_new_int(group, _("Use different settings for fullscreen"),
3249 options->stereo.enable_fsmode, &c_options->stereo.enable_fsmode);
3250 box2 = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
3251 pref_checkbox_link_sensitivity(fs_button, box2);
3252 table = pref_table_new(box2, 2, 1, FALSE, FALSE);
3253 add_stereo_mode_menu(table, 0, 0, _("Fullscreen stereo mode"), options->stereo.fsmode, &c_options->stereo.fsmode, TRUE);
3254 table = pref_table_new(box2, 2, 2, TRUE, FALSE);
3255 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3256 pref_checkbox_new_int(box, _("Mirror left image"),
3257 options->stereo.fsmode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.fs_mirror_left);
3258 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3259 pref_checkbox_new_int(box, _("Flip left image"),
3260 options->stereo.fsmode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.fs_flip_left);
3261 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3262 pref_checkbox_new_int(box, _("Mirror right image"),
3263 options->stereo.fsmode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.fs_mirror_right);
3264 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3265 pref_checkbox_new_int(box, _("Flip right image"),
3266 options->stereo.fsmode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.fs_flip_right);
3267 pref_checkbox_new_int(box2, _("Swap left and right images"),
3268 options->stereo.fsmode & PR_STEREO_SWAP, &c_options->stereo.tmp.fs_swap);
3269 pref_checkbox_new_int(box2, _("Disable stereo mode on single image source"),
3270 options->stereo.fsmode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.fs_temp_disable);
3272 group2 = pref_group_new(box2, FALSE, _("Fixed position"), GTK_ORIENTATION_VERTICAL);
3273 table = pref_table_new(group2, 5, 3, FALSE, FALSE);
3274 pref_table_spin_new_int(table, 0, 0, _("Width"), NULL,
3275 1, 5000, 1, options->stereo.fixed_w, &c_options->stereo.fixed_w);
3276 pref_table_spin_new_int(table, 3, 0, _("Height"), NULL,
3277 1, 5000, 1, options->stereo.fixed_h, &c_options->stereo.fixed_h);
3278 pref_table_spin_new_int(table, 0, 1, _("Left X"), NULL,
3279 0, 5000, 1, options->stereo.fixed_x1, &c_options->stereo.fixed_x1);
3280 pref_table_spin_new_int(table, 3, 1, _("Left Y"), NULL,
3281 0, 5000, 1, options->stereo.fixed_y1, &c_options->stereo.fixed_y1);
3282 pref_table_spin_new_int(table, 0, 2, _("Right X"), NULL,
3283 0, 5000, 1, options->stereo.fixed_x2, &c_options->stereo.fixed_x2);
3284 pref_table_spin_new_int(table, 3, 2, _("Right Y"), NULL,
3285 0, 5000, 1, options->stereo.fixed_y2, &c_options->stereo.fixed_y2);
3289 /* Main preferences window */
3290 static void config_window_create(void)
3292 GtkWidget *win_vbox;
3294 GtkWidget *notebook;
3296 GtkWidget *ct_button;
3298 if (!c_options) c_options = init_options(NULL);
3300 configwindow = window_new(GTK_WINDOW_TOPLEVEL, "preferences", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Preferences"));
3301 DEBUG_NAME(configwindow);
3302 gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
3303 g_signal_connect(G_OBJECT(configwindow), "delete_event",
3304 G_CALLBACK(config_window_delete), NULL);
3305 gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
3306 gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
3307 gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
3309 win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
3310 gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
3311 gtk_widget_show(win_vbox);
3313 notebook = gtk_notebook_new();
3314 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_LEFT);
3315 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE);
3316 gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
3318 config_tab_general(notebook);
3319 config_tab_image(notebook);
3320 config_tab_osd(notebook);
3321 config_tab_windows(notebook);
3322 config_tab_accelerators(notebook);
3323 config_tab_files(notebook);
3324 config_tab_metadata(notebook);
3325 config_tab_keywords(notebook);
3326 config_tab_color(notebook);
3327 config_tab_stereo(notebook);
3328 config_tab_behavior(notebook);
3329 config_tab_toolbar(notebook);
3331 hbox = gtk_hbutton_box_new();
3332 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
3333 gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
3334 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
3335 gtk_widget_show(hbox);
3337 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
3338 G_CALLBACK(config_window_help_cb), notebook);
3339 gtk_container_add(GTK_CONTAINER(hbox), button);
3340 gtk_widget_set_can_default(button, TRUE);
3341 gtk_widget_show(button);
3343 button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
3344 G_CALLBACK(config_window_ok_cb), NULL);
3345 gtk_container_add(GTK_CONTAINER(hbox), button);
3346 gtk_widget_set_can_default(button, TRUE);
3347 gtk_widget_grab_default(button);
3348 gtk_widget_show(button);
3352 button = pref_button_new(NULL, GTK_STOCK_SAVE, NULL, FALSE,
3353 G_CALLBACK(config_window_save_cb), NULL);
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_APPLY, NULL, FALSE,
3359 G_CALLBACK(config_window_apply_cb), NULL);
3360 gtk_container_add(GTK_CONTAINER(hbox), button);
3361 gtk_widget_set_can_default(button, TRUE);
3362 gtk_widget_show(button);
3364 button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
3365 G_CALLBACK(config_window_close_cb), NULL);
3366 gtk_container_add(GTK_CONTAINER(hbox), button);
3367 gtk_widget_set_can_default(button, TRUE);
3368 gtk_widget_show(button);
3370 if (!generic_dialog_get_alternative_button_order(configwindow))
3372 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
3375 gtk_widget_show(notebook);
3377 gtk_widget_show(configwindow);
3381 *-----------------------------------------------------------------------------
3382 * config window show (public)
3383 *-----------------------------------------------------------------------------
3386 void show_config_window(void)
3390 gtk_window_present(GTK_WINDOW(configwindow));
3394 config_window_create();
3403 void show_about_window(LayoutWindow *lw)
3405 GdkPixbuf *pixbuf_logo;
3406 GdkPixbuf *pixbuf_icon;
3407 gchar *authors[1000];
3415 #define LINE_LENGTH 1000
3416 gchar line[LINE_LENGTH];
3418 copyright = g_string_new(NULL);
3419 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");
3421 zd_path = g_build_filename(GQ_BIN_DIR, TIMEZONE_DATABASE, NULL);
3422 cd = ZDOpenDatabase(zd_path);
3425 copyright = g_string_append(copyright, ZDGetNotice(cd));
3427 ZDCloseDatabase(cd);
3431 path = g_build_filename(GQ_HELPDIR, "AUTHORS", NULL);
3432 fp = fopen(path, "r");
3435 while(fgets(line, LINE_LENGTH, fp))
3437 /* get rid of ending \n from fgets */
3438 line[strlen(line) - 1] = '\0';
3439 authors[i_authors] = g_strdup(line);
3442 authors[i_authors] = NULL;
3447 comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
3448 "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
3450 pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
3451 pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
3452 gtk_show_about_dialog(GTK_WINDOW(lw->window),
3453 "title", _("About Geeqie"),
3455 "program-name", GQ_APPNAME,
3457 "logo", pixbuf_logo,
3458 "icon", pixbuf_icon,
3459 "website", GQ_WEBSITE,
3460 "website-label", "Website",
3461 "comments", comment,
3463 "translator-credits", _("translator-credits"),
3464 "wrap-license", TRUE,
3465 "license", copyright->str,
3468 g_string_free(copyright, TRUE);
3471 while(n < i_authors)
3481 static void image_overlay_set_text_colours()
3483 c_options->image_overlay.text_red = options->image_overlay.text_red;
3484 c_options->image_overlay.text_green = options->image_overlay.text_green;
3485 c_options->image_overlay.text_blue = options->image_overlay.text_blue;
3486 c_options->image_overlay.text_alpha = options->image_overlay.text_alpha;
3487 c_options->image_overlay.background_red = options->image_overlay.background_red;
3488 c_options->image_overlay.background_green = options->image_overlay.background_green;
3489 c_options->image_overlay.background_blue = options->image_overlay.background_blue;
3490 c_options->image_overlay.background_alpha = options->image_overlay.background_alpha;
3492 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */