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->show_predefined_keyword_tree = c_options->show_predefined_keyword_tree;
422 options->marks_save = c_options->marks_save;
423 options->with_rename = c_options->with_rename;
424 options->collections_on_top = c_options->collections_on_top;
425 config_entry_to_option(help_search_engine_entry, &options->help_search_engine, NULL);
427 options->read_metadata_in_idle = c_options->read_metadata_in_idle;
429 options->star_rating.star = c_options->star_rating.star;
430 options->star_rating.rejected = c_options->star_rating.rejected;
432 set_debug_level(debug_c);
436 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
438 config_entry_to_option(color_profile_input_name_entry[i], &options->color_profile.input_name[i], NULL);
439 config_entry_to_option(color_profile_input_file_entry[i], &options->color_profile.input_file[i], NULL);
441 config_entry_to_option(color_profile_screen_file_entry, &options->color_profile.screen_file, NULL);
442 options->color_profile.use_x11_screen_profile = c_options->color_profile.use_x11_screen_profile;
443 if (options->color_profile.render_intent != c_options->color_profile.render_intent)
445 options->color_profile.render_intent = c_options->color_profile.render_intent;
450 config_tab_keywords_save();
452 image_options_sync();
457 layout_refresh(NULL);
460 if (accel_store) gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_apply_cb, NULL);
466 *-----------------------------------------------------------------------------
467 * config window main button callbacks (private)
468 *-----------------------------------------------------------------------------
471 static void config_window_close_cb(GtkWidget *widget, gpointer data)
473 gtk_widget_destroy(configwindow);
478 static void config_window_help_cb(GtkWidget *widget, gpointer data)
480 GtkWidget *notebook = data;
483 static gchar *html_section[] =
485 "GuideOptionsGeneral.html",
486 "GuideOptionsImage.html",
487 "GuideOptionsWindow.html",
488 "GuideOptionsKeyboard.html",
489 "GuideOptionsFiltering.html",
490 "GuideOptionsMetadata.html",
491 "GuideOptionsKeywords.html",
492 "GuideOptionsColor.html",
493 "GuideOptionsStereo.html",
494 "GuideOptionsBehavior.html",
495 "GuideOptionsToolbar.html"
498 i = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
499 help_window_show(html_section[i]);
502 static gboolean config_window_delete(GtkWidget *widget, GdkEventAny *event, gpointer data)
504 config_window_close_cb(NULL, NULL);
508 static void config_window_ok_cb(GtkWidget *widget, gpointer data)
510 config_window_apply();
511 config_window_close_cb(NULL, NULL);
514 static void config_window_apply_cb(GtkWidget *widget, gpointer data)
517 lw = layout_window_list->data;
519 config_window_apply();
520 layout_util_sync(lw);
523 static void config_window_save_cb(GtkWidget *widget, gpointer data)
525 config_window_apply();
526 save_options(options);
530 *-----------------------------------------------------------------------------
531 * config window setup (private)
532 *-----------------------------------------------------------------------------
535 static void quality_menu_cb(GtkWidget *combo, gpointer data)
539 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
543 *option = GDK_INTERP_NEAREST;
546 *option = GDK_INTERP_TILES;
549 *option = GDK_INTERP_BILINEAR;
552 *option = GDK_INTERP_HYPER;
557 static void clipboard_selection_menu_cb(GtkWidget *combo, gpointer data)
561 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
573 static void add_quality_menu(GtkWidget *table, gint column, gint row, const gchar *text,
574 guint option, guint *option_c)
581 pref_table_label(table, column, row, text, 0.0);
583 combo = gtk_combo_box_text_new();
585 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Nearest (worst, but fastest)"));
586 if (option == GDK_INTERP_NEAREST) current = 0;
587 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Tiles"));
588 if (option == GDK_INTERP_TILES) current = 1;
589 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Bilinear"));
590 if (option == GDK_INTERP_BILINEAR) current = 2;
591 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Hyper (best, but slowest)"));
592 if (option == GDK_INTERP_HYPER) current = 3;
594 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
596 g_signal_connect(G_OBJECT(combo), "changed",
597 G_CALLBACK(quality_menu_cb), option_c);
599 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
600 GTK_EXPAND | GTK_FILL, 0, 0, 0);
601 gtk_widget_show(combo);
604 static void add_clipboard_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
605 gint option, gint *option_c)
612 pref_table_label(table, column, row, text, 0.0);
614 combo = gtk_combo_box_text_new();
616 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("PRIMARY"));
617 if (option == PRIMARY) current = 0;
618 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("CLIPBOARD"));
619 if (option == CLIPBOARD) current = 1;
621 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
623 g_signal_connect(G_OBJECT(combo), "changed",
624 G_CALLBACK(clipboard_selection_menu_cb), option_c);
626 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
627 GTK_EXPAND | GTK_FILL, 0, 0, 0);
628 gtk_widget_show(combo);
631 static void thumb_size_menu_cb(GtkWidget *combo, gpointer data)
635 n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
638 if ((guint) n < sizeof(thumb_size_list) / sizeof(ThumbSize))
640 c_options->thumbnails.max_width = thumb_size_list[n].w;
641 c_options->thumbnails.max_height = thumb_size_list[n].h;
645 c_options->thumbnails.max_width = options->thumbnails.max_width;
646 c_options->thumbnails.max_height = options->thumbnails.max_height;
650 static void add_thumb_size_menu(GtkWidget *table, gint column, gint row, gchar *text)
656 c_options->thumbnails.max_width = options->thumbnails.max_width;
657 c_options->thumbnails.max_height = options->thumbnails.max_height;
659 pref_table_label(table, column, row, text, 0.0);
661 combo = gtk_combo_box_text_new();
664 for (i = 0; (guint) i < sizeof(thumb_size_list) / sizeof(ThumbSize); i++)
669 w = thumb_size_list[i].w;
670 h = thumb_size_list[i].h;
672 buf = g_strdup_printf("%d x %d", w, h);
673 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
676 if (w == options->thumbnails.max_width && h == options->thumbnails.max_height) current = i;
683 buf = g_strdup_printf("%s %d x %d", _("Custom"), options->thumbnails.max_width, options->thumbnails.max_height);
684 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
690 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
691 g_signal_connect(G_OBJECT(combo), "changed",
692 G_CALLBACK(thumb_size_menu_cb), NULL);
694 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
695 GTK_EXPAND | GTK_FILL, 0, 0, 0);
696 gtk_widget_show(combo);
699 static void stereo_mode_menu_cb(GtkWidget *combo, gpointer data)
703 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
707 *option = PR_STEREO_NONE;
710 *option = PR_STEREO_ANAGLYPH_RC;
713 *option = PR_STEREO_ANAGLYPH_GM;
716 *option = PR_STEREO_ANAGLYPH_YB;
719 *option = PR_STEREO_ANAGLYPH_GRAY_RC;
722 *option = PR_STEREO_ANAGLYPH_GRAY_GM;
725 *option = PR_STEREO_ANAGLYPH_GRAY_YB;
728 *option = PR_STEREO_ANAGLYPH_DB_RC;
731 *option = PR_STEREO_ANAGLYPH_DB_GM;
734 *option = PR_STEREO_ANAGLYPH_DB_YB;
737 *option = PR_STEREO_HORIZ;
740 *option = PR_STEREO_HORIZ | PR_STEREO_HALF;
743 *option = PR_STEREO_VERT;
746 *option = PR_STEREO_VERT | PR_STEREO_HALF;
749 *option = PR_STEREO_FIXED;
754 static void add_stereo_mode_menu(GtkWidget *table, gint column, gint row, const gchar *text,
755 gint option, gint *option_c, gboolean add_fixed)
762 pref_table_label(table, column, row, text, 0.0);
764 combo = gtk_combo_box_text_new();
766 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Single image"));
768 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Red-Cyan"));
769 if (option & PR_STEREO_ANAGLYPH_RC) current = 1;
770 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Green-Magenta"));
771 if (option & PR_STEREO_ANAGLYPH_GM) current = 2;
772 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Yellow-Blue"));
773 if (option & PR_STEREO_ANAGLYPH_YB) current = 3;
774 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Red-Cyan"));
775 if (option & PR_STEREO_ANAGLYPH_GRAY_RC) current = 4;
776 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Green-Magenta"));
777 if (option & PR_STEREO_ANAGLYPH_GRAY_GM) current = 5;
778 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Yellow-Blue"));
779 if (option & PR_STEREO_ANAGLYPH_GRAY_YB) current = 6;
780 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Red-Cyan"));
781 if (option & PR_STEREO_ANAGLYPH_DB_RC) current = 7;
782 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Green-Magenta"));
783 if (option & PR_STEREO_ANAGLYPH_DB_GM) current = 8;
784 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Yellow-Blue"));
785 if (option & PR_STEREO_ANAGLYPH_DB_YB) current = 9;
787 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side"));
788 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side Half size"));
789 if (option & PR_STEREO_HORIZ)
792 if (option & PR_STEREO_HALF) current = 11;
795 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom"));
796 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom Half size"));
797 if (option & PR_STEREO_VERT)
800 if (option & PR_STEREO_HALF) current = 13;
805 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Fixed position"));
806 if (option & PR_STEREO_FIXED) current = 14;
809 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
811 g_signal_connect(G_OBJECT(combo), "changed",
812 G_CALLBACK(stereo_mode_menu_cb), option_c);
814 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
815 GTK_EXPAND | GTK_FILL, 0, 0, 0);
816 gtk_widget_show(combo);
819 static void video_menu_cb(GtkWidget *combo, gpointer data)
821 gchar **option = data;
823 EditorDescription *ed = g_list_nth_data(editor_list_get(), gtk_combo_box_get_active(GTK_COMBO_BOX(combo)));
827 static void video_menu_populate(gpointer data, gpointer user_data)
829 GtkWidget *combo = user_data;
830 EditorDescription *ed = data;
832 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), ed->name);
835 static void add_video_menu(GtkWidget *table, gint column, gint row, const gchar *text,
836 gchar *option, gchar **option_c)
840 /* use lists since they are sorted */
841 GList *eds = editor_list_get();
845 pref_table_label(table, column, row, text, 0.0);
847 combo = gtk_combo_box_text_new();
848 g_list_foreach(eds,video_menu_populate,(gpointer)combo);
849 current = option ? g_list_index(eds,g_hash_table_lookup(editors,option)): -1;
851 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
853 g_signal_connect(G_OBJECT(combo), "changed",
854 G_CALLBACK(video_menu_cb), option_c);
856 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
857 GTK_EXPAND | GTK_FILL, 0, 0, 0);
858 gtk_widget_show(combo);
861 static void filter_store_populate(void)
865 if (!filter_store) return;
867 gtk_list_store_clear(filter_store);
869 work = filter_get_list();
878 gtk_list_store_append(filter_store, &iter);
879 gtk_list_store_set(filter_store, &iter, 0, fe, -1);
883 static void filter_store_ext_edit_cb(GtkCellRendererText *cell, gchar *path_str,
884 gchar *new_text, gpointer data)
886 GtkWidget *model = data;
887 FilterEntry *fe = data;
891 if (!new_text || strlen(new_text) < 1) return;
893 tpath = gtk_tree_path_new_from_string(path_str);
894 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
895 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
897 g_free(fe->extensions);
898 fe->extensions = g_strdup(new_text);
900 gtk_tree_path_free(tpath);
904 static void filter_store_class_edit_cb(GtkCellRendererText *cell, gchar *path_str,
905 gchar *new_text, gpointer data)
907 GtkWidget *model = data;
908 FilterEntry *fe = data;
913 if (!new_text || !new_text[0]) return;
915 tpath = gtk_tree_path_new_from_string(path_str);
916 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
917 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
919 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
921 if (strcmp(new_text, _(format_class_list[i])) == 0)
928 gtk_tree_path_free(tpath);
932 static void filter_store_desc_edit_cb(GtkCellRendererText *cell, gchar *path_str,
933 gchar *new_text, gpointer data)
935 GtkWidget *model = data;
940 if (!new_text || !new_text[0]) return;
942 tpath = gtk_tree_path_new_from_string(path_str);
943 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
944 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
946 g_free(fe->description);
947 fe->description = g_strdup(new_text);
949 gtk_tree_path_free(tpath);
952 static void filter_store_enable_cb(GtkCellRendererToggle *renderer,
953 gchar *path_str, gpointer data)
955 GtkWidget *model = data;
960 tpath = gtk_tree_path_new_from_string(path_str);
961 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
962 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
964 fe->enabled = !fe->enabled;
966 gtk_tree_path_free(tpath);
970 static void filter_store_writable_cb(GtkCellRendererToggle *renderer,
971 gchar *path_str, gpointer data)
973 GtkWidget *model = data;
978 tpath = gtk_tree_path_new_from_string(path_str);
979 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
980 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
982 fe->writable = !fe->writable;
983 if (fe->writable) fe->allow_sidecar = FALSE;
985 gtk_tree_path_free(tpath);
989 static void filter_store_sidecar_cb(GtkCellRendererToggle *renderer,
990 gchar *path_str, gpointer data)
992 GtkWidget *model = data;
997 tpath = gtk_tree_path_new_from_string(path_str);
998 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
999 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1001 fe->allow_sidecar = !fe->allow_sidecar;
1002 if (fe->allow_sidecar) fe->writable = FALSE;
1004 gtk_tree_path_free(tpath);
1008 static void filter_set_func(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
1009 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
1013 gtk_tree_model_get(tree_model, iter, 0, &fe, -1);
1015 switch (GPOINTER_TO_INT(data))
1018 g_object_set(GTK_CELL_RENDERER(cell),
1019 "active", fe->enabled, NULL);
1022 g_object_set(GTK_CELL_RENDERER(cell),
1023 "text", fe->extensions, NULL);
1025 case FE_DESCRIPTION:
1026 g_object_set(GTK_CELL_RENDERER(cell),
1027 "text", fe->description, NULL);
1030 g_object_set(GTK_CELL_RENDERER(cell),
1031 "text", _(format_class_list[fe->file_class]), NULL);
1034 g_object_set(GTK_CELL_RENDERER(cell),
1035 "active", fe->writable, NULL);
1037 case FE_ALLOW_SIDECAR:
1038 g_object_set(GTK_CELL_RENDERER(cell),
1039 "active", fe->allow_sidecar, NULL);
1044 static gboolean filter_add_scroll(gpointer data)
1048 GtkCellRenderer *cell;
1049 GtkTreeViewColumn *column;
1050 GList *list_columns;
1055 rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(filter_store), NULL);
1056 path = gtk_tree_path_new_from_indices(rows-1, -1);
1058 list_columns = gtk_tree_view_get_columns(GTK_TREE_VIEW(data));
1060 column = g_list_nth(list_columns,i)->data;
1061 title = gtk_tree_view_column_get_title(GTK_TREE_VIEW_COLUMN(column));
1063 } while (strcmp(title, "Filter") !=0 );
1065 list_cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column));
1066 cell = g_list_last(list_cells)->data;
1068 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1069 path, column, FALSE, 0.0, 0.0 );
1070 gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(data),
1071 path, column, cell, TRUE);
1073 gtk_tree_path_free(path);
1074 g_list_free(list_cells);
1075 g_list_free(list_columns);
1080 static void filter_add_cb(GtkWidget *widget, gpointer data)
1082 filter_add_unique("description", ".new", FORMAT_CLASS_IMAGE, TRUE, FALSE, TRUE);
1083 filter_store_populate();
1085 g_idle_add((GSourceFunc)filter_add_scroll, data);
1088 static void filter_remove_cb(GtkWidget *widget, gpointer data)
1090 GtkWidget *filter_view = data;
1091 GtkTreeSelection *selection;
1095 if (!filter_store) return;
1096 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1097 if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) return;
1098 gtk_tree_model_get(GTK_TREE_MODEL(filter_store), &iter, 0, &fe, -1);
1101 filter_remove_entry(fe);
1103 filter_store_populate();
1106 static gboolean filter_default_ok_scroll(GtkTreeView *data)
1110 GtkTreeViewColumn *column;
1112 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(filter_store), &iter);
1113 path = gtk_tree_model_get_path(GTK_TREE_MODEL(filter_store), &iter);
1114 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1116 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1120 gtk_tree_path_free(path);
1125 static void filter_default_ok_cb(GenericDialog *gd, gpointer data)
1128 filter_add_defaults();
1130 filter_store_populate();
1132 g_idle_add((GSourceFunc)filter_default_ok_scroll, gd->data);
1135 static void dummy_cancel_cb(GenericDialog *gd, gpointer data)
1137 /* no op, only so cancel button appears */
1140 static void filter_default_cb(GtkWidget *widget, gpointer data)
1144 gd = generic_dialog_new(_("Reset filters"),
1145 "reset_filter", widget, TRUE,
1146 dummy_cancel_cb, data);
1147 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset filters"),
1148 _("This will reset the file filters to the defaults.\nContinue?"), TRUE);
1149 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, filter_default_ok_cb, TRUE);
1150 gtk_widget_show(gd->dialog);
1153 static void filter_disable_cb(GtkWidget *widget, gpointer data)
1155 GtkWidget *frame = data;
1157 gtk_widget_set_sensitive(frame,
1158 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
1161 static void safe_delete_view_cb(GtkWidget *widget, gpointer data)
1163 layout_set_path(NULL, gtk_entry_get_text(GTK_ENTRY(safe_delete_path_entry)));
1166 static void safe_delete_clear_ok_cb(GenericDialog *gd, gpointer data)
1168 file_util_trash_clear();
1171 static void safe_delete_clear_cb(GtkWidget *widget, gpointer data)
1175 gd = generic_dialog_new(_("Clear trash"),
1176 "clear_trash", widget, TRUE,
1177 dummy_cancel_cb, NULL);
1178 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear trash"),
1179 _("This will remove the trash contents."), FALSE);
1180 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, safe_delete_clear_ok_cb, TRUE);
1181 entry = gtk_entry_new();
1182 gtk_widget_set_can_focus(entry, FALSE);
1183 gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE);
1184 if (options->file_ops.safe_delete_path) gtk_entry_set_text(GTK_ENTRY(entry), options->file_ops.safe_delete_path);
1185 gtk_box_pack_start(GTK_BOX(gd->vbox), entry, FALSE, FALSE, 0);
1186 gtk_widget_show(entry);
1187 gtk_widget_show(gd->dialog);
1190 static void image_overlay_template_view_changed_cb(GtkWidget *widget, gpointer data)
1192 GtkWidget *pTextView;
1193 GtkTextBuffer *pTextBuffer;
1197 pTextView = GTK_WIDGET(data);
1199 pTextBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pTextView));
1200 gtk_text_buffer_get_start_iter(pTextBuffer, &iStart);
1201 gtk_text_buffer_get_end_iter(pTextBuffer, &iEnd);
1203 set_image_overlay_template_string(&c_options->image_overlay.template_string,
1204 gtk_text_buffer_get_text(pTextBuffer, &iStart, &iEnd, TRUE));
1207 static void image_overlay_default_template_ok_cb(GenericDialog *gd, gpointer data)
1209 GtkTextView *text_view = data;
1210 GtkTextBuffer *buffer;
1212 set_default_image_overlay_template_string(&options->image_overlay.template_string);
1213 if (!configwindow) return;
1215 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
1216 gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1219 static void image_overlay_default_template_cb(GtkWidget *widget, gpointer data)
1223 gd = generic_dialog_new(_("Reset image overlay template string"),
1224 "reset_image_overlay_template_string", widget, TRUE,
1225 dummy_cancel_cb, data);
1226 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset image overlay template string"),
1227 _("This will reset the image overlay template string to the default.\nContinue?"), TRUE);
1228 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, image_overlay_default_template_ok_cb, TRUE);
1229 gtk_widget_show(gd->dialog);
1232 static void image_overlay_help_cb(GtkWidget *widget, gpointer data)
1234 help_window_show("GuideOptionsWindow.html#OverlayScreenDisplay");
1237 static void image_overlay_set_font_cb(GtkWidget *widget, gpointer data)
1239 #if GTK_CHECK_VERSION(3,4,0)
1242 PangoFontDescription *font_desc;
1244 dialog = gtk_font_chooser_dialog_new("Image Overlay Font", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1245 gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), options->image_overlay.font);
1247 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1249 font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
1250 font = pango_font_description_to_string(font_desc);
1251 g_free(c_options->image_overlay.font);
1252 c_options->image_overlay.font = g_strdup(font);
1256 gtk_widget_destroy(dialog);
1260 font = gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget));
1261 c_options->image_overlay.font = g_strdup(font);
1265 static void image_overlay_set_text_colour_cb(GtkWidget *widget, gpointer data)
1268 #if GTK_CHECK_VERSION(3,4,0)
1271 dialog = gtk_color_chooser_dialog_new("Image Overlay Text Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1272 colour.red = options->image_overlay.text_red;
1273 colour.green = options->image_overlay.text_green;
1274 colour.blue = options->image_overlay.text_blue;
1275 colour.alpha = options->image_overlay.text_alpha;
1276 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1277 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1279 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1281 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1282 c_options->image_overlay.text_red = colour.red*255;
1283 c_options->image_overlay.text_green = colour.green*255;
1284 c_options->image_overlay.text_blue = colour.blue*255;
1285 c_options->image_overlay.text_alpha = colour.alpha*255;
1287 gtk_widget_destroy(dialog);
1290 GtkColorSelection *colorsel;
1292 dialog = gtk_color_selection_dialog_new("Image Overlay Text Colour");
1293 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1294 colour.red = options->image_overlay.text_red*257;
1295 colour.green = options->image_overlay.text_green*257;
1296 colour.blue = options->image_overlay.text_blue*257;
1297 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1298 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1299 gtk_color_selection_set_current_color(colorsel, &colour);
1300 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.text_alpha*257);
1302 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1304 gtk_color_selection_get_current_color(colorsel, &colour);
1305 c_options->image_overlay.text_red = colour.red/257;
1306 c_options->image_overlay.text_green = colour.green/257;
1307 c_options->image_overlay.text_blue = colour.blue/257;
1308 c_options->image_overlay.text_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1310 gtk_widget_destroy (dialog);
1315 static void image_overlay_set_background_colour_cb(GtkWidget *widget, gpointer data)
1318 #if GTK_CHECK_VERSION(3,4,0)
1321 dialog = gtk_color_chooser_dialog_new("Image Overlay Background Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1322 colour.red = options->image_overlay.background_red;
1323 colour.green = options->image_overlay.background_green;
1324 colour.blue = options->image_overlay.background_blue;
1325 colour.alpha = options->image_overlay.background_alpha;
1326 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1327 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1329 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1331 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1332 c_options->image_overlay.background_red = colour.red*255;
1333 c_options->image_overlay.background_green = colour.green*255;
1334 c_options->image_overlay.background_blue = colour.blue*255;
1335 c_options->image_overlay.background_alpha = colour.alpha*255;
1337 gtk_widget_destroy(dialog);
1340 GtkColorSelection *colorsel;
1342 dialog = gtk_color_selection_dialog_new("Image Overlay Background Colour");
1343 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1344 colour.red = options->image_overlay.background_red*257;
1345 colour.green = options->image_overlay.background_green*257;
1346 colour.blue = options->image_overlay.background_blue*257;
1347 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1348 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1349 gtk_color_selection_set_current_color(colorsel, &colour);
1350 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.background_alpha*257);
1352 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1354 gtk_color_selection_get_current_color(colorsel, &colour);
1355 c_options->image_overlay.background_red = colour.red/257;
1356 c_options->image_overlay.background_green = colour.green/257;
1357 c_options->image_overlay.background_blue = colour.blue/257;
1358 c_options->image_overlay.background_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1360 gtk_widget_destroy(dialog);
1364 static void accel_store_populate(void)
1367 GList *groups, *actions;
1369 const gchar *accel_path;
1373 if (!accel_store || !layout_window_list || !layout_window_list->data) return;
1375 gtk_tree_store_clear(accel_store);
1376 lw = layout_window_list->data; /* get the actions from the first window, it should not matter, they should be the same in all windows */
1378 g_assert(lw && lw->ui_manager);
1379 groups = gtk_ui_manager_get_action_groups(lw->ui_manager);
1382 actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
1385 action = GTK_ACTION(actions->data);
1386 accel_path = gtk_action_get_accel_path(action);
1387 if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
1389 gchar *label, *label2, *tooltip, *accel;
1390 g_object_get(action,
1391 "tooltip", &tooltip,
1395 if (pango_parse_markup(label, -1, '_', NULL, &label2, NULL, NULL) && label2)
1401 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1405 gtk_tree_store_append(accel_store, &iter, NULL);
1406 gtk_tree_store_set(accel_store, &iter,
1409 AE_TOOLTIP, tooltip ? tooltip : "",
1410 AE_ACCEL, accel_path,
1418 actions = actions->next;
1421 groups = groups->next;
1425 static void accel_store_cleared_cb(GtkCellRendererAccel *accel, gchar *path_string, gpointer user_data)
1430 static gboolean accel_remove_key_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1432 gchar *accel1 = data;
1437 gtk_tree_model_get(model, iter, AE_KEY, &accel2, -1);
1439 gtk_accelerator_parse(accel1, &key1.accel_key, &key1.accel_mods);
1440 gtk_accelerator_parse(accel2, &key2.accel_key, &key2.accel_mods);
1442 if (key1.accel_key == key2.accel_key && key1.accel_mods == key2.accel_mods)
1444 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1445 DEBUG_1("accelerator key '%s' is already used, removing.", accel1);
1454 static void accel_store_edited_cb(GtkCellRendererAccel *accel, gchar *path_string, guint accel_key, GdkModifierType accel_mods, guint hardware_keycode, gpointer user_data)
1456 GtkTreeModel *model = (GtkTreeModel *)accel_store;
1460 GtkAccelKey old_key, key;
1461 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
1463 gtk_tree_model_get_iter(model, &iter, path);
1464 gtk_tree_model_get(model, &iter, AE_ACCEL, &accel_path, -1);
1466 /* test if the accelerator can be stored without conflicts*/
1467 gtk_accel_map_lookup_entry(accel_path, &old_key);
1469 /* change the key and read it back (change may fail on keys hardcoded in gtk)*/
1470 gtk_accel_map_change_entry(accel_path, accel_key, accel_mods, TRUE);
1471 gtk_accel_map_lookup_entry(accel_path, &key);
1473 /* restore the original for now, the key will be really changed when the changes are confirmed */
1474 gtk_accel_map_change_entry(accel_path, old_key.accel_key, old_key.accel_mods, TRUE);
1476 acc = gtk_accelerator_name(key.accel_key, key.accel_mods);
1477 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, acc);
1479 gtk_tree_store_set(accel_store, &iter, AE_KEY, acc, -1);
1480 gtk_tree_path_free(path);
1484 static gboolean accel_default_scroll(GtkTreeView *data)
1488 GtkTreeViewColumn *column;
1490 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(accel_store), &iter);
1491 path = gtk_tree_model_get_path(GTK_TREE_MODEL(accel_store), &iter);
1492 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1494 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1498 gtk_tree_path_free(path);
1503 static void accel_default_cb(GtkWidget *widget, gpointer data)
1505 accel_store_populate();
1507 g_idle_add((GSourceFunc)accel_default_scroll, data);
1510 void accel_remove_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1512 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1515 void accel_reset_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1518 gchar *accel_path, *accel;
1520 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, -1);
1521 gtk_accel_map_lookup_entry(accel_path, &key);
1522 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1524 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, accel);
1526 gtk_tree_store_set(accel_store, iter, AE_KEY, accel, -1);
1531 static void accel_reset_cb(GtkWidget *widget, gpointer data)
1533 GtkTreeSelection *selection;
1535 if (!accel_store) return;
1536 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data));
1537 gtk_tree_selection_selected_foreach(selection, &accel_reset_selection, NULL);
1542 static GtkWidget *scrolled_notebook_page(GtkWidget *notebook, const gchar *title)
1546 GtkWidget *scrolled;
1547 GtkWidget *viewport;
1549 scrolled = gtk_scrolled_window_new(NULL, NULL);
1550 gtk_container_set_border_width(GTK_CONTAINER(scrolled), PREF_PAD_BORDER);
1551 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1552 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1553 label = gtk_label_new(title);
1554 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, label);
1555 gtk_widget_show(scrolled);
1557 viewport = gtk_viewport_new(NULL, NULL);
1558 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1559 gtk_container_add(GTK_CONTAINER(scrolled), viewport);
1560 gtk_widget_show(viewport);
1562 vbox = gtk_vbox_new(FALSE, 0);
1563 gtk_container_add(GTK_CONTAINER(viewport), vbox);
1564 gtk_widget_show(vbox);
1569 static void cache_standard_cb(GtkWidget *widget, gpointer data)
1571 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1573 c_options->thumbnails.spec_standard =TRUE;
1574 c_options->thumbnails.cache_into_dirs = FALSE;
1578 static void cache_geeqie_cb(GtkWidget *widget, gpointer data)
1580 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1582 c_options->thumbnails.spec_standard =FALSE;
1583 c_options->thumbnails.cache_into_dirs = FALSE;
1587 static void cache_local_cb(GtkWidget *widget, gpointer data)
1589 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1591 c_options->thumbnails.cache_into_dirs = TRUE;
1592 c_options->thumbnails.spec_standard =FALSE;
1596 static void help_search_engine_entry_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1597 GdkEvent *event, gpointer userdata)
1599 if (pos == GTK_ENTRY_ICON_PRIMARY)
1601 gtk_entry_set_text(GTK_ENTRY(userdata), HELP_SEARCH_ENGINE);
1605 gtk_entry_set_text(GTK_ENTRY(userdata), "");
1609 static void star_rating_star_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1610 GdkEvent *event, gpointer userdata)
1612 gchar *rating_symbol;
1614 if (pos == GTK_ENTRY_ICON_PRIMARY)
1616 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_STAR);
1617 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1618 g_free(rating_symbol);
1622 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1623 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1624 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1628 static void star_rating_rejected_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1629 GdkEvent *event, gpointer userdata)
1631 gchar *rating_symbol;
1633 if (pos == GTK_ENTRY_ICON_PRIMARY)
1635 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_REJECTED);
1636 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1637 g_free(rating_symbol);
1641 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1642 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1643 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1647 static guint star_rating_symbol_test(GtkWidget *widget, gpointer data)
1649 GtkContainer *hbox = data;
1650 GString *str = g_string_new(NULL);
1651 GtkEntry *hex_code_entry;
1652 gchar *hex_code_full;
1655 guint64 hex_value = 0;
1657 list = gtk_container_get_children(hbox);
1659 hex_code_entry = g_list_nth_data(list, 2);
1660 hex_code_full = g_strdup(gtk_entry_get_text(hex_code_entry));
1662 hex_code = g_strsplit(hex_code_full, "+", 2);
1663 if (hex_code[0] && hex_code[1])
1665 hex_value = strtoull(hex_code[1], NULL, 16);
1667 if (!hex_value || hex_value > 0x10FFFF)
1669 hex_value = 0x003F; // Unicode 'Question Mark'
1671 str = g_string_append_unichar(str, (gunichar)hex_value);
1672 gtk_label_set_text(g_list_nth_data(list, 1), str->str);
1674 g_strfreev(hex_code);
1675 g_string_free(str, TRUE);
1676 g_free(hex_code_full);
1681 static void star_rating_star_test_cb(GtkWidget *widget, gpointer data)
1683 guint64 star_symbol;
1685 star_symbol = star_rating_symbol_test(widget, data);
1686 c_options->star_rating.star = star_symbol;
1689 static void star_rating_rejected_test_cb(GtkWidget *widget, gpointer data)
1691 guint64 rejected_symbol;
1693 rejected_symbol = star_rating_symbol_test(widget, data);
1694 c_options->star_rating.rejected = rejected_symbol;
1697 /* general options tab */
1698 static void config_tab_general(GtkWidget *notebook)
1703 GtkWidget *group_frame;
1704 GtkWidget *subgroup;
1706 GtkWidget *ct_button;
1709 gint hours, minutes, remainder;
1711 GtkWidget *star_rating_entry;
1713 gchar *rating_symbol;
1715 vbox = scrolled_notebook_page(notebook, _("General"));
1717 group = pref_group_new(vbox, FALSE, _("Thumbnails"), GTK_ORIENTATION_VERTICAL);
1719 table = pref_table_new(group, 2, 2, FALSE, FALSE);
1720 add_thumb_size_menu(table, 0, 0, _("Size:"));
1721 add_quality_menu(table, 0, 1, _("Quality:"), options->thumbnails.quality, &c_options->thumbnails.quality);
1723 ct_button = pref_checkbox_new_int(group, _("Cache thumbnails"),
1724 options->thumbnails.enable_caching, &c_options->thumbnails.enable_caching);
1726 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1727 pref_checkbox_link_sensitivity(ct_button, subgroup);
1729 c_options->thumbnails.spec_standard = options->thumbnails.spec_standard;
1730 c_options->thumbnails.cache_into_dirs = options->thumbnails.cache_into_dirs;
1731 group_frame = pref_frame_new(subgroup, TRUE, _("Use Geeqie thumbnail style and cache"),
1732 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1733 button = pref_radiobutton_new(group_frame, NULL, get_thumbnails_cache_dir(),
1734 !options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1735 G_CALLBACK(cache_geeqie_cb), NULL);
1737 group_frame = pref_frame_new(subgroup, TRUE,
1738 _("Store thumbnails local to image folder (non-standard)"),
1739 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1740 pref_radiobutton_new(group_frame, button, "*/.thumbnails",
1741 !options->thumbnails.spec_standard && options->thumbnails.cache_into_dirs,
1742 G_CALLBACK(cache_local_cb), NULL);
1744 group_frame = pref_frame_new(subgroup, TRUE,
1745 _("Use standard thumbnail style and cache, shared with other applications"),
1746 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1747 pref_radiobutton_new(group_frame, button, get_thumbnails_standard_cache_dir(),
1748 options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1749 G_CALLBACK(cache_standard_cb), NULL);
1751 pref_checkbox_new_int(group, _("Use EXIF thumbnails when available (EXIF thumbnails may be outdated)"),
1752 options->thumbnails.use_exif, &c_options->thumbnails.use_exif);
1754 spin = pref_spin_new_int(group, _("Collection preview:"), NULL,
1756 options->thumbnails.collection_preview, &c_options->thumbnails.collection_preview);
1757 gtk_widget_set_tooltip_text(spin, _("The maximum number of thumbnails shown in a Collection preview montage"));
1759 #ifdef HAVE_FFMPEGTHUMBNAILER_METADATA
1760 pref_checkbox_new_int(group, _("Use embedded metadata in video files as thumbnails when available"),
1761 options->thumbnails.use_ft_metadata, &c_options->thumbnails.use_ft_metadata);
1763 // pref_checkbox_new_int(group, _("Ignore embedded metadata if size is too small"),
1764 // options->thumbnails.use_ft_metadata_small, &c_options->thumbnails.use_ft_metadata_small);
1767 group = pref_group_new(vbox, FALSE, _("Star Rating"), GTK_ORIENTATION_VERTICAL);
1769 c_options->star_rating.star = options->star_rating.star;
1770 c_options->star_rating.rejected = options->star_rating.rejected;
1772 str = g_string_new(NULL);
1773 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1774 pref_label_new(hbox, "Star character: ");
1775 str = g_string_append_unichar(str, options->star_rating.star);
1776 pref_label_new(hbox, g_strdup(str->str));
1777 rating_symbol = g_strdup_printf("U+%X", options->star_rating.star);
1778 star_rating_entry = gtk_entry_new();
1779 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
1780 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
1781 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
1782 gtk_widget_show(star_rating_entry);
1783 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
1784 G_CALLBACK(star_rating_star_test_cb), hbox);
1785 gtk_widget_set_tooltip_text(button, _("Display selected character"));
1786 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1787 gtk_widget_show(button);
1788 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."));
1789 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1790 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
1791 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1792 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
1793 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1794 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
1795 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1796 GTK_ENTRY_ICON_PRIMARY, _("Default"));
1797 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
1798 G_CALLBACK(star_rating_star_icon_cb),
1801 g_string_free(str, TRUE);
1802 g_free(rating_symbol);
1804 str = g_string_new(NULL);
1805 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1806 pref_label_new(hbox, "Rejected character: ");
1807 str = g_string_append_unichar(str, options->star_rating.rejected);
1808 pref_label_new(hbox, g_strdup(str->str));
1809 rating_symbol = g_strdup_printf("U+%X", options->star_rating.rejected);
1810 star_rating_entry = gtk_entry_new();
1811 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
1812 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
1813 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
1814 gtk_widget_show(star_rating_entry);
1815 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
1816 G_CALLBACK(star_rating_rejected_test_cb), hbox);
1817 gtk_widget_set_tooltip_text(button, _("Display selected character"));
1818 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1819 gtk_widget_show(button);
1820 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."));
1821 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1822 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
1823 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1824 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
1825 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1826 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
1827 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1828 GTK_ENTRY_ICON_PRIMARY, _("Default"));
1829 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
1830 G_CALLBACK(star_rating_rejected_icon_cb),
1833 g_string_free(str, TRUE);
1834 g_free(rating_symbol);
1836 group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
1838 c_options->slideshow.delay = options->slideshow.delay;
1839 hours = options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
1840 remainder = options->slideshow.delay % (3600 * SLIDESHOW_SUBSECOND_PRECISION);
1841 minutes = remainder / (60 * SLIDESHOW_SUBSECOND_PRECISION);
1842 seconds = (gdouble)(remainder % (60 * SLIDESHOW_SUBSECOND_PRECISION)) /
1843 SLIDESHOW_SUBSECOND_PRECISION;
1845 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1847 spin = pref_spin_new(hbox, _("Delay between image change hrs:mins:secs.dec"), NULL,
1849 options->slideshow.delay ? hours : 0.0,
1850 G_CALLBACK(slideshow_delay_hours_cb), NULL);
1851 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1852 spin = pref_spin_new(hbox, ":" , NULL,
1854 options->slideshow.delay ? minutes: 0.0,
1855 G_CALLBACK(slideshow_delay_minutes_cb), NULL);
1856 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1857 spin = pref_spin_new(hbox, ":", NULL,
1858 SLIDESHOW_MIN_SECONDS, 59, 1.0, 1,
1859 options->slideshow.delay ? seconds : 10.0,
1860 G_CALLBACK(slideshow_delay_seconds_cb), NULL);
1861 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1863 pref_checkbox_new_int(group, _("Random"), options->slideshow.random, &c_options->slideshow.random);
1864 pref_checkbox_new_int(group, _("Repeat"), options->slideshow.repeat, &c_options->slideshow.repeat);
1866 group = pref_group_new(vbox, FALSE, _("Image loading and caching"), GTK_ORIENTATION_VERTICAL);
1868 pref_spin_new_int(group, _("Decoded image cache size (Mb):"), NULL,
1869 0, 99999, 1, options->image.image_cache_max, &c_options->image.image_cache_max);
1870 pref_checkbox_new_int(group, _("Preload next image"),
1871 options->image.enable_read_ahead, &c_options->image.enable_read_ahead);
1873 pref_checkbox_new_int(group, _("Refresh on file change"),
1874 options->update_on_time_change, &c_options->update_on_time_change);
1876 group = pref_group_new(vbox, FALSE, _("Info sidebar heights"), GTK_ORIENTATION_VERTICAL);
1877 pref_label_new(group, _("NOTE! Geeqie must be restarted for changes to take effect"));
1878 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1879 pref_spin_new_int(hbox, _("Keywords:"), NULL,
1881 options->info_keywords.height, &c_options->info_keywords.height);
1882 pref_spin_new_int(hbox, _("Title:"), NULL,
1884 options->info_title.height, &c_options->info_title.height);
1885 pref_spin_new_int(hbox, _("Comment:"), NULL,
1887 options->info_comment.height, &c_options->info_comment.height);
1888 pref_spin_new_int(hbox, _("Rating:"), NULL,
1890 options->info_rating.height, &c_options->info_rating.height);
1892 group = pref_group_new(vbox, FALSE, _("Show predefined keyword tree"), GTK_ORIENTATION_VERTICAL);
1894 pref_checkbox_new_int(group, _("Show predefined keyword tree (NOTE! Geeqie must be restarted for change to take effect)"),
1895 options->show_predefined_keyword_tree, &c_options->show_predefined_keyword_tree);
1897 group = pref_group_new(vbox, FALSE, _("On-line help search engine"), GTK_ORIENTATION_VERTICAL);
1899 help_search_engine_entry = gtk_entry_new();
1900 gtk_entry_set_text(GTK_ENTRY(help_search_engine_entry), options->help_search_engine);
1901 gtk_box_pack_start(GTK_BOX(group), help_search_engine_entry, FALSE, FALSE, 0);
1902 gtk_widget_show(help_search_engine_entry);
1904 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"));
1906 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
1907 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
1908 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
1909 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
1910 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
1911 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
1912 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
1913 GTK_ENTRY_ICON_PRIMARY, _("Default"));
1914 g_signal_connect(GTK_ENTRY(help_search_engine_entry), "icon-press",
1915 G_CALLBACK(help_search_engine_entry_icon_cb),
1916 help_search_engine_entry);
1920 static void config_tab_image(GtkWidget *notebook)
1925 GtkWidget *ct_button;
1926 GtkWidget *enlargement_button;
1930 vbox = scrolled_notebook_page(notebook, _("Image"));
1932 group = pref_group_new(vbox, FALSE, _("Zoom"), GTK_ORIENTATION_VERTICAL);
1934 table = pref_table_new(group, 2, 1, FALSE, FALSE);
1935 add_quality_menu(table, 0, 0, _("Quality:"), options->image.zoom_quality, &c_options->image.zoom_quality);
1938 pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library"),
1939 options->image.use_clutter_renderer, &c_options->image.use_clutter_renderer);
1942 pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"),
1943 options->image.zoom_2pass, &c_options->image.zoom_2pass);
1945 c_options->image.zoom_increment = options->image.zoom_increment;
1946 spin = pref_spin_new(group, _("Zoom increment:"), NULL,
1947 0.01, 4.0, 0.01, 2, (gdouble)options->image.zoom_increment / 100.0,
1948 G_CALLBACK(zoom_increment_cb), NULL);
1949 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1951 group = pref_group_new(vbox, FALSE, _("Fit image to window"), GTK_ORIENTATION_VERTICAL);
1953 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1954 enlargement_button = pref_checkbox_new_int(hbox, _("Allow enlargement of image (max. size in %)"),
1955 options->image.zoom_to_fit_allow_expand, &c_options->image.zoom_to_fit_allow_expand);
1956 spin = pref_spin_new_int(hbox, NULL, NULL,
1958 options->image.max_enlargement_size, &c_options->image.max_enlargement_size);
1959 pref_checkbox_link_sensitivity(enlargement_button, spin);
1960 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."));
1962 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1963 ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (% of actual window):"),
1964 options->image.limit_autofit_size, &c_options->image.limit_autofit_size);
1965 spin = pref_spin_new_int(hbox, NULL, NULL,
1967 options->image.max_autofit_size, &c_options->image.max_autofit_size);
1968 pref_checkbox_link_sensitivity(ct_button, spin);
1969 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."));
1971 group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
1973 pref_checkbox_new_int(group, _("Use custom border color in window mode"),
1974 options->image.use_custom_border_color, &c_options->image.use_custom_border_color);
1976 pref_checkbox_new_int(group, _("Use custom border color in fullscreen mode"),
1977 options->image.use_custom_border_color_in_fullscreen, &c_options->image.use_custom_border_color_in_fullscreen);
1979 pref_color_button_new(group, _("Border color"), &options->image.border_color,
1980 G_CALLBACK(pref_color_button_set_cb), &c_options->image.border_color);
1982 c_options->image.border_color = options->image.border_color;
1984 pref_color_button_new(group, _("Alpha channel color 1"), &options->image.alpha_color_1,
1985 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_1);
1987 pref_color_button_new(group, _("Alpha channel color 2"), &options->image.alpha_color_2,
1988 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_2);
1990 c_options->image.alpha_color_1 = options->image.alpha_color_1;
1991 c_options->image.alpha_color_2 = options->image.alpha_color_2;
1993 group = pref_group_new(vbox, FALSE, _("Convenience"), GTK_ORIENTATION_VERTICAL);
1995 pref_checkbox_new_int(group, _("Auto rotate proofs using Exif information"),
1996 options->image.exif_proof_rotate_enable, &c_options->image.exif_proof_rotate_enable);
2000 static void config_tab_windows(GtkWidget *notebook)
2006 GtkWidget *ct_button;
2008 GtkWidget *image_overlay_template_view;
2009 GtkWidget *scrolled;
2010 GtkTextBuffer *buffer;
2012 vbox = scrolled_notebook_page(notebook, _("Windows"));
2014 group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
2016 ct_button = pref_checkbox_new_int(group, _("Remember window positions"),
2017 options->save_window_positions, &c_options->save_window_positions);
2019 button = pref_checkbox_new_int(group, _("Use saved window positions also for new windows"),
2020 options->use_saved_window_positions_for_new_windows, &c_options->use_saved_window_positions_for_new_windows);
2021 pref_checkbox_link_sensitivity(ct_button, button);
2023 pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
2024 options->tools_restore_state, &c_options->tools_restore_state);
2026 pref_checkbox_new_int(group, _("Remember dialog window positions"),
2027 options->save_dialog_window_positions, &c_options->save_dialog_window_positions);
2029 pref_checkbox_new_int(group, _("Show window IDs"),
2030 options->show_window_ids, &c_options->show_window_ids);
2032 group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
2034 pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
2035 options->image.fit_window_to_image, &c_options->image.fit_window_to_image);
2037 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2038 ct_button = pref_checkbox_new_int(hbox, _("Limit size when auto-sizing window (%):"),
2039 options->image.limit_window_size, &c_options->image.limit_window_size);
2040 spin = pref_spin_new_int(hbox, NULL, NULL,
2042 options->image.max_window_size, &c_options->image.max_window_size);
2043 pref_checkbox_link_sensitivity(ct_button, spin);
2045 group = pref_group_new(vbox, FALSE, _("Full screen"), GTK_ORIENTATION_VERTICAL);
2047 c_options->fullscreen.screen = options->fullscreen.screen;
2048 c_options->fullscreen.above = options->fullscreen.above;
2049 hbox = fullscreen_prefs_selection_new(_("Location:"), &c_options->fullscreen.screen, &c_options->fullscreen.above);
2050 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2051 gtk_widget_show(hbox);
2053 pref_checkbox_new_int(group, _("Smooth image flip"),
2054 options->fullscreen.clean_flip, &c_options->fullscreen.clean_flip);
2055 pref_checkbox_new_int(group, _("Disable screen saver"),
2056 options->fullscreen.disable_saver, &c_options->fullscreen.disable_saver);
2059 group = pref_group_new(vbox, FALSE, _("Overlay Screen Display"), GTK_ORIENTATION_VERTICAL);
2061 pref_label_new(group, _("Image overlay template"));
2063 scrolled = gtk_scrolled_window_new(NULL, NULL);
2064 gtk_widget_set_size_request(scrolled, 200, 150);
2065 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2066 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
2067 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2068 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 5);
2069 gtk_widget_show(scrolled);
2071 image_overlay_template_view = gtk_text_view_new();
2073 gtk_widget_set_tooltip_markup(image_overlay_template_view,
2074 _("<i>%name%</i> results in the filename of the picture.\n"
2075 "Also available: <i>%collection%</i>, <i>%number%</i>, <i>%total%</i>, <i>%date%</i>,\n"
2076 "<i>%size%</i> (filesize), <i>%width%</i>, <i>%height%</i>, <i>%res%</i> (resolution),\n"
2077 "<i>%rating%</i>, <i>%keywords%</i>, <i>%comment%</i> (XMP), <i>%imagecomment%</i> (JPEG)\n"
2078 "To access exif data use the exif name, e. g. <i>%formatted.Camera%</i> is the formatted camera name,\n"
2079 "<i>%Exif.Photo.DateTimeOriginal%</i> the date of the original shot.\n"
2080 "<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"
2081 "If two or more variables are connected with the |-sign, it prints available variables with a separator.\n"
2082 "<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"
2083 "if there's no ISO information in the Exif data.\n"
2084 "If a line is empty, it is removed. This allows one to add lines that totally disappear when no data is available.\n"
2086 gtk_container_add(GTK_CONTAINER(scrolled), image_overlay_template_view);
2087 gtk_widget_show(image_overlay_template_view);
2089 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2091 #if GTK_CHECK_VERSION(3,4,0)
2092 button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
2093 G_CALLBACK(image_overlay_set_font_cb), notebook);
2095 button = gtk_font_button_new();
2096 gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Image Overlay Font");
2097 gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->image_overlay.font);
2098 g_signal_connect(G_OBJECT(button), "font-set",
2099 G_CALLBACK(image_overlay_set_font_cb),NULL);
2101 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2102 gtk_widget_show(button);
2104 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Text"), FALSE,
2105 G_CALLBACK(image_overlay_set_text_colour_cb), NULL);
2106 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2107 gtk_widget_show(button);
2109 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Background"), FALSE,
2110 G_CALLBACK(image_overlay_set_background_colour_cb), NULL);
2111 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2112 gtk_widget_show(button);
2113 image_overlay_set_text_colours();
2115 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2116 G_CALLBACK(image_overlay_default_template_cb), image_overlay_template_view);
2117 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2118 gtk_widget_show(button);
2120 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
2121 G_CALLBACK(image_overlay_help_cb), NULL);
2122 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2123 gtk_widget_show(button);
2125 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_overlay_template_view));
2126 if (options->image_overlay.template_string) gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
2127 g_signal_connect(G_OBJECT(buffer), "changed",
2128 G_CALLBACK(image_overlay_template_view_changed_cb), image_overlay_template_view);
2133 static GtkTreeModel *create_class_model(void)
2135 GtkListStore *model;
2139 /* create list store */
2140 model = gtk_list_store_new(1, G_TYPE_STRING);
2141 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
2143 gtk_list_store_append(model, &iter);
2144 gtk_list_store_set(model, &iter, 0, _(format_class_list[i]), -1);
2146 return GTK_TREE_MODEL (model);
2151 static void config_tab_files(GtkWidget *notebook)
2158 GtkWidget *ct_button;
2159 GtkWidget *scrolled;
2160 GtkWidget *filter_view;
2161 GtkCellRenderer *renderer;
2162 GtkTreeSelection *selection;
2163 GtkTreeViewColumn *column;
2165 vbox = scrolled_notebook_page(notebook, _("Files"));
2167 group = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2169 pref_checkbox_new_int(group, _("Show hidden files or folders"),
2170 options->file_filter.show_hidden_files, &c_options->file_filter.show_hidden_files);
2171 pref_checkbox_new_int(group, _("Show parent folder (..)"),
2172 options->file_filter.show_parent_directory, &c_options->file_filter.show_parent_directory);
2173 pref_checkbox_new_int(group, _("Case sensitive sort"),
2174 options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
2175 pref_checkbox_new_int(group, _("Natural sort order"),
2176 options->file_sort.natural, &c_options->file_sort.natural);
2177 pref_checkbox_new_int(group, _("Disable file extension checks"),
2178 options->file_filter.disable_file_extension_checks, &c_options->file_filter.disable_file_extension_checks);
2180 ct_button = pref_checkbox_new_int(group, _("Disable File Filtering"),
2181 options->file_filter.disable, &c_options->file_filter.disable);
2184 group = pref_group_new(vbox, FALSE, _("Grouping sidecar extensions"), GTK_ORIENTATION_VERTICAL);
2186 sidecar_ext_entry = gtk_entry_new();
2187 gtk_entry_set_text(GTK_ENTRY(sidecar_ext_entry), options->sidecar.ext);
2188 gtk_box_pack_start(GTK_BOX(group), sidecar_ext_entry, FALSE, FALSE, 0);
2189 gtk_widget_show(sidecar_ext_entry);
2191 group = pref_group_new(vbox, TRUE, _("File types"), GTK_ORIENTATION_VERTICAL);
2193 frame = pref_group_parent(group);
2194 g_signal_connect(G_OBJECT(ct_button), "toggled",
2195 G_CALLBACK(filter_disable_cb), frame);
2196 gtk_widget_set_sensitive(frame, !options->file_filter.disable);
2198 scrolled = gtk_scrolled_window_new(NULL, NULL);
2199 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2200 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2201 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2202 gtk_widget_show(scrolled);
2204 filter_store = gtk_list_store_new(1, G_TYPE_POINTER);
2205 filter_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(filter_store));
2206 g_object_unref(filter_store);
2207 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
2208 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
2210 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), FALSE);
2212 column = gtk_tree_view_column_new();
2213 gtk_tree_view_column_set_title(column, _("Filter"));
2214 gtk_tree_view_column_set_resizable(column, TRUE);
2216 renderer = gtk_cell_renderer_toggle_new();
2217 g_signal_connect(G_OBJECT(renderer), "toggled",
2218 G_CALLBACK(filter_store_enable_cb), filter_store);
2219 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2220 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2221 GINT_TO_POINTER(FE_ENABLE), NULL);
2223 renderer = gtk_cell_renderer_text_new();
2224 g_signal_connect(G_OBJECT(renderer), "edited",
2225 G_CALLBACK(filter_store_ext_edit_cb), filter_store);
2226 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2227 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2228 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2229 GINT_TO_POINTER(FE_EXTENSION), NULL);
2230 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2232 column = gtk_tree_view_column_new();
2233 gtk_tree_view_column_set_title(column, _("Description"));
2234 gtk_tree_view_column_set_resizable(column, TRUE);
2235 gtk_tree_view_column_set_fixed_width(column, 200);
2236 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
2238 renderer = gtk_cell_renderer_text_new();
2239 g_signal_connect(G_OBJECT(renderer), "edited",
2240 G_CALLBACK(filter_store_desc_edit_cb), filter_store);
2241 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2242 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2243 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2244 GINT_TO_POINTER(FE_DESCRIPTION), NULL);
2245 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2247 column = gtk_tree_view_column_new();
2248 gtk_tree_view_column_set_title(column, _("Class"));
2249 gtk_tree_view_column_set_resizable(column, TRUE);
2250 renderer = gtk_cell_renderer_combo_new();
2251 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE,
2252 "model", create_class_model(),
2257 g_signal_connect(G_OBJECT(renderer), "edited",
2258 G_CALLBACK(filter_store_class_edit_cb), filter_store);
2259 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2260 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2261 GINT_TO_POINTER(FE_CLASS), NULL);
2262 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2264 column = gtk_tree_view_column_new();
2265 gtk_tree_view_column_set_title(column, _("Writable"));
2266 gtk_tree_view_column_set_resizable(column, FALSE);
2267 renderer = gtk_cell_renderer_toggle_new();
2268 g_signal_connect(G_OBJECT(renderer), "toggled",
2269 G_CALLBACK(filter_store_writable_cb), filter_store);
2270 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2271 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2272 GINT_TO_POINTER(FE_WRITABLE), NULL);
2273 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2275 column = gtk_tree_view_column_new();
2276 gtk_tree_view_column_set_title(column, _("Sidecar is allowed"));
2277 gtk_tree_view_column_set_resizable(column, FALSE);
2278 renderer = gtk_cell_renderer_toggle_new();
2279 g_signal_connect(G_OBJECT(renderer), "toggled",
2280 G_CALLBACK(filter_store_sidecar_cb), filter_store);
2281 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2282 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2283 GINT_TO_POINTER(FE_ALLOW_SIDECAR), NULL);
2284 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2287 filter_store_populate();
2288 gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
2289 gtk_widget_show(filter_view);
2291 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2293 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2294 G_CALLBACK(filter_default_cb), filter_view);
2295 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2296 gtk_widget_show(button);
2298 button = pref_button_new(NULL, GTK_STOCK_REMOVE, NULL, FALSE,
2299 G_CALLBACK(filter_remove_cb), filter_view);
2300 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2301 gtk_widget_show(button);
2303 button = pref_button_new(NULL, GTK_STOCK_ADD, NULL, FALSE,
2304 G_CALLBACK(filter_add_cb), filter_view);
2305 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2306 gtk_widget_show(button);
2310 static void config_tab_metadata(GtkWidget *notebook)
2315 GtkWidget *ct_button;
2319 vbox = scrolled_notebook_page(notebook, _("Metadata"));
2322 group = pref_group_new(vbox, FALSE, _("Metadata writing process"), GTK_ORIENTATION_VERTICAL);
2324 label = pref_label_new(group, _("Warning: Geeqie is built without Exiv2. Some options are disabled."));
2326 label = pref_label_new(group, _("Metadata are written in the following order. The process ends after first success."));
2327 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2329 ct_button = pref_checkbox_new_int(group, _("1) Save metadata in image files, or sidecar files, according to the XMP standard"),
2330 options->metadata.save_in_image_file, &c_options->metadata.save_in_image_file);
2332 gtk_widget_set_sensitive(ct_button, FALSE);
2335 pref_checkbox_new_int(group, _("2) Save metadata in '.metadata' folder, local to image folder (non-standard)"),
2336 options->metadata.enable_metadata_dirs, &c_options->metadata.enable_metadata_dirs);
2338 text = g_strdup_printf(_("3) Save metadata in Geeqie private directory '%s'"), get_metadata_cache_dir());
2339 label = pref_label_new(group, text);
2340 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2341 gtk_misc_set_padding(GTK_MISC(label), 22, 0);
2344 group = pref_group_new(vbox, FALSE, _("Step 1: Write to image files"), GTK_ORIENTATION_VERTICAL);
2346 gtk_widget_set_sensitive(group, FALSE);
2349 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2350 pref_checkbox_link_sensitivity(ct_button, hbox);
2352 pref_checkbox_new_int(hbox, _("Store metadata also in legacy IPTC tags (converted according to IPTC4XMP standard)"),
2353 options->metadata.save_legacy_IPTC, &c_options->metadata.save_legacy_IPTC);
2355 pref_checkbox_new_int(hbox, _("Warn if the image files are unwritable"),
2356 options->metadata.warn_on_write_problems, &c_options->metadata.warn_on_write_problems);
2358 pref_checkbox_new_int(hbox, _("Ask before writing to image files"),
2359 options->metadata.confirm_write, &c_options->metadata.confirm_write);
2361 pref_checkbox_new_int(hbox, _("Create sidecar files named image.ext.xmp (as opposed to image.xmp)"),
2362 options->metadata.sidecar_extended_name, &c_options->metadata.sidecar_extended_name);
2364 group = pref_group_new(vbox, FALSE, _("Step 2 and 3: write to Geeqie private files"), GTK_ORIENTATION_VERTICAL);
2366 gtk_widget_set_sensitive(group, FALSE);
2369 pref_checkbox_new_int(group, _("Use GQview legacy metadata format (supports only keywords and comments) instead of XMP"),
2370 options->metadata.save_legacy_format, &c_options->metadata.save_legacy_format);
2373 group = pref_group_new(vbox, FALSE, _("Miscellaneous"), GTK_ORIENTATION_VERTICAL);
2374 pref_checkbox_new_int(group, _("Write the same description tags (keywords, comment, etc.) to all grouped sidecars"),
2375 options->metadata.sync_grouped_files, &c_options->metadata.sync_grouped_files);
2377 pref_checkbox_new_int(group, _("Allow keywords to differ only in case"),
2378 options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
2380 ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"),
2381 options->metadata.write_orientation, &c_options->metadata.write_orientation);
2383 gtk_widget_set_sensitive(ct_button, FALSE);
2386 group = pref_group_new(vbox, FALSE, _("Auto-save options"), GTK_ORIENTATION_VERTICAL);
2388 ct_button = pref_checkbox_new_int(group, _("Write metadata after timeout"),
2389 options->metadata.confirm_after_timeout, &c_options->metadata.confirm_after_timeout);
2391 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2392 pref_checkbox_link_sensitivity(ct_button, hbox);
2394 pref_spin_new_int(hbox, _("Timeout (seconds):"), NULL, 0, 900, 1,
2395 options->metadata.confirm_timeout, &c_options->metadata.confirm_timeout);
2397 pref_checkbox_new_int(group, _("Write metadata on image change"),
2398 options->metadata.confirm_on_image_change, &c_options->metadata.confirm_on_image_change);
2400 pref_checkbox_new_int(group, _("Write metadata on directory change"),
2401 options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
2403 group = pref_group_new(vbox, FALSE, _("Pre-load metadata"), GTK_ORIENTATION_VERTICAL);
2405 ct_button = pref_checkbox_new_int(group, _("Read metadata in background"),
2406 options->read_metadata_in_idle, &c_options->read_metadata_in_idle);
2407 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");
2412 typedef struct _KeywordFindData KeywordFindData;
2413 struct _KeywordFindData
2420 GtkWidget *button_close;
2421 GtkWidget *button_stop;
2422 GtkWidget *button_start;
2423 GtkWidget *progress;
2431 guint idle_id; /* event source id */
2434 #define KEYWORD_DIALOG_WIDTH 400
2436 static void keywords_find_folder(KeywordFindData *kfd, FileData *dir_fd)
2438 GList *list_d = NULL;
2439 GList *list_f = NULL;
2443 filelist_read(dir_fd, &list_f, &list_d);
2447 filelist_read(dir_fd, &list_f, NULL);
2450 list_f = filelist_filter(list_f, FALSE);
2451 list_d = filelist_filter(list_d, TRUE);
2453 kfd->list = g_list_concat(list_f, kfd->list);
2454 kfd->list_dir = g_list_concat(list_d, kfd->list_dir);
2457 static void keywords_find_reset(KeywordFindData *kfd)
2459 filelist_free(kfd->list);
2462 filelist_free(kfd->list_dir);
2463 kfd->list_dir = NULL;
2466 static void keywords_find_close_cb(GenericDialog *fd, gpointer data)
2468 KeywordFindData *kfd = data;
2470 if (!gtk_widget_get_sensitive(kfd->button_close)) return;
2472 keywords_find_reset(kfd);
2473 generic_dialog_close(kfd->gd);
2477 static void keywords_find_finish(KeywordFindData *kfd)
2479 keywords_find_reset(kfd);
2481 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("done"));
2482 spinner_set_interval(kfd->spinner, -1);
2484 gtk_widget_set_sensitive(kfd->group, TRUE);
2485 gtk_widget_set_sensitive(kfd->button_start, TRUE);
2486 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2487 gtk_widget_set_sensitive(kfd->button_close, TRUE);
2490 static void keywords_find_stop_cb(GenericDialog *fd, gpointer data)
2492 KeywordFindData *kfd = data;
2494 g_idle_remove_by_data(kfd);
2496 keywords_find_finish(kfd);
2499 static gboolean keywords_find_file(gpointer data)
2501 KeywordFindData *kfd = data;
2503 GtkTextBuffer *buffer;
2511 fd = kfd->list->data;
2512 kfd->list = g_list_remove(kfd->list, fd);
2514 keywords = metadata_read_list(fd, KEYWORD_KEY, METADATA_PLAIN);
2515 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2519 gtk_text_buffer_get_end_iter(buffer, &iter);
2520 tmp = g_strconcat(keywords->data, "\n", NULL);
2521 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
2523 keywords = keywords->next;
2526 gtk_entry_set_text(GTK_ENTRY(kfd->progress), fd->path);
2527 file_data_unref(fd);
2528 string_list_free(keywords);
2532 else if (kfd->list_dir)
2536 fd = kfd->list_dir->data;
2537 kfd->list_dir = g_list_remove(kfd->list_dir, fd);
2539 keywords_find_folder(kfd, fd);
2541 file_data_unref(fd);
2546 keywords_find_finish(kfd);
2551 static void keywords_find_start_cb(GenericDialog *fd, gpointer data)
2553 KeywordFindData *kfd = data;
2556 if (kfd->list || !gtk_widget_get_sensitive(kfd->button_start)) return;
2558 path = remove_trailing_slash((gtk_entry_get_text(GTK_ENTRY(kfd->entry))));
2559 parse_out_relatives(path);
2563 warning_dialog(_("Invalid folder"),
2564 _("The specified folder can not be found."),
2565 GTK_STOCK_DIALOG_WARNING, kfd->gd->dialog);
2571 gtk_widget_set_sensitive(kfd->group, FALSE);
2572 gtk_widget_set_sensitive(kfd->button_start, FALSE);
2573 gtk_widget_set_sensitive(kfd->button_stop, TRUE);
2574 gtk_widget_set_sensitive(kfd->button_close, FALSE);
2575 spinner_set_interval(kfd->spinner, SPINNER_SPEED);
2577 dir_fd = file_data_new_dir(path);
2578 keywords_find_folder(kfd, dir_fd);
2579 file_data_unref(dir_fd);
2580 kfd->idle_id = g_idle_add(keywords_find_file, kfd);
2586 static void keywords_find_dialog(GtkWidget *widget, const gchar *path)
2588 KeywordFindData *kfd;
2592 kfd = g_new0(KeywordFindData, 1);
2594 kfd->gd = generic_dialog_new(_("Search for keywords"),
2595 "search_for_keywords",
2598 gtk_window_set_default_size(GTK_WINDOW(kfd->gd->dialog), KEYWORD_DIALOG_WIDTH, -1);
2599 kfd->gd->cancel_cb = keywords_find_close_cb;
2600 kfd->button_close = generic_dialog_add_button(kfd->gd, GTK_STOCK_CLOSE, NULL,
2601 keywords_find_close_cb, FALSE);
2602 kfd->button_start = generic_dialog_add_button(kfd->gd, GTK_STOCK_OK, _("S_tart"),
2603 keywords_find_start_cb, FALSE);
2604 kfd->button_stop = generic_dialog_add_button(kfd->gd, GTK_STOCK_STOP, NULL,
2605 keywords_find_stop_cb, FALSE);
2606 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2608 generic_dialog_add_message(kfd->gd, NULL, _("Search for keywords"), NULL, FALSE);
2610 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0);
2611 pref_spacer(hbox, PREF_PAD_INDENT);
2612 kfd->group = pref_box_new(hbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2614 hbox = pref_box_new(kfd->group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2615 pref_label_new(hbox, _("Folder:"));
2617 label = tab_completion_new(&kfd->entry, path, NULL, NULL, NULL, NULL);
2618 tab_completion_add_select_button(kfd->entry,_("Select folder") , TRUE);
2619 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
2620 gtk_widget_show(label);
2622 pref_checkbox_new_int(kfd->group, _("Include subfolders"), FALSE, &kfd->recurse);
2624 pref_line(kfd->gd->vbox, PREF_PAD_SPACE);
2625 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2627 kfd->progress = gtk_entry_new();
2628 gtk_widget_set_can_focus(kfd->progress, FALSE);
2629 gtk_editable_set_editable(GTK_EDITABLE(kfd->progress), FALSE);
2630 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("click start to begin"));
2631 gtk_box_pack_start(GTK_BOX(hbox), kfd->progress, TRUE, TRUE, 0);
2632 gtk_widget_show(kfd->progress);
2634 kfd->spinner = spinner_new(NULL, -1);
2635 gtk_box_pack_start(GTK_BOX(hbox), kfd->spinner, FALSE, FALSE, 0);
2636 gtk_widget_show(kfd->spinner);
2640 gtk_widget_show(kfd->gd->dialog);
2643 static void keywords_find_cb(GtkWidget *widget, gpointer data)
2645 const gchar *path = layout_get_path(NULL);
2647 if (!path || !*path) path = homedir();
2648 keywords_find_dialog(widget, path);
2651 static void config_tab_keywords_save()
2653 GtkTextIter start, end;
2654 GtkTextBuffer *buffer;
2655 GList *kw_list = NULL;
2661 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2662 gtk_text_buffer_get_bounds(buffer, &start, &end);
2664 buffer_text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
2666 kw_split = strtok(buffer_text, "\n");
2667 while (kw_split != NULL)
2673 if (g_strcmp0(work->data, kw_split) == 0)
2682 kw_list = g_list_append(kw_list, g_strdup(kw_split));
2684 kw_split = strtok(NULL, "\n");
2687 keyword_list_set(kw_list);
2689 string_list_free(kw_list);
2690 g_free(buffer_text);
2693 static void config_tab_keywords(GtkWidget *notebook)
2699 GtkWidget *scrolled;
2701 GtkTextBuffer *buffer;
2704 vbox = scrolled_notebook_page(notebook, _("Keywords"));
2706 group = pref_group_new(vbox, TRUE, _("Edit keywords autocompletion list"), GTK_ORIENTATION_VERTICAL);
2708 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2710 button = pref_button_new(hbox, GTK_STOCK_EXECUTE, _("Search"), FALSE,
2711 G_CALLBACK(keywords_find_cb), keyword_text);
2712 gtk_widget_set_tooltip_text(button, "Search for existing keywords");
2715 keyword_text = gtk_text_view_new();
2716 gtk_widget_set_size_request(keyword_text, 20, 20);
2717 scrolled = gtk_scrolled_window_new(NULL, NULL);
2718 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2719 gtk_widget_show(scrolled);
2721 gtk_container_add(GTK_CONTAINER(scrolled), keyword_text);
2722 gtk_widget_show(keyword_text);
2724 gtk_text_view_set_editable(GTK_TEXT_VIEW(keyword_text), TRUE);
2726 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2727 gtk_text_buffer_create_tag(buffer, "monospace",
2728 "family", "monospace", NULL);
2730 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(keyword_text), GTK_WRAP_WORD);
2731 gtk_text_buffer_get_start_iter(buffer, &iter);
2732 gtk_text_buffer_create_mark(buffer, "end", &iter, FALSE);
2735 path = g_build_filename(get_rc_dir(), "keywords", NULL);
2737 GList *kwl = keyword_list_get();
2738 kwl = g_list_first(kwl);
2741 gtk_text_buffer_get_end_iter (buffer, &iter);
2742 tmp = g_strconcat(kwl->data, "\n", NULL);
2743 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
2748 gtk_text_buffer_set_modified(buffer, FALSE);
2755 static void intent_menu_cb(GtkWidget *combo, gpointer data)
2757 gint *option = data;
2759 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
2763 *option = INTENT_PERCEPTUAL;
2766 *option = INTENT_RELATIVE_COLORIMETRIC;
2769 *option = INTENT_SATURATION;
2772 *option = INTENT_ABSOLUTE_COLORIMETRIC;
2777 static void add_intent_menu(GtkWidget *table, gint column, gint row, const gchar *text,
2778 gint option, gint *option_c)
2785 pref_table_label(table, column, row, text, 0.0);
2787 combo = gtk_combo_box_text_new();
2789 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Perceptual"));
2790 if (option == INTENT_PERCEPTUAL) current = 0;
2791 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Relative Colorimetric"));
2792 if (option == INTENT_RELATIVE_COLORIMETRIC) current = 1;
2793 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Saturation"));
2794 if (option == INTENT_SATURATION) current = 2;
2795 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Absolute Colorimetric"));
2796 if (option == INTENT_ABSOLUTE_COLORIMETRIC) current = 3;
2798 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
2800 gtk_widget_set_tooltip_text(combo,"Refer to the lcms documentation for the defaults used when the selected Intent is not available");
2802 g_signal_connect(G_OBJECT(combo), "changed",
2803 G_CALLBACK(intent_menu_cb), option_c);
2805 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
2806 GTK_EXPAND | GTK_FILL, 0, 0, 0);
2807 gtk_widget_show(combo);
2811 static void config_tab_color(GtkWidget *notebook)
2820 vbox = scrolled_notebook_page(notebook, _("Color management"));
2822 group = pref_group_new(vbox, FALSE, _("Input profiles"), GTK_ORIENTATION_VERTICAL);
2824 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
2827 table = pref_table_new(group, 3, COLOR_PROFILE_INPUTS + 1, FALSE, FALSE);
2828 gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
2830 label = pref_table_label(table, 0, 0, _("Type"), 0.0);
2831 pref_label_bold(label, TRUE, FALSE);
2833 label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
2834 pref_label_bold(label, TRUE, FALSE);
2836 label = pref_table_label(table, 2, 0, _("File"), 0.0);
2837 pref_label_bold(label, TRUE, FALSE);
2839 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
2844 buf = g_strdup_printf(_("Input %d:"), i + COLOR_PROFILE_FILE);
2845 pref_table_label(table, 0, i + 1, buf, 1.0);
2848 entry = gtk_entry_new();
2849 gtk_entry_set_max_length(GTK_ENTRY(entry), EDITOR_NAME_MAX_LENGTH);
2850 if (options->color_profile.input_name[i])
2852 gtk_entry_set_text(GTK_ENTRY(entry), options->color_profile.input_name[i]);
2854 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, i + 1, i + 2,
2855 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2856 gtk_widget_show(entry);
2857 color_profile_input_name_entry[i] = entry;
2859 tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, ".icc", "ICC Files", NULL);
2860 tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
2861 gtk_widget_set_size_request(entry, 160, -1);
2862 gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
2863 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2864 gtk_widget_show(tabcomp);
2865 color_profile_input_file_entry[i] = entry;
2868 group = pref_group_new(vbox, FALSE, _("Screen profile"), GTK_ORIENTATION_VERTICAL);
2870 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
2872 pref_checkbox_new_int(group, _("Use system screen profile if available"),
2873 options->color_profile.use_x11_screen_profile, &c_options->color_profile.use_x11_screen_profile);
2875 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2877 pref_table_label(table, 0, 0, _("Screen:"), 1.0);
2878 tabcomp = tab_completion_new(&color_profile_screen_file_entry,
2879 options->color_profile.screen_file, NULL, ".icc", "ICC Files", NULL);
2880 tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
2881 gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
2883 add_intent_menu(table, 0, 1, _("Render Intent:"), options->color_profile.render_intent, &c_options->color_profile.render_intent);
2885 gtk_table_attach(GTK_TABLE(table), tabcomp, 1, 2,
2887 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2889 gtk_widget_show(tabcomp);
2892 /* advanced entry tab */
2893 static void config_tab_behavior(GtkWidget *notebook)
2900 GtkWidget *ct_button;
2904 GtkWidget *with_rename;
2905 GtkWidget *collections_on_top;
2907 vbox = scrolled_notebook_page(notebook, _("Behavior"));
2909 group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
2911 pref_checkbox_new_int(group, _("Confirm file delete"),
2912 options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
2913 pref_checkbox_new_int(group, _("Enable Delete key"),
2914 options->file_ops.enable_delete_key, &c_options->file_ops.enable_delete_key);
2916 ct_button = pref_checkbox_new_int(group, _("Safe delete"),
2917 options->file_ops.safe_delete_enable, &c_options->file_ops.safe_delete_enable);
2919 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2920 pref_checkbox_link_sensitivity(ct_button, hbox);
2922 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
2923 pref_label_new(hbox, _("Folder:"));
2925 tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL, NULL, NULL);
2926 tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
2927 gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
2928 gtk_widget_show(tabcomp);
2930 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2931 pref_checkbox_link_sensitivity(ct_button, hbox);
2933 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
2934 spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MB"),
2935 0, 2048, 1, options->file_ops.safe_delete_folder_maxsize, &c_options->file_ops.safe_delete_folder_maxsize);
2936 gtk_widget_set_tooltip_markup(spin, _("Set to 0 for unlimited size"));
2937 button = pref_button_new(NULL, NULL, _("View"), FALSE,
2938 G_CALLBACK(safe_delete_view_cb), NULL);
2939 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2940 gtk_widget_show(button);
2942 button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
2943 G_CALLBACK(safe_delete_clear_cb), NULL);
2944 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2945 gtk_widget_show(button);
2948 group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
2950 pref_checkbox_new_int(group, _("Descend folders in tree view"),
2951 options->tree_descend_subdirs, &c_options->tree_descend_subdirs);
2953 pref_checkbox_new_int(group, _("In place renaming"),
2954 options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
2956 pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
2957 options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
2959 marks = pref_checkbox_new_int(group, _("Save marks on exit"),
2960 options->marks_save, &c_options->marks_save);
2961 gtk_widget_set_tooltip_text(marks,"Note that marks linked to a keyword will be saved irrespective of this setting");
2963 with_rename = pref_checkbox_new_int(group, _("Use \"With Rename\" as default for Copy/Move dialogs"),
2964 options->with_rename, &c_options->with_rename);
2965 gtk_widget_set_tooltip_text(with_rename,"Change the default button for Copy/Move dialogs");
2967 collections_on_top = pref_checkbox_new_int(group, _("Open collections on top"),
2968 options->collections_on_top, &c_options->collections_on_top);
2969 gtk_widget_set_tooltip_text(collections_on_top,"Open collections window on top");
2971 pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
2972 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
2974 pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
2975 16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
2977 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2978 add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
2980 group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
2982 pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
2983 options->progressive_key_scrolling, &c_options->progressive_key_scrolling);
2984 pref_spin_new_int(group, _("Keyboard scrolling step multiplier:"), NULL,
2985 1, 32, 1, options->keyboard_scroll_step, (int *)&c_options->keyboard_scroll_step);
2986 pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
2987 options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
2988 pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
2989 options->image_lm_click_nav, &c_options->image_lm_click_nav);
2990 pref_checkbox_new_int(group, _("Play video by left click on image"),
2991 options->image_l_click_video, &c_options->image_l_click_video);
2992 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2993 add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
2997 group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
2999 pref_spin_new_int(group, _("Debug level:"), NULL,
3000 DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
3002 pref_checkbox_new_int(group, _("Timer data"),
3003 options->log_window.timer_data, &c_options->log_window.timer_data);
3005 pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
3006 1, 99999, 1, options->log_window_lines, &options->log_window_lines);
3010 /* accelerators tab */
3011 static void config_tab_accelerators(GtkWidget *notebook)
3017 GtkWidget *scrolled;
3018 GtkWidget *accel_view;
3019 GtkCellRenderer *renderer;
3020 GtkTreeSelection *selection;
3021 GtkTreeViewColumn *column;
3023 vbox = scrolled_notebook_page(notebook, _("Keyboard"));
3025 group = pref_group_new(vbox, TRUE, _("Accelerators"), GTK_ORIENTATION_VERTICAL);
3027 scrolled = gtk_scrolled_window_new(NULL, NULL);
3028 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
3029 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
3030 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3031 gtk_widget_show(scrolled);
3033 accel_store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
3035 accel_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(accel_store));
3036 g_object_unref(accel_store);
3037 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(accel_view));
3038 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
3040 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(accel_view), FALSE);
3042 renderer = gtk_cell_renderer_text_new();
3044 column = gtk_tree_view_column_new_with_attributes(_("Action"),
3049 gtk_tree_view_column_set_sort_column_id(column, AE_ACTION);
3050 gtk_tree_view_column_set_resizable(column, TRUE);
3051 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3054 renderer = gtk_cell_renderer_accel_new();
3055 g_signal_connect(G_OBJECT(renderer), "accel-cleared",
3056 G_CALLBACK(accel_store_cleared_cb), accel_store);
3057 g_signal_connect(G_OBJECT(renderer), "accel-edited",
3058 G_CALLBACK(accel_store_edited_cb), accel_store);
3061 g_object_set (renderer,
3063 "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
3066 column = gtk_tree_view_column_new_with_attributes(_("KEY"),
3071 gtk_tree_view_column_set_sort_column_id(column, AE_KEY);
3072 gtk_tree_view_column_set_resizable(column, TRUE);
3073 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3075 renderer = gtk_cell_renderer_text_new();
3077 column = gtk_tree_view_column_new_with_attributes(_("Tooltip"),
3082 gtk_tree_view_column_set_sort_column_id(column, AE_TOOLTIP);
3083 gtk_tree_view_column_set_resizable(column, TRUE);
3084 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3086 renderer = gtk_cell_renderer_text_new();
3088 column = gtk_tree_view_column_new_with_attributes("Accel",
3093 gtk_tree_view_column_set_sort_column_id(column, AE_ACCEL);
3094 gtk_tree_view_column_set_resizable(column, TRUE);
3095 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3097 accel_store_populate();
3098 gtk_container_add(GTK_CONTAINER(scrolled), accel_view);
3099 gtk_widget_show(accel_view);
3101 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3103 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
3104 G_CALLBACK(accel_default_cb), accel_view);
3105 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3106 gtk_widget_show(button);
3108 button = pref_button_new(NULL, NULL, _("Reset selected"), FALSE,
3109 G_CALLBACK(accel_reset_cb), accel_view);
3110 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3111 gtk_widget_show(button);
3115 static void config_tab_toolbar(GtkWidget *notebook)
3118 GtkWidget *toolbardata;
3121 lw = layout_window_list->data;
3123 vbox = scrolled_notebook_page(notebook, _("Toolbar"));
3125 toolbardata = toolbar_select_new(lw);
3126 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3127 gtk_widget_show(vbox);
3131 static void config_tab_stereo(GtkWidget *notebook)
3139 GtkWidget *fs_button;
3140 vbox = scrolled_notebook_page(notebook, _("Stereo"));
3142 group = pref_group_new(vbox, FALSE, _("Windowed stereo mode"), GTK_ORIENTATION_VERTICAL);
3144 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3145 add_stereo_mode_menu(table, 0, 0, _("Windowed stereo mode"), options->stereo.mode, &c_options->stereo.mode, FALSE);
3147 table = pref_table_new(group, 2, 2, TRUE, FALSE);
3148 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3149 pref_checkbox_new_int(box, _("Mirror left image"),
3150 options->stereo.mode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.mirror_left);
3151 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3152 pref_checkbox_new_int(box, _("Flip left image"),
3153 options->stereo.mode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.flip_left);
3154 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3155 pref_checkbox_new_int(box, _("Mirror right image"),
3156 options->stereo.mode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.mirror_right);
3157 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3158 pref_checkbox_new_int(box, _("Flip right image"),
3159 options->stereo.mode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.flip_right);
3160 pref_checkbox_new_int(group, _("Swap left and right images"),
3161 options->stereo.mode & PR_STEREO_SWAP, &c_options->stereo.tmp.swap);
3162 pref_checkbox_new_int(group, _("Disable stereo mode on single image source"),
3163 options->stereo.mode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.temp_disable);
3165 group = pref_group_new(vbox, FALSE, _("Fullscreen stereo mode"), GTK_ORIENTATION_VERTICAL);
3166 fs_button = pref_checkbox_new_int(group, _("Use different settings for fullscreen"),
3167 options->stereo.enable_fsmode, &c_options->stereo.enable_fsmode);
3168 box2 = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
3169 pref_checkbox_link_sensitivity(fs_button, box2);
3170 table = pref_table_new(box2, 2, 1, FALSE, FALSE);
3171 add_stereo_mode_menu(table, 0, 0, _("Fullscreen stereo mode"), options->stereo.fsmode, &c_options->stereo.fsmode, TRUE);
3172 table = pref_table_new(box2, 2, 2, TRUE, FALSE);
3173 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3174 pref_checkbox_new_int(box, _("Mirror left image"),
3175 options->stereo.fsmode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.fs_mirror_left);
3176 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3177 pref_checkbox_new_int(box, _("Flip left image"),
3178 options->stereo.fsmode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.fs_flip_left);
3179 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3180 pref_checkbox_new_int(box, _("Mirror right image"),
3181 options->stereo.fsmode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.fs_mirror_right);
3182 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3183 pref_checkbox_new_int(box, _("Flip right image"),
3184 options->stereo.fsmode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.fs_flip_right);
3185 pref_checkbox_new_int(box2, _("Swap left and right images"),
3186 options->stereo.fsmode & PR_STEREO_SWAP, &c_options->stereo.tmp.fs_swap);
3187 pref_checkbox_new_int(box2, _("Disable stereo mode on single image source"),
3188 options->stereo.fsmode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.fs_temp_disable);
3190 group2 = pref_group_new(box2, FALSE, _("Fixed position"), GTK_ORIENTATION_VERTICAL);
3191 table = pref_table_new(group2, 5, 3, FALSE, FALSE);
3192 pref_table_spin_new_int(table, 0, 0, _("Width"), NULL,
3193 1, 5000, 1, options->stereo.fixed_w, &c_options->stereo.fixed_w);
3194 pref_table_spin_new_int(table, 3, 0, _("Height"), NULL,
3195 1, 5000, 1, options->stereo.fixed_h, &c_options->stereo.fixed_h);
3196 pref_table_spin_new_int(table, 0, 1, _("Left X"), NULL,
3197 0, 5000, 1, options->stereo.fixed_x1, &c_options->stereo.fixed_x1);
3198 pref_table_spin_new_int(table, 3, 1, _("Left Y"), NULL,
3199 0, 5000, 1, options->stereo.fixed_y1, &c_options->stereo.fixed_y1);
3200 pref_table_spin_new_int(table, 0, 2, _("Right X"), NULL,
3201 0, 5000, 1, options->stereo.fixed_x2, &c_options->stereo.fixed_x2);
3202 pref_table_spin_new_int(table, 3, 2, _("Right Y"), NULL,
3203 0, 5000, 1, options->stereo.fixed_y2, &c_options->stereo.fixed_y2);
3207 /* Main preferences window */
3208 static void config_window_create(void)
3210 GtkWidget *win_vbox;
3212 GtkWidget *notebook;
3214 GtkWidget *ct_button;
3216 if (!c_options) c_options = init_options(NULL);
3218 configwindow = window_new(GTK_WINDOW_TOPLEVEL, "preferences", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Preferences"));
3219 gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
3220 g_signal_connect(G_OBJECT(configwindow), "delete_event",
3221 G_CALLBACK(config_window_delete), NULL);
3222 gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
3223 gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
3224 gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
3226 win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
3227 gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
3228 gtk_widget_show(win_vbox);
3230 notebook = gtk_notebook_new();
3231 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP);
3232 gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
3234 config_tab_general(notebook);
3235 config_tab_image(notebook);
3236 config_tab_windows(notebook);
3237 config_tab_accelerators(notebook);
3238 config_tab_files(notebook);
3239 config_tab_metadata(notebook);
3240 config_tab_keywords(notebook);
3241 config_tab_color(notebook);
3242 config_tab_stereo(notebook);
3243 config_tab_behavior(notebook);
3244 config_tab_toolbar(notebook);
3246 hbox = gtk_hbutton_box_new();
3247 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
3248 gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
3249 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
3250 gtk_widget_show(hbox);
3252 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
3253 G_CALLBACK(config_window_help_cb), notebook);
3254 gtk_container_add(GTK_CONTAINER(hbox), button);
3255 gtk_widget_set_can_default(button, TRUE);
3256 gtk_widget_show(button);
3258 button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
3259 G_CALLBACK(config_window_ok_cb), NULL);
3260 gtk_container_add(GTK_CONTAINER(hbox), button);
3261 gtk_widget_set_can_default(button, TRUE);
3262 gtk_widget_grab_default(button);
3263 gtk_widget_show(button);
3267 button = pref_button_new(NULL, GTK_STOCK_SAVE, NULL, FALSE,
3268 G_CALLBACK(config_window_save_cb), NULL);
3269 gtk_container_add(GTK_CONTAINER(hbox), button);
3270 gtk_widget_set_can_default(button, TRUE);
3271 gtk_widget_show(button);
3273 button = pref_button_new(NULL, GTK_STOCK_APPLY, NULL, FALSE,
3274 G_CALLBACK(config_window_apply_cb), NULL);
3275 gtk_container_add(GTK_CONTAINER(hbox), button);
3276 gtk_widget_set_can_default(button, TRUE);
3277 gtk_widget_show(button);
3279 button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
3280 G_CALLBACK(config_window_close_cb), NULL);
3281 gtk_container_add(GTK_CONTAINER(hbox), button);
3282 gtk_widget_set_can_default(button, TRUE);
3283 gtk_widget_show(button);
3285 if (!generic_dialog_get_alternative_button_order(configwindow))
3287 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
3290 gtk_widget_show(notebook);
3292 gtk_widget_show(configwindow);
3296 *-----------------------------------------------------------------------------
3297 * config window show (public)
3298 *-----------------------------------------------------------------------------
3301 void show_config_window(void)
3305 gtk_window_present(GTK_WINDOW(configwindow));
3309 config_window_create();
3318 void show_about_window(LayoutWindow *lw)
3320 GdkPixbuf *pixbuf_logo;
3321 GdkPixbuf *pixbuf_icon;
3322 gchar *authors[1000];
3330 #define LINE_LENGTH 1000
3331 gchar line[LINE_LENGTH];
3333 copyright = g_string_new(NULL);
3334 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");
3336 zd_path = g_build_filename(GQ_BIN_DIR, TIMEZONE_DATABASE, NULL);
3337 cd = ZDOpenDatabase(zd_path);
3340 copyright = g_string_append(copyright, ZDGetNotice(cd));
3342 ZDCloseDatabase(cd);
3346 path = g_build_filename(GQ_HELPDIR, "AUTHORS", NULL);
3347 fp = fopen(path, "r");
3350 while(fgets(line, LINE_LENGTH, fp))
3352 /* get rid of ending \n from fgets */
3353 line[strlen(line) - 1] = '\0';
3354 authors[i_authors] = g_strdup(line);
3357 authors[i_authors] = NULL;
3362 comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
3363 "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
3365 pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
3366 pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
3367 gtk_show_about_dialog(GTK_WINDOW(lw->window),
3368 "title", _("About Geeqie"),
3370 "program-name", GQ_APPNAME,
3372 "logo", pixbuf_logo,
3373 "icon", pixbuf_icon,
3374 "website", GQ_WEBSITE,
3375 "website-label", "Website",
3376 "comments", comment,
3378 "translator-credits", _("translator-credits"),
3379 "wrap-license", TRUE,
3380 "license", copyright->str,
3383 g_string_free(copyright, TRUE);
3386 while(n < i_authors)
3396 static void image_overlay_set_text_colours()
3398 c_options->image_overlay.text_red = options->image_overlay.text_red;
3399 c_options->image_overlay.text_green = options->image_overlay.text_green;
3400 c_options->image_overlay.text_blue = options->image_overlay.text_blue;
3401 c_options->image_overlay.text_alpha = options->image_overlay.text_alpha;
3402 c_options->image_overlay.background_red = options->image_overlay.background_red;
3403 c_options->image_overlay.background_green = options->image_overlay.background_green;
3404 c_options->image_overlay.background_blue = options->image_overlay.background_blue;
3405 c_options->image_overlay.background_alpha = options->image_overlay.background_alpha;
3407 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */