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"
32 #include "filefilter.h"
33 #include "fullscreen.h"
35 #include "image-overlay.h"
36 #include "color-man.h"
38 #include "layout_config.h"
39 #include "layout_util.h"
41 #include "pixbuf_util.h"
42 #include "slideshow.h"
46 #include "ui_fileops.h"
48 #include "ui_spinner.h"
49 #include "ui_tabcomp.h"
50 #include "ui_utildlg.h"
52 #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.safe_delete_enable = c_options->file_ops.safe_delete_enable;
264 options->file_ops.safe_delete_folder_maxsize = c_options->file_ops.safe_delete_folder_maxsize;
265 options->tools_restore_state = c_options->tools_restore_state;
266 options->save_window_positions = c_options->save_window_positions;
267 options->use_saved_window_positions_for_new_windows = c_options->use_saved_window_positions_for_new_windows;
268 options->save_dialog_window_positions = c_options->save_dialog_window_positions;
269 options->show_window_ids = c_options->show_window_ids;
270 options->image.scroll_reset_method = c_options->image.scroll_reset_method;
271 options->image.zoom_2pass = c_options->image.zoom_2pass;
272 options->image.fit_window_to_image = c_options->image.fit_window_to_image;
273 options->image.limit_window_size = c_options->image.limit_window_size;
274 options->image.zoom_to_fit_allow_expand = c_options->image.zoom_to_fit_allow_expand;
275 options->image.max_window_size = c_options->image.max_window_size;
276 options->image.limit_autofit_size = c_options->image.limit_autofit_size;
277 options->image.max_autofit_size = c_options->image.max_autofit_size;
278 options->image.max_enlargement_size = c_options->image.max_enlargement_size;
279 options->image.use_clutter_renderer = c_options->image.use_clutter_renderer;
280 options->progressive_key_scrolling = c_options->progressive_key_scrolling;
281 options->keyboard_scroll_step = c_options->keyboard_scroll_step;
283 if (options->thumbnails.max_width != c_options->thumbnails.max_width
284 || options->thumbnails.max_height != c_options->thumbnails.max_height
285 || options->thumbnails.quality != c_options->thumbnails.quality)
287 thumb_format_changed = TRUE;
289 options->thumbnails.max_width = c_options->thumbnails.max_width;
290 options->thumbnails.max_height = c_options->thumbnails.max_height;
291 options->thumbnails.quality = c_options->thumbnails.quality;
293 options->thumbnails.enable_caching = c_options->thumbnails.enable_caching;
294 options->thumbnails.cache_into_dirs = c_options->thumbnails.cache_into_dirs;
295 options->thumbnails.use_exif = c_options->thumbnails.use_exif;
296 options->thumbnails.collection_preview = c_options->thumbnails.collection_preview;
297 options->thumbnails.use_ft_metadata = c_options->thumbnails.use_ft_metadata;
298 // options->thumbnails.use_ft_metadata_small = c_options->thumbnails.use_ft_metadata_small;
299 options->thumbnails.spec_standard = c_options->thumbnails.spec_standard;
300 options->metadata.enable_metadata_dirs = c_options->metadata.enable_metadata_dirs;
301 options->file_filter.show_hidden_files = c_options->file_filter.show_hidden_files;
302 options->file_filter.show_parent_directory = c_options->file_filter.show_parent_directory;
303 options->file_filter.show_dot_directory = c_options->file_filter.show_dot_directory;
304 options->file_filter.disable_file_extension_checks = c_options->file_filter.disable_file_extension_checks;
306 options->file_sort.case_sensitive = c_options->file_sort.case_sensitive;
307 options->file_sort.natural = c_options->file_sort.natural;
308 options->file_filter.disable = c_options->file_filter.disable;
310 config_entry_to_option(sidecar_ext_entry, &options->sidecar.ext, NULL);
311 sidecar_ext_parse(options->sidecar.ext);
313 options->slideshow.random = c_options->slideshow.random;
314 options->slideshow.repeat = c_options->slideshow.repeat;
315 options->slideshow.delay = c_options->slideshow.delay;
317 options->mousewheel_scrolls = c_options->mousewheel_scrolls;
318 options->image_lm_click_nav = c_options->image_lm_click_nav;
319 options->image_l_click_video = c_options->image_l_click_video;
320 options->image_l_click_video_editor = c_options->image_l_click_video_editor;
322 options->file_ops.enable_in_place_rename = c_options->file_ops.enable_in_place_rename;
324 options->image.tile_cache_max = c_options->image.tile_cache_max;
325 options->image.image_cache_max = c_options->image.image_cache_max;
327 options->image.zoom_quality = c_options->image.zoom_quality;
329 options->image.zoom_increment = c_options->image.zoom_increment;
331 options->image.enable_read_ahead = c_options->image.enable_read_ahead;
334 if (options->image.use_custom_border_color != c_options->image.use_custom_border_color
335 || options->image.use_custom_border_color_in_fullscreen != c_options->image.use_custom_border_color_in_fullscreen
336 || !gdk_color_equal(&options->image.border_color, &c_options->image.border_color))
338 options->image.use_custom_border_color_in_fullscreen = c_options->image.use_custom_border_color_in_fullscreen;
339 options->image.use_custom_border_color = c_options->image.use_custom_border_color;
340 options->image.border_color = c_options->image.border_color;
341 layout_colors_update();
342 view_window_colors_update();
345 options->image.alpha_color_1 = c_options->image.alpha_color_1;
346 options->image.alpha_color_2 = c_options->image.alpha_color_2;
348 options->fullscreen.screen = c_options->fullscreen.screen;
349 options->fullscreen.clean_flip = c_options->fullscreen.clean_flip;
350 options->fullscreen.disable_saver = c_options->fullscreen.disable_saver;
351 options->fullscreen.above = c_options->fullscreen.above;
352 if (c_options->image_overlay.template_string)
353 set_image_overlay_template_string(&options->image_overlay.template_string,
354 c_options->image_overlay.template_string);
355 if (c_options->image_overlay.font)
356 set_image_overlay_font_string(&options->image_overlay.font,
357 c_options->image_overlay.font);
358 options->image_overlay.text_red = c_options->image_overlay.text_red;
359 options->image_overlay.text_green = c_options->image_overlay.text_green;
360 options->image_overlay.text_blue = c_options->image_overlay.text_blue;
361 options->image_overlay.text_alpha = c_options->image_overlay.text_alpha;
362 options->image_overlay.background_red = c_options->image_overlay.background_red;
363 options->image_overlay.background_green = c_options->image_overlay.background_green;
364 options->image_overlay.background_blue = c_options->image_overlay.background_blue;
365 options->image_overlay.background_alpha = c_options->image_overlay.background_alpha;
366 options->update_on_time_change = c_options->update_on_time_change;
367 options->image.exif_proof_rotate_enable = c_options->image.exif_proof_rotate_enable;
369 options->duplicates_similarity_threshold = c_options->duplicates_similarity_threshold;
370 options->rot_invariant_sim = c_options->rot_invariant_sim;
372 options->tree_descend_subdirs = c_options->tree_descend_subdirs;
374 options->view_dir_list_single_click_enter = c_options->view_dir_list_single_click_enter;
376 options->open_recent_list_maxsize = c_options->open_recent_list_maxsize;
377 options->dnd_icon_size = c_options->dnd_icon_size;
378 options->clipboard_selection = c_options->clipboard_selection;
380 options->metadata.save_in_image_file = c_options->metadata.save_in_image_file;
381 options->metadata.save_legacy_IPTC = c_options->metadata.save_legacy_IPTC;
382 options->metadata.warn_on_write_problems = c_options->metadata.warn_on_write_problems;
383 options->metadata.save_legacy_format = c_options->metadata.save_legacy_format;
384 options->metadata.sync_grouped_files = c_options->metadata.sync_grouped_files;
385 options->metadata.confirm_write = c_options->metadata.confirm_write;
386 options->metadata.sidecar_extended_name = c_options->metadata.sidecar_extended_name;
387 options->metadata.confirm_timeout = c_options->metadata.confirm_timeout;
388 options->metadata.confirm_after_timeout = c_options->metadata.confirm_after_timeout;
389 options->metadata.confirm_on_image_change = c_options->metadata.confirm_on_image_change;
390 options->metadata.confirm_on_dir_change = c_options->metadata.confirm_on_dir_change;
391 options->metadata.keywords_case_sensitive = c_options->metadata.keywords_case_sensitive;
392 options->metadata.write_orientation = c_options->metadata.write_orientation;
393 options->stereo.mode = (c_options->stereo.mode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
394 (c_options->stereo.tmp.mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
395 (c_options->stereo.tmp.flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
396 (c_options->stereo.tmp.mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
397 (c_options->stereo.tmp.flip_left ? PR_STEREO_FLIP_LEFT : 0) |
398 (c_options->stereo.tmp.swap ? PR_STEREO_SWAP : 0) |
399 (c_options->stereo.tmp.temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
400 options->stereo.fsmode = (c_options->stereo.fsmode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
401 (c_options->stereo.tmp.fs_mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
402 (c_options->stereo.tmp.fs_flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
403 (c_options->stereo.tmp.fs_mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
404 (c_options->stereo.tmp.fs_flip_left ? PR_STEREO_FLIP_LEFT : 0) |
405 (c_options->stereo.tmp.fs_swap ? PR_STEREO_SWAP : 0) |
406 (c_options->stereo.tmp.fs_temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
407 options->stereo.enable_fsmode = c_options->stereo.enable_fsmode;
408 options->stereo.fixed_w = c_options->stereo.fixed_w;
409 options->stereo.fixed_h = c_options->stereo.fixed_h;
410 options->stereo.fixed_x1 = c_options->stereo.fixed_x1;
411 options->stereo.fixed_y1 = c_options->stereo.fixed_y1;
412 options->stereo.fixed_x2 = c_options->stereo.fixed_x2;
413 options->stereo.fixed_y2 = c_options->stereo.fixed_y2;
415 options->info_keywords.height = c_options->info_keywords.height;
416 options->info_title.height = c_options->info_title.height;
417 options->info_comment.height = c_options->info_comment.height;
418 options->info_rating.height = c_options->info_rating.height;
420 options->marks_save = c_options->marks_save;
421 options->with_rename = c_options->with_rename;
422 options->collections_on_top = c_options->collections_on_top;
423 config_entry_to_option(help_search_engine_entry, &options->help_search_engine, NULL);
425 options->read_metadata_in_idle = c_options->read_metadata_in_idle;
427 options->star_rating.star = c_options->star_rating.star;
428 options->star_rating.rejected = c_options->star_rating.rejected;
430 set_debug_level(debug_c);
434 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
436 config_entry_to_option(color_profile_input_name_entry[i], &options->color_profile.input_name[i], NULL);
437 config_entry_to_option(color_profile_input_file_entry[i], &options->color_profile.input_file[i], NULL);
439 config_entry_to_option(color_profile_screen_file_entry, &options->color_profile.screen_file, NULL);
440 options->color_profile.use_x11_screen_profile = c_options->color_profile.use_x11_screen_profile;
441 if (options->color_profile.render_intent != c_options->color_profile.render_intent)
443 options->color_profile.render_intent = c_options->color_profile.render_intent;
448 config_tab_keywords_save();
450 image_options_sync();
455 layout_refresh(NULL);
458 if (accel_store) gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_apply_cb, NULL);
464 *-----------------------------------------------------------------------------
465 * config window main button callbacks (private)
466 *-----------------------------------------------------------------------------
469 static void config_window_close_cb(GtkWidget *widget, gpointer data)
471 gtk_widget_destroy(configwindow);
476 static void config_window_help_cb(GtkWidget *widget, gpointer data)
478 GtkWidget *notebook = data;
481 static gchar *html_section[] =
483 "GuideOptionsGeneral.html",
484 "GuideOptionsImage.html",
485 "GuideOptionsWindow.html",
486 "GuideOptionsKeyboard.html",
487 "GuideOptionsFiltering.html",
488 "GuideOptionsMetadata.html",
489 "GuideOptionsKeywords.html",
490 "GuideOptionsColor.html",
491 "GuideOptionsStereo.html",
492 "GuideOptionsBehavior.html",
493 "GuideOptionsToolbar.html"
496 i = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
497 help_window_show(html_section[i]);
500 static gboolean config_window_delete(GtkWidget *widget, GdkEventAny *event, gpointer data)
502 config_window_close_cb(NULL, NULL);
506 static void config_window_ok_cb(GtkWidget *widget, gpointer data)
508 config_window_apply();
509 config_window_close_cb(NULL, NULL);
512 static void config_window_apply_cb(GtkWidget *widget, gpointer data)
515 lw = layout_window_list->data;
517 config_window_apply();
518 layout_util_sync(lw);
521 static void config_window_save_cb(GtkWidget *widget, gpointer data)
523 config_window_apply();
524 save_options(options);
528 *-----------------------------------------------------------------------------
529 * config window setup (private)
530 *-----------------------------------------------------------------------------
533 static void quality_menu_cb(GtkWidget *combo, gpointer data)
537 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
541 *option = GDK_INTERP_NEAREST;
544 *option = GDK_INTERP_TILES;
547 *option = GDK_INTERP_BILINEAR;
550 *option = GDK_INTERP_HYPER;
555 static void clipboard_selection_menu_cb(GtkWidget *combo, gpointer data)
559 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
571 static void add_quality_menu(GtkWidget *table, gint column, gint row, const gchar *text,
572 guint option, guint *option_c)
579 pref_table_label(table, column, row, text, 0.0);
581 combo = gtk_combo_box_text_new();
583 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Nearest (worst, but fastest)"));
584 if (option == GDK_INTERP_NEAREST) current = 0;
585 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Tiles"));
586 if (option == GDK_INTERP_TILES) current = 1;
587 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Bilinear"));
588 if (option == GDK_INTERP_BILINEAR) current = 2;
589 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Hyper (best, but slowest)"));
590 if (option == GDK_INTERP_HYPER) current = 3;
592 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
594 g_signal_connect(G_OBJECT(combo), "changed",
595 G_CALLBACK(quality_menu_cb), option_c);
597 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
598 GTK_EXPAND | GTK_FILL, 0, 0, 0);
599 gtk_widget_show(combo);
602 static void add_clipboard_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
603 gint option, gint *option_c)
610 pref_table_label(table, column, row, text, 0.0);
612 combo = gtk_combo_box_text_new();
614 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("PRIMARY"));
615 if (option == PRIMARY) current = 0;
616 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("CLIPBOARD"));
617 if (option == CLIPBOARD) current = 1;
619 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
621 g_signal_connect(G_OBJECT(combo), "changed",
622 G_CALLBACK(clipboard_selection_menu_cb), option_c);
624 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
625 GTK_EXPAND | GTK_FILL, 0, 0, 0);
626 gtk_widget_show(combo);
629 static void thumb_size_menu_cb(GtkWidget *combo, gpointer data)
633 n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
636 if ((guint) n < sizeof(thumb_size_list) / sizeof(ThumbSize))
638 c_options->thumbnails.max_width = thumb_size_list[n].w;
639 c_options->thumbnails.max_height = thumb_size_list[n].h;
643 c_options->thumbnails.max_width = options->thumbnails.max_width;
644 c_options->thumbnails.max_height = options->thumbnails.max_height;
648 static void add_thumb_size_menu(GtkWidget *table, gint column, gint row, gchar *text)
654 c_options->thumbnails.max_width = options->thumbnails.max_width;
655 c_options->thumbnails.max_height = options->thumbnails.max_height;
657 pref_table_label(table, column, row, text, 0.0);
659 combo = gtk_combo_box_text_new();
662 for (i = 0; (guint) i < sizeof(thumb_size_list) / sizeof(ThumbSize); i++)
667 w = thumb_size_list[i].w;
668 h = thumb_size_list[i].h;
670 buf = g_strdup_printf("%d x %d", w, h);
671 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
674 if (w == options->thumbnails.max_width && h == options->thumbnails.max_height) current = i;
681 buf = g_strdup_printf("%s %d x %d", _("Custom"), options->thumbnails.max_width, options->thumbnails.max_height);
682 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
688 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
689 g_signal_connect(G_OBJECT(combo), "changed",
690 G_CALLBACK(thumb_size_menu_cb), NULL);
692 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
693 GTK_EXPAND | GTK_FILL, 0, 0, 0);
694 gtk_widget_show(combo);
697 static void stereo_mode_menu_cb(GtkWidget *combo, gpointer data)
701 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
705 *option = PR_STEREO_NONE;
708 *option = PR_STEREO_ANAGLYPH_RC;
711 *option = PR_STEREO_ANAGLYPH_GM;
714 *option = PR_STEREO_ANAGLYPH_YB;
717 *option = PR_STEREO_ANAGLYPH_GRAY_RC;
720 *option = PR_STEREO_ANAGLYPH_GRAY_GM;
723 *option = PR_STEREO_ANAGLYPH_GRAY_YB;
726 *option = PR_STEREO_ANAGLYPH_DB_RC;
729 *option = PR_STEREO_ANAGLYPH_DB_GM;
732 *option = PR_STEREO_ANAGLYPH_DB_YB;
735 *option = PR_STEREO_HORIZ;
738 *option = PR_STEREO_HORIZ | PR_STEREO_HALF;
741 *option = PR_STEREO_VERT;
744 *option = PR_STEREO_VERT | PR_STEREO_HALF;
747 *option = PR_STEREO_FIXED;
752 static void add_stereo_mode_menu(GtkWidget *table, gint column, gint row, const gchar *text,
753 gint option, gint *option_c, gboolean add_fixed)
760 pref_table_label(table, column, row, text, 0.0);
762 combo = gtk_combo_box_text_new();
764 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Single image"));
766 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Red-Cyan"));
767 if (option & PR_STEREO_ANAGLYPH_RC) current = 1;
768 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Green-Magenta"));
769 if (option & PR_STEREO_ANAGLYPH_GM) current = 2;
770 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Yellow-Blue"));
771 if (option & PR_STEREO_ANAGLYPH_YB) current = 3;
772 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Red-Cyan"));
773 if (option & PR_STEREO_ANAGLYPH_GRAY_RC) current = 4;
774 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Green-Magenta"));
775 if (option & PR_STEREO_ANAGLYPH_GRAY_GM) current = 5;
776 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Yellow-Blue"));
777 if (option & PR_STEREO_ANAGLYPH_GRAY_YB) current = 6;
778 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Red-Cyan"));
779 if (option & PR_STEREO_ANAGLYPH_DB_RC) current = 7;
780 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Green-Magenta"));
781 if (option & PR_STEREO_ANAGLYPH_DB_GM) current = 8;
782 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Yellow-Blue"));
783 if (option & PR_STEREO_ANAGLYPH_DB_YB) current = 9;
785 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side"));
786 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side Half size"));
787 if (option & PR_STEREO_HORIZ)
790 if (option & PR_STEREO_HALF) current = 11;
793 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom"));
794 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom Half size"));
795 if (option & PR_STEREO_VERT)
798 if (option & PR_STEREO_HALF) current = 13;
803 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Fixed position"));
804 if (option & PR_STEREO_FIXED) current = 14;
807 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
809 g_signal_connect(G_OBJECT(combo), "changed",
810 G_CALLBACK(stereo_mode_menu_cb), option_c);
812 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
813 GTK_EXPAND | GTK_FILL, 0, 0, 0);
814 gtk_widget_show(combo);
817 static void video_menu_cb(GtkWidget *combo, gpointer data)
819 gchar **option = data;
821 EditorDescription *ed = g_list_nth_data(editor_list_get(), gtk_combo_box_get_active(GTK_COMBO_BOX(combo)));
825 static void video_menu_populate(gpointer data, gpointer user_data)
827 GtkWidget *combo = user_data;
828 EditorDescription *ed = data;
830 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), ed->name);
833 static void add_video_menu(GtkWidget *table, gint column, gint row, const gchar *text,
834 gchar *option, gchar **option_c)
838 /* use lists since they are sorted */
839 GList *eds = editor_list_get();
843 pref_table_label(table, column, row, text, 0.0);
845 combo = gtk_combo_box_text_new();
846 g_list_foreach(eds,video_menu_populate,(gpointer)combo);
847 current = option ? g_list_index(eds,g_hash_table_lookup(editors,option)): -1;
849 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
851 g_signal_connect(G_OBJECT(combo), "changed",
852 G_CALLBACK(video_menu_cb), option_c);
854 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
855 GTK_EXPAND | GTK_FILL, 0, 0, 0);
856 gtk_widget_show(combo);
859 static void filter_store_populate(void)
863 if (!filter_store) return;
865 gtk_list_store_clear(filter_store);
867 work = filter_get_list();
876 gtk_list_store_append(filter_store, &iter);
877 gtk_list_store_set(filter_store, &iter, 0, fe, -1);
881 static void filter_store_ext_edit_cb(GtkCellRendererText *cell, gchar *path_str,
882 gchar *new_text, gpointer data)
884 GtkWidget *model = data;
885 FilterEntry *fe = data;
889 if (!new_text || strlen(new_text) < 1) return;
891 tpath = gtk_tree_path_new_from_string(path_str);
892 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
893 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
895 g_free(fe->extensions);
896 fe->extensions = g_strdup(new_text);
898 gtk_tree_path_free(tpath);
902 static void filter_store_class_edit_cb(GtkCellRendererText *cell, gchar *path_str,
903 gchar *new_text, gpointer data)
905 GtkWidget *model = data;
906 FilterEntry *fe = data;
911 if (!new_text || !new_text[0]) return;
913 tpath = gtk_tree_path_new_from_string(path_str);
914 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
915 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
917 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
919 if (strcmp(new_text, _(format_class_list[i])) == 0)
926 gtk_tree_path_free(tpath);
930 static void filter_store_desc_edit_cb(GtkCellRendererText *cell, gchar *path_str,
931 gchar *new_text, gpointer data)
933 GtkWidget *model = data;
938 if (!new_text || !new_text[0]) return;
940 tpath = gtk_tree_path_new_from_string(path_str);
941 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
942 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
944 g_free(fe->description);
945 fe->description = g_strdup(new_text);
947 gtk_tree_path_free(tpath);
950 static void filter_store_enable_cb(GtkCellRendererToggle *renderer,
951 gchar *path_str, gpointer data)
953 GtkWidget *model = data;
958 tpath = gtk_tree_path_new_from_string(path_str);
959 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
960 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
962 fe->enabled = !fe->enabled;
964 gtk_tree_path_free(tpath);
968 static void filter_store_writable_cb(GtkCellRendererToggle *renderer,
969 gchar *path_str, gpointer data)
971 GtkWidget *model = data;
976 tpath = gtk_tree_path_new_from_string(path_str);
977 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
978 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
980 fe->writable = !fe->writable;
981 if (fe->writable) fe->allow_sidecar = FALSE;
983 gtk_tree_path_free(tpath);
987 static void filter_store_sidecar_cb(GtkCellRendererToggle *renderer,
988 gchar *path_str, gpointer data)
990 GtkWidget *model = data;
995 tpath = gtk_tree_path_new_from_string(path_str);
996 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
997 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
999 fe->allow_sidecar = !fe->allow_sidecar;
1000 if (fe->allow_sidecar) fe->writable = FALSE;
1002 gtk_tree_path_free(tpath);
1006 static void filter_set_func(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
1007 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
1011 gtk_tree_model_get(tree_model, iter, 0, &fe, -1);
1013 switch (GPOINTER_TO_INT(data))
1016 g_object_set(GTK_CELL_RENDERER(cell),
1017 "active", fe->enabled, NULL);
1020 g_object_set(GTK_CELL_RENDERER(cell),
1021 "text", fe->extensions, NULL);
1023 case FE_DESCRIPTION:
1024 g_object_set(GTK_CELL_RENDERER(cell),
1025 "text", fe->description, NULL);
1028 g_object_set(GTK_CELL_RENDERER(cell),
1029 "text", _(format_class_list[fe->file_class]), NULL);
1032 g_object_set(GTK_CELL_RENDERER(cell),
1033 "active", fe->writable, NULL);
1035 case FE_ALLOW_SIDECAR:
1036 g_object_set(GTK_CELL_RENDERER(cell),
1037 "active", fe->allow_sidecar, NULL);
1042 static gboolean filter_add_scroll(gpointer data)
1046 GtkCellRenderer *cell;
1047 GtkTreeViewColumn *column;
1048 GList *list_columns;
1053 rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(filter_store), NULL);
1054 path = gtk_tree_path_new_from_indices(rows-1, -1);
1056 list_columns = gtk_tree_view_get_columns(GTK_TREE_VIEW(data));
1058 column = g_list_nth(list_columns,i)->data;
1059 title = gtk_tree_view_column_get_title(GTK_TREE_VIEW_COLUMN(column));
1061 } while (strcmp(title, "Filter") !=0 );
1063 list_cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column));
1064 cell = g_list_last(list_cells)->data;
1066 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1067 path, column, FALSE, 0.0, 0.0 );
1068 gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(data),
1069 path, column, cell, TRUE);
1071 gtk_tree_path_free(path);
1072 g_list_free(list_cells);
1073 g_list_free(list_columns);
1078 static void filter_add_cb(GtkWidget *widget, gpointer data)
1080 filter_add_unique("description", ".new", FORMAT_CLASS_IMAGE, TRUE, FALSE, TRUE);
1081 filter_store_populate();
1083 g_idle_add((GSourceFunc)filter_add_scroll, data);
1086 static void filter_remove_cb(GtkWidget *widget, gpointer data)
1088 GtkWidget *filter_view = data;
1089 GtkTreeSelection *selection;
1093 if (!filter_store) return;
1094 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1095 if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) return;
1096 gtk_tree_model_get(GTK_TREE_MODEL(filter_store), &iter, 0, &fe, -1);
1099 filter_remove_entry(fe);
1101 filter_store_populate();
1104 static gboolean filter_default_ok_scroll(GtkTreeView *data)
1108 GtkTreeViewColumn *column;
1110 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(filter_store), &iter);
1111 path = gtk_tree_model_get_path(GTK_TREE_MODEL(filter_store), &iter);
1112 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1114 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1118 gtk_tree_path_free(path);
1123 static void filter_default_ok_cb(GenericDialog *gd, gpointer data)
1126 filter_add_defaults();
1128 filter_store_populate();
1130 g_idle_add((GSourceFunc)filter_default_ok_scroll, gd->data);
1133 static void dummy_cancel_cb(GenericDialog *gd, gpointer data)
1135 /* no op, only so cancel button appears */
1138 static void filter_default_cb(GtkWidget *widget, gpointer data)
1142 gd = generic_dialog_new(_("Reset filters"),
1143 "reset_filter", widget, TRUE,
1144 dummy_cancel_cb, data);
1145 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset filters"),
1146 _("This will reset the file filters to the defaults.\nContinue?"), TRUE);
1147 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, filter_default_ok_cb, TRUE);
1148 gtk_widget_show(gd->dialog);
1151 static void filter_disable_cb(GtkWidget *widget, gpointer data)
1153 GtkWidget *frame = data;
1155 gtk_widget_set_sensitive(frame,
1156 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
1159 static void safe_delete_view_cb(GtkWidget *widget, gpointer data)
1161 layout_set_path(NULL, gtk_entry_get_text(GTK_ENTRY(safe_delete_path_entry)));
1164 static void safe_delete_clear_ok_cb(GenericDialog *gd, gpointer data)
1166 file_util_trash_clear();
1169 static void safe_delete_clear_cb(GtkWidget *widget, gpointer data)
1173 gd = generic_dialog_new(_("Clear trash"),
1174 "clear_trash", widget, TRUE,
1175 dummy_cancel_cb, NULL);
1176 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear trash"),
1177 _("This will remove the trash contents."), FALSE);
1178 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, safe_delete_clear_ok_cb, TRUE);
1179 entry = gtk_entry_new();
1180 gtk_widget_set_can_focus(entry, FALSE);
1181 gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE);
1182 if (options->file_ops.safe_delete_path) gtk_entry_set_text(GTK_ENTRY(entry), options->file_ops.safe_delete_path);
1183 gtk_box_pack_start(GTK_BOX(gd->vbox), entry, FALSE, FALSE, 0);
1184 gtk_widget_show(entry);
1185 gtk_widget_show(gd->dialog);
1188 static void image_overlay_template_view_changed_cb(GtkWidget *widget, gpointer data)
1190 GtkWidget *pTextView;
1191 GtkTextBuffer *pTextBuffer;
1195 pTextView = GTK_WIDGET(data);
1197 pTextBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pTextView));
1198 gtk_text_buffer_get_start_iter(pTextBuffer, &iStart);
1199 gtk_text_buffer_get_end_iter(pTextBuffer, &iEnd);
1201 set_image_overlay_template_string(&c_options->image_overlay.template_string,
1202 gtk_text_buffer_get_text(pTextBuffer, &iStart, &iEnd, TRUE));
1205 static void image_overlay_default_template_ok_cb(GenericDialog *gd, gpointer data)
1207 GtkTextView *text_view = data;
1208 GtkTextBuffer *buffer;
1210 set_default_image_overlay_template_string(&options->image_overlay.template_string);
1211 if (!configwindow) return;
1213 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
1214 gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1217 static void image_overlay_default_template_cb(GtkWidget *widget, gpointer data)
1221 gd = generic_dialog_new(_("Reset image overlay template string"),
1222 "reset_image_overlay_template_string", widget, TRUE,
1223 dummy_cancel_cb, data);
1224 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset image overlay template string"),
1225 _("This will reset the image overlay template string to the default.\nContinue?"), TRUE);
1226 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, image_overlay_default_template_ok_cb, TRUE);
1227 gtk_widget_show(gd->dialog);
1230 static void image_overlay_help_cb(GtkWidget *widget, gpointer data)
1232 help_window_show("GuideOptionsWindow.html#OverlayScreenDisplay");
1235 static void image_overlay_set_font_cb(GtkWidget *widget, gpointer data)
1237 #if GTK_CHECK_VERSION(3,4,0)
1240 PangoFontDescription *font_desc;
1242 dialog = gtk_font_chooser_dialog_new("Image Overlay Font", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1243 gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), options->image_overlay.font);
1245 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1247 font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
1248 font = pango_font_description_to_string(font_desc);
1249 g_free(c_options->image_overlay.font);
1250 c_options->image_overlay.font = g_strdup(font);
1254 gtk_widget_destroy(dialog);
1258 font = gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget));
1259 c_options->image_overlay.font = g_strdup(font);
1263 static void image_overlay_set_text_colour_cb(GtkWidget *widget, gpointer data)
1266 #if GTK_CHECK_VERSION(3,4,0)
1269 dialog = gtk_color_chooser_dialog_new("Image Overlay Text Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1270 colour.red = options->image_overlay.text_red;
1271 colour.green = options->image_overlay.text_green;
1272 colour.blue = options->image_overlay.text_blue;
1273 colour.alpha = options->image_overlay.text_alpha;
1274 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1275 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1277 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1279 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1280 c_options->image_overlay.text_red = colour.red*255;
1281 c_options->image_overlay.text_green = colour.green*255;
1282 c_options->image_overlay.text_blue = colour.blue*255;
1283 c_options->image_overlay.text_alpha = colour.alpha*255;
1285 gtk_widget_destroy(dialog);
1288 GtkColorSelection *colorsel;
1290 dialog = gtk_color_selection_dialog_new("Image Overlay Text Colour");
1291 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1292 colour.red = options->image_overlay.text_red*257;
1293 colour.green = options->image_overlay.text_green*257;
1294 colour.blue = options->image_overlay.text_blue*257;
1295 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1296 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1297 gtk_color_selection_set_current_color(colorsel, &colour);
1298 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.text_alpha*257);
1300 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1302 gtk_color_selection_get_current_color(colorsel, &colour);
1303 c_options->image_overlay.text_red = colour.red/257;
1304 c_options->image_overlay.text_green = colour.green/257;
1305 c_options->image_overlay.text_blue = colour.blue/257;
1306 c_options->image_overlay.text_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1308 gtk_widget_destroy (dialog);
1313 static void image_overlay_set_background_colour_cb(GtkWidget *widget, gpointer data)
1316 #if GTK_CHECK_VERSION(3,4,0)
1319 dialog = gtk_color_chooser_dialog_new("Image Overlay Background Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1320 colour.red = options->image_overlay.background_red;
1321 colour.green = options->image_overlay.background_green;
1322 colour.blue = options->image_overlay.background_blue;
1323 colour.alpha = options->image_overlay.background_alpha;
1324 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1325 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1327 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1329 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1330 c_options->image_overlay.background_red = colour.red*255;
1331 c_options->image_overlay.background_green = colour.green*255;
1332 c_options->image_overlay.background_blue = colour.blue*255;
1333 c_options->image_overlay.background_alpha = colour.alpha*255;
1335 gtk_widget_destroy(dialog);
1338 GtkColorSelection *colorsel;
1340 dialog = gtk_color_selection_dialog_new("Image Overlay Background Colour");
1341 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1342 colour.red = options->image_overlay.background_red*257;
1343 colour.green = options->image_overlay.background_green*257;
1344 colour.blue = options->image_overlay.background_blue*257;
1345 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1346 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1347 gtk_color_selection_set_current_color(colorsel, &colour);
1348 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.background_alpha*257);
1350 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1352 gtk_color_selection_get_current_color(colorsel, &colour);
1353 c_options->image_overlay.background_red = colour.red/257;
1354 c_options->image_overlay.background_green = colour.green/257;
1355 c_options->image_overlay.background_blue = colour.blue/257;
1356 c_options->image_overlay.background_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1358 gtk_widget_destroy(dialog);
1362 static void accel_store_populate(void)
1365 GList *groups, *actions;
1367 const gchar *accel_path;
1371 if (!accel_store || !layout_window_list || !layout_window_list->data) return;
1373 gtk_tree_store_clear(accel_store);
1374 lw = layout_window_list->data; /* get the actions from the first window, it should not matter, they should be the same in all windows */
1376 g_assert(lw && lw->ui_manager);
1377 groups = gtk_ui_manager_get_action_groups(lw->ui_manager);
1380 actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
1383 action = GTK_ACTION(actions->data);
1384 accel_path = gtk_action_get_accel_path(action);
1385 if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
1387 gchar *label, *label2, *tooltip, *accel;
1388 g_object_get(action,
1389 "tooltip", &tooltip,
1393 if (pango_parse_markup(label, -1, '_', NULL, &label2, NULL, NULL) && label2)
1399 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1403 gtk_tree_store_append(accel_store, &iter, NULL);
1404 gtk_tree_store_set(accel_store, &iter,
1407 AE_TOOLTIP, tooltip ? tooltip : "",
1408 AE_ACCEL, accel_path,
1416 actions = actions->next;
1419 groups = groups->next;
1423 static void accel_store_cleared_cb(GtkCellRendererAccel *accel, gchar *path_string, gpointer user_data)
1428 static gboolean accel_remove_key_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1430 gchar *accel1 = data;
1435 gtk_tree_model_get(model, iter, AE_KEY, &accel2, -1);
1437 gtk_accelerator_parse(accel1, &key1.accel_key, &key1.accel_mods);
1438 gtk_accelerator_parse(accel2, &key2.accel_key, &key2.accel_mods);
1440 if (key1.accel_key == key2.accel_key && key1.accel_mods == key2.accel_mods)
1442 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1443 DEBUG_1("accelerator key '%s' is already used, removing.", accel1);
1452 static void accel_store_edited_cb(GtkCellRendererAccel *accel, gchar *path_string, guint accel_key, GdkModifierType accel_mods, guint hardware_keycode, gpointer user_data)
1454 GtkTreeModel *model = (GtkTreeModel *)accel_store;
1458 GtkAccelKey old_key, key;
1459 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
1461 gtk_tree_model_get_iter(model, &iter, path);
1462 gtk_tree_model_get(model, &iter, AE_ACCEL, &accel_path, -1);
1464 /* test if the accelerator can be stored without conflicts*/
1465 gtk_accel_map_lookup_entry(accel_path, &old_key);
1467 /* change the key and read it back (change may fail on keys hardcoded in gtk)*/
1468 gtk_accel_map_change_entry(accel_path, accel_key, accel_mods, TRUE);
1469 gtk_accel_map_lookup_entry(accel_path, &key);
1471 /* restore the original for now, the key will be really changed when the changes are confirmed */
1472 gtk_accel_map_change_entry(accel_path, old_key.accel_key, old_key.accel_mods, TRUE);
1474 acc = gtk_accelerator_name(key.accel_key, key.accel_mods);
1475 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, acc);
1477 gtk_tree_store_set(accel_store, &iter, AE_KEY, acc, -1);
1478 gtk_tree_path_free(path);
1482 static gboolean accel_default_scroll(GtkTreeView *data)
1486 GtkTreeViewColumn *column;
1488 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(accel_store), &iter);
1489 path = gtk_tree_model_get_path(GTK_TREE_MODEL(accel_store), &iter);
1490 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1492 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1496 gtk_tree_path_free(path);
1501 static void accel_default_cb(GtkWidget *widget, gpointer data)
1503 accel_store_populate();
1505 g_idle_add((GSourceFunc)accel_default_scroll, data);
1508 void accel_remove_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1510 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1513 void accel_reset_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1516 gchar *accel_path, *accel;
1518 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, -1);
1519 gtk_accel_map_lookup_entry(accel_path, &key);
1520 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1522 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, accel);
1524 gtk_tree_store_set(accel_store, iter, AE_KEY, accel, -1);
1529 static void accel_reset_cb(GtkWidget *widget, gpointer data)
1531 GtkTreeSelection *selection;
1533 if (!accel_store) return;
1534 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data));
1535 gtk_tree_selection_selected_foreach(selection, &accel_reset_selection, NULL);
1540 static GtkWidget *scrolled_notebook_page(GtkWidget *notebook, const gchar *title)
1544 GtkWidget *scrolled;
1545 GtkWidget *viewport;
1547 scrolled = gtk_scrolled_window_new(NULL, NULL);
1548 gtk_container_set_border_width(GTK_CONTAINER(scrolled), PREF_PAD_BORDER);
1549 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1550 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1551 label = gtk_label_new(title);
1552 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, label);
1553 gtk_widget_show(scrolled);
1555 viewport = gtk_viewport_new(NULL, NULL);
1556 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1557 gtk_container_add(GTK_CONTAINER(scrolled), viewport);
1558 gtk_widget_show(viewport);
1560 vbox = gtk_vbox_new(FALSE, 0);
1561 gtk_container_add(GTK_CONTAINER(viewport), vbox);
1562 gtk_widget_show(vbox);
1567 static void cache_standard_cb(GtkWidget *widget, gpointer data)
1569 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1571 c_options->thumbnails.spec_standard =TRUE;
1572 c_options->thumbnails.cache_into_dirs = FALSE;
1576 static void cache_geeqie_cb(GtkWidget *widget, gpointer data)
1578 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1580 c_options->thumbnails.spec_standard =FALSE;
1581 c_options->thumbnails.cache_into_dirs = FALSE;
1585 static void cache_local_cb(GtkWidget *widget, gpointer data)
1587 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1589 c_options->thumbnails.cache_into_dirs = TRUE;
1590 c_options->thumbnails.spec_standard =FALSE;
1594 static void help_search_engine_entry_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1595 GdkEvent *event, gpointer userdata)
1597 if (pos == GTK_ENTRY_ICON_PRIMARY)
1599 gtk_entry_set_text(GTK_ENTRY(userdata), HELP_SEARCH_ENGINE);
1603 gtk_entry_set_text(GTK_ENTRY(userdata), "");
1607 static void star_rating_star_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1608 GdkEvent *event, gpointer userdata)
1610 gchar *rating_symbol;
1612 if (pos == GTK_ENTRY_ICON_PRIMARY)
1614 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_STAR);
1615 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1616 g_free(rating_symbol);
1620 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1621 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1622 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1626 static void star_rating_rejected_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1627 GdkEvent *event, gpointer userdata)
1629 gchar *rating_symbol;
1631 if (pos == GTK_ENTRY_ICON_PRIMARY)
1633 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_REJECTED);
1634 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1635 g_free(rating_symbol);
1639 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1640 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1641 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1645 static guint star_rating_symbol_test(GtkWidget *widget, gpointer data)
1647 GtkContainer *hbox = data;
1648 GString *str = g_string_new(NULL);
1649 GtkEntry *hex_code_entry;
1650 gchar *hex_code_full;
1653 guint64 hex_value = 0;
1655 list = gtk_container_get_children(hbox);
1657 hex_code_entry = g_list_nth_data(list, 2);
1658 hex_code_full = g_strdup(gtk_entry_get_text(hex_code_entry));
1660 hex_code = g_strsplit(hex_code_full, "+", 2);
1661 if (hex_code[0] && hex_code[1])
1663 hex_value = strtoull(hex_code[1], NULL, 16);
1665 if (!hex_value || hex_value > 0x10FFFF)
1667 hex_value = 0x003F; // Unicode 'Question Mark'
1669 str = g_string_append_unichar(str, (gunichar)hex_value);
1670 gtk_label_set_text(g_list_nth_data(list, 1), str->str);
1672 g_strfreev(hex_code);
1673 g_string_free(str, TRUE);
1674 g_free(hex_code_full);
1679 static void star_rating_star_test_cb(GtkWidget *widget, gpointer data)
1681 guint64 star_symbol;
1683 star_symbol = star_rating_symbol_test(widget, data);
1684 c_options->star_rating.star = star_symbol;
1687 static void star_rating_rejected_test_cb(GtkWidget *widget, gpointer data)
1689 guint64 rejected_symbol;
1691 rejected_symbol = star_rating_symbol_test(widget, data);
1692 c_options->star_rating.rejected = rejected_symbol;
1695 /* general options tab */
1696 static void config_tab_general(GtkWidget *notebook)
1701 GtkWidget *group_frame;
1702 GtkWidget *subgroup;
1704 GtkWidget *ct_button;
1707 gint hours, minutes, remainder;
1709 GtkWidget *star_rating_entry;
1711 gchar *rating_symbol;
1713 vbox = scrolled_notebook_page(notebook, _("General"));
1715 group = pref_group_new(vbox, FALSE, _("Thumbnails"), GTK_ORIENTATION_VERTICAL);
1717 table = pref_table_new(group, 2, 2, FALSE, FALSE);
1718 add_thumb_size_menu(table, 0, 0, _("Size:"));
1719 add_quality_menu(table, 0, 1, _("Quality:"), options->thumbnails.quality, &c_options->thumbnails.quality);
1721 ct_button = pref_checkbox_new_int(group, _("Cache thumbnails"),
1722 options->thumbnails.enable_caching, &c_options->thumbnails.enable_caching);
1724 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1725 pref_checkbox_link_sensitivity(ct_button, subgroup);
1727 c_options->thumbnails.spec_standard = options->thumbnails.spec_standard;
1728 c_options->thumbnails.cache_into_dirs = options->thumbnails.cache_into_dirs;
1729 group_frame = pref_frame_new(subgroup, TRUE, _("Use Geeqie thumbnail style and cache"),
1730 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1731 button = pref_radiobutton_new(group_frame, NULL, get_thumbnails_cache_dir(),
1732 !options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1733 G_CALLBACK(cache_geeqie_cb), NULL);
1735 group_frame = pref_frame_new(subgroup, TRUE,
1736 _("Store thumbnails local to image folder (non-standard)"),
1737 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1738 pref_radiobutton_new(group_frame, button, "*/.thumbnails",
1739 !options->thumbnails.spec_standard && options->thumbnails.cache_into_dirs,
1740 G_CALLBACK(cache_local_cb), NULL);
1742 group_frame = pref_frame_new(subgroup, TRUE,
1743 _("Use standard thumbnail style and cache, shared with other applications"),
1744 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1745 pref_radiobutton_new(group_frame, button, get_thumbnails_standard_cache_dir(),
1746 options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1747 G_CALLBACK(cache_standard_cb), NULL);
1749 pref_checkbox_new_int(group, _("Use EXIF thumbnails when available (EXIF thumbnails may be outdated)"),
1750 options->thumbnails.use_exif, &c_options->thumbnails.use_exif);
1752 spin = pref_spin_new_int(group, _("Collection preview:"), NULL,
1754 options->thumbnails.collection_preview, &c_options->thumbnails.collection_preview);
1755 gtk_widget_set_tooltip_text(spin, _("The maximum number of thumbnails shown in a Collection preview montage"));
1757 #ifdef HAVE_FFMPEGTHUMBNAILER_METADATA
1758 pref_checkbox_new_int(group, _("Use embedded metadata in video files as thumbnails when available"),
1759 options->thumbnails.use_ft_metadata, &c_options->thumbnails.use_ft_metadata);
1761 // pref_checkbox_new_int(group, _("Ignore embedded metadata if size is too small"),
1762 // options->thumbnails.use_ft_metadata_small, &c_options->thumbnails.use_ft_metadata_small);
1765 group = pref_group_new(vbox, FALSE, _("Star Rating"), GTK_ORIENTATION_VERTICAL);
1767 c_options->star_rating.star = options->star_rating.star;
1768 c_options->star_rating.rejected = options->star_rating.rejected;
1770 str = g_string_new(NULL);
1771 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1772 pref_label_new(hbox, "Star character: ");
1773 str = g_string_append_unichar(str, options->star_rating.star);
1774 pref_label_new(hbox, g_strdup(str->str));
1775 rating_symbol = g_strdup_printf("U+%X", options->star_rating.star);
1776 star_rating_entry = gtk_entry_new();
1777 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
1778 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
1779 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
1780 gtk_widget_show(star_rating_entry);
1781 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
1782 G_CALLBACK(star_rating_star_test_cb), hbox);
1783 gtk_widget_set_tooltip_text(button, _("Display selected character"));
1784 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1785 gtk_widget_show(button);
1786 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."));
1787 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1788 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
1789 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1790 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
1791 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1792 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
1793 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1794 GTK_ENTRY_ICON_PRIMARY, _("Default"));
1795 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
1796 G_CALLBACK(star_rating_star_icon_cb),
1799 g_string_free(str, TRUE);
1800 g_free(rating_symbol);
1802 str = g_string_new(NULL);
1803 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1804 pref_label_new(hbox, "Rejected character: ");
1805 str = g_string_append_unichar(str, options->star_rating.rejected);
1806 pref_label_new(hbox, g_strdup(str->str));
1807 rating_symbol = g_strdup_printf("U+%X", options->star_rating.rejected);
1808 star_rating_entry = gtk_entry_new();
1809 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
1810 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
1811 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
1812 gtk_widget_show(star_rating_entry);
1813 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
1814 G_CALLBACK(star_rating_rejected_test_cb), hbox);
1815 gtk_widget_set_tooltip_text(button, _("Display selected character"));
1816 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1817 gtk_widget_show(button);
1818 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."));
1819 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1820 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
1821 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1822 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
1823 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1824 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
1825 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1826 GTK_ENTRY_ICON_PRIMARY, _("Default"));
1827 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
1828 G_CALLBACK(star_rating_rejected_icon_cb),
1831 g_string_free(str, TRUE);
1832 g_free(rating_symbol);
1834 group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
1836 c_options->slideshow.delay = options->slideshow.delay;
1837 hours = options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
1838 remainder = options->slideshow.delay % (3600 * SLIDESHOW_SUBSECOND_PRECISION);
1839 minutes = remainder / (60 * SLIDESHOW_SUBSECOND_PRECISION);
1840 seconds = (gdouble)(remainder % (60 * SLIDESHOW_SUBSECOND_PRECISION)) /
1841 SLIDESHOW_SUBSECOND_PRECISION;
1843 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1845 spin = pref_spin_new(hbox, _("Delay between image change hrs:mins:secs.dec"), NULL,
1847 options->slideshow.delay ? hours : 0.0,
1848 G_CALLBACK(slideshow_delay_hours_cb), NULL);
1849 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1850 spin = pref_spin_new(hbox, ":" , NULL,
1852 options->slideshow.delay ? minutes: 0.0,
1853 G_CALLBACK(slideshow_delay_minutes_cb), NULL);
1854 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1855 spin = pref_spin_new(hbox, ":", NULL,
1856 SLIDESHOW_MIN_SECONDS, 59, 1.0, 1,
1857 options->slideshow.delay ? seconds : 10.0,
1858 G_CALLBACK(slideshow_delay_seconds_cb), NULL);
1859 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1861 pref_checkbox_new_int(group, _("Random"), options->slideshow.random, &c_options->slideshow.random);
1862 pref_checkbox_new_int(group, _("Repeat"), options->slideshow.repeat, &c_options->slideshow.repeat);
1864 group = pref_group_new(vbox, FALSE, _("Image loading and caching"), GTK_ORIENTATION_VERTICAL);
1866 pref_spin_new_int(group, _("Decoded image cache size (Mb):"), NULL,
1867 0, 99999, 1, options->image.image_cache_max, &c_options->image.image_cache_max);
1868 pref_checkbox_new_int(group, _("Preload next image"),
1869 options->image.enable_read_ahead, &c_options->image.enable_read_ahead);
1871 pref_checkbox_new_int(group, _("Refresh on file change"),
1872 options->update_on_time_change, &c_options->update_on_time_change);
1874 group = pref_group_new(vbox, FALSE, _("Info sidebar heights"), GTK_ORIENTATION_VERTICAL);
1875 pref_label_new(group, _("NOTE! Geeqie must be restarted for changes to take effect"));
1876 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1877 pref_spin_new_int(hbox, _("Keywords:"), NULL,
1879 options->info_keywords.height, &c_options->info_keywords.height);
1880 pref_spin_new_int(hbox, _("Title:"), NULL,
1882 options->info_title.height, &c_options->info_title.height);
1883 pref_spin_new_int(hbox, _("Comment:"), NULL,
1885 options->info_comment.height, &c_options->info_comment.height);
1886 pref_spin_new_int(hbox, _("Rating:"), NULL,
1888 options->info_rating.height, &c_options->info_rating.height);
1890 group = pref_group_new(vbox, FALSE, _("On-line help search engine"), GTK_ORIENTATION_VERTICAL);
1892 help_search_engine_entry = gtk_entry_new();
1893 gtk_entry_set_text(GTK_ENTRY(help_search_engine_entry), options->help_search_engine);
1894 gtk_box_pack_start(GTK_BOX(group), help_search_engine_entry, FALSE, FALSE, 0);
1895 gtk_widget_show(help_search_engine_entry);
1897 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"));
1899 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
1900 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
1901 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
1902 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
1903 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
1904 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
1905 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
1906 GTK_ENTRY_ICON_PRIMARY, _("Default"));
1907 g_signal_connect(GTK_ENTRY(help_search_engine_entry), "icon-press",
1908 G_CALLBACK(help_search_engine_entry_icon_cb),
1909 help_search_engine_entry);
1913 static void config_tab_image(GtkWidget *notebook)
1918 GtkWidget *ct_button;
1919 GtkWidget *enlargement_button;
1923 vbox = scrolled_notebook_page(notebook, _("Image"));
1925 group = pref_group_new(vbox, FALSE, _("Zoom"), GTK_ORIENTATION_VERTICAL);
1927 table = pref_table_new(group, 2, 1, FALSE, FALSE);
1928 add_quality_menu(table, 0, 0, _("Quality:"), options->image.zoom_quality, &c_options->image.zoom_quality);
1931 pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library"),
1932 options->image.use_clutter_renderer, &c_options->image.use_clutter_renderer);
1935 pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"),
1936 options->image.zoom_2pass, &c_options->image.zoom_2pass);
1938 c_options->image.zoom_increment = options->image.zoom_increment;
1939 spin = pref_spin_new(group, _("Zoom increment:"), NULL,
1940 0.01, 4.0, 0.01, 2, (gdouble)options->image.zoom_increment / 100.0,
1941 G_CALLBACK(zoom_increment_cb), NULL);
1942 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1944 group = pref_group_new(vbox, FALSE, _("Fit image to window"), GTK_ORIENTATION_VERTICAL);
1946 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1947 enlargement_button = pref_checkbox_new_int(hbox, _("Allow enlargement of image (max. size in %)"),
1948 options->image.zoom_to_fit_allow_expand, &c_options->image.zoom_to_fit_allow_expand);
1949 spin = pref_spin_new_int(hbox, NULL, NULL,
1951 options->image.max_enlargement_size, &c_options->image.max_enlargement_size);
1952 pref_checkbox_link_sensitivity(enlargement_button, spin);
1953 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."));
1955 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1956 ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (% of actual window):"),
1957 options->image.limit_autofit_size, &c_options->image.limit_autofit_size);
1958 spin = pref_spin_new_int(hbox, NULL, NULL,
1960 options->image.max_autofit_size, &c_options->image.max_autofit_size);
1961 pref_checkbox_link_sensitivity(ct_button, spin);
1962 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."));
1964 group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
1966 pref_checkbox_new_int(group, _("Use custom border color in window mode"),
1967 options->image.use_custom_border_color, &c_options->image.use_custom_border_color);
1969 pref_checkbox_new_int(group, _("Use custom border color in fullscreen mode"),
1970 options->image.use_custom_border_color_in_fullscreen, &c_options->image.use_custom_border_color_in_fullscreen);
1972 pref_color_button_new(group, _("Border color"), &options->image.border_color,
1973 G_CALLBACK(pref_color_button_set_cb), &c_options->image.border_color);
1975 c_options->image.border_color = options->image.border_color;
1977 pref_color_button_new(group, _("Alpha channel color 1"), &options->image.alpha_color_1,
1978 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_1);
1980 pref_color_button_new(group, _("Alpha channel color 2"), &options->image.alpha_color_2,
1981 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_2);
1983 c_options->image.alpha_color_1 = options->image.alpha_color_1;
1984 c_options->image.alpha_color_2 = options->image.alpha_color_2;
1986 group = pref_group_new(vbox, FALSE, _("Convenience"), GTK_ORIENTATION_VERTICAL);
1988 pref_checkbox_new_int(group, _("Auto rotate proofs using Exif information"),
1989 options->image.exif_proof_rotate_enable, &c_options->image.exif_proof_rotate_enable);
1993 static void config_tab_windows(GtkWidget *notebook)
1999 GtkWidget *ct_button;
2001 GtkWidget *image_overlay_template_view;
2002 GtkWidget *scrolled;
2003 GtkTextBuffer *buffer;
2005 vbox = scrolled_notebook_page(notebook, _("Windows"));
2007 group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
2009 ct_button = pref_checkbox_new_int(group, _("Remember window positions"),
2010 options->save_window_positions, &c_options->save_window_positions);
2012 button = pref_checkbox_new_int(group, _("Use saved window positions also for new windows"),
2013 options->use_saved_window_positions_for_new_windows, &c_options->use_saved_window_positions_for_new_windows);
2014 pref_checkbox_link_sensitivity(ct_button, button);
2016 pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
2017 options->tools_restore_state, &c_options->tools_restore_state);
2019 pref_checkbox_new_int(group, _("Remember dialog window positions"),
2020 options->save_dialog_window_positions, &c_options->save_dialog_window_positions);
2022 pref_checkbox_new_int(group, _("Show window IDs"),
2023 options->show_window_ids, &c_options->show_window_ids);
2025 group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
2027 pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
2028 options->image.fit_window_to_image, &c_options->image.fit_window_to_image);
2030 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2031 ct_button = pref_checkbox_new_int(hbox, _("Limit size when auto-sizing window (%):"),
2032 options->image.limit_window_size, &c_options->image.limit_window_size);
2033 spin = pref_spin_new_int(hbox, NULL, NULL,
2035 options->image.max_window_size, &c_options->image.max_window_size);
2036 pref_checkbox_link_sensitivity(ct_button, spin);
2038 group = pref_group_new(vbox, FALSE, _("Full screen"), GTK_ORIENTATION_VERTICAL);
2040 c_options->fullscreen.screen = options->fullscreen.screen;
2041 c_options->fullscreen.above = options->fullscreen.above;
2042 hbox = fullscreen_prefs_selection_new(_("Location:"), &c_options->fullscreen.screen, &c_options->fullscreen.above);
2043 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2044 gtk_widget_show(hbox);
2046 pref_checkbox_new_int(group, _("Smooth image flip"),
2047 options->fullscreen.clean_flip, &c_options->fullscreen.clean_flip);
2048 pref_checkbox_new_int(group, _("Disable screen saver"),
2049 options->fullscreen.disable_saver, &c_options->fullscreen.disable_saver);
2052 group = pref_group_new(vbox, FALSE, _("Overlay Screen Display"), GTK_ORIENTATION_VERTICAL);
2054 pref_label_new(group, _("Image overlay template"));
2056 scrolled = gtk_scrolled_window_new(NULL, NULL);
2057 gtk_widget_set_size_request(scrolled, 200, 150);
2058 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2059 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
2060 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2061 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 5);
2062 gtk_widget_show(scrolled);
2064 image_overlay_template_view = gtk_text_view_new();
2066 gtk_widget_set_tooltip_markup(image_overlay_template_view,
2067 _("<i>%name%</i> results in the filename of the picture.\n"
2068 "Also available: <i>%collection%</i>, <i>%number%</i>, <i>%total%</i>, <i>%date%</i>,\n"
2069 "<i>%size%</i> (filesize), <i>%width%</i>, <i>%height%</i>, <i>%res%</i> (resolution),\n"
2070 "<i>%rating%</i>, <i>%keywords%</i>, <i>%comment%</i> (XMP), <i>%imagecomment%</i> (JPEG)\n"
2071 "To access exif data use the exif name, e. g. <i>%formatted.Camera%</i> is the formatted camera name,\n"
2072 "<i>%Exif.Photo.DateTimeOriginal%</i> the date of the original shot.\n"
2073 "<i>%formatted.Camera:20</i> notation will truncate the displayed data to 20 characters and will add 3 dots at the end to denote the truncation.\n"
2074 "If two or more variables are connected with the |-sign, it prints available variables with a separator.\n"
2075 "<i>%formatted.ShutterSpeed%</i>|<i>%formatted.ISOSpeedRating%</i>|<i>%formatted.FocalLength%</i> could show \"1/20s - 400 - 80 mm\" or \"1/200 - 80 mm\",\n"
2076 "if there's no ISO information in the Exif data.\n"
2077 "If a line is empty, it is removed. This allows one to add lines that totally disappear when no data is available.\n"
2079 gtk_container_add(GTK_CONTAINER(scrolled), image_overlay_template_view);
2080 gtk_widget_show(image_overlay_template_view);
2082 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2084 #if GTK_CHECK_VERSION(3,4,0)
2085 button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
2086 G_CALLBACK(image_overlay_set_font_cb), notebook);
2088 button = gtk_font_button_new();
2089 gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Image Overlay Font");
2090 gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->image_overlay.font);
2091 g_signal_connect(G_OBJECT(button), "font-set",
2092 G_CALLBACK(image_overlay_set_font_cb),NULL);
2094 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2095 gtk_widget_show(button);
2097 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Text"), FALSE,
2098 G_CALLBACK(image_overlay_set_text_colour_cb), NULL);
2099 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2100 gtk_widget_show(button);
2102 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Background"), FALSE,
2103 G_CALLBACK(image_overlay_set_background_colour_cb), NULL);
2104 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2105 gtk_widget_show(button);
2106 image_overlay_set_text_colours();
2108 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2109 G_CALLBACK(image_overlay_default_template_cb), image_overlay_template_view);
2110 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2111 gtk_widget_show(button);
2113 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
2114 G_CALLBACK(image_overlay_help_cb), NULL);
2115 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2116 gtk_widget_show(button);
2118 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_overlay_template_view));
2119 if (options->image_overlay.template_string) gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
2120 g_signal_connect(G_OBJECT(buffer), "changed",
2121 G_CALLBACK(image_overlay_template_view_changed_cb), image_overlay_template_view);
2126 static GtkTreeModel *create_class_model(void)
2128 GtkListStore *model;
2132 /* create list store */
2133 model = gtk_list_store_new(1, G_TYPE_STRING);
2134 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
2136 gtk_list_store_append(model, &iter);
2137 gtk_list_store_set(model, &iter, 0, _(format_class_list[i]), -1);
2139 return GTK_TREE_MODEL (model);
2144 static void config_tab_files(GtkWidget *notebook)
2151 GtkWidget *ct_button;
2152 GtkWidget *scrolled;
2153 GtkWidget *filter_view;
2154 GtkCellRenderer *renderer;
2155 GtkTreeSelection *selection;
2156 GtkTreeViewColumn *column;
2158 vbox = scrolled_notebook_page(notebook, _("Files"));
2160 group = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2162 pref_checkbox_new_int(group, _("Show hidden files or folders"),
2163 options->file_filter.show_hidden_files, &c_options->file_filter.show_hidden_files);
2164 pref_checkbox_new_int(group, _("Show parent folder (..)"),
2165 options->file_filter.show_parent_directory, &c_options->file_filter.show_parent_directory);
2166 pref_checkbox_new_int(group, _("Case sensitive sort"),
2167 options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
2168 pref_checkbox_new_int(group, _("Natural sort order"),
2169 options->file_sort.natural, &c_options->file_sort.natural);
2170 pref_checkbox_new_int(group, _("Disable file extension checks"),
2171 options->file_filter.disable_file_extension_checks, &c_options->file_filter.disable_file_extension_checks);
2173 ct_button = pref_checkbox_new_int(group, _("Disable File Filtering"),
2174 options->file_filter.disable, &c_options->file_filter.disable);
2177 group = pref_group_new(vbox, FALSE, _("Grouping sidecar extensions"), GTK_ORIENTATION_VERTICAL);
2179 sidecar_ext_entry = gtk_entry_new();
2180 gtk_entry_set_text(GTK_ENTRY(sidecar_ext_entry), options->sidecar.ext);
2181 gtk_box_pack_start(GTK_BOX(group), sidecar_ext_entry, FALSE, FALSE, 0);
2182 gtk_widget_show(sidecar_ext_entry);
2184 group = pref_group_new(vbox, TRUE, _("File types"), GTK_ORIENTATION_VERTICAL);
2186 frame = pref_group_parent(group);
2187 g_signal_connect(G_OBJECT(ct_button), "toggled",
2188 G_CALLBACK(filter_disable_cb), frame);
2189 gtk_widget_set_sensitive(frame, !options->file_filter.disable);
2191 scrolled = gtk_scrolled_window_new(NULL, NULL);
2192 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2193 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2194 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2195 gtk_widget_show(scrolled);
2197 filter_store = gtk_list_store_new(1, G_TYPE_POINTER);
2198 filter_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(filter_store));
2199 g_object_unref(filter_store);
2200 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
2201 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
2203 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), FALSE);
2205 column = gtk_tree_view_column_new();
2206 gtk_tree_view_column_set_title(column, _("Filter"));
2207 gtk_tree_view_column_set_resizable(column, TRUE);
2209 renderer = gtk_cell_renderer_toggle_new();
2210 g_signal_connect(G_OBJECT(renderer), "toggled",
2211 G_CALLBACK(filter_store_enable_cb), filter_store);
2212 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2213 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2214 GINT_TO_POINTER(FE_ENABLE), NULL);
2216 renderer = gtk_cell_renderer_text_new();
2217 g_signal_connect(G_OBJECT(renderer), "edited",
2218 G_CALLBACK(filter_store_ext_edit_cb), filter_store);
2219 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2220 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2221 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2222 GINT_TO_POINTER(FE_EXTENSION), NULL);
2223 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2225 column = gtk_tree_view_column_new();
2226 gtk_tree_view_column_set_title(column, _("Description"));
2227 gtk_tree_view_column_set_resizable(column, TRUE);
2228 gtk_tree_view_column_set_fixed_width(column, 200);
2229 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
2231 renderer = gtk_cell_renderer_text_new();
2232 g_signal_connect(G_OBJECT(renderer), "edited",
2233 G_CALLBACK(filter_store_desc_edit_cb), filter_store);
2234 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2235 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2236 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2237 GINT_TO_POINTER(FE_DESCRIPTION), NULL);
2238 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2240 column = gtk_tree_view_column_new();
2241 gtk_tree_view_column_set_title(column, _("Class"));
2242 gtk_tree_view_column_set_resizable(column, TRUE);
2243 renderer = gtk_cell_renderer_combo_new();
2244 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE,
2245 "model", create_class_model(),
2250 g_signal_connect(G_OBJECT(renderer), "edited",
2251 G_CALLBACK(filter_store_class_edit_cb), filter_store);
2252 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2253 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2254 GINT_TO_POINTER(FE_CLASS), NULL);
2255 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2257 column = gtk_tree_view_column_new();
2258 gtk_tree_view_column_set_title(column, _("Writable"));
2259 gtk_tree_view_column_set_resizable(column, FALSE);
2260 renderer = gtk_cell_renderer_toggle_new();
2261 g_signal_connect(G_OBJECT(renderer), "toggled",
2262 G_CALLBACK(filter_store_writable_cb), filter_store);
2263 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2264 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2265 GINT_TO_POINTER(FE_WRITABLE), NULL);
2266 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2268 column = gtk_tree_view_column_new();
2269 gtk_tree_view_column_set_title(column, _("Sidecar is allowed"));
2270 gtk_tree_view_column_set_resizable(column, FALSE);
2271 renderer = gtk_cell_renderer_toggle_new();
2272 g_signal_connect(G_OBJECT(renderer), "toggled",
2273 G_CALLBACK(filter_store_sidecar_cb), filter_store);
2274 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2275 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2276 GINT_TO_POINTER(FE_ALLOW_SIDECAR), NULL);
2277 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2280 filter_store_populate();
2281 gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
2282 gtk_widget_show(filter_view);
2284 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2286 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2287 G_CALLBACK(filter_default_cb), filter_view);
2288 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2289 gtk_widget_show(button);
2291 button = pref_button_new(NULL, GTK_STOCK_REMOVE, NULL, FALSE,
2292 G_CALLBACK(filter_remove_cb), filter_view);
2293 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2294 gtk_widget_show(button);
2296 button = pref_button_new(NULL, GTK_STOCK_ADD, NULL, FALSE,
2297 G_CALLBACK(filter_add_cb), filter_view);
2298 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2299 gtk_widget_show(button);
2303 static void config_tab_metadata(GtkWidget *notebook)
2308 GtkWidget *ct_button;
2312 vbox = scrolled_notebook_page(notebook, _("Metadata"));
2315 group = pref_group_new(vbox, FALSE, _("Metadata writing process"), GTK_ORIENTATION_VERTICAL);
2317 label = pref_label_new(group, _("Warning: Geeqie is built without Exiv2. Some options are disabled."));
2319 label = pref_label_new(group, _("Metadata are written in the following order. The process ends after first success."));
2320 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2322 ct_button = pref_checkbox_new_int(group, _("1) Save metadata in image files, or sidecar files, according to the XMP standard"),
2323 options->metadata.save_in_image_file, &c_options->metadata.save_in_image_file);
2325 gtk_widget_set_sensitive(ct_button, FALSE);
2328 pref_checkbox_new_int(group, _("2) Save metadata in '.metadata' folder, local to image folder (non-standard)"),
2329 options->metadata.enable_metadata_dirs, &c_options->metadata.enable_metadata_dirs);
2331 text = g_strdup_printf(_("3) Save metadata in Geeqie private directory '%s'"), get_metadata_cache_dir());
2332 label = pref_label_new(group, text);
2333 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2334 gtk_misc_set_padding(GTK_MISC(label), 22, 0);
2337 group = pref_group_new(vbox, FALSE, _("Step 1: Write to image files"), GTK_ORIENTATION_VERTICAL);
2339 gtk_widget_set_sensitive(group, FALSE);
2342 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2343 pref_checkbox_link_sensitivity(ct_button, hbox);
2345 pref_checkbox_new_int(hbox, _("Store metadata also in legacy IPTC tags (converted according to IPTC4XMP standard)"),
2346 options->metadata.save_legacy_IPTC, &c_options->metadata.save_legacy_IPTC);
2348 pref_checkbox_new_int(hbox, _("Warn if the image files are unwritable"),
2349 options->metadata.warn_on_write_problems, &c_options->metadata.warn_on_write_problems);
2351 pref_checkbox_new_int(hbox, _("Ask before writing to image files"),
2352 options->metadata.confirm_write, &c_options->metadata.confirm_write);
2354 pref_checkbox_new_int(hbox, _("Create sidecar files named image.ext.xmp (as opposed to image.xmp)"),
2355 options->metadata.sidecar_extended_name, &c_options->metadata.sidecar_extended_name);
2357 group = pref_group_new(vbox, FALSE, _("Step 2 and 3: write to Geeqie private files"), GTK_ORIENTATION_VERTICAL);
2359 gtk_widget_set_sensitive(group, FALSE);
2362 pref_checkbox_new_int(group, _("Use GQview legacy metadata format (supports only keywords and comments) instead of XMP"),
2363 options->metadata.save_legacy_format, &c_options->metadata.save_legacy_format);
2366 group = pref_group_new(vbox, FALSE, _("Miscellaneous"), GTK_ORIENTATION_VERTICAL);
2367 pref_checkbox_new_int(group, _("Write the same description tags (keywords, comment, etc.) to all grouped sidecars"),
2368 options->metadata.sync_grouped_files, &c_options->metadata.sync_grouped_files);
2370 pref_checkbox_new_int(group, _("Allow keywords to differ only in case"),
2371 options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
2373 ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"),
2374 options->metadata.write_orientation, &c_options->metadata.write_orientation);
2376 gtk_widget_set_sensitive(ct_button, FALSE);
2379 group = pref_group_new(vbox, FALSE, _("Auto-save options"), GTK_ORIENTATION_VERTICAL);
2381 ct_button = pref_checkbox_new_int(group, _("Write metadata after timeout"),
2382 options->metadata.confirm_after_timeout, &c_options->metadata.confirm_after_timeout);
2384 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2385 pref_checkbox_link_sensitivity(ct_button, hbox);
2387 pref_spin_new_int(hbox, _("Timeout (seconds):"), NULL, 0, 900, 1,
2388 options->metadata.confirm_timeout, &c_options->metadata.confirm_timeout);
2390 pref_checkbox_new_int(group, _("Write metadata on image change"),
2391 options->metadata.confirm_on_image_change, &c_options->metadata.confirm_on_image_change);
2393 pref_checkbox_new_int(group, _("Write metadata on directory change"),
2394 options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
2396 group = pref_group_new(vbox, FALSE, _("Pre-load metadata"), GTK_ORIENTATION_VERTICAL);
2398 ct_button = pref_checkbox_new_int(group, _("Read metadata in background"),
2399 options->read_metadata_in_idle, &c_options->read_metadata_in_idle);
2400 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");
2405 typedef struct _KeywordFindData KeywordFindData;
2406 struct _KeywordFindData
2413 GtkWidget *button_close;
2414 GtkWidget *button_stop;
2415 GtkWidget *button_start;
2416 GtkWidget *progress;
2424 guint idle_id; /* event source id */
2427 #define KEYWORD_DIALOG_WIDTH 400
2429 static void keywords_find_folder(KeywordFindData *kfd, FileData *dir_fd)
2431 GList *list_d = NULL;
2432 GList *list_f = NULL;
2436 filelist_read(dir_fd, &list_f, &list_d);
2440 filelist_read(dir_fd, &list_f, NULL);
2443 list_f = filelist_filter(list_f, FALSE);
2444 list_d = filelist_filter(list_d, TRUE);
2446 kfd->list = g_list_concat(list_f, kfd->list);
2447 kfd->list_dir = g_list_concat(list_d, kfd->list_dir);
2450 static void keywords_find_reset(KeywordFindData *kfd)
2452 filelist_free(kfd->list);
2455 filelist_free(kfd->list_dir);
2456 kfd->list_dir = NULL;
2459 static void keywords_find_close_cb(GenericDialog *fd, gpointer data)
2461 KeywordFindData *kfd = data;
2463 if (!gtk_widget_get_sensitive(kfd->button_close)) return;
2465 keywords_find_reset(kfd);
2466 generic_dialog_close(kfd->gd);
2470 static void keywords_find_finish(KeywordFindData *kfd)
2472 keywords_find_reset(kfd);
2474 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("done"));
2475 spinner_set_interval(kfd->spinner, -1);
2477 gtk_widget_set_sensitive(kfd->group, TRUE);
2478 gtk_widget_set_sensitive(kfd->button_start, TRUE);
2479 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2480 gtk_widget_set_sensitive(kfd->button_close, TRUE);
2483 static void keywords_find_stop_cb(GenericDialog *fd, gpointer data)
2485 KeywordFindData *kfd = data;
2487 g_idle_remove_by_data(kfd);
2489 keywords_find_finish(kfd);
2492 static gboolean keywords_find_file(gpointer data)
2494 KeywordFindData *kfd = data;
2496 GtkTextBuffer *buffer;
2504 fd = kfd->list->data;
2505 kfd->list = g_list_remove(kfd->list, fd);
2507 keywords = metadata_read_list(fd, KEYWORD_KEY, METADATA_PLAIN);
2508 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2512 gtk_text_buffer_get_end_iter(buffer, &iter);
2513 tmp = g_strconcat(keywords->data, "\n", NULL);
2514 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
2516 keywords = keywords->next;
2519 gtk_entry_set_text(GTK_ENTRY(kfd->progress), fd->path);
2520 file_data_unref(fd);
2521 string_list_free(keywords);
2525 else if (kfd->list_dir)
2529 fd = kfd->list_dir->data;
2530 kfd->list_dir = g_list_remove(kfd->list_dir, fd);
2532 keywords_find_folder(kfd, fd);
2534 file_data_unref(fd);
2539 keywords_find_finish(kfd);
2544 static void keywords_find_start_cb(GenericDialog *fd, gpointer data)
2546 KeywordFindData *kfd = data;
2549 if (kfd->list || !gtk_widget_get_sensitive(kfd->button_start)) return;
2551 path = remove_trailing_slash((gtk_entry_get_text(GTK_ENTRY(kfd->entry))));
2552 parse_out_relatives(path);
2556 warning_dialog(_("Invalid folder"),
2557 _("The specified folder can not be found."),
2558 GTK_STOCK_DIALOG_WARNING, kfd->gd->dialog);
2564 gtk_widget_set_sensitive(kfd->group, FALSE);
2565 gtk_widget_set_sensitive(kfd->button_start, FALSE);
2566 gtk_widget_set_sensitive(kfd->button_stop, TRUE);
2567 gtk_widget_set_sensitive(kfd->button_close, FALSE);
2568 spinner_set_interval(kfd->spinner, SPINNER_SPEED);
2570 dir_fd = file_data_new_dir(path);
2571 keywords_find_folder(kfd, dir_fd);
2572 file_data_unref(dir_fd);
2573 kfd->idle_id = g_idle_add(keywords_find_file, kfd);
2579 static void keywords_find_dialog(GtkWidget *widget, const gchar *path)
2581 KeywordFindData *kfd;
2585 kfd = g_new0(KeywordFindData, 1);
2587 kfd->gd = generic_dialog_new(_("Search for keywords"),
2588 "search_for_keywords",
2591 gtk_window_set_default_size(GTK_WINDOW(kfd->gd->dialog), KEYWORD_DIALOG_WIDTH, -1);
2592 kfd->gd->cancel_cb = keywords_find_close_cb;
2593 kfd->button_close = generic_dialog_add_button(kfd->gd, GTK_STOCK_CLOSE, NULL,
2594 keywords_find_close_cb, FALSE);
2595 kfd->button_start = generic_dialog_add_button(kfd->gd, GTK_STOCK_OK, _("S_tart"),
2596 keywords_find_start_cb, FALSE);
2597 kfd->button_stop = generic_dialog_add_button(kfd->gd, GTK_STOCK_STOP, NULL,
2598 keywords_find_stop_cb, FALSE);
2599 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2601 generic_dialog_add_message(kfd->gd, NULL, _("Search for keywords"), NULL, FALSE);
2603 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0);
2604 pref_spacer(hbox, PREF_PAD_INDENT);
2605 kfd->group = pref_box_new(hbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2607 hbox = pref_box_new(kfd->group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2608 pref_label_new(hbox, _("Folder:"));
2610 label = tab_completion_new(&kfd->entry, path, NULL, NULL, NULL, NULL);
2611 tab_completion_add_select_button(kfd->entry,_("Select folder") , TRUE);
2612 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
2613 gtk_widget_show(label);
2615 pref_checkbox_new_int(kfd->group, _("Include subfolders"), FALSE, &kfd->recurse);
2617 pref_line(kfd->gd->vbox, PREF_PAD_SPACE);
2618 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2620 kfd->progress = gtk_entry_new();
2621 gtk_widget_set_can_focus(kfd->progress, FALSE);
2622 gtk_editable_set_editable(GTK_EDITABLE(kfd->progress), FALSE);
2623 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("click start to begin"));
2624 gtk_box_pack_start(GTK_BOX(hbox), kfd->progress, TRUE, TRUE, 0);
2625 gtk_widget_show(kfd->progress);
2627 kfd->spinner = spinner_new(NULL, -1);
2628 gtk_box_pack_start(GTK_BOX(hbox), kfd->spinner, FALSE, FALSE, 0);
2629 gtk_widget_show(kfd->spinner);
2633 gtk_widget_show(kfd->gd->dialog);
2636 static void keywords_find_cb(GtkWidget *widget, gpointer data)
2638 const gchar *path = layout_get_path(NULL);
2640 if (!path || !*path) path = homedir();
2641 keywords_find_dialog(widget, path);
2644 static void config_tab_keywords_save()
2646 GtkTextIter start, end;
2647 GtkTextBuffer *buffer;
2648 GList *kw_list = NULL;
2654 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2655 gtk_text_buffer_get_bounds(buffer, &start, &end);
2657 buffer_text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
2659 kw_split = strtok(buffer_text, "\n");
2660 while (kw_split != NULL)
2666 if (g_strcmp0(work->data, kw_split) == 0)
2675 kw_list = g_list_append(kw_list, g_strdup(kw_split));
2677 kw_split = strtok(NULL, "\n");
2680 keyword_list_set(kw_list);
2682 string_list_free(kw_list);
2683 g_free(buffer_text);
2686 static void config_tab_keywords(GtkWidget *notebook)
2692 GtkWidget *scrolled;
2694 GtkTextBuffer *buffer;
2697 vbox = scrolled_notebook_page(notebook, _("Keywords"));
2699 group = pref_group_new(vbox, TRUE, _("Edit keywords autocompletion list"), GTK_ORIENTATION_VERTICAL);
2701 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2703 button = pref_button_new(hbox, GTK_STOCK_EXECUTE, _("Search"), FALSE,
2704 G_CALLBACK(keywords_find_cb), keyword_text);
2705 gtk_widget_set_tooltip_text(button, "Search for existing keywords");
2708 keyword_text = gtk_text_view_new();
2709 gtk_widget_set_size_request(keyword_text, 20, 20);
2710 scrolled = gtk_scrolled_window_new(NULL, NULL);
2711 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2712 gtk_widget_show(scrolled);
2714 gtk_container_add(GTK_CONTAINER(scrolled), keyword_text);
2715 gtk_widget_show(keyword_text);
2717 gtk_text_view_set_editable(GTK_TEXT_VIEW(keyword_text), TRUE);
2719 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2720 gtk_text_buffer_create_tag(buffer, "monospace",
2721 "family", "monospace", NULL);
2723 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(keyword_text), GTK_WRAP_WORD);
2724 gtk_text_buffer_get_start_iter(buffer, &iter);
2725 gtk_text_buffer_create_mark(buffer, "end", &iter, FALSE);
2728 path = g_build_filename(get_rc_dir(), "keywords", NULL);
2730 GList *kwl = keyword_list_get();
2731 kwl = g_list_first(kwl);
2734 gtk_text_buffer_get_end_iter (buffer, &iter);
2735 tmp = g_strconcat(kwl->data, "\n", NULL);
2736 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
2741 gtk_text_buffer_set_modified(buffer, FALSE);
2748 static void intent_menu_cb(GtkWidget *combo, gpointer data)
2750 gint *option = data;
2752 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
2756 *option = INTENT_PERCEPTUAL;
2759 *option = INTENT_RELATIVE_COLORIMETRIC;
2762 *option = INTENT_SATURATION;
2765 *option = INTENT_ABSOLUTE_COLORIMETRIC;
2770 static void add_intent_menu(GtkWidget *table, gint column, gint row, const gchar *text,
2771 gint option, gint *option_c)
2778 pref_table_label(table, column, row, text, 0.0);
2780 combo = gtk_combo_box_text_new();
2782 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Perceptual"));
2783 if (option == INTENT_PERCEPTUAL) current = 0;
2784 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Relative Colorimetric"));
2785 if (option == INTENT_RELATIVE_COLORIMETRIC) current = 1;
2786 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Saturation"));
2787 if (option == INTENT_SATURATION) current = 2;
2788 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Absolute Colorimetric"));
2789 if (option == INTENT_ABSOLUTE_COLORIMETRIC) current = 3;
2791 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
2793 gtk_widget_set_tooltip_text(combo,"Refer to the lcms documentation for the defaults used when the selected Intent is not available");
2795 g_signal_connect(G_OBJECT(combo), "changed",
2796 G_CALLBACK(intent_menu_cb), option_c);
2798 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
2799 GTK_EXPAND | GTK_FILL, 0, 0, 0);
2800 gtk_widget_show(combo);
2804 static void config_tab_color(GtkWidget *notebook)
2813 vbox = scrolled_notebook_page(notebook, _("Color management"));
2815 group = pref_group_new(vbox, FALSE, _("Input profiles"), GTK_ORIENTATION_VERTICAL);
2817 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
2820 table = pref_table_new(group, 3, COLOR_PROFILE_INPUTS + 1, FALSE, FALSE);
2821 gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
2823 label = pref_table_label(table, 0, 0, _("Type"), 0.0);
2824 pref_label_bold(label, TRUE, FALSE);
2826 label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
2827 pref_label_bold(label, TRUE, FALSE);
2829 label = pref_table_label(table, 2, 0, _("File"), 0.0);
2830 pref_label_bold(label, TRUE, FALSE);
2832 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
2837 buf = g_strdup_printf(_("Input %d:"), i + COLOR_PROFILE_FILE);
2838 pref_table_label(table, 0, i + 1, buf, 1.0);
2841 entry = gtk_entry_new();
2842 gtk_entry_set_max_length(GTK_ENTRY(entry), EDITOR_NAME_MAX_LENGTH);
2843 if (options->color_profile.input_name[i])
2845 gtk_entry_set_text(GTK_ENTRY(entry), options->color_profile.input_name[i]);
2847 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, i + 1, i + 2,
2848 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2849 gtk_widget_show(entry);
2850 color_profile_input_name_entry[i] = entry;
2852 tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, ".icc", "ICC Files", NULL);
2853 tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
2854 gtk_widget_set_size_request(entry, 160, -1);
2855 gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
2856 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2857 gtk_widget_show(tabcomp);
2858 color_profile_input_file_entry[i] = entry;
2861 group = pref_group_new(vbox, FALSE, _("Screen profile"), GTK_ORIENTATION_VERTICAL);
2863 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
2865 pref_checkbox_new_int(group, _("Use system screen profile if available"),
2866 options->color_profile.use_x11_screen_profile, &c_options->color_profile.use_x11_screen_profile);
2868 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2870 pref_table_label(table, 0, 0, _("Screen:"), 1.0);
2871 tabcomp = tab_completion_new(&color_profile_screen_file_entry,
2872 options->color_profile.screen_file, NULL, ".icc", "ICC Files", NULL);
2873 tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
2874 gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
2876 add_intent_menu(table, 0, 1, _("Render Intent:"), options->color_profile.render_intent, &c_options->color_profile.render_intent);
2878 gtk_table_attach(GTK_TABLE(table), tabcomp, 1, 2,
2880 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2882 gtk_widget_show(tabcomp);
2885 /* advanced entry tab */
2886 static void config_tab_behavior(GtkWidget *notebook)
2893 GtkWidget *ct_button;
2897 GtkWidget *with_rename;
2898 GtkWidget *collections_on_top;
2900 vbox = scrolled_notebook_page(notebook, _("Behavior"));
2902 group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
2904 pref_checkbox_new_int(group, _("Confirm file delete"),
2905 options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
2906 pref_checkbox_new_int(group, _("Enable Delete key"),
2907 options->file_ops.enable_delete_key, &c_options->file_ops.enable_delete_key);
2909 ct_button = pref_checkbox_new_int(group, _("Safe delete"),
2910 options->file_ops.safe_delete_enable, &c_options->file_ops.safe_delete_enable);
2912 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2913 pref_checkbox_link_sensitivity(ct_button, hbox);
2915 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
2916 pref_label_new(hbox, _("Folder:"));
2918 tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL, NULL, NULL);
2919 tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
2920 gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
2921 gtk_widget_show(tabcomp);
2923 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2924 pref_checkbox_link_sensitivity(ct_button, hbox);
2926 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
2927 spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MB"),
2928 0, 2048, 1, options->file_ops.safe_delete_folder_maxsize, &c_options->file_ops.safe_delete_folder_maxsize);
2929 gtk_widget_set_tooltip_markup(spin, _("Set to 0 for unlimited size"));
2930 button = pref_button_new(NULL, NULL, _("View"), FALSE,
2931 G_CALLBACK(safe_delete_view_cb), NULL);
2932 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2933 gtk_widget_show(button);
2935 button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
2936 G_CALLBACK(safe_delete_clear_cb), NULL);
2937 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2938 gtk_widget_show(button);
2941 group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
2943 pref_checkbox_new_int(group, _("Descend folders in tree view"),
2944 options->tree_descend_subdirs, &c_options->tree_descend_subdirs);
2946 pref_checkbox_new_int(group, _("In place renaming"),
2947 options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
2949 pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
2950 options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
2952 marks = pref_checkbox_new_int(group, _("Save marks on exit"),
2953 options->marks_save, &c_options->marks_save);
2954 gtk_widget_set_tooltip_text(marks,"Note that marks linked to a keyword will be saved irrespective of this setting");
2956 with_rename = pref_checkbox_new_int(group, _("Use \"With Rename\" as default for Copy/Move dialogs"),
2957 options->with_rename, &c_options->with_rename);
2958 gtk_widget_set_tooltip_text(with_rename,"Change the default button for Copy/Move dialogs");
2960 collections_on_top = pref_checkbox_new_int(group, _("Open collections on top"),
2961 options->collections_on_top, &c_options->collections_on_top);
2962 gtk_widget_set_tooltip_text(collections_on_top,"Open collections window on top");
2964 pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
2965 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
2967 pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
2968 16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
2970 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2971 add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
2973 group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
2975 pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
2976 options->progressive_key_scrolling, &c_options->progressive_key_scrolling);
2977 pref_spin_new_int(group, _("Keyboard scrolling step multiplier:"), NULL,
2978 1, 32, 1, options->keyboard_scroll_step, (int *)&c_options->keyboard_scroll_step);
2979 pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
2980 options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
2981 pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
2982 options->image_lm_click_nav, &c_options->image_lm_click_nav);
2983 pref_checkbox_new_int(group, _("Play video by left click on image"),
2984 options->image_l_click_video, &c_options->image_l_click_video);
2985 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2986 add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
2990 group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
2992 pref_spin_new_int(group, _("Debug level:"), NULL,
2993 DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
2995 pref_checkbox_new_int(group, _("Timer data"),
2996 options->log_window.timer_data, &c_options->log_window.timer_data);
2998 pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
2999 1, 99999, 1, options->log_window_lines, &options->log_window_lines);
3003 /* accelerators tab */
3004 static void config_tab_accelerators(GtkWidget *notebook)
3010 GtkWidget *scrolled;
3011 GtkWidget *accel_view;
3012 GtkCellRenderer *renderer;
3013 GtkTreeSelection *selection;
3014 GtkTreeViewColumn *column;
3016 vbox = scrolled_notebook_page(notebook, _("Keyboard"));
3018 group = pref_group_new(vbox, TRUE, _("Accelerators"), GTK_ORIENTATION_VERTICAL);
3020 scrolled = gtk_scrolled_window_new(NULL, NULL);
3021 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
3022 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
3023 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3024 gtk_widget_show(scrolled);
3026 accel_store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
3028 accel_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(accel_store));
3029 g_object_unref(accel_store);
3030 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(accel_view));
3031 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
3033 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(accel_view), FALSE);
3035 renderer = gtk_cell_renderer_text_new();
3037 column = gtk_tree_view_column_new_with_attributes(_("Action"),
3042 gtk_tree_view_column_set_sort_column_id(column, AE_ACTION);
3043 gtk_tree_view_column_set_resizable(column, TRUE);
3044 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3047 renderer = gtk_cell_renderer_accel_new();
3048 g_signal_connect(G_OBJECT(renderer), "accel-cleared",
3049 G_CALLBACK(accel_store_cleared_cb), accel_store);
3050 g_signal_connect(G_OBJECT(renderer), "accel-edited",
3051 G_CALLBACK(accel_store_edited_cb), accel_store);
3054 g_object_set (renderer,
3056 "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
3059 column = gtk_tree_view_column_new_with_attributes(_("KEY"),
3064 gtk_tree_view_column_set_sort_column_id(column, AE_KEY);
3065 gtk_tree_view_column_set_resizable(column, TRUE);
3066 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3068 renderer = gtk_cell_renderer_text_new();
3070 column = gtk_tree_view_column_new_with_attributes(_("Tooltip"),
3075 gtk_tree_view_column_set_sort_column_id(column, AE_TOOLTIP);
3076 gtk_tree_view_column_set_resizable(column, TRUE);
3077 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3079 renderer = gtk_cell_renderer_text_new();
3081 column = gtk_tree_view_column_new_with_attributes("Accel",
3086 gtk_tree_view_column_set_sort_column_id(column, AE_ACCEL);
3087 gtk_tree_view_column_set_resizable(column, TRUE);
3088 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3090 accel_store_populate();
3091 gtk_container_add(GTK_CONTAINER(scrolled), accel_view);
3092 gtk_widget_show(accel_view);
3094 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3096 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
3097 G_CALLBACK(accel_default_cb), accel_view);
3098 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3099 gtk_widget_show(button);
3101 button = pref_button_new(NULL, NULL, _("Reset selected"), FALSE,
3102 G_CALLBACK(accel_reset_cb), accel_view);
3103 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3104 gtk_widget_show(button);
3108 static void config_tab_toolbar(GtkWidget *notebook)
3111 GtkWidget *toolbardata;
3114 lw = layout_window_list->data;
3116 vbox = scrolled_notebook_page(notebook, _("Toolbar"));
3118 toolbardata = toolbar_select_new(lw);
3119 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3120 gtk_widget_show(vbox);
3124 static void config_tab_stereo(GtkWidget *notebook)
3132 GtkWidget *fs_button;
3133 vbox = scrolled_notebook_page(notebook, _("Stereo"));
3135 group = pref_group_new(vbox, FALSE, _("Windowed stereo mode"), GTK_ORIENTATION_VERTICAL);
3137 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3138 add_stereo_mode_menu(table, 0, 0, _("Windowed stereo mode"), options->stereo.mode, &c_options->stereo.mode, FALSE);
3140 table = pref_table_new(group, 2, 2, TRUE, FALSE);
3141 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3142 pref_checkbox_new_int(box, _("Mirror left image"),
3143 options->stereo.mode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.mirror_left);
3144 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3145 pref_checkbox_new_int(box, _("Flip left image"),
3146 options->stereo.mode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.flip_left);
3147 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3148 pref_checkbox_new_int(box, _("Mirror right image"),
3149 options->stereo.mode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.mirror_right);
3150 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3151 pref_checkbox_new_int(box, _("Flip right image"),
3152 options->stereo.mode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.flip_right);
3153 pref_checkbox_new_int(group, _("Swap left and right images"),
3154 options->stereo.mode & PR_STEREO_SWAP, &c_options->stereo.tmp.swap);
3155 pref_checkbox_new_int(group, _("Disable stereo mode on single image source"),
3156 options->stereo.mode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.temp_disable);
3158 group = pref_group_new(vbox, FALSE, _("Fullscreen stereo mode"), GTK_ORIENTATION_VERTICAL);
3159 fs_button = pref_checkbox_new_int(group, _("Use different settings for fullscreen"),
3160 options->stereo.enable_fsmode, &c_options->stereo.enable_fsmode);
3161 box2 = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
3162 pref_checkbox_link_sensitivity(fs_button, box2);
3163 table = pref_table_new(box2, 2, 1, FALSE, FALSE);
3164 add_stereo_mode_menu(table, 0, 0, _("Fullscreen stereo mode"), options->stereo.fsmode, &c_options->stereo.fsmode, TRUE);
3165 table = pref_table_new(box2, 2, 2, TRUE, FALSE);
3166 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3167 pref_checkbox_new_int(box, _("Mirror left image"),
3168 options->stereo.fsmode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.fs_mirror_left);
3169 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3170 pref_checkbox_new_int(box, _("Flip left image"),
3171 options->stereo.fsmode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.fs_flip_left);
3172 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3173 pref_checkbox_new_int(box, _("Mirror right image"),
3174 options->stereo.fsmode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.fs_mirror_right);
3175 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3176 pref_checkbox_new_int(box, _("Flip right image"),
3177 options->stereo.fsmode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.fs_flip_right);
3178 pref_checkbox_new_int(box2, _("Swap left and right images"),
3179 options->stereo.fsmode & PR_STEREO_SWAP, &c_options->stereo.tmp.fs_swap);
3180 pref_checkbox_new_int(box2, _("Disable stereo mode on single image source"),
3181 options->stereo.fsmode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.fs_temp_disable);
3183 group2 = pref_group_new(box2, FALSE, _("Fixed position"), GTK_ORIENTATION_VERTICAL);
3184 table = pref_table_new(group2, 5, 3, FALSE, FALSE);
3185 pref_table_spin_new_int(table, 0, 0, _("Width"), NULL,
3186 1, 5000, 1, options->stereo.fixed_w, &c_options->stereo.fixed_w);
3187 pref_table_spin_new_int(table, 3, 0, _("Height"), NULL,
3188 1, 5000, 1, options->stereo.fixed_h, &c_options->stereo.fixed_h);
3189 pref_table_spin_new_int(table, 0, 1, _("Left X"), NULL,
3190 0, 5000, 1, options->stereo.fixed_x1, &c_options->stereo.fixed_x1);
3191 pref_table_spin_new_int(table, 3, 1, _("Left Y"), NULL,
3192 0, 5000, 1, options->stereo.fixed_y1, &c_options->stereo.fixed_y1);
3193 pref_table_spin_new_int(table, 0, 2, _("Right X"), NULL,
3194 0, 5000, 1, options->stereo.fixed_x2, &c_options->stereo.fixed_x2);
3195 pref_table_spin_new_int(table, 3, 2, _("Right Y"), NULL,
3196 0, 5000, 1, options->stereo.fixed_y2, &c_options->stereo.fixed_y2);
3200 /* Main preferences window */
3201 static void config_window_create(void)
3203 GtkWidget *win_vbox;
3205 GtkWidget *notebook;
3207 GtkWidget *ct_button;
3209 if (!c_options) c_options = init_options(NULL);
3211 configwindow = window_new(GTK_WINDOW_TOPLEVEL, "preferences", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Preferences"));
3212 gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
3213 g_signal_connect(G_OBJECT(configwindow), "delete_event",
3214 G_CALLBACK(config_window_delete), NULL);
3215 gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
3216 gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
3217 gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
3219 win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
3220 gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
3221 gtk_widget_show(win_vbox);
3223 notebook = gtk_notebook_new();
3224 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP);
3225 gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
3227 config_tab_general(notebook);
3228 config_tab_image(notebook);
3229 config_tab_windows(notebook);
3230 config_tab_accelerators(notebook);
3231 config_tab_files(notebook);
3232 config_tab_metadata(notebook);
3233 config_tab_keywords(notebook);
3234 config_tab_color(notebook);
3235 config_tab_stereo(notebook);
3236 config_tab_behavior(notebook);
3237 config_tab_toolbar(notebook);
3239 hbox = gtk_hbutton_box_new();
3240 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
3241 gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
3242 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
3243 gtk_widget_show(hbox);
3245 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
3246 G_CALLBACK(config_window_help_cb), notebook);
3247 gtk_container_add(GTK_CONTAINER(hbox), button);
3248 gtk_widget_set_can_default(button, TRUE);
3249 gtk_widget_show(button);
3251 button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
3252 G_CALLBACK(config_window_ok_cb), NULL);
3253 gtk_container_add(GTK_CONTAINER(hbox), button);
3254 gtk_widget_set_can_default(button, TRUE);
3255 gtk_widget_grab_default(button);
3256 gtk_widget_show(button);
3260 button = pref_button_new(NULL, GTK_STOCK_SAVE, NULL, FALSE,
3261 G_CALLBACK(config_window_save_cb), NULL);
3262 gtk_container_add(GTK_CONTAINER(hbox), button);
3263 gtk_widget_set_can_default(button, TRUE);
3264 gtk_widget_show(button);
3266 button = pref_button_new(NULL, GTK_STOCK_APPLY, NULL, FALSE,
3267 G_CALLBACK(config_window_apply_cb), NULL);
3268 gtk_container_add(GTK_CONTAINER(hbox), button);
3269 gtk_widget_set_can_default(button, TRUE);
3270 gtk_widget_show(button);
3272 button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
3273 G_CALLBACK(config_window_close_cb), NULL);
3274 gtk_container_add(GTK_CONTAINER(hbox), button);
3275 gtk_widget_set_can_default(button, TRUE);
3276 gtk_widget_show(button);
3278 if (!generic_dialog_get_alternative_button_order(configwindow))
3280 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
3283 gtk_widget_show(notebook);
3285 gtk_widget_show(configwindow);
3289 *-----------------------------------------------------------------------------
3290 * config window show (public)
3291 *-----------------------------------------------------------------------------
3294 void show_config_window(void)
3298 gtk_window_present(GTK_WINDOW(configwindow));
3302 config_window_create();
3311 void show_about_window(LayoutWindow *lw)
3313 GdkPixbuf *pixbuf_logo;
3314 GdkPixbuf *pixbuf_icon;
3315 gchar *authors[1000];
3323 #define LINE_LENGTH 1000
3324 gchar line[LINE_LENGTH];
3326 copyright = g_string_new(NULL);
3327 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");
3329 zd_path = g_build_filename(GQ_BIN_DIR, TIMEZONE_DATABASE, NULL);
3330 cd = ZDOpenDatabase(zd_path);
3333 copyright = g_string_append(copyright, ZDGetNotice(cd));
3335 ZDCloseDatabase(cd);
3339 path = g_build_filename(GQ_HELPDIR, "AUTHORS", NULL);
3340 fp = fopen(path, "r");
3343 while(fgets(line, LINE_LENGTH, fp))
3345 /* get rid of ending \n from fgets */
3346 line[strlen(line) - 1] = '\0';
3347 authors[i_authors] = g_strdup(line);
3350 authors[i_authors] = NULL;
3355 comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
3356 "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
3358 pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
3359 pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
3360 gtk_show_about_dialog(GTK_WINDOW(lw->window),
3361 "title", _("About Geeqie"),
3363 "program-name", GQ_APPNAME,
3365 "logo", pixbuf_logo,
3366 "icon", pixbuf_icon,
3367 "website", GQ_WEBSITE,
3368 "website-label", "Website",
3369 "comments", comment,
3371 "translator-credits", _("translator-credits"),
3372 "wrap-license", TRUE,
3373 "license", copyright->str,
3376 g_string_free(copyright, TRUE);
3379 while(n < i_authors)
3389 static void image_overlay_set_text_colours()
3391 c_options->image_overlay.text_red = options->image_overlay.text_red;
3392 c_options->image_overlay.text_green = options->image_overlay.text_green;
3393 c_options->image_overlay.text_blue = options->image_overlay.text_blue;
3394 c_options->image_overlay.text_alpha = options->image_overlay.text_alpha;
3395 c_options->image_overlay.background_red = options->image_overlay.background_red;
3396 c_options->image_overlay.background_green = options->image_overlay.background_green;
3397 c_options->image_overlay.background_blue = options->image_overlay.background_blue;
3398 c_options->image_overlay.background_alpha = options->image_overlay.background_alpha;
3400 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */