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 "GuideOptionsColor.html",
490 "GuideOptionsStereo.html",
491 "GuideOptionsBehavior.html",
492 "GuideOptionsToolbar.html"
495 i = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
496 help_window_show(html_section[i]);
499 static gboolean config_window_delete(GtkWidget *widget, GdkEventAny *event, gpointer data)
501 config_window_close_cb(NULL, NULL);
505 static void config_window_ok_cb(GtkWidget *widget, gpointer data)
507 config_window_apply();
508 config_window_close_cb(NULL, NULL);
511 static void config_window_apply_cb(GtkWidget *widget, gpointer data)
514 lw = layout_window_list->data;
516 config_window_apply();
517 layout_util_sync(lw);
520 static void config_window_save_cb(GtkWidget *widget, gpointer data)
522 config_window_apply();
523 save_options(options);
527 *-----------------------------------------------------------------------------
528 * config window setup (private)
529 *-----------------------------------------------------------------------------
532 static void quality_menu_cb(GtkWidget *combo, gpointer data)
536 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
540 *option = GDK_INTERP_NEAREST;
543 *option = GDK_INTERP_TILES;
546 *option = GDK_INTERP_BILINEAR;
549 *option = GDK_INTERP_HYPER;
554 static void clipboard_selection_menu_cb(GtkWidget *combo, gpointer data)
558 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
570 static void add_quality_menu(GtkWidget *table, gint column, gint row, const gchar *text,
571 guint option, guint *option_c)
578 pref_table_label(table, column, row, text, 0.0);
580 combo = gtk_combo_box_text_new();
582 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Nearest (worst, but fastest)"));
583 if (option == GDK_INTERP_NEAREST) current = 0;
584 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Tiles"));
585 if (option == GDK_INTERP_TILES) current = 1;
586 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Bilinear"));
587 if (option == GDK_INTERP_BILINEAR) current = 2;
588 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Hyper (best, but slowest)"));
589 if (option == GDK_INTERP_HYPER) current = 3;
591 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
593 g_signal_connect(G_OBJECT(combo), "changed",
594 G_CALLBACK(quality_menu_cb), option_c);
596 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
597 GTK_EXPAND | GTK_FILL, 0, 0, 0);
598 gtk_widget_show(combo);
601 static void add_clipboard_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
602 gint option, gint *option_c)
609 pref_table_label(table, column, row, text, 0.0);
611 combo = gtk_combo_box_text_new();
613 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("PRIMARY"));
614 if (option == PRIMARY) current = 0;
615 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("CLIPBOARD"));
616 if (option == CLIPBOARD) current = 1;
618 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
620 g_signal_connect(G_OBJECT(combo), "changed",
621 G_CALLBACK(clipboard_selection_menu_cb), option_c);
623 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
624 GTK_EXPAND | GTK_FILL, 0, 0, 0);
625 gtk_widget_show(combo);
628 static void thumb_size_menu_cb(GtkWidget *combo, gpointer data)
632 n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
635 if ((guint) n < sizeof(thumb_size_list) / sizeof(ThumbSize))
637 c_options->thumbnails.max_width = thumb_size_list[n].w;
638 c_options->thumbnails.max_height = thumb_size_list[n].h;
642 c_options->thumbnails.max_width = options->thumbnails.max_width;
643 c_options->thumbnails.max_height = options->thumbnails.max_height;
647 static void add_thumb_size_menu(GtkWidget *table, gint column, gint row, gchar *text)
653 c_options->thumbnails.max_width = options->thumbnails.max_width;
654 c_options->thumbnails.max_height = options->thumbnails.max_height;
656 pref_table_label(table, column, row, text, 0.0);
658 combo = gtk_combo_box_text_new();
661 for (i = 0; (guint) i < sizeof(thumb_size_list) / sizeof(ThumbSize); i++)
666 w = thumb_size_list[i].w;
667 h = thumb_size_list[i].h;
669 buf = g_strdup_printf("%d x %d", w, h);
670 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
673 if (w == options->thumbnails.max_width && h == options->thumbnails.max_height) current = i;
680 buf = g_strdup_printf("%s %d x %d", _("Custom"), options->thumbnails.max_width, options->thumbnails.max_height);
681 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
687 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
688 g_signal_connect(G_OBJECT(combo), "changed",
689 G_CALLBACK(thumb_size_menu_cb), NULL);
691 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
692 GTK_EXPAND | GTK_FILL, 0, 0, 0);
693 gtk_widget_show(combo);
696 static void stereo_mode_menu_cb(GtkWidget *combo, gpointer data)
700 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
704 *option = PR_STEREO_NONE;
707 *option = PR_STEREO_ANAGLYPH_RC;
710 *option = PR_STEREO_ANAGLYPH_GM;
713 *option = PR_STEREO_ANAGLYPH_YB;
716 *option = PR_STEREO_ANAGLYPH_GRAY_RC;
719 *option = PR_STEREO_ANAGLYPH_GRAY_GM;
722 *option = PR_STEREO_ANAGLYPH_GRAY_YB;
725 *option = PR_STEREO_ANAGLYPH_DB_RC;
728 *option = PR_STEREO_ANAGLYPH_DB_GM;
731 *option = PR_STEREO_ANAGLYPH_DB_YB;
734 *option = PR_STEREO_HORIZ;
737 *option = PR_STEREO_HORIZ | PR_STEREO_HALF;
740 *option = PR_STEREO_VERT;
743 *option = PR_STEREO_VERT | PR_STEREO_HALF;
746 *option = PR_STEREO_FIXED;
751 static void add_stereo_mode_menu(GtkWidget *table, gint column, gint row, const gchar *text,
752 gint option, gint *option_c, gboolean add_fixed)
759 pref_table_label(table, column, row, text, 0.0);
761 combo = gtk_combo_box_text_new();
763 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Single image"));
765 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Red-Cyan"));
766 if (option & PR_STEREO_ANAGLYPH_RC) current = 1;
767 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Green-Magenta"));
768 if (option & PR_STEREO_ANAGLYPH_GM) current = 2;
769 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Yellow-Blue"));
770 if (option & PR_STEREO_ANAGLYPH_YB) current = 3;
771 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Red-Cyan"));
772 if (option & PR_STEREO_ANAGLYPH_GRAY_RC) current = 4;
773 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Green-Magenta"));
774 if (option & PR_STEREO_ANAGLYPH_GRAY_GM) current = 5;
775 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Yellow-Blue"));
776 if (option & PR_STEREO_ANAGLYPH_GRAY_YB) current = 6;
777 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Red-Cyan"));
778 if (option & PR_STEREO_ANAGLYPH_DB_RC) current = 7;
779 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Green-Magenta"));
780 if (option & PR_STEREO_ANAGLYPH_DB_GM) current = 8;
781 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Yellow-Blue"));
782 if (option & PR_STEREO_ANAGLYPH_DB_YB) current = 9;
784 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side"));
785 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side Half size"));
786 if (option & PR_STEREO_HORIZ)
789 if (option & PR_STEREO_HALF) current = 11;
792 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom"));
793 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom Half size"));
794 if (option & PR_STEREO_VERT)
797 if (option & PR_STEREO_HALF) current = 13;
802 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Fixed position"));
803 if (option & PR_STEREO_FIXED) current = 14;
806 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
808 g_signal_connect(G_OBJECT(combo), "changed",
809 G_CALLBACK(stereo_mode_menu_cb), option_c);
811 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
812 GTK_EXPAND | GTK_FILL, 0, 0, 0);
813 gtk_widget_show(combo);
816 static void video_menu_cb(GtkWidget *combo, gpointer data)
818 gchar **option = data;
820 EditorDescription *ed = g_list_nth_data(editor_list_get(), gtk_combo_box_get_active(GTK_COMBO_BOX(combo)));
824 static void video_menu_populate(gpointer data, gpointer user_data)
826 GtkWidget *combo = user_data;
827 EditorDescription *ed = data;
829 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), ed->name);
832 static void add_video_menu(GtkWidget *table, gint column, gint row, const gchar *text,
833 gchar *option, gchar **option_c)
837 /* use lists since they are sorted */
838 GList *eds = editor_list_get();
842 pref_table_label(table, column, row, text, 0.0);
844 combo = gtk_combo_box_text_new();
845 g_list_foreach(eds,video_menu_populate,(gpointer)combo);
846 current = option ? g_list_index(eds,g_hash_table_lookup(editors,option)): -1;
848 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
850 g_signal_connect(G_OBJECT(combo), "changed",
851 G_CALLBACK(video_menu_cb), option_c);
853 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
854 GTK_EXPAND | GTK_FILL, 0, 0, 0);
855 gtk_widget_show(combo);
858 static void filter_store_populate(void)
862 if (!filter_store) return;
864 gtk_list_store_clear(filter_store);
866 work = filter_get_list();
875 gtk_list_store_append(filter_store, &iter);
876 gtk_list_store_set(filter_store, &iter, 0, fe, -1);
880 static void filter_store_ext_edit_cb(GtkCellRendererText *cell, gchar *path_str,
881 gchar *new_text, gpointer data)
883 GtkWidget *model = data;
884 FilterEntry *fe = data;
888 if (!new_text || strlen(new_text) < 1) return;
890 tpath = gtk_tree_path_new_from_string(path_str);
891 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
892 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
894 g_free(fe->extensions);
895 fe->extensions = g_strdup(new_text);
897 gtk_tree_path_free(tpath);
901 static void filter_store_class_edit_cb(GtkCellRendererText *cell, gchar *path_str,
902 gchar *new_text, gpointer data)
904 GtkWidget *model = data;
905 FilterEntry *fe = data;
910 if (!new_text || !new_text[0]) return;
912 tpath = gtk_tree_path_new_from_string(path_str);
913 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
914 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
916 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
918 if (strcmp(new_text, _(format_class_list[i])) == 0)
925 gtk_tree_path_free(tpath);
929 static void filter_store_desc_edit_cb(GtkCellRendererText *cell, gchar *path_str,
930 gchar *new_text, gpointer data)
932 GtkWidget *model = data;
937 if (!new_text || !new_text[0]) return;
939 tpath = gtk_tree_path_new_from_string(path_str);
940 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
941 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
943 g_free(fe->description);
944 fe->description = g_strdup(new_text);
946 gtk_tree_path_free(tpath);
949 static void filter_store_enable_cb(GtkCellRendererToggle *renderer,
950 gchar *path_str, gpointer data)
952 GtkWidget *model = data;
957 tpath = gtk_tree_path_new_from_string(path_str);
958 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
959 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
961 fe->enabled = !fe->enabled;
963 gtk_tree_path_free(tpath);
967 static void filter_store_writable_cb(GtkCellRendererToggle *renderer,
968 gchar *path_str, gpointer data)
970 GtkWidget *model = data;
975 tpath = gtk_tree_path_new_from_string(path_str);
976 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
977 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
979 fe->writable = !fe->writable;
980 if (fe->writable) fe->allow_sidecar = FALSE;
982 gtk_tree_path_free(tpath);
986 static void filter_store_sidecar_cb(GtkCellRendererToggle *renderer,
987 gchar *path_str, gpointer data)
989 GtkWidget *model = data;
994 tpath = gtk_tree_path_new_from_string(path_str);
995 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
996 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
998 fe->allow_sidecar = !fe->allow_sidecar;
999 if (fe->allow_sidecar) fe->writable = FALSE;
1001 gtk_tree_path_free(tpath);
1005 static void filter_set_func(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
1006 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
1010 gtk_tree_model_get(tree_model, iter, 0, &fe, -1);
1012 switch (GPOINTER_TO_INT(data))
1015 g_object_set(GTK_CELL_RENDERER(cell),
1016 "active", fe->enabled, NULL);
1019 g_object_set(GTK_CELL_RENDERER(cell),
1020 "text", fe->extensions, NULL);
1022 case FE_DESCRIPTION:
1023 g_object_set(GTK_CELL_RENDERER(cell),
1024 "text", fe->description, NULL);
1027 g_object_set(GTK_CELL_RENDERER(cell),
1028 "text", _(format_class_list[fe->file_class]), NULL);
1031 g_object_set(GTK_CELL_RENDERER(cell),
1032 "active", fe->writable, NULL);
1034 case FE_ALLOW_SIDECAR:
1035 g_object_set(GTK_CELL_RENDERER(cell),
1036 "active", fe->allow_sidecar, NULL);
1041 static gboolean filter_add_scroll(gpointer data)
1045 GtkCellRenderer *cell;
1046 GtkTreeViewColumn *column;
1047 GList *list_columns;
1052 rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(filter_store), NULL);
1053 path = gtk_tree_path_new_from_indices(rows-1, -1);
1055 list_columns = gtk_tree_view_get_columns(GTK_TREE_VIEW(data));
1057 column = g_list_nth(list_columns,i)->data;
1058 title = gtk_tree_view_column_get_title(GTK_TREE_VIEW_COLUMN(column));
1060 } while (strcmp(title, "Filter") !=0 );
1062 list_cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column));
1063 cell = g_list_last(list_cells)->data;
1065 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1066 path, column, FALSE, 0.0, 0.0 );
1067 gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(data),
1068 path, column, cell, TRUE);
1070 gtk_tree_path_free(path);
1071 g_list_free(list_cells);
1072 g_list_free(list_columns);
1077 static void filter_add_cb(GtkWidget *widget, gpointer data)
1079 filter_add_unique("description", ".new", FORMAT_CLASS_IMAGE, TRUE, FALSE, TRUE);
1080 filter_store_populate();
1082 g_idle_add((GSourceFunc)filter_add_scroll, data);
1085 static void filter_remove_cb(GtkWidget *widget, gpointer data)
1087 GtkWidget *filter_view = data;
1088 GtkTreeSelection *selection;
1092 if (!filter_store) return;
1093 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1094 if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) return;
1095 gtk_tree_model_get(GTK_TREE_MODEL(filter_store), &iter, 0, &fe, -1);
1098 filter_remove_entry(fe);
1100 filter_store_populate();
1103 static gboolean filter_default_ok_scroll(GtkTreeView *data)
1107 GtkTreeViewColumn *column;
1109 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(filter_store), &iter);
1110 path = gtk_tree_model_get_path(GTK_TREE_MODEL(filter_store), &iter);
1111 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1113 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1117 gtk_tree_path_free(path);
1122 static void filter_default_ok_cb(GenericDialog *gd, gpointer data)
1125 filter_add_defaults();
1127 filter_store_populate();
1129 g_idle_add((GSourceFunc)filter_default_ok_scroll, gd->data);
1132 static void dummy_cancel_cb(GenericDialog *gd, gpointer data)
1134 /* no op, only so cancel button appears */
1137 static void filter_default_cb(GtkWidget *widget, gpointer data)
1141 gd = generic_dialog_new(_("Reset filters"),
1142 "reset_filter", widget, TRUE,
1143 dummy_cancel_cb, data);
1144 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset filters"),
1145 _("This will reset the file filters to the defaults.\nContinue?"), TRUE);
1146 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, filter_default_ok_cb, TRUE);
1147 gtk_widget_show(gd->dialog);
1150 static void filter_disable_cb(GtkWidget *widget, gpointer data)
1152 GtkWidget *frame = data;
1154 gtk_widget_set_sensitive(frame,
1155 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
1158 static void safe_delete_view_cb(GtkWidget *widget, gpointer data)
1160 layout_set_path(NULL, gtk_entry_get_text(GTK_ENTRY(safe_delete_path_entry)));
1163 static void safe_delete_clear_ok_cb(GenericDialog *gd, gpointer data)
1165 file_util_trash_clear();
1168 static void safe_delete_clear_cb(GtkWidget *widget, gpointer data)
1172 gd = generic_dialog_new(_("Clear trash"),
1173 "clear_trash", widget, TRUE,
1174 dummy_cancel_cb, NULL);
1175 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear trash"),
1176 _("This will remove the trash contents."), FALSE);
1177 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, safe_delete_clear_ok_cb, TRUE);
1178 entry = gtk_entry_new();
1179 gtk_widget_set_can_focus(entry, FALSE);
1180 gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE);
1181 if (options->file_ops.safe_delete_path) gtk_entry_set_text(GTK_ENTRY(entry), options->file_ops.safe_delete_path);
1182 gtk_box_pack_start(GTK_BOX(gd->vbox), entry, FALSE, FALSE, 0);
1183 gtk_widget_show(entry);
1184 gtk_widget_show(gd->dialog);
1187 static void image_overlay_template_view_changed_cb(GtkWidget *widget, gpointer data)
1189 GtkWidget *pTextView;
1190 GtkTextBuffer *pTextBuffer;
1194 pTextView = GTK_WIDGET(data);
1196 pTextBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pTextView));
1197 gtk_text_buffer_get_start_iter(pTextBuffer, &iStart);
1198 gtk_text_buffer_get_end_iter(pTextBuffer, &iEnd);
1200 set_image_overlay_template_string(&c_options->image_overlay.template_string,
1201 gtk_text_buffer_get_text(pTextBuffer, &iStart, &iEnd, TRUE));
1204 static void image_overlay_default_template_ok_cb(GenericDialog *gd, gpointer data)
1206 GtkTextView *text_view = data;
1207 GtkTextBuffer *buffer;
1209 set_default_image_overlay_template_string(&options->image_overlay.template_string);
1210 if (!configwindow) return;
1212 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
1213 gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1216 static void image_overlay_default_template_cb(GtkWidget *widget, gpointer data)
1220 gd = generic_dialog_new(_("Reset image overlay template string"),
1221 "reset_image_overlay_template_string", widget, TRUE,
1222 dummy_cancel_cb, data);
1223 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset image overlay template string"),
1224 _("This will reset the image overlay template string to the default.\nContinue?"), TRUE);
1225 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, image_overlay_default_template_ok_cb, TRUE);
1226 gtk_widget_show(gd->dialog);
1229 static void image_overlay_help_cb(GtkWidget *widget, gpointer data)
1231 help_window_show("GuideOptionsWindow.html#OverlayScreenDisplay");
1234 static void image_overlay_set_font_cb(GtkWidget *widget, gpointer data)
1236 #if GTK_CHECK_VERSION(3,4,0)
1239 PangoFontDescription *font_desc;
1241 dialog = gtk_font_chooser_dialog_new("Image Overlay Font", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1242 gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), options->image_overlay.font);
1244 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1246 font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
1247 font = pango_font_description_to_string(font_desc);
1248 g_free(c_options->image_overlay.font);
1249 c_options->image_overlay.font = g_strdup(font);
1253 gtk_widget_destroy(dialog);
1257 font = gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget));
1258 c_options->image_overlay.font = g_strdup(font);
1262 static void image_overlay_set_text_colour_cb(GtkWidget *widget, gpointer data)
1265 #if GTK_CHECK_VERSION(3,4,0)
1268 dialog = gtk_color_chooser_dialog_new("Image Overlay Text Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1269 colour.red = options->image_overlay.text_red;
1270 colour.green = options->image_overlay.text_green;
1271 colour.blue = options->image_overlay.text_blue;
1272 colour.alpha = options->image_overlay.text_alpha;
1273 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1274 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1276 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1278 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1279 c_options->image_overlay.text_red = colour.red*255;
1280 c_options->image_overlay.text_green = colour.green*255;
1281 c_options->image_overlay.text_blue = colour.blue*255;
1282 c_options->image_overlay.text_alpha = colour.alpha*255;
1284 gtk_widget_destroy(dialog);
1287 GtkColorSelection *colorsel;
1289 dialog = gtk_color_selection_dialog_new("Image Overlay Text Colour");
1290 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1291 colour.red = options->image_overlay.text_red*257;
1292 colour.green = options->image_overlay.text_green*257;
1293 colour.blue = options->image_overlay.text_blue*257;
1294 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1295 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1296 gtk_color_selection_set_current_color(colorsel, &colour);
1297 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.text_alpha*257);
1299 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1301 gtk_color_selection_get_current_color(colorsel, &colour);
1302 c_options->image_overlay.text_red = colour.red/257;
1303 c_options->image_overlay.text_green = colour.green/257;
1304 c_options->image_overlay.text_blue = colour.blue/257;
1305 c_options->image_overlay.text_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1307 gtk_widget_destroy (dialog);
1312 static void image_overlay_set_background_colour_cb(GtkWidget *widget, gpointer data)
1315 #if GTK_CHECK_VERSION(3,4,0)
1318 dialog = gtk_color_chooser_dialog_new("Image Overlay Background Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1319 colour.red = options->image_overlay.background_red;
1320 colour.green = options->image_overlay.background_green;
1321 colour.blue = options->image_overlay.background_blue;
1322 colour.alpha = options->image_overlay.background_alpha;
1323 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1324 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1326 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1328 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1329 c_options->image_overlay.background_red = colour.red*255;
1330 c_options->image_overlay.background_green = colour.green*255;
1331 c_options->image_overlay.background_blue = colour.blue*255;
1332 c_options->image_overlay.background_alpha = colour.alpha*255;
1334 gtk_widget_destroy(dialog);
1337 GtkColorSelection *colorsel;
1339 dialog = gtk_color_selection_dialog_new("Image Overlay Background Colour");
1340 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1341 colour.red = options->image_overlay.background_red*257;
1342 colour.green = options->image_overlay.background_green*257;
1343 colour.blue = options->image_overlay.background_blue*257;
1344 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1345 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1346 gtk_color_selection_set_current_color(colorsel, &colour);
1347 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.background_alpha*257);
1349 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1351 gtk_color_selection_get_current_color(colorsel, &colour);
1352 c_options->image_overlay.background_red = colour.red/257;
1353 c_options->image_overlay.background_green = colour.green/257;
1354 c_options->image_overlay.background_blue = colour.blue/257;
1355 c_options->image_overlay.background_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1357 gtk_widget_destroy(dialog);
1361 static void accel_store_populate(void)
1364 GList *groups, *actions;
1366 const gchar *accel_path;
1370 if (!accel_store || !layout_window_list || !layout_window_list->data) return;
1372 gtk_tree_store_clear(accel_store);
1373 lw = layout_window_list->data; /* get the actions from the first window, it should not matter, they should be the same in all windows */
1375 g_assert(lw && lw->ui_manager);
1376 groups = gtk_ui_manager_get_action_groups(lw->ui_manager);
1379 actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
1382 action = GTK_ACTION(actions->data);
1383 accel_path = gtk_action_get_accel_path(action);
1384 if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
1386 gchar *label, *label2, *tooltip, *accel;
1387 g_object_get(action,
1388 "tooltip", &tooltip,
1392 if (pango_parse_markup(label, -1, '_', NULL, &label2, NULL, NULL) && label2)
1398 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1402 gtk_tree_store_append(accel_store, &iter, NULL);
1403 gtk_tree_store_set(accel_store, &iter,
1406 AE_TOOLTIP, tooltip ? tooltip : "",
1407 AE_ACCEL, accel_path,
1415 actions = actions->next;
1418 groups = groups->next;
1422 static void accel_store_cleared_cb(GtkCellRendererAccel *accel, gchar *path_string, gpointer user_data)
1427 static gboolean accel_remove_key_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1429 gchar *accel1 = data;
1434 gtk_tree_model_get(model, iter, AE_KEY, &accel2, -1);
1436 gtk_accelerator_parse(accel1, &key1.accel_key, &key1.accel_mods);
1437 gtk_accelerator_parse(accel2, &key2.accel_key, &key2.accel_mods);
1439 if (key1.accel_key == key2.accel_key && key1.accel_mods == key2.accel_mods)
1441 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1442 DEBUG_1("accelerator key '%s' is already used, removing.", accel1);
1451 static void accel_store_edited_cb(GtkCellRendererAccel *accel, gchar *path_string, guint accel_key, GdkModifierType accel_mods, guint hardware_keycode, gpointer user_data)
1453 GtkTreeModel *model = (GtkTreeModel *)accel_store;
1457 GtkAccelKey old_key, key;
1458 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
1460 gtk_tree_model_get_iter(model, &iter, path);
1461 gtk_tree_model_get(model, &iter, AE_ACCEL, &accel_path, -1);
1463 /* test if the accelerator can be stored without conflicts*/
1464 gtk_accel_map_lookup_entry(accel_path, &old_key);
1466 /* change the key and read it back (change may fail on keys hardcoded in gtk)*/
1467 gtk_accel_map_change_entry(accel_path, accel_key, accel_mods, TRUE);
1468 gtk_accel_map_lookup_entry(accel_path, &key);
1470 /* restore the original for now, the key will be really changed when the changes are confirmed */
1471 gtk_accel_map_change_entry(accel_path, old_key.accel_key, old_key.accel_mods, TRUE);
1473 acc = gtk_accelerator_name(key.accel_key, key.accel_mods);
1474 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, acc);
1476 gtk_tree_store_set(accel_store, &iter, AE_KEY, acc, -1);
1477 gtk_tree_path_free(path);
1481 static gboolean accel_default_scroll(GtkTreeView *data)
1485 GtkTreeViewColumn *column;
1487 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(accel_store), &iter);
1488 path = gtk_tree_model_get_path(GTK_TREE_MODEL(accel_store), &iter);
1489 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1491 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1495 gtk_tree_path_free(path);
1500 static void accel_default_cb(GtkWidget *widget, gpointer data)
1502 accel_store_populate();
1504 g_idle_add((GSourceFunc)accel_default_scroll, data);
1507 void accel_remove_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1509 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1512 void accel_reset_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1515 gchar *accel_path, *accel;
1517 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, -1);
1518 gtk_accel_map_lookup_entry(accel_path, &key);
1519 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1521 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, accel);
1523 gtk_tree_store_set(accel_store, iter, AE_KEY, accel, -1);
1528 static void accel_reset_cb(GtkWidget *widget, gpointer data)
1530 GtkTreeSelection *selection;
1532 if (!accel_store) return;
1533 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data));
1534 gtk_tree_selection_selected_foreach(selection, &accel_reset_selection, NULL);
1539 static GtkWidget *scrolled_notebook_page(GtkWidget *notebook, const gchar *title)
1543 GtkWidget *scrolled;
1544 GtkWidget *viewport;
1546 scrolled = gtk_scrolled_window_new(NULL, NULL);
1547 gtk_container_set_border_width(GTK_CONTAINER(scrolled), PREF_PAD_BORDER);
1548 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1549 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1550 label = gtk_label_new(title);
1551 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, label);
1552 gtk_widget_show(scrolled);
1554 viewport = gtk_viewport_new(NULL, NULL);
1555 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1556 gtk_container_add(GTK_CONTAINER(scrolled), viewport);
1557 gtk_widget_show(viewport);
1559 vbox = gtk_vbox_new(FALSE, 0);
1560 gtk_container_add(GTK_CONTAINER(viewport), vbox);
1561 gtk_widget_show(vbox);
1566 static void cache_standard_cb(GtkWidget *widget, gpointer data)
1568 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1570 c_options->thumbnails.spec_standard =TRUE;
1571 c_options->thumbnails.cache_into_dirs = FALSE;
1575 static void cache_geeqie_cb(GtkWidget *widget, gpointer data)
1577 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1579 c_options->thumbnails.spec_standard =FALSE;
1580 c_options->thumbnails.cache_into_dirs = FALSE;
1584 static void cache_local_cb(GtkWidget *widget, gpointer data)
1586 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1588 c_options->thumbnails.cache_into_dirs = TRUE;
1589 c_options->thumbnails.spec_standard =FALSE;
1593 static void help_search_engine_entry_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1594 GdkEvent *event, gpointer userdata)
1596 if (pos == GTK_ENTRY_ICON_PRIMARY)
1598 gtk_entry_set_text(GTK_ENTRY(userdata), HELP_SEARCH_ENGINE);
1602 gtk_entry_set_text(GTK_ENTRY(userdata), "");
1606 static void star_rating_star_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1607 GdkEvent *event, gpointer userdata)
1609 gchar *rating_symbol;
1611 if (pos == GTK_ENTRY_ICON_PRIMARY)
1613 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_STAR);
1614 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1615 g_free(rating_symbol);
1619 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1620 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1621 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1625 static void star_rating_rejected_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1626 GdkEvent *event, gpointer userdata)
1628 gchar *rating_symbol;
1630 if (pos == GTK_ENTRY_ICON_PRIMARY)
1632 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_REJECTED);
1633 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1634 g_free(rating_symbol);
1638 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1639 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1640 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1644 static guint star_rating_symbol_test(GtkWidget *widget, gpointer data)
1646 GtkContainer *hbox = data;
1647 GString *str = g_string_new(NULL);
1648 GtkEntry *hex_code_entry;
1649 gchar *hex_code_full;
1652 guint64 hex_value = 0;
1654 list = gtk_container_get_children(hbox);
1656 hex_code_entry = g_list_nth_data(list, 2);
1657 hex_code_full = g_strdup(gtk_entry_get_text(hex_code_entry));
1659 hex_code = g_strsplit(hex_code_full, "+", 2);
1660 if (hex_code[0] && hex_code[1])
1662 hex_value = strtoull(hex_code[1], NULL, 16);
1664 if (!hex_value || hex_value > 0x10FFFF)
1666 hex_value = 0x003F; // Unicode 'Question Mark'
1668 str = g_string_append_unichar(str, (gunichar)hex_value);
1669 gtk_label_set_text(g_list_nth_data(list, 1), str->str);
1671 g_strfreev(hex_code);
1672 g_string_free(str, TRUE);
1673 g_free(hex_code_full);
1678 static void star_rating_star_test_cb(GtkWidget *widget, gpointer data)
1680 guint64 star_symbol;
1682 star_symbol = star_rating_symbol_test(widget, data);
1683 c_options->star_rating.star = star_symbol;
1686 static void star_rating_rejected_test_cb(GtkWidget *widget, gpointer data)
1688 guint64 rejected_symbol;
1690 rejected_symbol = star_rating_symbol_test(widget, data);
1691 c_options->star_rating.rejected = rejected_symbol;
1694 /* general options tab */
1695 static void config_tab_general(GtkWidget *notebook)
1700 GtkWidget *group_frame;
1701 GtkWidget *subgroup;
1703 GtkWidget *ct_button;
1706 gint hours, minutes, remainder;
1708 GtkWidget *star_rating_entry;
1710 gchar *rating_symbol;
1712 vbox = scrolled_notebook_page(notebook, _("General"));
1714 group = pref_group_new(vbox, FALSE, _("Thumbnails"), GTK_ORIENTATION_VERTICAL);
1716 table = pref_table_new(group, 2, 2, FALSE, FALSE);
1717 add_thumb_size_menu(table, 0, 0, _("Size:"));
1718 add_quality_menu(table, 0, 1, _("Quality:"), options->thumbnails.quality, &c_options->thumbnails.quality);
1720 ct_button = pref_checkbox_new_int(group, _("Cache thumbnails"),
1721 options->thumbnails.enable_caching, &c_options->thumbnails.enable_caching);
1723 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1724 pref_checkbox_link_sensitivity(ct_button, subgroup);
1726 c_options->thumbnails.spec_standard = options->thumbnails.spec_standard;
1727 c_options->thumbnails.cache_into_dirs = options->thumbnails.cache_into_dirs;
1728 group_frame = pref_frame_new(subgroup, TRUE, _("Use Geeqie thumbnail style and cache"),
1729 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1730 button = pref_radiobutton_new(group_frame, NULL, get_thumbnails_cache_dir(),
1731 !options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1732 G_CALLBACK(cache_geeqie_cb), NULL);
1734 group_frame = pref_frame_new(subgroup, TRUE,
1735 _("Store thumbnails local to image folder (non-standard)"),
1736 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1737 pref_radiobutton_new(group_frame, button, "*/.thumbnails",
1738 !options->thumbnails.spec_standard && options->thumbnails.cache_into_dirs,
1739 G_CALLBACK(cache_local_cb), NULL);
1741 group_frame = pref_frame_new(subgroup, TRUE,
1742 _("Use standard thumbnail style and cache, shared with other applications"),
1743 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1744 pref_radiobutton_new(group_frame, button, get_thumbnails_standard_cache_dir(),
1745 options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1746 G_CALLBACK(cache_standard_cb), NULL);
1748 pref_checkbox_new_int(group, _("Use EXIF thumbnails when available (EXIF thumbnails may be outdated)"),
1749 options->thumbnails.use_exif, &c_options->thumbnails.use_exif);
1751 spin = pref_spin_new_int(group, _("Collection preview:"), NULL,
1753 options->thumbnails.collection_preview, &c_options->thumbnails.collection_preview);
1754 gtk_widget_set_tooltip_text(spin, _("The maximum number of thumbnails shown in a Collection preview montage"));
1756 #ifdef HAVE_FFMPEGTHUMBNAILER_METADATA
1757 pref_checkbox_new_int(group, _("Use embedded metadata in video files as thumbnails when available"),
1758 options->thumbnails.use_ft_metadata, &c_options->thumbnails.use_ft_metadata);
1760 // pref_checkbox_new_int(group, _("Ignore embedded metadata if size is too small"),
1761 // options->thumbnails.use_ft_metadata_small, &c_options->thumbnails.use_ft_metadata_small);
1764 group = pref_group_new(vbox, FALSE, _("Star Rating"), GTK_ORIENTATION_VERTICAL);
1766 c_options->star_rating.star = options->star_rating.star;
1767 c_options->star_rating.rejected = options->star_rating.rejected;
1769 str = g_string_new(NULL);
1770 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1771 pref_label_new(hbox, "Star character: ");
1772 str = g_string_append_unichar(str, options->star_rating.star);
1773 pref_label_new(hbox, g_strdup(str->str));
1774 rating_symbol = g_strdup_printf("U+%X", options->star_rating.star);
1775 star_rating_entry = gtk_entry_new();
1776 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
1777 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
1778 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
1779 gtk_widget_show(star_rating_entry);
1780 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
1781 G_CALLBACK(star_rating_star_test_cb), hbox);
1782 gtk_widget_set_tooltip_text(button, _("Display selected character"));
1783 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1784 gtk_widget_show(button);
1785 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."));
1786 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1787 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
1788 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1789 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
1790 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1791 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
1792 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1793 GTK_ENTRY_ICON_PRIMARY, _("Default"));
1794 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
1795 G_CALLBACK(star_rating_star_icon_cb),
1798 g_string_free(str, TRUE);
1799 g_free(rating_symbol);
1801 str = g_string_new(NULL);
1802 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1803 pref_label_new(hbox, "Rejected character: ");
1804 str = g_string_append_unichar(str, options->star_rating.rejected);
1805 pref_label_new(hbox, g_strdup(str->str));
1806 rating_symbol = g_strdup_printf("U+%X", options->star_rating.rejected);
1807 star_rating_entry = gtk_entry_new();
1808 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
1809 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
1810 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
1811 gtk_widget_show(star_rating_entry);
1812 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
1813 G_CALLBACK(star_rating_rejected_test_cb), hbox);
1814 gtk_widget_set_tooltip_text(button, _("Display selected character"));
1815 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1816 gtk_widget_show(button);
1817 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."));
1818 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1819 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
1820 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1821 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
1822 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1823 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
1824 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1825 GTK_ENTRY_ICON_PRIMARY, _("Default"));
1826 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
1827 G_CALLBACK(star_rating_rejected_icon_cb),
1830 g_string_free(str, TRUE);
1831 g_free(rating_symbol);
1833 group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
1835 c_options->slideshow.delay = options->slideshow.delay;
1836 hours = options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
1837 remainder = options->slideshow.delay % (3600 * SLIDESHOW_SUBSECOND_PRECISION);
1838 minutes = remainder / (60 * SLIDESHOW_SUBSECOND_PRECISION);
1839 seconds = (gdouble)(remainder % (60 * SLIDESHOW_SUBSECOND_PRECISION)) /
1840 SLIDESHOW_SUBSECOND_PRECISION;
1842 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1844 spin = pref_spin_new(hbox, _("Delay between image change hrs:mins:secs.dec"), NULL,
1846 options->slideshow.delay ? hours : 0.0,
1847 G_CALLBACK(slideshow_delay_hours_cb), NULL);
1848 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1849 spin = pref_spin_new(hbox, ":" , NULL,
1851 options->slideshow.delay ? minutes: 0.0,
1852 G_CALLBACK(slideshow_delay_minutes_cb), NULL);
1853 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1854 spin = pref_spin_new(hbox, ":", NULL,
1855 SLIDESHOW_MIN_SECONDS, 59, 1.0, 1,
1856 options->slideshow.delay ? seconds : 10.0,
1857 G_CALLBACK(slideshow_delay_seconds_cb), NULL);
1858 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1860 pref_checkbox_new_int(group, _("Random"), options->slideshow.random, &c_options->slideshow.random);
1861 pref_checkbox_new_int(group, _("Repeat"), options->slideshow.repeat, &c_options->slideshow.repeat);
1863 group = pref_group_new(vbox, FALSE, _("Image loading and caching"), GTK_ORIENTATION_VERTICAL);
1865 pref_spin_new_int(group, _("Decoded image cache size (Mb):"), NULL,
1866 0, 99999, 1, options->image.image_cache_max, &c_options->image.image_cache_max);
1867 pref_checkbox_new_int(group, _("Preload next image"),
1868 options->image.enable_read_ahead, &c_options->image.enable_read_ahead);
1870 pref_checkbox_new_int(group, _("Refresh on file change"),
1871 options->update_on_time_change, &c_options->update_on_time_change);
1873 group = pref_group_new(vbox, FALSE, _("Info sidebar heights"), GTK_ORIENTATION_VERTICAL);
1874 pref_label_new(group, _("NOTE! Geeqie must be restarted for changes to take effect"));
1875 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1876 pref_spin_new_int(hbox, _("Keywords:"), NULL,
1878 options->info_keywords.height, &c_options->info_keywords.height);
1879 pref_spin_new_int(hbox, _("Title:"), NULL,
1881 options->info_title.height, &c_options->info_title.height);
1882 pref_spin_new_int(hbox, _("Comment:"), NULL,
1884 options->info_comment.height, &c_options->info_comment.height);
1885 pref_spin_new_int(hbox, _("Rating:"), NULL,
1887 options->info_rating.height, &c_options->info_rating.height);
1889 group = pref_group_new(vbox, FALSE, _("On-line help search engine"), GTK_ORIENTATION_VERTICAL);
1891 help_search_engine_entry = gtk_entry_new();
1892 gtk_entry_set_text(GTK_ENTRY(help_search_engine_entry), options->help_search_engine);
1893 gtk_box_pack_start(GTK_BOX(group), help_search_engine_entry, FALSE, FALSE, 0);
1894 gtk_widget_show(help_search_engine_entry);
1896 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"));
1898 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
1899 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
1900 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
1901 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
1902 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
1903 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
1904 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
1905 GTK_ENTRY_ICON_PRIMARY, _("Default"));
1906 g_signal_connect(GTK_ENTRY(help_search_engine_entry), "icon-press",
1907 G_CALLBACK(help_search_engine_entry_icon_cb),
1908 help_search_engine_entry);
1912 static void config_tab_image(GtkWidget *notebook)
1917 GtkWidget *ct_button;
1918 GtkWidget *enlargement_button;
1922 vbox = scrolled_notebook_page(notebook, _("Image"));
1924 group = pref_group_new(vbox, FALSE, _("Zoom"), GTK_ORIENTATION_VERTICAL);
1926 table = pref_table_new(group, 2, 1, FALSE, FALSE);
1927 add_quality_menu(table, 0, 0, _("Quality:"), options->image.zoom_quality, &c_options->image.zoom_quality);
1930 pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library"),
1931 options->image.use_clutter_renderer, &c_options->image.use_clutter_renderer);
1934 pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"),
1935 options->image.zoom_2pass, &c_options->image.zoom_2pass);
1937 c_options->image.zoom_increment = options->image.zoom_increment;
1938 spin = pref_spin_new(group, _("Zoom increment:"), NULL,
1939 0.01, 4.0, 0.01, 2, (gdouble)options->image.zoom_increment / 100.0,
1940 G_CALLBACK(zoom_increment_cb), NULL);
1941 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1943 group = pref_group_new(vbox, FALSE, _("Fit image to window"), GTK_ORIENTATION_VERTICAL);
1945 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1946 enlargement_button = pref_checkbox_new_int(hbox, _("Allow enlargement of image (max. size in %)"),
1947 options->image.zoom_to_fit_allow_expand, &c_options->image.zoom_to_fit_allow_expand);
1948 spin = pref_spin_new_int(hbox, NULL, NULL,
1950 options->image.max_enlargement_size, &c_options->image.max_enlargement_size);
1951 pref_checkbox_link_sensitivity(enlargement_button, spin);
1952 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."));
1954 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1955 ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (% of actual window):"),
1956 options->image.limit_autofit_size, &c_options->image.limit_autofit_size);
1957 spin = pref_spin_new_int(hbox, NULL, NULL,
1959 options->image.max_autofit_size, &c_options->image.max_autofit_size);
1960 pref_checkbox_link_sensitivity(ct_button, spin);
1961 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."));
1963 group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
1965 pref_checkbox_new_int(group, _("Use custom border color in window mode"),
1966 options->image.use_custom_border_color, &c_options->image.use_custom_border_color);
1968 pref_checkbox_new_int(group, _("Use custom border color in fullscreen mode"),
1969 options->image.use_custom_border_color_in_fullscreen, &c_options->image.use_custom_border_color_in_fullscreen);
1971 pref_color_button_new(group, _("Border color"), &options->image.border_color,
1972 G_CALLBACK(pref_color_button_set_cb), &c_options->image.border_color);
1974 c_options->image.border_color = options->image.border_color;
1976 pref_color_button_new(group, _("Alpha channel color 1"), &options->image.alpha_color_1,
1977 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_1);
1979 pref_color_button_new(group, _("Alpha channel color 2"), &options->image.alpha_color_2,
1980 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_2);
1982 c_options->image.alpha_color_1 = options->image.alpha_color_1;
1983 c_options->image.alpha_color_2 = options->image.alpha_color_2;
1985 group = pref_group_new(vbox, FALSE, _("Convenience"), GTK_ORIENTATION_VERTICAL);
1987 pref_checkbox_new_int(group, _("Auto rotate proofs using Exif information"),
1988 options->image.exif_proof_rotate_enable, &c_options->image.exif_proof_rotate_enable);
1992 static void config_tab_windows(GtkWidget *notebook)
1998 GtkWidget *ct_button;
2000 GtkWidget *image_overlay_template_view;
2001 GtkWidget *scrolled;
2002 GtkTextBuffer *buffer;
2004 vbox = scrolled_notebook_page(notebook, _("Windows"));
2006 group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
2008 ct_button = pref_checkbox_new_int(group, _("Remember window positions"),
2009 options->save_window_positions, &c_options->save_window_positions);
2011 button = pref_checkbox_new_int(group, _("Use saved window positions also for new windows"),
2012 options->use_saved_window_positions_for_new_windows, &c_options->use_saved_window_positions_for_new_windows);
2013 pref_checkbox_link_sensitivity(ct_button, button);
2015 pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
2016 options->tools_restore_state, &c_options->tools_restore_state);
2018 pref_checkbox_new_int(group, _("Remember dialog window positions"),
2019 options->save_dialog_window_positions, &c_options->save_dialog_window_positions);
2021 pref_checkbox_new_int(group, _("Show window IDs"),
2022 options->show_window_ids, &c_options->show_window_ids);
2024 group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
2026 pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
2027 options->image.fit_window_to_image, &c_options->image.fit_window_to_image);
2029 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2030 ct_button = pref_checkbox_new_int(hbox, _("Limit size when auto-sizing window (%):"),
2031 options->image.limit_window_size, &c_options->image.limit_window_size);
2032 spin = pref_spin_new_int(hbox, NULL, NULL,
2034 options->image.max_window_size, &c_options->image.max_window_size);
2035 pref_checkbox_link_sensitivity(ct_button, spin);
2037 group = pref_group_new(vbox, FALSE, _("Full screen"), GTK_ORIENTATION_VERTICAL);
2039 c_options->fullscreen.screen = options->fullscreen.screen;
2040 c_options->fullscreen.above = options->fullscreen.above;
2041 hbox = fullscreen_prefs_selection_new(_("Location:"), &c_options->fullscreen.screen, &c_options->fullscreen.above);
2042 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2043 gtk_widget_show(hbox);
2045 pref_checkbox_new_int(group, _("Smooth image flip"),
2046 options->fullscreen.clean_flip, &c_options->fullscreen.clean_flip);
2047 pref_checkbox_new_int(group, _("Disable screen saver"),
2048 options->fullscreen.disable_saver, &c_options->fullscreen.disable_saver);
2051 group = pref_group_new(vbox, FALSE, _("Overlay Screen Display"), GTK_ORIENTATION_VERTICAL);
2053 pref_label_new(group, _("Image overlay template"));
2055 scrolled = gtk_scrolled_window_new(NULL, NULL);
2056 gtk_widget_set_size_request(scrolled, 200, 150);
2057 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2058 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
2059 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2060 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 5);
2061 gtk_widget_show(scrolled);
2063 image_overlay_template_view = gtk_text_view_new();
2065 gtk_widget_set_tooltip_markup(image_overlay_template_view,
2066 _("<i>%name%</i> results in the filename of the picture.\n"
2067 "Also available: <i>%collection%</i>, <i>%number%</i>, <i>%total%</i>, <i>%date%</i>,\n"
2068 "<i>%size%</i> (filesize), <i>%width%</i>, <i>%height%</i>, <i>%res%</i> (resolution),\n"
2069 "<i>%rating%</i>, <i>%keywords%</i>, <i>%comment%</i> (XMP), <i>%imagecomment%</i> (JPEG)\n"
2070 "To access exif data use the exif name, e. g. <i>%formatted.Camera%</i> is the formatted camera name,\n"
2071 "<i>%Exif.Photo.DateTimeOriginal%</i> the date of the original shot.\n"
2072 "<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"
2073 "If two or more variables are connected with the |-sign, it prints available variables with a separator.\n"
2074 "<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"
2075 "if there's no ISO information in the Exif data.\n"
2076 "If a line is empty, it is removed. This allows one to add lines that totally disappear when no data is available.\n"
2078 gtk_container_add(GTK_CONTAINER(scrolled), image_overlay_template_view);
2079 gtk_widget_show(image_overlay_template_view);
2081 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2083 #if GTK_CHECK_VERSION(3,4,0)
2084 button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
2085 G_CALLBACK(image_overlay_set_font_cb), notebook);
2087 button = gtk_font_button_new();
2088 gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Image Overlay Font");
2089 gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->image_overlay.font);
2090 g_signal_connect(G_OBJECT(button), "font-set",
2091 G_CALLBACK(image_overlay_set_font_cb),NULL);
2093 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2094 gtk_widget_show(button);
2096 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Text"), FALSE,
2097 G_CALLBACK(image_overlay_set_text_colour_cb), NULL);
2098 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2099 gtk_widget_show(button);
2101 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Background"), FALSE,
2102 G_CALLBACK(image_overlay_set_background_colour_cb), NULL);
2103 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2104 gtk_widget_show(button);
2105 image_overlay_set_text_colours();
2107 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2108 G_CALLBACK(image_overlay_default_template_cb), image_overlay_template_view);
2109 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2110 gtk_widget_show(button);
2112 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
2113 G_CALLBACK(image_overlay_help_cb), NULL);
2114 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2115 gtk_widget_show(button);
2117 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_overlay_template_view));
2118 if (options->image_overlay.template_string) gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
2119 g_signal_connect(G_OBJECT(buffer), "changed",
2120 G_CALLBACK(image_overlay_template_view_changed_cb), image_overlay_template_view);
2125 static GtkTreeModel *create_class_model(void)
2127 GtkListStore *model;
2131 /* create list store */
2132 model = gtk_list_store_new(1, G_TYPE_STRING);
2133 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
2135 gtk_list_store_append(model, &iter);
2136 gtk_list_store_set(model, &iter, 0, _(format_class_list[i]), -1);
2138 return GTK_TREE_MODEL (model);
2143 static void config_tab_files(GtkWidget *notebook)
2150 GtkWidget *ct_button;
2151 GtkWidget *scrolled;
2152 GtkWidget *filter_view;
2153 GtkCellRenderer *renderer;
2154 GtkTreeSelection *selection;
2155 GtkTreeViewColumn *column;
2157 vbox = scrolled_notebook_page(notebook, _("Files"));
2159 group = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2161 pref_checkbox_new_int(group, _("Show hidden files or folders"),
2162 options->file_filter.show_hidden_files, &c_options->file_filter.show_hidden_files);
2163 pref_checkbox_new_int(group, _("Show parent folder (..)"),
2164 options->file_filter.show_parent_directory, &c_options->file_filter.show_parent_directory);
2165 pref_checkbox_new_int(group, _("Case sensitive sort"),
2166 options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
2167 pref_checkbox_new_int(group, _("Natural sort order"),
2168 options->file_sort.natural, &c_options->file_sort.natural);
2169 pref_checkbox_new_int(group, _("Disable file extension checks"),
2170 options->file_filter.disable_file_extension_checks, &c_options->file_filter.disable_file_extension_checks);
2172 ct_button = pref_checkbox_new_int(group, _("Disable File Filtering"),
2173 options->file_filter.disable, &c_options->file_filter.disable);
2176 group = pref_group_new(vbox, FALSE, _("Grouping sidecar extensions"), GTK_ORIENTATION_VERTICAL);
2178 sidecar_ext_entry = gtk_entry_new();
2179 gtk_entry_set_text(GTK_ENTRY(sidecar_ext_entry), options->sidecar.ext);
2180 gtk_box_pack_start(GTK_BOX(group), sidecar_ext_entry, FALSE, FALSE, 0);
2181 gtk_widget_show(sidecar_ext_entry);
2183 group = pref_group_new(vbox, TRUE, _("File types"), GTK_ORIENTATION_VERTICAL);
2185 frame = pref_group_parent(group);
2186 g_signal_connect(G_OBJECT(ct_button), "toggled",
2187 G_CALLBACK(filter_disable_cb), frame);
2188 gtk_widget_set_sensitive(frame, !options->file_filter.disable);
2190 scrolled = gtk_scrolled_window_new(NULL, NULL);
2191 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2192 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2193 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2194 gtk_widget_show(scrolled);
2196 filter_store = gtk_list_store_new(1, G_TYPE_POINTER);
2197 filter_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(filter_store));
2198 g_object_unref(filter_store);
2199 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
2200 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
2202 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), FALSE);
2204 column = gtk_tree_view_column_new();
2205 gtk_tree_view_column_set_title(column, _("Filter"));
2206 gtk_tree_view_column_set_resizable(column, TRUE);
2208 renderer = gtk_cell_renderer_toggle_new();
2209 g_signal_connect(G_OBJECT(renderer), "toggled",
2210 G_CALLBACK(filter_store_enable_cb), filter_store);
2211 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2212 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2213 GINT_TO_POINTER(FE_ENABLE), NULL);
2215 renderer = gtk_cell_renderer_text_new();
2216 g_signal_connect(G_OBJECT(renderer), "edited",
2217 G_CALLBACK(filter_store_ext_edit_cb), filter_store);
2218 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2219 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2220 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2221 GINT_TO_POINTER(FE_EXTENSION), NULL);
2222 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2224 column = gtk_tree_view_column_new();
2225 gtk_tree_view_column_set_title(column, _("Description"));
2226 gtk_tree_view_column_set_resizable(column, TRUE);
2227 gtk_tree_view_column_set_fixed_width(column, 200);
2228 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
2230 renderer = gtk_cell_renderer_text_new();
2231 g_signal_connect(G_OBJECT(renderer), "edited",
2232 G_CALLBACK(filter_store_desc_edit_cb), filter_store);
2233 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2234 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2235 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2236 GINT_TO_POINTER(FE_DESCRIPTION), NULL);
2237 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2239 column = gtk_tree_view_column_new();
2240 gtk_tree_view_column_set_title(column, _("Class"));
2241 gtk_tree_view_column_set_resizable(column, TRUE);
2242 renderer = gtk_cell_renderer_combo_new();
2243 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE,
2244 "model", create_class_model(),
2249 g_signal_connect(G_OBJECT(renderer), "edited",
2250 G_CALLBACK(filter_store_class_edit_cb), filter_store);
2251 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2252 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2253 GINT_TO_POINTER(FE_CLASS), NULL);
2254 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2256 column = gtk_tree_view_column_new();
2257 gtk_tree_view_column_set_title(column, _("Writable"));
2258 gtk_tree_view_column_set_resizable(column, FALSE);
2259 renderer = gtk_cell_renderer_toggle_new();
2260 g_signal_connect(G_OBJECT(renderer), "toggled",
2261 G_CALLBACK(filter_store_writable_cb), filter_store);
2262 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2263 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2264 GINT_TO_POINTER(FE_WRITABLE), NULL);
2265 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2267 column = gtk_tree_view_column_new();
2268 gtk_tree_view_column_set_title(column, _("Sidecar is allowed"));
2269 gtk_tree_view_column_set_resizable(column, FALSE);
2270 renderer = gtk_cell_renderer_toggle_new();
2271 g_signal_connect(G_OBJECT(renderer), "toggled",
2272 G_CALLBACK(filter_store_sidecar_cb), filter_store);
2273 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2274 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2275 GINT_TO_POINTER(FE_ALLOW_SIDECAR), NULL);
2276 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2279 filter_store_populate();
2280 gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
2281 gtk_widget_show(filter_view);
2283 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2285 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2286 G_CALLBACK(filter_default_cb), filter_view);
2287 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2288 gtk_widget_show(button);
2290 button = pref_button_new(NULL, GTK_STOCK_REMOVE, NULL, FALSE,
2291 G_CALLBACK(filter_remove_cb), filter_view);
2292 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2293 gtk_widget_show(button);
2295 button = pref_button_new(NULL, GTK_STOCK_ADD, NULL, FALSE,
2296 G_CALLBACK(filter_add_cb), filter_view);
2297 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2298 gtk_widget_show(button);
2302 static void config_tab_metadata(GtkWidget *notebook)
2307 GtkWidget *ct_button;
2311 vbox = scrolled_notebook_page(notebook, _("Metadata"));
2314 group = pref_group_new(vbox, FALSE, _("Metadata writing process"), GTK_ORIENTATION_VERTICAL);
2316 label = pref_label_new(group, _("Warning: Geeqie is built without Exiv2. Some options are disabled."));
2318 label = pref_label_new(group, _("Metadata are written in the following order. The process ends after first success."));
2319 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2321 ct_button = pref_checkbox_new_int(group, _("1) Save metadata in image files, or sidecar files, according to the XMP standard"),
2322 options->metadata.save_in_image_file, &c_options->metadata.save_in_image_file);
2324 gtk_widget_set_sensitive(ct_button, FALSE);
2327 pref_checkbox_new_int(group, _("2) Save metadata in '.metadata' folder, local to image folder (non-standard)"),
2328 options->metadata.enable_metadata_dirs, &c_options->metadata.enable_metadata_dirs);
2330 text = g_strdup_printf(_("3) Save metadata in Geeqie private directory '%s'"), get_metadata_cache_dir());
2331 label = pref_label_new(group, text);
2332 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2333 gtk_misc_set_padding(GTK_MISC(label), 22, 0);
2336 group = pref_group_new(vbox, FALSE, _("Step 1: Write to image files"), GTK_ORIENTATION_VERTICAL);
2338 gtk_widget_set_sensitive(group, FALSE);
2341 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2342 pref_checkbox_link_sensitivity(ct_button, hbox);
2344 pref_checkbox_new_int(hbox, _("Store metadata also in legacy IPTC tags (converted according to IPTC4XMP standard)"),
2345 options->metadata.save_legacy_IPTC, &c_options->metadata.save_legacy_IPTC);
2347 pref_checkbox_new_int(hbox, _("Warn if the image files are unwritable"),
2348 options->metadata.warn_on_write_problems, &c_options->metadata.warn_on_write_problems);
2350 pref_checkbox_new_int(hbox, _("Ask before writing to image files"),
2351 options->metadata.confirm_write, &c_options->metadata.confirm_write);
2353 pref_checkbox_new_int(hbox, _("Create sidecar files named image.ext.xmp (as opposed to image.xmp)"),
2354 options->metadata.sidecar_extended_name, &c_options->metadata.sidecar_extended_name);
2356 group = pref_group_new(vbox, FALSE, _("Step 2 and 3: write to Geeqie private files"), GTK_ORIENTATION_VERTICAL);
2358 gtk_widget_set_sensitive(group, FALSE);
2361 pref_checkbox_new_int(group, _("Use GQview legacy metadata format (supports only keywords and comments) instead of XMP"),
2362 options->metadata.save_legacy_format, &c_options->metadata.save_legacy_format);
2365 group = pref_group_new(vbox, FALSE, _("Miscellaneous"), GTK_ORIENTATION_VERTICAL);
2366 pref_checkbox_new_int(group, _("Write the same description tags (keywords, comment, etc.) to all grouped sidecars"),
2367 options->metadata.sync_grouped_files, &c_options->metadata.sync_grouped_files);
2369 pref_checkbox_new_int(group, _("Allow keywords to differ only in case"),
2370 options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
2372 ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"),
2373 options->metadata.write_orientation, &c_options->metadata.write_orientation);
2375 gtk_widget_set_sensitive(ct_button, FALSE);
2378 group = pref_group_new(vbox, FALSE, _("Auto-save options"), GTK_ORIENTATION_VERTICAL);
2380 ct_button = pref_checkbox_new_int(group, _("Write metadata after timeout"),
2381 options->metadata.confirm_after_timeout, &c_options->metadata.confirm_after_timeout);
2383 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2384 pref_checkbox_link_sensitivity(ct_button, hbox);
2386 pref_spin_new_int(hbox, _("Timeout (seconds):"), NULL, 0, 900, 1,
2387 options->metadata.confirm_timeout, &c_options->metadata.confirm_timeout);
2389 pref_checkbox_new_int(group, _("Write metadata on image change"),
2390 options->metadata.confirm_on_image_change, &c_options->metadata.confirm_on_image_change);
2392 pref_checkbox_new_int(group, _("Write metadata on directory change"),
2393 options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
2395 group = pref_group_new(vbox, FALSE, _("Pre-load metadata"), GTK_ORIENTATION_VERTICAL);
2397 ct_button = pref_checkbox_new_int(group, _("Read metadata in background"),
2398 options->read_metadata_in_idle, &c_options->read_metadata_in_idle);
2399 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");
2404 typedef struct _KeywordFindData KeywordFindData;
2405 struct _KeywordFindData
2412 GtkWidget *button_close;
2413 GtkWidget *button_stop;
2414 GtkWidget *button_start;
2415 GtkWidget *progress;
2423 guint idle_id; /* event source id */
2426 #define KEYWORD_DIALOG_WIDTH 400
2428 static void keywords_find_folder(KeywordFindData *kfd, FileData *dir_fd)
2430 GList *list_d = NULL;
2431 GList *list_f = NULL;
2435 filelist_read(dir_fd, &list_f, &list_d);
2439 filelist_read(dir_fd, &list_f, NULL);
2442 list_f = filelist_filter(list_f, FALSE);
2443 list_d = filelist_filter(list_d, TRUE);
2445 kfd->list = g_list_concat(list_f, kfd->list);
2446 kfd->list_dir = g_list_concat(list_d, kfd->list_dir);
2449 static void keywords_find_reset(KeywordFindData *kfd)
2451 filelist_free(kfd->list);
2454 filelist_free(kfd->list_dir);
2455 kfd->list_dir = NULL;
2458 static void keywords_find_close_cb(GenericDialog *fd, gpointer data)
2460 KeywordFindData *kfd = data;
2462 if (!gtk_widget_get_sensitive(kfd->button_close)) return;
2464 keywords_find_reset(kfd);
2465 generic_dialog_close(kfd->gd);
2469 static void keywords_find_finish(KeywordFindData *kfd)
2471 keywords_find_reset(kfd);
2473 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("done"));
2474 spinner_set_interval(kfd->spinner, -1);
2476 gtk_widget_set_sensitive(kfd->group, TRUE);
2477 gtk_widget_set_sensitive(kfd->button_start, TRUE);
2478 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2479 gtk_widget_set_sensitive(kfd->button_close, TRUE);
2482 static void keywords_find_stop_cb(GenericDialog *fd, gpointer data)
2484 KeywordFindData *kfd = data;
2486 g_idle_remove_by_data(kfd);
2488 keywords_find_finish(kfd);
2491 static gboolean keywords_find_file(gpointer data)
2493 KeywordFindData *kfd = data;
2495 GtkTextBuffer *buffer;
2503 fd = kfd->list->data;
2504 kfd->list = g_list_remove(kfd->list, fd);
2506 keywords = metadata_read_list(fd, KEYWORD_KEY, METADATA_PLAIN);
2507 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2511 gtk_text_buffer_get_end_iter(buffer, &iter);
2512 tmp = g_strconcat(keywords->data, "\n", NULL);
2513 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
2515 keywords = keywords->next;
2518 gtk_entry_set_text(GTK_ENTRY(kfd->progress), fd->path);
2519 file_data_unref(fd);
2520 string_list_free(keywords);
2524 else if (kfd->list_dir)
2528 fd = kfd->list_dir->data;
2529 kfd->list_dir = g_list_remove(kfd->list_dir, fd);
2531 keywords_find_folder(kfd, fd);
2533 file_data_unref(fd);
2538 keywords_find_finish(kfd);
2543 static void keywords_find_start_cb(GenericDialog *fd, gpointer data)
2545 KeywordFindData *kfd = data;
2548 if (kfd->list || !gtk_widget_get_sensitive(kfd->button_start)) return;
2550 path = remove_trailing_slash((gtk_entry_get_text(GTK_ENTRY(kfd->entry))));
2551 parse_out_relatives(path);
2555 warning_dialog(_("Invalid folder"),
2556 _("The specified folder can not be found."),
2557 GTK_STOCK_DIALOG_WARNING, kfd->gd->dialog);
2563 gtk_widget_set_sensitive(kfd->group, FALSE);
2564 gtk_widget_set_sensitive(kfd->button_start, FALSE);
2565 gtk_widget_set_sensitive(kfd->button_stop, TRUE);
2566 gtk_widget_set_sensitive(kfd->button_close, FALSE);
2567 spinner_set_interval(kfd->spinner, SPINNER_SPEED);
2569 dir_fd = file_data_new_dir(path);
2570 keywords_find_folder(kfd, dir_fd);
2571 file_data_unref(dir_fd);
2572 kfd->idle_id = g_idle_add(keywords_find_file, kfd);
2578 static void keywords_find_dialog(GtkWidget *widget, const gchar *path)
2580 KeywordFindData *kfd;
2584 kfd = g_new0(KeywordFindData, 1);
2586 kfd->gd = generic_dialog_new(_("Search for keywords"),
2587 "search_for_keywords",
2590 gtk_window_set_default_size(GTK_WINDOW(kfd->gd->dialog), KEYWORD_DIALOG_WIDTH, -1);
2591 kfd->gd->cancel_cb = keywords_find_close_cb;
2592 kfd->button_close = generic_dialog_add_button(kfd->gd, GTK_STOCK_CLOSE, NULL,
2593 keywords_find_close_cb, FALSE);
2594 kfd->button_start = generic_dialog_add_button(kfd->gd, GTK_STOCK_OK, _("S_tart"),
2595 keywords_find_start_cb, FALSE);
2596 kfd->button_stop = generic_dialog_add_button(kfd->gd, GTK_STOCK_STOP, NULL,
2597 keywords_find_stop_cb, FALSE);
2598 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2600 generic_dialog_add_message(kfd->gd, NULL, _("Search for keywords"), NULL, FALSE);
2602 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0);
2603 pref_spacer(hbox, PREF_PAD_INDENT);
2604 kfd->group = pref_box_new(hbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2606 hbox = pref_box_new(kfd->group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2607 pref_label_new(hbox, _("Folder:"));
2609 label = tab_completion_new(&kfd->entry, path, NULL, NULL, NULL, NULL);
2610 tab_completion_add_select_button(kfd->entry,_("Select folder") , TRUE);
2611 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
2612 gtk_widget_show(label);
2614 pref_checkbox_new_int(kfd->group, _("Include subfolders"), FALSE, &kfd->recurse);
2616 pref_line(kfd->gd->vbox, PREF_PAD_SPACE);
2617 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2619 kfd->progress = gtk_entry_new();
2620 gtk_widget_set_can_focus(kfd->progress, FALSE);
2621 gtk_editable_set_editable(GTK_EDITABLE(kfd->progress), FALSE);
2622 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("click start to begin"));
2623 gtk_box_pack_start(GTK_BOX(hbox), kfd->progress, TRUE, TRUE, 0);
2624 gtk_widget_show(kfd->progress);
2626 kfd->spinner = spinner_new(NULL, -1);
2627 gtk_box_pack_start(GTK_BOX(hbox), kfd->spinner, FALSE, FALSE, 0);
2628 gtk_widget_show(kfd->spinner);
2632 gtk_widget_show(kfd->gd->dialog);
2635 static void keywords_find_cb(GtkWidget *widget, gpointer data)
2637 const gchar *path = layout_get_path(NULL);
2639 if (!path || !*path) path = homedir();
2640 keywords_find_dialog(widget, path);
2643 static void config_tab_keywords_save()
2645 GtkTextIter start, end;
2646 GtkTextBuffer *buffer;
2647 GList *kw_list = NULL;
2653 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2654 gtk_text_buffer_get_bounds(buffer, &start, &end);
2656 buffer_text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
2658 kw_split = strtok(buffer_text, "\n");
2659 while (kw_split != NULL)
2665 if (g_strcmp0(work->data, kw_split) == 0)
2674 kw_list = g_list_append(kw_list, g_strdup(kw_split));
2676 kw_split = strtok(NULL, "\n");
2679 keyword_list_set(kw_list);
2681 string_list_free(kw_list);
2682 g_free(buffer_text);
2685 static void config_tab_keywords(GtkWidget *notebook)
2691 GtkWidget *scrolled;
2693 GtkTextBuffer *buffer;
2696 vbox = scrolled_notebook_page(notebook, _("Keywords"));
2698 group = pref_group_new(vbox, TRUE, _("Edit keywords autocompletion list"), GTK_ORIENTATION_VERTICAL);
2700 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2702 button = pref_button_new(hbox, GTK_STOCK_EXECUTE, _("Search"), FALSE,
2703 G_CALLBACK(keywords_find_cb), keyword_text);
2704 gtk_widget_set_tooltip_text(button, "Search for existing keywords");
2707 keyword_text = gtk_text_view_new();
2708 gtk_widget_set_size_request(keyword_text, 20, 20);
2709 scrolled = gtk_scrolled_window_new(NULL, NULL);
2710 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2711 gtk_widget_show(scrolled);
2713 gtk_container_add(GTK_CONTAINER(scrolled), keyword_text);
2714 gtk_widget_show(keyword_text);
2716 gtk_text_view_set_editable(GTK_TEXT_VIEW(keyword_text), TRUE);
2718 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2719 gtk_text_buffer_create_tag(buffer, "monospace",
2720 "family", "monospace", NULL);
2722 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(keyword_text), GTK_WRAP_WORD);
2723 gtk_text_buffer_get_start_iter(buffer, &iter);
2724 gtk_text_buffer_create_mark(buffer, "end", &iter, FALSE);
2727 path = g_build_filename(get_rc_dir(), "keywords", NULL);
2729 GList *kwl = keyword_list_get();
2730 kwl = g_list_first(kwl);
2733 gtk_text_buffer_get_end_iter (buffer, &iter);
2734 tmp = g_strconcat(kwl->data, "\n", NULL);
2735 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
2740 gtk_text_buffer_set_modified(buffer, FALSE);
2747 static void intent_menu_cb(GtkWidget *combo, gpointer data)
2749 gint *option = data;
2751 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
2755 *option = INTENT_PERCEPTUAL;
2758 *option = INTENT_RELATIVE_COLORIMETRIC;
2761 *option = INTENT_SATURATION;
2764 *option = INTENT_ABSOLUTE_COLORIMETRIC;
2769 static void add_intent_menu(GtkWidget *table, gint column, gint row, const gchar *text,
2770 gint option, gint *option_c)
2777 pref_table_label(table, column, row, text, 0.0);
2779 combo = gtk_combo_box_text_new();
2781 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Perceptual"));
2782 if (option == INTENT_PERCEPTUAL) current = 0;
2783 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Relative Colorimetric"));
2784 if (option == INTENT_RELATIVE_COLORIMETRIC) current = 1;
2785 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Saturation"));
2786 if (option == INTENT_SATURATION) current = 2;
2787 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Absolute Colorimetric"));
2788 if (option == INTENT_ABSOLUTE_COLORIMETRIC) current = 3;
2790 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
2792 gtk_widget_set_tooltip_text(combo,"Refer to the lcms documentation for the defaults used when the selected Intent is not available");
2794 g_signal_connect(G_OBJECT(combo), "changed",
2795 G_CALLBACK(intent_menu_cb), option_c);
2797 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
2798 GTK_EXPAND | GTK_FILL, 0, 0, 0);
2799 gtk_widget_show(combo);
2803 static void config_tab_color(GtkWidget *notebook)
2812 vbox = scrolled_notebook_page(notebook, _("Color management"));
2814 group = pref_group_new(vbox, FALSE, _("Input profiles"), GTK_ORIENTATION_VERTICAL);
2816 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
2819 table = pref_table_new(group, 3, COLOR_PROFILE_INPUTS + 1, FALSE, FALSE);
2820 gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
2822 label = pref_table_label(table, 0, 0, _("Type"), 0.0);
2823 pref_label_bold(label, TRUE, FALSE);
2825 label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
2826 pref_label_bold(label, TRUE, FALSE);
2828 label = pref_table_label(table, 2, 0, _("File"), 0.0);
2829 pref_label_bold(label, TRUE, FALSE);
2831 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
2836 buf = g_strdup_printf(_("Input %d:"), i + COLOR_PROFILE_FILE);
2837 pref_table_label(table, 0, i + 1, buf, 1.0);
2840 entry = gtk_entry_new();
2841 gtk_entry_set_max_length(GTK_ENTRY(entry), EDITOR_NAME_MAX_LENGTH);
2842 if (options->color_profile.input_name[i])
2844 gtk_entry_set_text(GTK_ENTRY(entry), options->color_profile.input_name[i]);
2846 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, i + 1, i + 2,
2847 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2848 gtk_widget_show(entry);
2849 color_profile_input_name_entry[i] = entry;
2851 tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, ".icc", "ICC Files", NULL);
2852 tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
2853 gtk_widget_set_size_request(entry, 160, -1);
2854 gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
2855 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2856 gtk_widget_show(tabcomp);
2857 color_profile_input_file_entry[i] = entry;
2860 group = pref_group_new(vbox, FALSE, _("Screen profile"), GTK_ORIENTATION_VERTICAL);
2862 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
2864 pref_checkbox_new_int(group, _("Use system screen profile if available"),
2865 options->color_profile.use_x11_screen_profile, &c_options->color_profile.use_x11_screen_profile);
2867 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2869 pref_table_label(table, 0, 0, _("Screen:"), 1.0);
2870 tabcomp = tab_completion_new(&color_profile_screen_file_entry,
2871 options->color_profile.screen_file, NULL, ".icc", "ICC Files", NULL);
2872 tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
2873 gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
2875 add_intent_menu(table, 0, 1, _("Render Intent:"), options->color_profile.render_intent, &c_options->color_profile.render_intent);
2877 gtk_table_attach(GTK_TABLE(table), tabcomp, 1, 2,
2879 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2881 gtk_widget_show(tabcomp);
2884 /* advanced entry tab */
2885 static void config_tab_behavior(GtkWidget *notebook)
2892 GtkWidget *ct_button;
2896 GtkWidget *with_rename;
2897 GtkWidget *collections_on_top;
2899 vbox = scrolled_notebook_page(notebook, _("Behavior"));
2901 group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
2903 pref_checkbox_new_int(group, _("Confirm file delete"),
2904 options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
2905 pref_checkbox_new_int(group, _("Enable Delete key"),
2906 options->file_ops.enable_delete_key, &c_options->file_ops.enable_delete_key);
2908 ct_button = pref_checkbox_new_int(group, _("Safe delete"),
2909 options->file_ops.safe_delete_enable, &c_options->file_ops.safe_delete_enable);
2911 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2912 pref_checkbox_link_sensitivity(ct_button, hbox);
2914 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
2915 pref_label_new(hbox, _("Folder:"));
2917 tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL, NULL, NULL);
2918 tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
2919 gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
2920 gtk_widget_show(tabcomp);
2922 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2923 pref_checkbox_link_sensitivity(ct_button, hbox);
2925 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
2926 spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MB"),
2927 0, 2048, 1, options->file_ops.safe_delete_folder_maxsize, &c_options->file_ops.safe_delete_folder_maxsize);
2928 gtk_widget_set_tooltip_markup(spin, _("Set to 0 for unlimited size"));
2929 button = pref_button_new(NULL, NULL, _("View"), FALSE,
2930 G_CALLBACK(safe_delete_view_cb), NULL);
2931 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2932 gtk_widget_show(button);
2934 button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
2935 G_CALLBACK(safe_delete_clear_cb), NULL);
2936 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2937 gtk_widget_show(button);
2940 group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
2942 pref_checkbox_new_int(group, _("Descend folders in tree view"),
2943 options->tree_descend_subdirs, &c_options->tree_descend_subdirs);
2945 pref_checkbox_new_int(group, _("In place renaming"),
2946 options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
2948 pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
2949 options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
2951 marks = pref_checkbox_new_int(group, _("Save marks on exit"),
2952 options->marks_save, &c_options->marks_save);
2953 gtk_widget_set_tooltip_text(marks,"Note that marks linked to a keyword will be saved irrespective of this setting");
2955 with_rename = pref_checkbox_new_int(group, _("Use \"With Rename\" as default for Copy/Move dialogs"),
2956 options->with_rename, &c_options->with_rename);
2957 gtk_widget_set_tooltip_text(with_rename,"Change the default button for Copy/Move dialogs");
2959 collections_on_top = pref_checkbox_new_int(group, _("Open collections on top"),
2960 options->collections_on_top, &c_options->collections_on_top);
2961 gtk_widget_set_tooltip_text(collections_on_top,"Open collections window on top");
2963 pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
2964 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
2966 pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
2967 16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
2969 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2970 add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
2972 group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
2974 pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
2975 options->progressive_key_scrolling, &c_options->progressive_key_scrolling);
2976 pref_spin_new_int(group, _("Keyboard scrolling step multiplier:"), NULL,
2977 1, 32, 1, options->keyboard_scroll_step, (int *)&c_options->keyboard_scroll_step);
2978 pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
2979 options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
2980 pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
2981 options->image_lm_click_nav, &c_options->image_lm_click_nav);
2982 pref_checkbox_new_int(group, _("Play video by left click on image"),
2983 options->image_l_click_video, &c_options->image_l_click_video);
2984 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2985 add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
2989 group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
2991 pref_spin_new_int(group, _("Debug level:"), NULL,
2992 DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
2994 pref_checkbox_new_int(group, _("Timer data"),
2995 options->log_window.timer_data, &c_options->log_window.timer_data);
2997 pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
2998 1, 99999, 1, options->log_window_lines, &options->log_window_lines);
3002 /* accelerators tab */
3003 static void config_tab_accelerators(GtkWidget *notebook)
3009 GtkWidget *scrolled;
3010 GtkWidget *accel_view;
3011 GtkCellRenderer *renderer;
3012 GtkTreeSelection *selection;
3013 GtkTreeViewColumn *column;
3015 vbox = scrolled_notebook_page(notebook, _("Keyboard"));
3017 group = pref_group_new(vbox, TRUE, _("Accelerators"), GTK_ORIENTATION_VERTICAL);
3019 scrolled = gtk_scrolled_window_new(NULL, NULL);
3020 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
3021 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
3022 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3023 gtk_widget_show(scrolled);
3025 accel_store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
3027 accel_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(accel_store));
3028 g_object_unref(accel_store);
3029 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(accel_view));
3030 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
3032 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(accel_view), FALSE);
3034 renderer = gtk_cell_renderer_text_new();
3036 column = gtk_tree_view_column_new_with_attributes(_("Action"),
3041 gtk_tree_view_column_set_sort_column_id(column, AE_ACTION);
3042 gtk_tree_view_column_set_resizable(column, TRUE);
3043 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3046 renderer = gtk_cell_renderer_accel_new();
3047 g_signal_connect(G_OBJECT(renderer), "accel-cleared",
3048 G_CALLBACK(accel_store_cleared_cb), accel_store);
3049 g_signal_connect(G_OBJECT(renderer), "accel-edited",
3050 G_CALLBACK(accel_store_edited_cb), accel_store);
3053 g_object_set (renderer,
3055 "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
3058 column = gtk_tree_view_column_new_with_attributes(_("KEY"),
3063 gtk_tree_view_column_set_sort_column_id(column, AE_KEY);
3064 gtk_tree_view_column_set_resizable(column, TRUE);
3065 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3067 renderer = gtk_cell_renderer_text_new();
3069 column = gtk_tree_view_column_new_with_attributes(_("Tooltip"),
3074 gtk_tree_view_column_set_sort_column_id(column, AE_TOOLTIP);
3075 gtk_tree_view_column_set_resizable(column, TRUE);
3076 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3078 renderer = gtk_cell_renderer_text_new();
3080 column = gtk_tree_view_column_new_with_attributes("Accel",
3085 gtk_tree_view_column_set_sort_column_id(column, AE_ACCEL);
3086 gtk_tree_view_column_set_resizable(column, TRUE);
3087 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3089 accel_store_populate();
3090 gtk_container_add(GTK_CONTAINER(scrolled), accel_view);
3091 gtk_widget_show(accel_view);
3093 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3095 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
3096 G_CALLBACK(accel_default_cb), accel_view);
3097 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3098 gtk_widget_show(button);
3100 button = pref_button_new(NULL, NULL, _("Reset selected"), FALSE,
3101 G_CALLBACK(accel_reset_cb), accel_view);
3102 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3103 gtk_widget_show(button);
3107 static void config_tab_toolbar(GtkWidget *notebook)
3110 GtkWidget *toolbardata;
3113 lw = layout_window_list->data;
3115 vbox = scrolled_notebook_page(notebook, _("Toolbar"));
3117 toolbardata = toolbar_select_new(lw);
3118 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3119 gtk_widget_show(vbox);
3123 static void config_tab_stereo(GtkWidget *notebook)
3131 GtkWidget *fs_button;
3132 vbox = scrolled_notebook_page(notebook, _("Stereo"));
3134 group = pref_group_new(vbox, FALSE, _("Windowed stereo mode"), GTK_ORIENTATION_VERTICAL);
3136 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3137 add_stereo_mode_menu(table, 0, 0, _("Windowed stereo mode"), options->stereo.mode, &c_options->stereo.mode, FALSE);
3139 table = pref_table_new(group, 2, 2, TRUE, FALSE);
3140 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3141 pref_checkbox_new_int(box, _("Mirror left image"),
3142 options->stereo.mode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.mirror_left);
3143 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3144 pref_checkbox_new_int(box, _("Flip left image"),
3145 options->stereo.mode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.flip_left);
3146 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3147 pref_checkbox_new_int(box, _("Mirror right image"),
3148 options->stereo.mode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.mirror_right);
3149 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3150 pref_checkbox_new_int(box, _("Flip right image"),
3151 options->stereo.mode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.flip_right);
3152 pref_checkbox_new_int(group, _("Swap left and right images"),
3153 options->stereo.mode & PR_STEREO_SWAP, &c_options->stereo.tmp.swap);
3154 pref_checkbox_new_int(group, _("Disable stereo mode on single image source"),
3155 options->stereo.mode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.temp_disable);
3157 group = pref_group_new(vbox, FALSE, _("Fullscreen stereo mode"), GTK_ORIENTATION_VERTICAL);
3158 fs_button = pref_checkbox_new_int(group, _("Use different settings for fullscreen"),
3159 options->stereo.enable_fsmode, &c_options->stereo.enable_fsmode);
3160 box2 = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
3161 pref_checkbox_link_sensitivity(fs_button, box2);
3162 table = pref_table_new(box2, 2, 1, FALSE, FALSE);
3163 add_stereo_mode_menu(table, 0, 0, _("Fullscreen stereo mode"), options->stereo.fsmode, &c_options->stereo.fsmode, TRUE);
3164 table = pref_table_new(box2, 2, 2, TRUE, FALSE);
3165 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3166 pref_checkbox_new_int(box, _("Mirror left image"),
3167 options->stereo.fsmode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.fs_mirror_left);
3168 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3169 pref_checkbox_new_int(box, _("Flip left image"),
3170 options->stereo.fsmode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.fs_flip_left);
3171 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3172 pref_checkbox_new_int(box, _("Mirror right image"),
3173 options->stereo.fsmode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.fs_mirror_right);
3174 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3175 pref_checkbox_new_int(box, _("Flip right image"),
3176 options->stereo.fsmode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.fs_flip_right);
3177 pref_checkbox_new_int(box2, _("Swap left and right images"),
3178 options->stereo.fsmode & PR_STEREO_SWAP, &c_options->stereo.tmp.fs_swap);
3179 pref_checkbox_new_int(box2, _("Disable stereo mode on single image source"),
3180 options->stereo.fsmode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.fs_temp_disable);
3182 group2 = pref_group_new(box2, FALSE, _("Fixed position"), GTK_ORIENTATION_VERTICAL);
3183 table = pref_table_new(group2, 5, 3, FALSE, FALSE);
3184 pref_table_spin_new_int(table, 0, 0, _("Width"), NULL,
3185 1, 5000, 1, options->stereo.fixed_w, &c_options->stereo.fixed_w);
3186 pref_table_spin_new_int(table, 3, 0, _("Height"), NULL,
3187 1, 5000, 1, options->stereo.fixed_h, &c_options->stereo.fixed_h);
3188 pref_table_spin_new_int(table, 0, 1, _("Left X"), NULL,
3189 0, 5000, 1, options->stereo.fixed_x1, &c_options->stereo.fixed_x1);
3190 pref_table_spin_new_int(table, 3, 1, _("Left Y"), NULL,
3191 0, 5000, 1, options->stereo.fixed_y1, &c_options->stereo.fixed_y1);
3192 pref_table_spin_new_int(table, 0, 2, _("Right X"), NULL,
3193 0, 5000, 1, options->stereo.fixed_x2, &c_options->stereo.fixed_x2);
3194 pref_table_spin_new_int(table, 3, 2, _("Right Y"), NULL,
3195 0, 5000, 1, options->stereo.fixed_y2, &c_options->stereo.fixed_y2);
3199 /* Main preferences window */
3200 static void config_window_create(void)
3202 GtkWidget *win_vbox;
3204 GtkWidget *notebook;
3206 GtkWidget *ct_button;
3208 if (!c_options) c_options = init_options(NULL);
3210 configwindow = window_new(GTK_WINDOW_TOPLEVEL, "preferences", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Preferences"));
3211 gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
3212 g_signal_connect(G_OBJECT(configwindow), "delete_event",
3213 G_CALLBACK(config_window_delete), NULL);
3214 gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
3215 gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
3216 gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
3218 win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
3219 gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
3220 gtk_widget_show(win_vbox);
3222 notebook = gtk_notebook_new();
3223 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP);
3224 gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
3226 config_tab_general(notebook);
3227 config_tab_image(notebook);
3228 config_tab_windows(notebook);
3229 config_tab_accelerators(notebook);
3230 config_tab_files(notebook);
3231 config_tab_metadata(notebook);
3232 config_tab_keywords(notebook);
3233 config_tab_color(notebook);
3234 config_tab_stereo(notebook);
3235 config_tab_behavior(notebook);
3236 config_tab_toolbar(notebook);
3238 hbox = gtk_hbutton_box_new();
3239 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
3240 gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
3241 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
3242 gtk_widget_show(hbox);
3244 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
3245 G_CALLBACK(config_window_help_cb), notebook);
3246 gtk_container_add(GTK_CONTAINER(hbox), button);
3247 gtk_widget_set_can_default(button, TRUE);
3248 gtk_widget_show(button);
3250 button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
3251 G_CALLBACK(config_window_ok_cb), NULL);
3252 gtk_container_add(GTK_CONTAINER(hbox), button);
3253 gtk_widget_set_can_default(button, TRUE);
3254 gtk_widget_grab_default(button);
3255 gtk_widget_show(button);
3259 button = pref_button_new(NULL, GTK_STOCK_SAVE, NULL, FALSE,
3260 G_CALLBACK(config_window_save_cb), NULL);
3261 gtk_container_add(GTK_CONTAINER(hbox), button);
3262 gtk_widget_set_can_default(button, TRUE);
3263 gtk_widget_show(button);
3265 button = pref_button_new(NULL, GTK_STOCK_APPLY, NULL, FALSE,
3266 G_CALLBACK(config_window_apply_cb), NULL);
3267 gtk_container_add(GTK_CONTAINER(hbox), button);
3268 gtk_widget_set_can_default(button, TRUE);
3269 gtk_widget_show(button);
3271 button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
3272 G_CALLBACK(config_window_close_cb), NULL);
3273 gtk_container_add(GTK_CONTAINER(hbox), button);
3274 gtk_widget_set_can_default(button, TRUE);
3275 gtk_widget_show(button);
3277 if (!generic_dialog_get_alternative_button_order(configwindow))
3279 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
3282 gtk_widget_show(notebook);
3284 gtk_widget_show(configwindow);
3288 *-----------------------------------------------------------------------------
3289 * config window show (public)
3290 *-----------------------------------------------------------------------------
3293 void show_config_window(void)
3297 gtk_window_present(GTK_WINDOW(configwindow));
3301 config_window_create();
3310 void show_about_window(LayoutWindow *lw)
3312 GdkPixbuf *pixbuf_logo;
3313 GdkPixbuf *pixbuf_icon;
3314 gchar *authors[1000];
3322 #define LINE_LENGTH 1000
3323 gchar line[LINE_LENGTH];
3325 copyright = g_string_new(NULL);
3326 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");
3328 zd_path = g_build_filename(GQ_BIN_DIR, TIMEZONE_DATABASE, NULL);
3329 cd = ZDOpenDatabase(zd_path);
3332 copyright = g_string_append(copyright, ZDGetNotice(cd));
3334 ZDCloseDatabase(cd);
3338 path = g_build_filename(GQ_HELPDIR, "AUTHORS", NULL);
3339 fp = fopen(path, "r");
3342 while(fgets(line, LINE_LENGTH, fp))
3344 /* get rid of ending \n from fgets */
3345 line[strlen(line) - 1] = '\0';
3346 authors[i_authors] = g_strdup(line);
3349 authors[i_authors] = NULL;
3354 comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
3355 "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
3357 pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
3358 pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
3359 gtk_show_about_dialog(GTK_WINDOW(lw->window),
3360 "title", _("About Geeqie"),
3362 "program-name", GQ_APPNAME,
3364 "logo", pixbuf_logo,
3365 "icon", pixbuf_icon,
3366 "website", GQ_WEBSITE,
3367 "website-label", "Website",
3368 "comments", comment,
3370 "translator-credits", _("translator-credits"),
3371 "wrap-license", TRUE,
3372 "license", copyright->str,
3375 g_string_free(copyright, TRUE);
3378 while(n < i_authors)
3388 static void image_overlay_set_text_colours()
3390 c_options->image_overlay.text_red = options->image_overlay.text_red;
3391 c_options->image_overlay.text_green = options->image_overlay.text_green;
3392 c_options->image_overlay.text_blue = options->image_overlay.text_blue;
3393 c_options->image_overlay.text_alpha = options->image_overlay.text_alpha;
3394 c_options->image_overlay.background_red = options->image_overlay.background_red;
3395 c_options->image_overlay.background_green = options->image_overlay.background_green;
3396 c_options->image_overlay.background_blue = options->image_overlay.background_blue;
3397 c_options->image_overlay.background_alpha = options->image_overlay.background_alpha;
3399 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */