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;
1052 GList *list_columns;
1057 rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(filter_store), NULL);
1058 path = gtk_tree_path_new_from_indices(rows-1, -1);
1060 list_columns = gtk_tree_view_get_columns(GTK_TREE_VIEW(data));
1062 column = g_list_nth(list_columns,i)->data;
1063 title = gtk_tree_view_column_get_title(GTK_TREE_VIEW_COLUMN(column));
1065 } while (strcmp(title, "Filter") !=0 );
1067 list_cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column));
1068 cell = g_list_last(list_cells)->data;
1070 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1071 path, column, FALSE, 0.0, 0.0 );
1072 gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(data),
1073 path, column, cell, TRUE);
1075 gtk_tree_path_free(path);
1076 g_list_free(list_cells);
1077 g_list_free(list_columns);
1082 static void filter_add_cb(GtkWidget *widget, gpointer data)
1084 filter_add_unique("description", ".new", FORMAT_CLASS_IMAGE, TRUE, FALSE, TRUE);
1085 filter_store_populate();
1087 g_idle_add((GSourceFunc)filter_add_scroll, data);
1090 static void filter_remove_cb(GtkWidget *widget, gpointer data)
1092 GtkWidget *filter_view = data;
1093 GtkTreeSelection *selection;
1097 if (!filter_store) return;
1098 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1099 if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) return;
1100 gtk_tree_model_get(GTK_TREE_MODEL(filter_store), &iter, 0, &fe, -1);
1103 filter_remove_entry(fe);
1105 filter_store_populate();
1108 static gboolean filter_default_ok_scroll(GtkTreeView *data)
1112 GtkTreeViewColumn *column;
1114 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(filter_store), &iter);
1115 path = gtk_tree_model_get_path(GTK_TREE_MODEL(filter_store), &iter);
1116 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1118 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1122 gtk_tree_path_free(path);
1127 static void filter_default_ok_cb(GenericDialog *gd, gpointer data)
1130 filter_add_defaults();
1132 filter_store_populate();
1134 g_idle_add((GSourceFunc)filter_default_ok_scroll, gd->data);
1137 static void dummy_cancel_cb(GenericDialog *gd, gpointer data)
1139 /* no op, only so cancel button appears */
1142 static void filter_default_cb(GtkWidget *widget, gpointer data)
1146 gd = generic_dialog_new(_("Reset filters"),
1147 "reset_filter", widget, TRUE,
1148 dummy_cancel_cb, data);
1149 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset filters"),
1150 _("This will reset the file filters to the defaults.\nContinue?"), TRUE);
1151 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, filter_default_ok_cb, TRUE);
1152 gtk_widget_show(gd->dialog);
1155 static void filter_disable_cb(GtkWidget *widget, gpointer data)
1157 GtkWidget *frame = data;
1159 gtk_widget_set_sensitive(frame,
1160 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
1163 static void safe_delete_view_cb(GtkWidget *widget, gpointer data)
1165 layout_set_path(NULL, gtk_entry_get_text(GTK_ENTRY(safe_delete_path_entry)));
1168 static void safe_delete_clear_ok_cb(GenericDialog *gd, gpointer data)
1170 file_util_trash_clear();
1173 static void safe_delete_clear_cb(GtkWidget *widget, gpointer data)
1177 gd = generic_dialog_new(_("Clear trash"),
1178 "clear_trash", widget, TRUE,
1179 dummy_cancel_cb, NULL);
1180 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear trash"),
1181 _("This will remove the trash contents."), FALSE);
1182 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, safe_delete_clear_ok_cb, TRUE);
1183 entry = gtk_entry_new();
1184 gtk_widget_set_can_focus(entry, FALSE);
1185 gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE);
1186 if (options->file_ops.safe_delete_path) gtk_entry_set_text(GTK_ENTRY(entry), options->file_ops.safe_delete_path);
1187 gtk_box_pack_start(GTK_BOX(gd->vbox), entry, FALSE, FALSE, 0);
1188 gtk_widget_show(entry);
1189 gtk_widget_show(gd->dialog);
1192 static void image_overlay_template_view_changed_cb(GtkWidget *widget, gpointer data)
1194 GtkWidget *pTextView;
1195 GtkTextBuffer *pTextBuffer;
1199 pTextView = GTK_WIDGET(data);
1201 pTextBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pTextView));
1202 gtk_text_buffer_get_start_iter(pTextBuffer, &iStart);
1203 gtk_text_buffer_get_end_iter(pTextBuffer, &iEnd);
1205 set_image_overlay_template_string(&c_options->image_overlay.template_string,
1206 gtk_text_buffer_get_text(pTextBuffer, &iStart, &iEnd, TRUE));
1209 static void image_overlay_default_template_ok_cb(GenericDialog *gd, gpointer data)
1211 GtkTextView *text_view = data;
1212 GtkTextBuffer *buffer;
1214 set_default_image_overlay_template_string(&options->image_overlay.template_string);
1215 if (!configwindow) return;
1217 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
1218 gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1221 static void image_overlay_default_template_cb(GtkWidget *widget, gpointer data)
1225 gd = generic_dialog_new(_("Reset image overlay template string"),
1226 "reset_image_overlay_template_string", widget, TRUE,
1227 dummy_cancel_cb, data);
1228 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset image overlay template string"),
1229 _("This will reset the image overlay template string to the default.\nContinue?"), TRUE);
1230 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, image_overlay_default_template_ok_cb, TRUE);
1231 gtk_widget_show(gd->dialog);
1234 static void image_overlay_help_cb(GtkWidget *widget, gpointer data)
1236 help_window_show("GuideOptionsOSD.html");
1239 static void image_overlay_set_font_cb(GtkWidget *widget, gpointer data)
1241 #if GTK_CHECK_VERSION(3,4,0)
1244 PangoFontDescription *font_desc;
1246 dialog = gtk_font_chooser_dialog_new("Image Overlay Font", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1247 gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), options->image_overlay.font);
1249 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1251 font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
1252 font = pango_font_description_to_string(font_desc);
1253 g_free(c_options->image_overlay.font);
1254 c_options->image_overlay.font = g_strdup(font);
1258 gtk_widget_destroy(dialog);
1262 font = gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget));
1263 c_options->image_overlay.font = g_strdup(font);
1267 static void image_overlay_set_text_colour_cb(GtkWidget *widget, gpointer data)
1270 #if GTK_CHECK_VERSION(3,4,0)
1273 dialog = gtk_color_chooser_dialog_new("Image Overlay Text Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1274 colour.red = options->image_overlay.text_red;
1275 colour.green = options->image_overlay.text_green;
1276 colour.blue = options->image_overlay.text_blue;
1277 colour.alpha = options->image_overlay.text_alpha;
1278 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1279 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1281 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1283 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1284 c_options->image_overlay.text_red = colour.red*255;
1285 c_options->image_overlay.text_green = colour.green*255;
1286 c_options->image_overlay.text_blue = colour.blue*255;
1287 c_options->image_overlay.text_alpha = colour.alpha*255;
1289 gtk_widget_destroy(dialog);
1292 GtkColorSelection *colorsel;
1294 dialog = gtk_color_selection_dialog_new("Image Overlay Text Colour");
1295 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1296 colour.red = options->image_overlay.text_red*257;
1297 colour.green = options->image_overlay.text_green*257;
1298 colour.blue = options->image_overlay.text_blue*257;
1299 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1300 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1301 gtk_color_selection_set_current_color(colorsel, &colour);
1302 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.text_alpha*257);
1304 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1306 gtk_color_selection_get_current_color(colorsel, &colour);
1307 c_options->image_overlay.text_red = colour.red/257;
1308 c_options->image_overlay.text_green = colour.green/257;
1309 c_options->image_overlay.text_blue = colour.blue/257;
1310 c_options->image_overlay.text_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1312 gtk_widget_destroy (dialog);
1317 static void image_overlay_set_background_colour_cb(GtkWidget *widget, gpointer data)
1320 #if GTK_CHECK_VERSION(3,4,0)
1323 dialog = gtk_color_chooser_dialog_new("Image Overlay Background Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1324 colour.red = options->image_overlay.background_red;
1325 colour.green = options->image_overlay.background_green;
1326 colour.blue = options->image_overlay.background_blue;
1327 colour.alpha = options->image_overlay.background_alpha;
1328 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1329 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1331 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1333 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1334 c_options->image_overlay.background_red = colour.red*255;
1335 c_options->image_overlay.background_green = colour.green*255;
1336 c_options->image_overlay.background_blue = colour.blue*255;
1337 c_options->image_overlay.background_alpha = colour.alpha*255;
1339 gtk_widget_destroy(dialog);
1342 GtkColorSelection *colorsel;
1344 dialog = gtk_color_selection_dialog_new("Image Overlay Background Colour");
1345 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1346 colour.red = options->image_overlay.background_red*257;
1347 colour.green = options->image_overlay.background_green*257;
1348 colour.blue = options->image_overlay.background_blue*257;
1349 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1350 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1351 gtk_color_selection_set_current_color(colorsel, &colour);
1352 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.background_alpha*257);
1354 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1356 gtk_color_selection_get_current_color(colorsel, &colour);
1357 c_options->image_overlay.background_red = colour.red/257;
1358 c_options->image_overlay.background_green = colour.green/257;
1359 c_options->image_overlay.background_blue = colour.blue/257;
1360 c_options->image_overlay.background_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1362 gtk_widget_destroy(dialog);
1366 static void accel_store_populate(void)
1369 GList *groups, *actions;
1371 const gchar *accel_path;
1375 if (!accel_store || !layout_window_list || !layout_window_list->data) return;
1377 gtk_tree_store_clear(accel_store);
1378 lw = layout_window_list->data; /* get the actions from the first window, it should not matter, they should be the same in all windows */
1380 g_assert(lw && lw->ui_manager);
1381 groups = gtk_ui_manager_get_action_groups(lw->ui_manager);
1384 actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
1387 action = GTK_ACTION(actions->data);
1388 accel_path = gtk_action_get_accel_path(action);
1389 if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
1391 gchar *label, *label2, *tooltip, *accel;
1392 g_object_get(action,
1393 "tooltip", &tooltip,
1397 if (pango_parse_markup(label, -1, '_', NULL, &label2, NULL, NULL) && label2)
1403 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1407 gtk_tree_store_append(accel_store, &iter, NULL);
1408 gtk_tree_store_set(accel_store, &iter,
1411 AE_TOOLTIP, tooltip ? tooltip : "",
1412 AE_ACCEL, accel_path,
1420 actions = actions->next;
1423 groups = groups->next;
1427 static void accel_store_cleared_cb(GtkCellRendererAccel *accel, gchar *path_string, gpointer user_data)
1432 static gboolean accel_remove_key_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1434 gchar *accel1 = data;
1439 gtk_tree_model_get(model, iter, AE_KEY, &accel2, -1);
1441 gtk_accelerator_parse(accel1, &key1.accel_key, &key1.accel_mods);
1442 gtk_accelerator_parse(accel2, &key2.accel_key, &key2.accel_mods);
1444 if (key1.accel_key == key2.accel_key && key1.accel_mods == key2.accel_mods)
1446 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1447 DEBUG_1("accelerator key '%s' is already used, removing.", accel1);
1456 static void accel_store_edited_cb(GtkCellRendererAccel *accel, gchar *path_string, guint accel_key, GdkModifierType accel_mods, guint hardware_keycode, gpointer user_data)
1458 GtkTreeModel *model = (GtkTreeModel *)accel_store;
1462 GtkAccelKey old_key, key;
1463 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
1465 gtk_tree_model_get_iter(model, &iter, path);
1466 gtk_tree_model_get(model, &iter, AE_ACCEL, &accel_path, -1);
1468 /* test if the accelerator can be stored without conflicts*/
1469 gtk_accel_map_lookup_entry(accel_path, &old_key);
1471 /* change the key and read it back (change may fail on keys hardcoded in gtk)*/
1472 gtk_accel_map_change_entry(accel_path, accel_key, accel_mods, TRUE);
1473 gtk_accel_map_lookup_entry(accel_path, &key);
1475 /* restore the original for now, the key will be really changed when the changes are confirmed */
1476 gtk_accel_map_change_entry(accel_path, old_key.accel_key, old_key.accel_mods, TRUE);
1478 acc = gtk_accelerator_name(key.accel_key, key.accel_mods);
1479 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, acc);
1481 gtk_tree_store_set(accel_store, &iter, AE_KEY, acc, -1);
1482 gtk_tree_path_free(path);
1486 static gboolean accel_default_scroll(GtkTreeView *data)
1490 GtkTreeViewColumn *column;
1492 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(accel_store), &iter);
1493 path = gtk_tree_model_get_path(GTK_TREE_MODEL(accel_store), &iter);
1494 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1496 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1500 gtk_tree_path_free(path);
1505 static void accel_default_cb(GtkWidget *widget, gpointer data)
1507 accel_store_populate();
1509 g_idle_add((GSourceFunc)accel_default_scroll, data);
1512 void accel_remove_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1514 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1517 void accel_reset_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1520 gchar *accel_path, *accel;
1522 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, -1);
1523 gtk_accel_map_lookup_entry(accel_path, &key);
1524 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1526 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, accel);
1528 gtk_tree_store_set(accel_store, iter, AE_KEY, accel, -1);
1533 static void accel_reset_cb(GtkWidget *widget, gpointer data)
1535 GtkTreeSelection *selection;
1537 if (!accel_store) return;
1538 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data));
1539 gtk_tree_selection_selected_foreach(selection, &accel_reset_selection, NULL);
1544 static GtkWidget *scrolled_notebook_page(GtkWidget *notebook, const gchar *title)
1548 GtkWidget *scrolled;
1549 GtkWidget *viewport;
1551 scrolled = gtk_scrolled_window_new(NULL, NULL);
1552 gtk_container_set_border_width(GTK_CONTAINER(scrolled), PREF_PAD_BORDER);
1553 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1554 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1555 label = gtk_label_new(title);
1556 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, label);
1557 gtk_widget_show(scrolled);
1559 viewport = gtk_viewport_new(NULL, NULL);
1560 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1561 gtk_container_add(GTK_CONTAINER(scrolled), viewport);
1562 gtk_widget_show(viewport);
1564 vbox = gtk_vbox_new(FALSE, 0);
1565 gtk_container_add(GTK_CONTAINER(viewport), vbox);
1566 gtk_widget_show(vbox);
1571 static void cache_standard_cb(GtkWidget *widget, gpointer data)
1573 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1575 c_options->thumbnails.spec_standard =TRUE;
1576 c_options->thumbnails.cache_into_dirs = FALSE;
1580 static void cache_geeqie_cb(GtkWidget *widget, gpointer data)
1582 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1584 c_options->thumbnails.spec_standard =FALSE;
1585 c_options->thumbnails.cache_into_dirs = FALSE;
1589 static void cache_local_cb(GtkWidget *widget, gpointer data)
1591 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1593 c_options->thumbnails.cache_into_dirs = TRUE;
1594 c_options->thumbnails.spec_standard =FALSE;
1598 static void help_search_engine_entry_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1599 GdkEvent *event, gpointer userdata)
1601 if (pos == GTK_ENTRY_ICON_PRIMARY)
1603 gtk_entry_set_text(GTK_ENTRY(userdata), HELP_SEARCH_ENGINE);
1607 gtk_entry_set_text(GTK_ENTRY(userdata), "");
1611 static void star_rating_star_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1612 GdkEvent *event, gpointer userdata)
1614 gchar *rating_symbol;
1616 if (pos == GTK_ENTRY_ICON_PRIMARY)
1618 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_STAR);
1619 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1620 g_free(rating_symbol);
1624 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1625 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1626 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1630 static void star_rating_rejected_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1631 GdkEvent *event, gpointer userdata)
1633 gchar *rating_symbol;
1635 if (pos == GTK_ENTRY_ICON_PRIMARY)
1637 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_REJECTED);
1638 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1639 g_free(rating_symbol);
1643 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1644 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1645 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1649 static guint star_rating_symbol_test(GtkWidget *widget, gpointer data)
1651 GtkContainer *hbox = data;
1652 GString *str = g_string_new(NULL);
1653 GtkEntry *hex_code_entry;
1654 gchar *hex_code_full;
1657 guint64 hex_value = 0;
1659 list = gtk_container_get_children(hbox);
1661 hex_code_entry = g_list_nth_data(list, 2);
1662 hex_code_full = g_strdup(gtk_entry_get_text(hex_code_entry));
1664 hex_code = g_strsplit(hex_code_full, "+", 2);
1665 if (hex_code[0] && hex_code[1])
1667 hex_value = strtoull(hex_code[1], NULL, 16);
1669 if (!hex_value || hex_value > 0x10FFFF)
1671 hex_value = 0x003F; // Unicode 'Question Mark'
1673 str = g_string_append_unichar(str, (gunichar)hex_value);
1674 gtk_label_set_text(g_list_nth_data(list, 1), str->str);
1676 g_strfreev(hex_code);
1677 g_string_free(str, TRUE);
1678 g_free(hex_code_full);
1683 static void star_rating_star_test_cb(GtkWidget *widget, gpointer data)
1685 guint64 star_symbol;
1687 star_symbol = star_rating_symbol_test(widget, data);
1688 c_options->star_rating.star = star_symbol;
1691 static void star_rating_rejected_test_cb(GtkWidget *widget, gpointer data)
1693 guint64 rejected_symbol;
1695 rejected_symbol = star_rating_symbol_test(widget, data);
1696 c_options->star_rating.rejected = rejected_symbol;
1699 /* general options tab */
1700 static void config_tab_general(GtkWidget *notebook)
1705 GtkWidget *group_frame;
1706 GtkWidget *subgroup;
1708 GtkWidget *ct_button;
1711 gint hours, minutes, remainder;
1713 GtkWidget *star_rating_entry;
1715 gchar *rating_symbol;
1717 vbox = scrolled_notebook_page(notebook, _("General"));
1719 group = pref_group_new(vbox, FALSE, _("Thumbnails"), GTK_ORIENTATION_VERTICAL);
1721 table = pref_table_new(group, 2, 2, FALSE, FALSE);
1722 add_thumb_size_menu(table, 0, 0, _("Size:"));
1723 add_quality_menu(table, 0, 1, _("Quality:"), options->thumbnails.quality, &c_options->thumbnails.quality);
1725 ct_button = pref_checkbox_new_int(group, _("Cache thumbnails"),
1726 options->thumbnails.enable_caching, &c_options->thumbnails.enable_caching);
1728 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1729 pref_checkbox_link_sensitivity(ct_button, subgroup);
1731 c_options->thumbnails.spec_standard = options->thumbnails.spec_standard;
1732 c_options->thumbnails.cache_into_dirs = options->thumbnails.cache_into_dirs;
1733 group_frame = pref_frame_new(subgroup, TRUE, _("Use Geeqie thumbnail style and cache"),
1734 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1735 button = pref_radiobutton_new(group_frame, NULL, get_thumbnails_cache_dir(),
1736 !options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1737 G_CALLBACK(cache_geeqie_cb), NULL);
1739 group_frame = pref_frame_new(subgroup, TRUE,
1740 _("Store thumbnails local to image folder (non-standard)"),
1741 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1742 pref_radiobutton_new(group_frame, button, "*/.thumbnails",
1743 !options->thumbnails.spec_standard && options->thumbnails.cache_into_dirs,
1744 G_CALLBACK(cache_local_cb), NULL);
1746 group_frame = pref_frame_new(subgroup, TRUE,
1747 _("Use standard thumbnail style and cache, shared with other applications"),
1748 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1749 pref_radiobutton_new(group_frame, button, get_thumbnails_standard_cache_dir(),
1750 options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1751 G_CALLBACK(cache_standard_cb), NULL);
1753 pref_checkbox_new_int(group, _("Use EXIF thumbnails when available (EXIF thumbnails may be outdated)"),
1754 options->thumbnails.use_exif, &c_options->thumbnails.use_exif);
1756 spin = pref_spin_new_int(group, _("Collection preview:"), NULL,
1758 options->thumbnails.collection_preview, &c_options->thumbnails.collection_preview);
1759 gtk_widget_set_tooltip_text(spin, _("The maximum number of thumbnails shown in a Collection preview montage"));
1761 #ifdef HAVE_FFMPEGTHUMBNAILER_METADATA
1762 pref_checkbox_new_int(group, _("Use embedded metadata in video files as thumbnails when available"),
1763 options->thumbnails.use_ft_metadata, &c_options->thumbnails.use_ft_metadata);
1765 // pref_checkbox_new_int(group, _("Ignore embedded metadata if size is too small"),
1766 // options->thumbnails.use_ft_metadata_small, &c_options->thumbnails.use_ft_metadata_small);
1769 group = pref_group_new(vbox, FALSE, _("Star Rating"), GTK_ORIENTATION_VERTICAL);
1771 c_options->star_rating.star = options->star_rating.star;
1772 c_options->star_rating.rejected = options->star_rating.rejected;
1774 str = g_string_new(NULL);
1775 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1776 pref_label_new(hbox, "Star character: ");
1777 str = g_string_append_unichar(str, options->star_rating.star);
1778 pref_label_new(hbox, g_strdup(str->str));
1779 rating_symbol = g_strdup_printf("U+%X", options->star_rating.star);
1780 star_rating_entry = gtk_entry_new();
1781 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
1782 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
1783 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
1784 gtk_widget_show(star_rating_entry);
1785 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
1786 G_CALLBACK(star_rating_star_test_cb), hbox);
1787 gtk_widget_set_tooltip_text(button, _("Display selected character"));
1788 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1789 gtk_widget_show(button);
1790 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."));
1791 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1792 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
1793 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1794 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
1795 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1796 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
1797 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1798 GTK_ENTRY_ICON_PRIMARY, _("Default"));
1799 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
1800 G_CALLBACK(star_rating_star_icon_cb),
1803 g_string_free(str, TRUE);
1804 g_free(rating_symbol);
1806 str = g_string_new(NULL);
1807 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1808 pref_label_new(hbox, "Rejected character: ");
1809 str = g_string_append_unichar(str, options->star_rating.rejected);
1810 pref_label_new(hbox, g_strdup(str->str));
1811 rating_symbol = g_strdup_printf("U+%X", options->star_rating.rejected);
1812 star_rating_entry = gtk_entry_new();
1813 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
1814 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
1815 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
1816 gtk_widget_show(star_rating_entry);
1817 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
1818 G_CALLBACK(star_rating_rejected_test_cb), hbox);
1819 gtk_widget_set_tooltip_text(button, _("Display selected character"));
1820 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1821 gtk_widget_show(button);
1822 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."));
1823 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1824 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
1825 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1826 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
1827 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1828 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
1829 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1830 GTK_ENTRY_ICON_PRIMARY, _("Default"));
1831 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
1832 G_CALLBACK(star_rating_rejected_icon_cb),
1835 g_string_free(str, TRUE);
1836 g_free(rating_symbol);
1838 group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
1840 c_options->slideshow.delay = options->slideshow.delay;
1841 hours = options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
1842 remainder = options->slideshow.delay % (3600 * SLIDESHOW_SUBSECOND_PRECISION);
1843 minutes = remainder / (60 * SLIDESHOW_SUBSECOND_PRECISION);
1844 seconds = (gdouble)(remainder % (60 * SLIDESHOW_SUBSECOND_PRECISION)) /
1845 SLIDESHOW_SUBSECOND_PRECISION;
1847 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1849 spin = pref_spin_new(hbox, _("Delay between image change hrs:mins:secs.dec"), NULL,
1851 options->slideshow.delay ? hours : 0.0,
1852 G_CALLBACK(slideshow_delay_hours_cb), NULL);
1853 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1854 spin = pref_spin_new(hbox, ":" , NULL,
1856 options->slideshow.delay ? minutes: 0.0,
1857 G_CALLBACK(slideshow_delay_minutes_cb), NULL);
1858 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1859 spin = pref_spin_new(hbox, ":", NULL,
1860 SLIDESHOW_MIN_SECONDS, 59, 1.0, 1,
1861 options->slideshow.delay ? seconds : 10.0,
1862 G_CALLBACK(slideshow_delay_seconds_cb), NULL);
1863 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1865 pref_checkbox_new_int(group, _("Random"), options->slideshow.random, &c_options->slideshow.random);
1866 pref_checkbox_new_int(group, _("Repeat"), options->slideshow.repeat, &c_options->slideshow.repeat);
1868 group = pref_group_new(vbox, FALSE, _("Image loading and caching"), GTK_ORIENTATION_VERTICAL);
1870 pref_spin_new_int(group, _("Decoded image cache size (Mb):"), NULL,
1871 0, 99999, 1, options->image.image_cache_max, &c_options->image.image_cache_max);
1872 pref_checkbox_new_int(group, _("Preload next image"),
1873 options->image.enable_read_ahead, &c_options->image.enable_read_ahead);
1875 pref_checkbox_new_int(group, _("Refresh on file change"),
1876 options->update_on_time_change, &c_options->update_on_time_change);
1878 group = pref_group_new(vbox, FALSE, _("Info sidebar heights"), GTK_ORIENTATION_VERTICAL);
1879 pref_label_new(group, _("NOTE! Geeqie must be restarted for changes to take effect"));
1880 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1881 pref_spin_new_int(hbox, _("Keywords:"), NULL,
1883 options->info_keywords.height, &c_options->info_keywords.height);
1884 pref_spin_new_int(hbox, _("Title:"), NULL,
1886 options->info_title.height, &c_options->info_title.height);
1887 pref_spin_new_int(hbox, _("Comment:"), NULL,
1889 options->info_comment.height, &c_options->info_comment.height);
1890 pref_spin_new_int(hbox, _("Rating:"), NULL,
1892 options->info_rating.height, &c_options->info_rating.height);
1894 group = pref_group_new(vbox, FALSE, _("Show predefined keyword tree"), GTK_ORIENTATION_VERTICAL);
1896 pref_checkbox_new_int(group, _("Show predefined keyword tree (NOTE! Geeqie must be restarted for change to take effect)"),
1897 options->show_predefined_keyword_tree, &c_options->show_predefined_keyword_tree);
1899 group = pref_group_new(vbox, FALSE, _("On-line help search engine"), GTK_ORIENTATION_VERTICAL);
1901 help_search_engine_entry = gtk_entry_new();
1902 gtk_entry_set_text(GTK_ENTRY(help_search_engine_entry), options->help_search_engine);
1903 gtk_box_pack_start(GTK_BOX(group), help_search_engine_entry, FALSE, FALSE, 0);
1904 gtk_widget_show(help_search_engine_entry);
1906 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"));
1908 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
1909 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
1910 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
1911 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
1912 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
1913 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
1914 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
1915 GTK_ENTRY_ICON_PRIMARY, _("Default"));
1916 g_signal_connect(GTK_ENTRY(help_search_engine_entry), "icon-press",
1917 G_CALLBACK(help_search_engine_entry_icon_cb),
1918 help_search_engine_entry);
1922 static void config_tab_image(GtkWidget *notebook)
1927 GtkWidget *ct_button;
1928 GtkWidget *enlargement_button;
1932 vbox = scrolled_notebook_page(notebook, _("Image"));
1934 group = pref_group_new(vbox, FALSE, _("Zoom"), GTK_ORIENTATION_VERTICAL);
1936 table = pref_table_new(group, 2, 1, FALSE, FALSE);
1937 add_quality_menu(table, 0, 0, _("Quality:"), options->image.zoom_quality, &c_options->image.zoom_quality);
1940 pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library"),
1941 options->image.use_clutter_renderer, &c_options->image.use_clutter_renderer);
1944 pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"),
1945 options->image.zoom_2pass, &c_options->image.zoom_2pass);
1947 c_options->image.zoom_increment = options->image.zoom_increment;
1948 spin = pref_spin_new(group, _("Zoom increment:"), NULL,
1949 0.01, 4.0, 0.01, 2, (gdouble)options->image.zoom_increment / 100.0,
1950 G_CALLBACK(zoom_increment_cb), NULL);
1951 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1953 group = pref_group_new(vbox, FALSE, _("Fit image to window"), GTK_ORIENTATION_VERTICAL);
1955 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1956 enlargement_button = pref_checkbox_new_int(hbox, _("Allow enlargement of image (max. size in %)"),
1957 options->image.zoom_to_fit_allow_expand, &c_options->image.zoom_to_fit_allow_expand);
1958 spin = pref_spin_new_int(hbox, NULL, NULL,
1960 options->image.max_enlargement_size, &c_options->image.max_enlargement_size);
1961 pref_checkbox_link_sensitivity(enlargement_button, spin);
1962 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."));
1964 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1965 ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (% of actual window):"),
1966 options->image.limit_autofit_size, &c_options->image.limit_autofit_size);
1967 spin = pref_spin_new_int(hbox, NULL, NULL,
1969 options->image.max_autofit_size, &c_options->image.max_autofit_size);
1970 pref_checkbox_link_sensitivity(ct_button, spin);
1971 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."));
1973 group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
1975 pref_checkbox_new_int(group, _("Use custom border color in window mode"),
1976 options->image.use_custom_border_color, &c_options->image.use_custom_border_color);
1978 pref_checkbox_new_int(group, _("Use custom border color in fullscreen mode"),
1979 options->image.use_custom_border_color_in_fullscreen, &c_options->image.use_custom_border_color_in_fullscreen);
1981 pref_color_button_new(group, _("Border color"), &options->image.border_color,
1982 G_CALLBACK(pref_color_button_set_cb), &c_options->image.border_color);
1984 c_options->image.border_color = options->image.border_color;
1986 pref_color_button_new(group, _("Alpha channel color 1"), &options->image.alpha_color_1,
1987 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_1);
1989 pref_color_button_new(group, _("Alpha channel color 2"), &options->image.alpha_color_2,
1990 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_2);
1992 c_options->image.alpha_color_1 = options->image.alpha_color_1;
1993 c_options->image.alpha_color_2 = options->image.alpha_color_2;
1995 group = pref_group_new(vbox, FALSE, _("Convenience"), GTK_ORIENTATION_VERTICAL);
1997 pref_checkbox_new_int(group, _("Auto rotate proofs using Exif information"),
1998 options->image.exif_proof_rotate_enable, &c_options->image.exif_proof_rotate_enable);
2002 static void config_tab_windows(GtkWidget *notebook)
2008 GtkWidget *ct_button;
2011 vbox = scrolled_notebook_page(notebook, _("Windows"));
2013 group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
2015 ct_button = pref_checkbox_new_int(group, _("Remember window positions"),
2016 options->save_window_positions, &c_options->save_window_positions);
2018 button = pref_checkbox_new_int(group, _("Use saved window positions also for new windows"),
2019 options->use_saved_window_positions_for_new_windows, &c_options->use_saved_window_positions_for_new_windows);
2020 pref_checkbox_link_sensitivity(ct_button, button);
2022 pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
2023 options->tools_restore_state, &c_options->tools_restore_state);
2025 pref_checkbox_new_int(group, _("Remember dialog window positions"),
2026 options->save_dialog_window_positions, &c_options->save_dialog_window_positions);
2028 pref_checkbox_new_int(group, _("Show window IDs"),
2029 options->show_window_ids, &c_options->show_window_ids);
2031 group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
2033 pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
2034 options->image.fit_window_to_image, &c_options->image.fit_window_to_image);
2036 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2037 ct_button = pref_checkbox_new_int(hbox, _("Limit size when auto-sizing window (%):"),
2038 options->image.limit_window_size, &c_options->image.limit_window_size);
2039 spin = pref_spin_new_int(hbox, NULL, NULL,
2041 options->image.max_window_size, &c_options->image.max_window_size);
2042 pref_checkbox_link_sensitivity(ct_button, spin);
2044 group = pref_group_new(vbox, FALSE, _("Full screen"), GTK_ORIENTATION_VERTICAL);
2046 c_options->fullscreen.screen = options->fullscreen.screen;
2047 c_options->fullscreen.above = options->fullscreen.above;
2048 hbox = fullscreen_prefs_selection_new(_("Location:"), &c_options->fullscreen.screen, &c_options->fullscreen.above);
2049 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2050 gtk_widget_show(hbox);
2052 pref_checkbox_new_int(group, _("Smooth image flip"),
2053 options->fullscreen.clean_flip, &c_options->fullscreen.clean_flip);
2054 pref_checkbox_new_int(group, _("Disable screen saver"),
2055 options->fullscreen.disable_saver, &c_options->fullscreen.disable_saver);
2058 #define PRE_FORMATTED_COLUMNS 5
2059 static void config_tab_osd(GtkWidget *notebook)
2063 GtkWidget *vbox_buttons;
2066 GtkWidget *image_overlay_template_view;
2067 GtkWidget *scrolled;
2068 GtkWidget *scrolled_pre_formatted;
2069 GtkTextBuffer *buffer;
2071 GtkWidget * subgroup;
2076 vbox = scrolled_notebook_page(notebook, _("OSD"));
2078 image_overlay_template_view = gtk_text_view_new();
2080 group = pref_group_new(vbox, FALSE, _("Overlay Screen Display"), GTK_ORIENTATION_VERTICAL);
2082 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2084 scrolled_pre_formatted = osd_new(PRE_FORMATTED_COLUMNS, image_overlay_template_view);
2085 gtk_widget_set_size_request(scrolled_pre_formatted, 200, 150);
2086 gtk_box_pack_start(GTK_BOX(subgroup), scrolled_pre_formatted, FALSE, FALSE, 0);
2087 gtk_widget_show(scrolled_pre_formatted);
2088 gtk_widget_show(subgroup);
2090 pref_line(group, PREF_PAD_GAP);
2092 pref_label_new(group, _("Image overlay template"));
2094 scrolled = gtk_scrolled_window_new(NULL, NULL);
2095 gtk_widget_set_size_request(scrolled, 200, 150);
2096 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2097 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
2098 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2099 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 5);
2100 gtk_widget_show(scrolled);
2102 gtk_widget_set_tooltip_markup(image_overlay_template_view,
2103 _("Extensive formatting options are shown in the Help file"));
2105 gtk_container_add(GTK_CONTAINER(scrolled), image_overlay_template_view);
2106 gtk_widget_show(image_overlay_template_view);
2108 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2110 #if GTK_CHECK_VERSION(3,4,0)
2111 button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
2112 G_CALLBACK(image_overlay_set_font_cb), notebook);
2114 button = gtk_font_button_new();
2115 gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Image Overlay Font");
2116 gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->image_overlay.font);
2117 g_signal_connect(G_OBJECT(button), "font-set",
2118 G_CALLBACK(image_overlay_set_font_cb),NULL);
2120 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2121 gtk_widget_show(button);
2123 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Text"), FALSE,
2124 G_CALLBACK(image_overlay_set_text_colour_cb), NULL);
2125 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2126 gtk_widget_show(button);
2128 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Background"), FALSE,
2129 G_CALLBACK(image_overlay_set_background_colour_cb), NULL);
2130 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2131 gtk_widget_show(button);
2132 image_overlay_set_text_colours();
2134 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2135 G_CALLBACK(image_overlay_default_template_cb), image_overlay_template_view);
2136 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2137 gtk_widget_show(button);
2139 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
2140 G_CALLBACK(image_overlay_help_cb), NULL);
2141 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2142 gtk_widget_show(button);
2144 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_overlay_template_view));
2145 if (options->image_overlay.template_string) gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
2146 g_signal_connect(G_OBJECT(buffer), "changed",
2147 G_CALLBACK(image_overlay_template_view_changed_cb), image_overlay_template_view);
2149 pref_line(group, PREF_PAD_GAP);
2151 group = pref_group_new(vbox, FALSE, _("Exif, XMP or IPTC tags"), GTK_ORIENTATION_VERTICAL);
2152 hbox = gtk_hbox_new(FALSE, 0);
2153 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2154 gtk_widget_show(hbox);
2155 label = gtk_label_new(_("%Exif.Image.Orientation%"));
2156 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2157 gtk_widget_show(label);
2158 pref_spacer(group,TRUE);
2160 group = pref_group_new(vbox, FALSE, _("Field separators"), GTK_ORIENTATION_VERTICAL);
2161 hbox = gtk_hbox_new(FALSE, 0);
2162 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2163 gtk_widget_show(hbox);
2164 label = gtk_label_new(_("Separator shown only if both fields are non-null:\n%formatted.ShutterSpeed%|%formatted.ISOSpeedRating%"));
2165 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2166 gtk_widget_show(label);
2167 pref_spacer(group,TRUE);
2169 group = pref_group_new(vbox, FALSE, _("Field maximum length"), GTK_ORIENTATION_VERTICAL);
2170 hbox = gtk_hbox_new(FALSE, 0);
2171 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2172 gtk_widget_show(hbox);
2173 label = gtk_label_new(_("%path:39%"));
2174 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2175 gtk_widget_show(label);
2176 pref_spacer(group,TRUE);
2178 group = pref_group_new(vbox, FALSE, _("Pre- and post- text"), GTK_ORIENTATION_VERTICAL);
2179 hbox = gtk_hbox_new(FALSE, 0);
2180 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2181 gtk_widget_show(hbox);
2182 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%"));
2183 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2184 gtk_widget_show(label);
2185 pref_spacer(group,TRUE);
2187 group = pref_group_new(vbox, FALSE, _("Pango markup"), GTK_ORIENTATION_VERTICAL);
2188 hbox = gtk_hbox_new(FALSE, 0);
2189 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2190 gtk_widget_show(hbox);
2191 label = gtk_label_new(_("<b>bold</b>\n<u>underline</u>\n<i>italic</i>\n<s>strikethrough</s>"));
2192 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2193 gtk_widget_show(label);
2196 static GtkTreeModel *create_class_model(void)
2198 GtkListStore *model;
2202 /* create list store */
2203 model = gtk_list_store_new(1, G_TYPE_STRING);
2204 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
2206 gtk_list_store_append(model, &iter);
2207 gtk_list_store_set(model, &iter, 0, _(format_class_list[i]), -1);
2209 return GTK_TREE_MODEL (model);
2214 static void config_tab_files(GtkWidget *notebook)
2221 GtkWidget *ct_button;
2222 GtkWidget *scrolled;
2223 GtkWidget *filter_view;
2224 GtkCellRenderer *renderer;
2225 GtkTreeSelection *selection;
2226 GtkTreeViewColumn *column;
2228 vbox = scrolled_notebook_page(notebook, _("Files"));
2230 group = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2232 pref_checkbox_new_int(group, _("Show hidden files or folders"),
2233 options->file_filter.show_hidden_files, &c_options->file_filter.show_hidden_files);
2234 pref_checkbox_new_int(group, _("Show parent folder (..)"),
2235 options->file_filter.show_parent_directory, &c_options->file_filter.show_parent_directory);
2236 pref_checkbox_new_int(group, _("Case sensitive sort"),
2237 options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
2238 pref_checkbox_new_int(group, _("Natural sort order"),
2239 options->file_sort.natural, &c_options->file_sort.natural);
2240 pref_checkbox_new_int(group, _("Disable file extension checks"),
2241 options->file_filter.disable_file_extension_checks, &c_options->file_filter.disable_file_extension_checks);
2243 ct_button = pref_checkbox_new_int(group, _("Disable File Filtering"),
2244 options->file_filter.disable, &c_options->file_filter.disable);
2247 group = pref_group_new(vbox, FALSE, _("Grouping sidecar extensions"), GTK_ORIENTATION_VERTICAL);
2249 sidecar_ext_entry = gtk_entry_new();
2250 gtk_entry_set_text(GTK_ENTRY(sidecar_ext_entry), options->sidecar.ext);
2251 gtk_box_pack_start(GTK_BOX(group), sidecar_ext_entry, FALSE, FALSE, 0);
2252 gtk_widget_show(sidecar_ext_entry);
2254 group = pref_group_new(vbox, TRUE, _("File types"), GTK_ORIENTATION_VERTICAL);
2256 frame = pref_group_parent(group);
2257 g_signal_connect(G_OBJECT(ct_button), "toggled",
2258 G_CALLBACK(filter_disable_cb), frame);
2259 gtk_widget_set_sensitive(frame, !options->file_filter.disable);
2261 scrolled = gtk_scrolled_window_new(NULL, NULL);
2262 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2263 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2264 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2265 gtk_widget_show(scrolled);
2267 filter_store = gtk_list_store_new(1, G_TYPE_POINTER);
2268 filter_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(filter_store));
2269 g_object_unref(filter_store);
2270 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
2271 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
2273 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), FALSE);
2275 column = gtk_tree_view_column_new();
2276 gtk_tree_view_column_set_title(column, _("Filter"));
2277 gtk_tree_view_column_set_resizable(column, TRUE);
2279 renderer = gtk_cell_renderer_toggle_new();
2280 g_signal_connect(G_OBJECT(renderer), "toggled",
2281 G_CALLBACK(filter_store_enable_cb), filter_store);
2282 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2283 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2284 GINT_TO_POINTER(FE_ENABLE), NULL);
2286 renderer = gtk_cell_renderer_text_new();
2287 g_signal_connect(G_OBJECT(renderer), "edited",
2288 G_CALLBACK(filter_store_ext_edit_cb), filter_store);
2289 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2290 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2291 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2292 GINT_TO_POINTER(FE_EXTENSION), NULL);
2293 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2295 column = gtk_tree_view_column_new();
2296 gtk_tree_view_column_set_title(column, _("Description"));
2297 gtk_tree_view_column_set_resizable(column, TRUE);
2298 gtk_tree_view_column_set_fixed_width(column, 200);
2299 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
2301 renderer = gtk_cell_renderer_text_new();
2302 g_signal_connect(G_OBJECT(renderer), "edited",
2303 G_CALLBACK(filter_store_desc_edit_cb), filter_store);
2304 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2305 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2306 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2307 GINT_TO_POINTER(FE_DESCRIPTION), NULL);
2308 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2310 column = gtk_tree_view_column_new();
2311 gtk_tree_view_column_set_title(column, _("Class"));
2312 gtk_tree_view_column_set_resizable(column, TRUE);
2313 renderer = gtk_cell_renderer_combo_new();
2314 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE,
2315 "model", create_class_model(),
2320 g_signal_connect(G_OBJECT(renderer), "edited",
2321 G_CALLBACK(filter_store_class_edit_cb), filter_store);
2322 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2323 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2324 GINT_TO_POINTER(FE_CLASS), NULL);
2325 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2327 column = gtk_tree_view_column_new();
2328 gtk_tree_view_column_set_title(column, _("Writable"));
2329 gtk_tree_view_column_set_resizable(column, FALSE);
2330 renderer = gtk_cell_renderer_toggle_new();
2331 g_signal_connect(G_OBJECT(renderer), "toggled",
2332 G_CALLBACK(filter_store_writable_cb), filter_store);
2333 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2334 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2335 GINT_TO_POINTER(FE_WRITABLE), NULL);
2336 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2338 column = gtk_tree_view_column_new();
2339 gtk_tree_view_column_set_title(column, _("Sidecar is allowed"));
2340 gtk_tree_view_column_set_resizable(column, FALSE);
2341 renderer = gtk_cell_renderer_toggle_new();
2342 g_signal_connect(G_OBJECT(renderer), "toggled",
2343 G_CALLBACK(filter_store_sidecar_cb), filter_store);
2344 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2345 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2346 GINT_TO_POINTER(FE_ALLOW_SIDECAR), NULL);
2347 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2350 filter_store_populate();
2351 gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
2352 gtk_widget_show(filter_view);
2354 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2356 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2357 G_CALLBACK(filter_default_cb), filter_view);
2358 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2359 gtk_widget_show(button);
2361 button = pref_button_new(NULL, GTK_STOCK_REMOVE, NULL, FALSE,
2362 G_CALLBACK(filter_remove_cb), filter_view);
2363 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2364 gtk_widget_show(button);
2366 button = pref_button_new(NULL, GTK_STOCK_ADD, NULL, FALSE,
2367 G_CALLBACK(filter_add_cb), filter_view);
2368 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2369 gtk_widget_show(button);
2373 static void config_tab_metadata(GtkWidget *notebook)
2378 GtkWidget *ct_button;
2382 vbox = scrolled_notebook_page(notebook, _("Metadata"));
2385 group = pref_group_new(vbox, FALSE, _("Metadata writing process"), GTK_ORIENTATION_VERTICAL);
2387 label = pref_label_new(group, _("Warning: Geeqie is built without Exiv2. Some options are disabled."));
2389 label = pref_label_new(group, _("Metadata are written in the following order. The process ends after first success."));
2390 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2392 ct_button = pref_checkbox_new_int(group, _("1) Save metadata in image files, or sidecar files, according to the XMP standard"),
2393 options->metadata.save_in_image_file, &c_options->metadata.save_in_image_file);
2395 gtk_widget_set_sensitive(ct_button, FALSE);
2398 pref_checkbox_new_int(group, _("2) Save metadata in '.metadata' folder, local to image folder (non-standard)"),
2399 options->metadata.enable_metadata_dirs, &c_options->metadata.enable_metadata_dirs);
2401 text = g_strdup_printf(_("3) Save metadata in Geeqie private directory '%s'"), get_metadata_cache_dir());
2402 label = pref_label_new(group, text);
2403 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2404 gtk_misc_set_padding(GTK_MISC(label), 22, 0);
2407 group = pref_group_new(vbox, FALSE, _("Step 1: Write to image files"), GTK_ORIENTATION_VERTICAL);
2409 gtk_widget_set_sensitive(group, FALSE);
2412 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2413 pref_checkbox_link_sensitivity(ct_button, hbox);
2415 pref_checkbox_new_int(hbox, _("Store metadata also in legacy IPTC tags (converted according to IPTC4XMP standard)"),
2416 options->metadata.save_legacy_IPTC, &c_options->metadata.save_legacy_IPTC);
2418 pref_checkbox_new_int(hbox, _("Warn if the image files are unwritable"),
2419 options->metadata.warn_on_write_problems, &c_options->metadata.warn_on_write_problems);
2421 pref_checkbox_new_int(hbox, _("Ask before writing to image files"),
2422 options->metadata.confirm_write, &c_options->metadata.confirm_write);
2424 pref_checkbox_new_int(hbox, _("Create sidecar files named image.ext.xmp (as opposed to image.xmp)"),
2425 options->metadata.sidecar_extended_name, &c_options->metadata.sidecar_extended_name);
2427 group = pref_group_new(vbox, FALSE, _("Step 2 and 3: write to Geeqie private files"), GTK_ORIENTATION_VERTICAL);
2429 gtk_widget_set_sensitive(group, FALSE);
2432 pref_checkbox_new_int(group, _("Use GQview legacy metadata format (supports only keywords and comments) instead of XMP"),
2433 options->metadata.save_legacy_format, &c_options->metadata.save_legacy_format);
2436 group = pref_group_new(vbox, FALSE, _("Miscellaneous"), GTK_ORIENTATION_VERTICAL);
2437 pref_checkbox_new_int(group, _("Write the same description tags (keywords, comment, etc.) to all grouped sidecars"),
2438 options->metadata.sync_grouped_files, &c_options->metadata.sync_grouped_files);
2440 pref_checkbox_new_int(group, _("Allow keywords to differ only in case"),
2441 options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
2443 ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"),
2444 options->metadata.write_orientation, &c_options->metadata.write_orientation);
2446 gtk_widget_set_sensitive(ct_button, FALSE);
2449 group = pref_group_new(vbox, FALSE, _("Auto-save options"), GTK_ORIENTATION_VERTICAL);
2451 ct_button = pref_checkbox_new_int(group, _("Write metadata after timeout"),
2452 options->metadata.confirm_after_timeout, &c_options->metadata.confirm_after_timeout);
2454 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2455 pref_checkbox_link_sensitivity(ct_button, hbox);
2457 pref_spin_new_int(hbox, _("Timeout (seconds):"), NULL, 0, 900, 1,
2458 options->metadata.confirm_timeout, &c_options->metadata.confirm_timeout);
2460 pref_checkbox_new_int(group, _("Write metadata on image change"),
2461 options->metadata.confirm_on_image_change, &c_options->metadata.confirm_on_image_change);
2463 pref_checkbox_new_int(group, _("Write metadata on directory change"),
2464 options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
2466 group = pref_group_new(vbox, FALSE, _("Pre-load metadata"), GTK_ORIENTATION_VERTICAL);
2468 ct_button = pref_checkbox_new_int(group, _("Read metadata in background"),
2469 options->read_metadata_in_idle, &c_options->read_metadata_in_idle);
2470 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");
2475 typedef struct _KeywordFindData KeywordFindData;
2476 struct _KeywordFindData
2483 GtkWidget *button_close;
2484 GtkWidget *button_stop;
2485 GtkWidget *button_start;
2486 GtkWidget *progress;
2494 guint idle_id; /* event source id */
2497 #define KEYWORD_DIALOG_WIDTH 400
2499 static void keywords_find_folder(KeywordFindData *kfd, FileData *dir_fd)
2501 GList *list_d = NULL;
2502 GList *list_f = NULL;
2506 filelist_read(dir_fd, &list_f, &list_d);
2510 filelist_read(dir_fd, &list_f, NULL);
2513 list_f = filelist_filter(list_f, FALSE);
2514 list_d = filelist_filter(list_d, TRUE);
2516 kfd->list = g_list_concat(list_f, kfd->list);
2517 kfd->list_dir = g_list_concat(list_d, kfd->list_dir);
2520 static void keywords_find_reset(KeywordFindData *kfd)
2522 filelist_free(kfd->list);
2525 filelist_free(kfd->list_dir);
2526 kfd->list_dir = NULL;
2529 static void keywords_find_close_cb(GenericDialog *fd, gpointer data)
2531 KeywordFindData *kfd = data;
2533 if (!gtk_widget_get_sensitive(kfd->button_close)) return;
2535 keywords_find_reset(kfd);
2536 generic_dialog_close(kfd->gd);
2540 static void keywords_find_finish(KeywordFindData *kfd)
2542 keywords_find_reset(kfd);
2544 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("done"));
2545 spinner_set_interval(kfd->spinner, -1);
2547 gtk_widget_set_sensitive(kfd->group, TRUE);
2548 gtk_widget_set_sensitive(kfd->button_start, TRUE);
2549 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2550 gtk_widget_set_sensitive(kfd->button_close, TRUE);
2553 static void keywords_find_stop_cb(GenericDialog *fd, gpointer data)
2555 KeywordFindData *kfd = data;
2557 g_idle_remove_by_data(kfd);
2559 keywords_find_finish(kfd);
2562 static gboolean keywords_find_file(gpointer data)
2564 KeywordFindData *kfd = data;
2566 GtkTextBuffer *buffer;
2574 fd = kfd->list->data;
2575 kfd->list = g_list_remove(kfd->list, fd);
2577 keywords = metadata_read_list(fd, KEYWORD_KEY, METADATA_PLAIN);
2578 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2582 gtk_text_buffer_get_end_iter(buffer, &iter);
2583 tmp = g_strconcat(keywords->data, "\n", NULL);
2584 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
2586 keywords = keywords->next;
2589 gtk_entry_set_text(GTK_ENTRY(kfd->progress), fd->path);
2590 file_data_unref(fd);
2591 string_list_free(keywords);
2595 else if (kfd->list_dir)
2599 fd = kfd->list_dir->data;
2600 kfd->list_dir = g_list_remove(kfd->list_dir, fd);
2602 keywords_find_folder(kfd, fd);
2604 file_data_unref(fd);
2609 keywords_find_finish(kfd);
2614 static void keywords_find_start_cb(GenericDialog *fd, gpointer data)
2616 KeywordFindData *kfd = data;
2619 if (kfd->list || !gtk_widget_get_sensitive(kfd->button_start)) return;
2621 path = remove_trailing_slash((gtk_entry_get_text(GTK_ENTRY(kfd->entry))));
2622 parse_out_relatives(path);
2626 warning_dialog(_("Invalid folder"),
2627 _("The specified folder can not be found."),
2628 GTK_STOCK_DIALOG_WARNING, kfd->gd->dialog);
2634 gtk_widget_set_sensitive(kfd->group, FALSE);
2635 gtk_widget_set_sensitive(kfd->button_start, FALSE);
2636 gtk_widget_set_sensitive(kfd->button_stop, TRUE);
2637 gtk_widget_set_sensitive(kfd->button_close, FALSE);
2638 spinner_set_interval(kfd->spinner, SPINNER_SPEED);
2640 dir_fd = file_data_new_dir(path);
2641 keywords_find_folder(kfd, dir_fd);
2642 file_data_unref(dir_fd);
2643 kfd->idle_id = g_idle_add(keywords_find_file, kfd);
2649 static void keywords_find_dialog(GtkWidget *widget, const gchar *path)
2651 KeywordFindData *kfd;
2655 kfd = g_new0(KeywordFindData, 1);
2657 kfd->gd = generic_dialog_new(_("Search for keywords"),
2658 "search_for_keywords",
2661 gtk_window_set_default_size(GTK_WINDOW(kfd->gd->dialog), KEYWORD_DIALOG_WIDTH, -1);
2662 kfd->gd->cancel_cb = keywords_find_close_cb;
2663 kfd->button_close = generic_dialog_add_button(kfd->gd, GTK_STOCK_CLOSE, NULL,
2664 keywords_find_close_cb, FALSE);
2665 kfd->button_start = generic_dialog_add_button(kfd->gd, GTK_STOCK_OK, _("S_tart"),
2666 keywords_find_start_cb, FALSE);
2667 kfd->button_stop = generic_dialog_add_button(kfd->gd, GTK_STOCK_STOP, NULL,
2668 keywords_find_stop_cb, FALSE);
2669 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2671 generic_dialog_add_message(kfd->gd, NULL, _("Search for keywords"), NULL, FALSE);
2673 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0);
2674 pref_spacer(hbox, PREF_PAD_INDENT);
2675 kfd->group = pref_box_new(hbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2677 hbox = pref_box_new(kfd->group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2678 pref_label_new(hbox, _("Folder:"));
2680 label = tab_completion_new(&kfd->entry, path, NULL, NULL, NULL, NULL);
2681 tab_completion_add_select_button(kfd->entry,_("Select folder") , TRUE);
2682 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
2683 gtk_widget_show(label);
2685 pref_checkbox_new_int(kfd->group, _("Include subfolders"), FALSE, &kfd->recurse);
2687 pref_line(kfd->gd->vbox, PREF_PAD_SPACE);
2688 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2690 kfd->progress = gtk_entry_new();
2691 gtk_widget_set_can_focus(kfd->progress, FALSE);
2692 gtk_editable_set_editable(GTK_EDITABLE(kfd->progress), FALSE);
2693 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("click start to begin"));
2694 gtk_box_pack_start(GTK_BOX(hbox), kfd->progress, TRUE, TRUE, 0);
2695 gtk_widget_show(kfd->progress);
2697 kfd->spinner = spinner_new(NULL, -1);
2698 gtk_box_pack_start(GTK_BOX(hbox), kfd->spinner, FALSE, FALSE, 0);
2699 gtk_widget_show(kfd->spinner);
2703 gtk_widget_show(kfd->gd->dialog);
2706 static void keywords_find_cb(GtkWidget *widget, gpointer data)
2708 const gchar *path = layout_get_path(NULL);
2710 if (!path || !*path) path = homedir();
2711 keywords_find_dialog(widget, path);
2714 static void config_tab_keywords_save()
2716 GtkTextIter start, end;
2717 GtkTextBuffer *buffer;
2718 GList *kw_list = NULL;
2724 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2725 gtk_text_buffer_get_bounds(buffer, &start, &end);
2727 buffer_text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
2729 kw_split = strtok(buffer_text, "\n");
2730 while (kw_split != NULL)
2736 if (g_strcmp0(work->data, kw_split) == 0)
2745 kw_list = g_list_append(kw_list, g_strdup(kw_split));
2747 kw_split = strtok(NULL, "\n");
2750 keyword_list_set(kw_list);
2752 string_list_free(kw_list);
2753 g_free(buffer_text);
2756 static void config_tab_keywords(GtkWidget *notebook)
2762 GtkWidget *scrolled;
2764 GtkTextBuffer *buffer;
2767 vbox = scrolled_notebook_page(notebook, _("Keywords"));
2769 group = pref_group_new(vbox, TRUE, _("Edit keywords autocompletion list"), GTK_ORIENTATION_VERTICAL);
2771 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2773 button = pref_button_new(hbox, GTK_STOCK_EXECUTE, _("Search"), FALSE,
2774 G_CALLBACK(keywords_find_cb), keyword_text);
2775 gtk_widget_set_tooltip_text(button, "Search for existing keywords");
2778 keyword_text = gtk_text_view_new();
2779 gtk_widget_set_size_request(keyword_text, 20, 20);
2780 scrolled = gtk_scrolled_window_new(NULL, NULL);
2781 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2782 gtk_widget_show(scrolled);
2784 gtk_container_add(GTK_CONTAINER(scrolled), keyword_text);
2785 gtk_widget_show(keyword_text);
2787 gtk_text_view_set_editable(GTK_TEXT_VIEW(keyword_text), TRUE);
2789 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2790 gtk_text_buffer_create_tag(buffer, "monospace",
2791 "family", "monospace", NULL);
2793 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(keyword_text), GTK_WRAP_WORD);
2794 gtk_text_buffer_get_start_iter(buffer, &iter);
2795 gtk_text_buffer_create_mark(buffer, "end", &iter, FALSE);
2798 path = g_build_filename(get_rc_dir(), "keywords", NULL);
2800 GList *kwl = keyword_list_get();
2801 kwl = g_list_first(kwl);
2804 gtk_text_buffer_get_end_iter (buffer, &iter);
2805 tmp = g_strconcat(kwl->data, "\n", NULL);
2806 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
2811 gtk_text_buffer_set_modified(buffer, FALSE);
2818 static void intent_menu_cb(GtkWidget *combo, gpointer data)
2820 gint *option = data;
2822 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
2826 *option = INTENT_PERCEPTUAL;
2829 *option = INTENT_RELATIVE_COLORIMETRIC;
2832 *option = INTENT_SATURATION;
2835 *option = INTENT_ABSOLUTE_COLORIMETRIC;
2840 static void add_intent_menu(GtkWidget *table, gint column, gint row, const gchar *text,
2841 gint option, gint *option_c)
2848 pref_table_label(table, column, row, text, 0.0);
2850 combo = gtk_combo_box_text_new();
2852 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Perceptual"));
2853 if (option == INTENT_PERCEPTUAL) current = 0;
2854 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Relative Colorimetric"));
2855 if (option == INTENT_RELATIVE_COLORIMETRIC) current = 1;
2856 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Saturation"));
2857 if (option == INTENT_SATURATION) current = 2;
2858 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Absolute Colorimetric"));
2859 if (option == INTENT_ABSOLUTE_COLORIMETRIC) current = 3;
2861 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
2863 gtk_widget_set_tooltip_text(combo,"Refer to the lcms documentation for the defaults used when the selected Intent is not available");
2865 g_signal_connect(G_OBJECT(combo), "changed",
2866 G_CALLBACK(intent_menu_cb), option_c);
2868 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
2869 GTK_EXPAND | GTK_FILL, 0, 0, 0);
2870 gtk_widget_show(combo);
2874 static void config_tab_color(GtkWidget *notebook)
2883 vbox = scrolled_notebook_page(notebook, _("Color management"));
2885 group = pref_group_new(vbox, FALSE, _("Input profiles"), GTK_ORIENTATION_VERTICAL);
2887 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
2890 table = pref_table_new(group, 3, COLOR_PROFILE_INPUTS + 1, FALSE, FALSE);
2891 gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
2893 label = pref_table_label(table, 0, 0, _("Type"), 0.0);
2894 pref_label_bold(label, TRUE, FALSE);
2896 label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
2897 pref_label_bold(label, TRUE, FALSE);
2899 label = pref_table_label(table, 2, 0, _("File"), 0.0);
2900 pref_label_bold(label, TRUE, FALSE);
2902 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
2907 buf = g_strdup_printf(_("Input %d:"), i + COLOR_PROFILE_FILE);
2908 pref_table_label(table, 0, i + 1, buf, 1.0);
2911 entry = gtk_entry_new();
2912 gtk_entry_set_max_length(GTK_ENTRY(entry), EDITOR_NAME_MAX_LENGTH);
2913 if (options->color_profile.input_name[i])
2915 gtk_entry_set_text(GTK_ENTRY(entry), options->color_profile.input_name[i]);
2917 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, i + 1, i + 2,
2918 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2919 gtk_widget_show(entry);
2920 color_profile_input_name_entry[i] = entry;
2922 tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, ".icc", "ICC Files", NULL);
2923 tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
2924 gtk_widget_set_size_request(entry, 160, -1);
2925 gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
2926 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2927 gtk_widget_show(tabcomp);
2928 color_profile_input_file_entry[i] = entry;
2931 group = pref_group_new(vbox, FALSE, _("Screen profile"), GTK_ORIENTATION_VERTICAL);
2933 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
2935 pref_checkbox_new_int(group, _("Use system screen profile if available"),
2936 options->color_profile.use_x11_screen_profile, &c_options->color_profile.use_x11_screen_profile);
2938 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2940 pref_table_label(table, 0, 0, _("Screen:"), 1.0);
2941 tabcomp = tab_completion_new(&color_profile_screen_file_entry,
2942 options->color_profile.screen_file, NULL, ".icc", "ICC Files", NULL);
2943 tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
2944 gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
2946 add_intent_menu(table, 0, 1, _("Render Intent:"), options->color_profile.render_intent, &c_options->color_profile.render_intent);
2948 gtk_table_attach(GTK_TABLE(table), tabcomp, 1, 2,
2950 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2952 gtk_widget_show(tabcomp);
2955 /* advanced entry tab */
2956 static void use_geeqie_trash_cb(GtkWidget *widget, gpointer data)
2958 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
2960 c_options->file_ops.use_system_trash = FALSE;
2964 static void use_system_trash_cb(GtkWidget *widget, gpointer data)
2966 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
2968 c_options->file_ops.use_system_trash = TRUE;
2972 static void config_tab_behavior(GtkWidget *notebook)
2979 GtkWidget *ct_button;
2983 GtkWidget *with_rename;
2984 GtkWidget *collections_on_top;
2986 vbox = scrolled_notebook_page(notebook, _("Behavior"));
2988 group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
2990 pref_checkbox_new_int(group, _("Confirm permanent file delete"),
2991 options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
2992 pref_checkbox_new_int(group, _("Confirm move file to Trash"),
2993 options->file_ops.confirm_move_to_trash, &c_options->file_ops.confirm_move_to_trash);
2994 pref_checkbox_new_int(group, _("Enable Delete key"),
2995 options->file_ops.enable_delete_key, &c_options->file_ops.enable_delete_key);
2997 ct_button = pref_radiobutton_new(group, NULL, _("Use Geeqie trash location"),
2998 !options->file_ops.use_system_trash, G_CALLBACK(use_geeqie_trash_cb),NULL);
3000 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3001 pref_checkbox_link_sensitivity(ct_button, hbox);
3003 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
3004 pref_label_new(hbox, _("Folder:"));
3006 tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL, NULL, NULL);
3007 tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
3008 gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
3009 gtk_widget_show(tabcomp);
3011 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3012 pref_checkbox_link_sensitivity(ct_button, hbox);
3014 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
3015 spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MB"),
3016 0, 2048, 1, options->file_ops.safe_delete_folder_maxsize, &c_options->file_ops.safe_delete_folder_maxsize);
3017 gtk_widget_set_tooltip_markup(spin, _("Set to 0 for unlimited size"));
3018 button = pref_button_new(NULL, NULL, _("View"), FALSE,
3019 G_CALLBACK(safe_delete_view_cb), NULL);
3020 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3021 gtk_widget_show(button);
3023 button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
3024 G_CALLBACK(safe_delete_clear_cb), NULL);
3025 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3026 pref_radiobutton_new(group, ct_button, _("Use system Trash bin"),
3027 options->file_ops.use_system_trash, G_CALLBACK(use_system_trash_cb), NULL);
3028 gtk_widget_show(button);
3030 pref_spacer(group, PREF_PAD_GROUP);
3033 group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
3035 pref_checkbox_new_int(group, _("Descend folders in tree view"),
3036 options->tree_descend_subdirs, &c_options->tree_descend_subdirs);
3038 pref_checkbox_new_int(group, _("In place renaming"),
3039 options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
3041 pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
3042 options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
3044 marks = pref_checkbox_new_int(group, _("Save marks on exit"),
3045 options->marks_save, &c_options->marks_save);
3046 gtk_widget_set_tooltip_text(marks,"Note that marks linked to a keyword will be saved irrespective of this setting");
3048 with_rename = pref_checkbox_new_int(group, _("Use \"With Rename\" as default for Copy/Move dialogs"),
3049 options->with_rename, &c_options->with_rename);
3050 gtk_widget_set_tooltip_text(with_rename,"Change the default button for Copy/Move dialogs");
3052 collections_on_top = pref_checkbox_new_int(group, _("Open collections on top"),
3053 options->collections_on_top, &c_options->collections_on_top);
3054 gtk_widget_set_tooltip_text(collections_on_top,"Open collections window on top");
3056 pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
3057 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
3059 pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
3060 16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
3062 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3063 add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
3065 pref_spacer(group, PREF_PAD_GROUP);
3067 group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
3069 pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
3070 options->progressive_key_scrolling, &c_options->progressive_key_scrolling);
3071 pref_spin_new_int(group, _("Keyboard scrolling step multiplier:"), NULL,
3072 1, 32, 1, options->keyboard_scroll_step, (int *)&c_options->keyboard_scroll_step);
3073 pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
3074 options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
3075 pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
3076 options->image_lm_click_nav, &c_options->image_lm_click_nav);
3077 pref_checkbox_new_int(group, _("Play video by left click on image"),
3078 options->image_l_click_video, &c_options->image_l_click_video);
3079 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3080 add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
3084 pref_spacer(group, PREF_PAD_GROUP);
3086 group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
3088 pref_spin_new_int(group, _("Debug level:"), NULL,
3089 DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
3091 pref_checkbox_new_int(group, _("Timer data"),
3092 options->log_window.timer_data, &c_options->log_window.timer_data);
3094 pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
3095 1, 99999, 1, options->log_window_lines, &options->log_window_lines);
3099 /* accelerators tab */
3100 static void config_tab_accelerators(GtkWidget *notebook)
3106 GtkWidget *scrolled;
3107 GtkWidget *accel_view;
3108 GtkCellRenderer *renderer;
3109 GtkTreeSelection *selection;
3110 GtkTreeViewColumn *column;
3112 vbox = scrolled_notebook_page(notebook, _("Keyboard"));
3114 group = pref_group_new(vbox, TRUE, _("Accelerators"), GTK_ORIENTATION_VERTICAL);
3116 scrolled = gtk_scrolled_window_new(NULL, NULL);
3117 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
3118 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
3119 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3120 gtk_widget_show(scrolled);
3122 accel_store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
3124 accel_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(accel_store));
3125 g_object_unref(accel_store);
3126 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(accel_view));
3127 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
3129 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(accel_view), FALSE);
3131 renderer = gtk_cell_renderer_text_new();
3133 column = gtk_tree_view_column_new_with_attributes(_("Action"),
3138 gtk_tree_view_column_set_sort_column_id(column, AE_ACTION);
3139 gtk_tree_view_column_set_resizable(column, TRUE);
3140 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3143 renderer = gtk_cell_renderer_accel_new();
3144 g_signal_connect(G_OBJECT(renderer), "accel-cleared",
3145 G_CALLBACK(accel_store_cleared_cb), accel_store);
3146 g_signal_connect(G_OBJECT(renderer), "accel-edited",
3147 G_CALLBACK(accel_store_edited_cb), accel_store);
3150 g_object_set (renderer,
3152 "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
3155 column = gtk_tree_view_column_new_with_attributes(_("KEY"),
3160 gtk_tree_view_column_set_sort_column_id(column, AE_KEY);
3161 gtk_tree_view_column_set_resizable(column, TRUE);
3162 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3164 renderer = gtk_cell_renderer_text_new();
3166 column = gtk_tree_view_column_new_with_attributes(_("Tooltip"),
3171 gtk_tree_view_column_set_sort_column_id(column, AE_TOOLTIP);
3172 gtk_tree_view_column_set_resizable(column, TRUE);
3173 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3175 renderer = gtk_cell_renderer_text_new();
3177 column = gtk_tree_view_column_new_with_attributes("Accel",
3182 gtk_tree_view_column_set_sort_column_id(column, AE_ACCEL);
3183 gtk_tree_view_column_set_resizable(column, TRUE);
3184 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3186 accel_store_populate();
3187 gtk_container_add(GTK_CONTAINER(scrolled), accel_view);
3188 gtk_widget_show(accel_view);
3190 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3192 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
3193 G_CALLBACK(accel_default_cb), accel_view);
3194 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3195 gtk_widget_show(button);
3197 button = pref_button_new(NULL, NULL, _("Reset selected"), FALSE,
3198 G_CALLBACK(accel_reset_cb), accel_view);
3199 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3200 gtk_widget_show(button);
3204 static void config_tab_toolbar(GtkWidget *notebook)
3207 GtkWidget *toolbardata;
3210 lw = layout_window_list->data;
3212 vbox = scrolled_notebook_page(notebook, _("Toolbar"));
3214 toolbardata = toolbar_select_new(lw);
3215 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3216 gtk_widget_show(vbox);
3220 static void config_tab_stereo(GtkWidget *notebook)
3228 GtkWidget *fs_button;
3229 vbox = scrolled_notebook_page(notebook, _("Stereo"));
3231 group = pref_group_new(vbox, FALSE, _("Windowed stereo mode"), GTK_ORIENTATION_VERTICAL);
3233 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3234 add_stereo_mode_menu(table, 0, 0, _("Windowed stereo mode"), options->stereo.mode, &c_options->stereo.mode, FALSE);
3236 table = pref_table_new(group, 2, 2, TRUE, FALSE);
3237 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3238 pref_checkbox_new_int(box, _("Mirror left image"),
3239 options->stereo.mode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.mirror_left);
3240 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3241 pref_checkbox_new_int(box, _("Flip left image"),
3242 options->stereo.mode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.flip_left);
3243 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3244 pref_checkbox_new_int(box, _("Mirror right image"),
3245 options->stereo.mode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.mirror_right);
3246 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3247 pref_checkbox_new_int(box, _("Flip right image"),
3248 options->stereo.mode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.flip_right);
3249 pref_checkbox_new_int(group, _("Swap left and right images"),
3250 options->stereo.mode & PR_STEREO_SWAP, &c_options->stereo.tmp.swap);
3251 pref_checkbox_new_int(group, _("Disable stereo mode on single image source"),
3252 options->stereo.mode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.temp_disable);
3254 group = pref_group_new(vbox, FALSE, _("Fullscreen stereo mode"), GTK_ORIENTATION_VERTICAL);
3255 fs_button = pref_checkbox_new_int(group, _("Use different settings for fullscreen"),
3256 options->stereo.enable_fsmode, &c_options->stereo.enable_fsmode);
3257 box2 = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
3258 pref_checkbox_link_sensitivity(fs_button, box2);
3259 table = pref_table_new(box2, 2, 1, FALSE, FALSE);
3260 add_stereo_mode_menu(table, 0, 0, _("Fullscreen stereo mode"), options->stereo.fsmode, &c_options->stereo.fsmode, TRUE);
3261 table = pref_table_new(box2, 2, 2, TRUE, FALSE);
3262 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3263 pref_checkbox_new_int(box, _("Mirror left image"),
3264 options->stereo.fsmode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.fs_mirror_left);
3265 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3266 pref_checkbox_new_int(box, _("Flip left image"),
3267 options->stereo.fsmode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.fs_flip_left);
3268 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3269 pref_checkbox_new_int(box, _("Mirror right image"),
3270 options->stereo.fsmode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.fs_mirror_right);
3271 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3272 pref_checkbox_new_int(box, _("Flip right image"),
3273 options->stereo.fsmode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.fs_flip_right);
3274 pref_checkbox_new_int(box2, _("Swap left and right images"),
3275 options->stereo.fsmode & PR_STEREO_SWAP, &c_options->stereo.tmp.fs_swap);
3276 pref_checkbox_new_int(box2, _("Disable stereo mode on single image source"),
3277 options->stereo.fsmode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.fs_temp_disable);
3279 group2 = pref_group_new(box2, FALSE, _("Fixed position"), GTK_ORIENTATION_VERTICAL);
3280 table = pref_table_new(group2, 5, 3, FALSE, FALSE);
3281 pref_table_spin_new_int(table, 0, 0, _("Width"), NULL,
3282 1, 5000, 1, options->stereo.fixed_w, &c_options->stereo.fixed_w);
3283 pref_table_spin_new_int(table, 3, 0, _("Height"), NULL,
3284 1, 5000, 1, options->stereo.fixed_h, &c_options->stereo.fixed_h);
3285 pref_table_spin_new_int(table, 0, 1, _("Left X"), NULL,
3286 0, 5000, 1, options->stereo.fixed_x1, &c_options->stereo.fixed_x1);
3287 pref_table_spin_new_int(table, 3, 1, _("Left Y"), NULL,
3288 0, 5000, 1, options->stereo.fixed_y1, &c_options->stereo.fixed_y1);
3289 pref_table_spin_new_int(table, 0, 2, _("Right X"), NULL,
3290 0, 5000, 1, options->stereo.fixed_x2, &c_options->stereo.fixed_x2);
3291 pref_table_spin_new_int(table, 3, 2, _("Right Y"), NULL,
3292 0, 5000, 1, options->stereo.fixed_y2, &c_options->stereo.fixed_y2);
3296 /* Main preferences window */
3297 static void config_window_create(void)
3299 GtkWidget *win_vbox;
3301 GtkWidget *notebook;
3303 GtkWidget *ct_button;
3305 if (!c_options) c_options = init_options(NULL);
3307 configwindow = window_new(GTK_WINDOW_TOPLEVEL, "preferences", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Preferences"));
3308 gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
3309 g_signal_connect(G_OBJECT(configwindow), "delete_event",
3310 G_CALLBACK(config_window_delete), NULL);
3311 gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
3312 gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
3313 gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
3315 win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
3316 gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
3317 gtk_widget_show(win_vbox);
3319 notebook = gtk_notebook_new();
3320 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP);
3321 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE);
3322 gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
3324 config_tab_general(notebook);
3325 config_tab_image(notebook);
3326 config_tab_osd(notebook);
3327 config_tab_windows(notebook);
3328 config_tab_accelerators(notebook);
3329 config_tab_files(notebook);
3330 config_tab_metadata(notebook);
3331 config_tab_keywords(notebook);
3332 config_tab_color(notebook);
3333 config_tab_stereo(notebook);
3334 config_tab_behavior(notebook);
3335 config_tab_toolbar(notebook);
3337 hbox = gtk_hbutton_box_new();
3338 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
3339 gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
3340 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
3341 gtk_widget_show(hbox);
3343 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
3344 G_CALLBACK(config_window_help_cb), notebook);
3345 gtk_container_add(GTK_CONTAINER(hbox), button);
3346 gtk_widget_set_can_default(button, TRUE);
3347 gtk_widget_show(button);
3349 button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
3350 G_CALLBACK(config_window_ok_cb), NULL);
3351 gtk_container_add(GTK_CONTAINER(hbox), button);
3352 gtk_widget_set_can_default(button, TRUE);
3353 gtk_widget_grab_default(button);
3354 gtk_widget_show(button);
3358 button = pref_button_new(NULL, GTK_STOCK_SAVE, NULL, FALSE,
3359 G_CALLBACK(config_window_save_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_APPLY, NULL, FALSE,
3365 G_CALLBACK(config_window_apply_cb), NULL);
3366 gtk_container_add(GTK_CONTAINER(hbox), button);
3367 gtk_widget_set_can_default(button, TRUE);
3368 gtk_widget_show(button);
3370 button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
3371 G_CALLBACK(config_window_close_cb), NULL);
3372 gtk_container_add(GTK_CONTAINER(hbox), button);
3373 gtk_widget_set_can_default(button, TRUE);
3374 gtk_widget_show(button);
3376 if (!generic_dialog_get_alternative_button_order(configwindow))
3378 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
3381 gtk_widget_show(notebook);
3383 gtk_widget_show(configwindow);
3387 *-----------------------------------------------------------------------------
3388 * config window show (public)
3389 *-----------------------------------------------------------------------------
3392 void show_config_window(void)
3396 gtk_window_present(GTK_WINDOW(configwindow));
3400 config_window_create();
3409 void show_about_window(LayoutWindow *lw)
3411 GdkPixbuf *pixbuf_logo;
3412 GdkPixbuf *pixbuf_icon;
3413 gchar *authors[1000];
3421 #define LINE_LENGTH 1000
3422 gchar line[LINE_LENGTH];
3424 copyright = g_string_new(NULL);
3425 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");
3427 zd_path = g_build_filename(GQ_BIN_DIR, TIMEZONE_DATABASE, NULL);
3428 cd = ZDOpenDatabase(zd_path);
3431 copyright = g_string_append(copyright, ZDGetNotice(cd));
3433 ZDCloseDatabase(cd);
3437 path = g_build_filename(GQ_HELPDIR, "AUTHORS", NULL);
3438 fp = fopen(path, "r");
3441 while(fgets(line, LINE_LENGTH, fp))
3443 /* get rid of ending \n from fgets */
3444 line[strlen(line) - 1] = '\0';
3445 authors[i_authors] = g_strdup(line);
3448 authors[i_authors] = NULL;
3453 comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
3454 "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
3456 pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
3457 pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
3458 gtk_show_about_dialog(GTK_WINDOW(lw->window),
3459 "title", _("About Geeqie"),
3461 "program-name", GQ_APPNAME,
3463 "logo", pixbuf_logo,
3464 "icon", pixbuf_icon,
3465 "website", GQ_WEBSITE,
3466 "website-label", "Website",
3467 "comments", comment,
3469 "translator-credits", _("translator-credits"),
3470 "wrap-license", TRUE,
3471 "license", copyright->str,
3474 g_string_free(copyright, TRUE);
3477 while(n < i_authors)
3487 static void image_overlay_set_text_colours()
3489 c_options->image_overlay.text_red = options->image_overlay.text_red;
3490 c_options->image_overlay.text_green = options->image_overlay.text_green;
3491 c_options->image_overlay.text_blue = options->image_overlay.text_blue;
3492 c_options->image_overlay.text_alpha = options->image_overlay.text_alpha;
3493 c_options->image_overlay.background_red = options->image_overlay.background_red;
3494 c_options->image_overlay.background_green = options->image_overlay.background_green;
3495 c_options->image_overlay.background_blue = options->image_overlay.background_blue;
3496 c_options->image_overlay.background_alpha = options->image_overlay.background_alpha;
3498 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */