2 * Copyright (C) 2006 John Ellis
3 * Copyright (C) 2008 - 2016 The Geeqie Team
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include "preferences.h"
26 #include "bar_keywords.h"
28 #include "cache_maint.h"
33 #include "filefilter.h"
34 #include "fullscreen.h"
36 #include "image-overlay.h"
37 #include "color-man.h"
39 #include "layout_config.h"
40 #include "layout_util.h"
43 #include "pixbuf_util.h"
44 #include "slideshow.h"
48 #include "ui_fileops.h"
50 #include "ui_spinner.h"
51 #include "ui_tabcomp.h"
52 #include "ui_utildlg.h"
54 #include "zonedetect.h"
64 #define EDITOR_NAME_MAX_LENGTH 32
65 #define EDITOR_COMMAND_MAX_LENGTH 1024
67 static void image_overlay_set_text_colours();
69 GtkWidget *keyword_text;
70 static void config_tab_keywords_save();
72 typedef struct _ThumbSize ThumbSize;
79 static ThumbSize thumb_size_list[] =
113 gchar *format_class_list[] = {
123 /* config memory values */
124 static ConfOptions *c_options = NULL;
131 static GtkWidget *configwindow = NULL;
132 static GtkListStore *filter_store = NULL;
133 static GtkTreeStore *accel_store = NULL;
135 static GtkWidget *safe_delete_path_entry;
137 static GtkWidget *color_profile_input_file_entry[COLOR_PROFILE_INPUTS];
138 static GtkWidget *color_profile_input_name_entry[COLOR_PROFILE_INPUTS];
139 static GtkWidget *color_profile_screen_file_entry;
141 static GtkWidget *sidecar_ext_entry;
142 static GtkWidget *help_search_engine_entry;
145 #define CONFIG_WINDOW_DEF_WIDTH 700
146 #define CONFIG_WINDOW_DEF_HEIGHT 600
149 *-----------------------------------------------------------------------------
150 * option widget callbacks (private)
151 *-----------------------------------------------------------------------------
154 static void zoom_increment_cb(GtkWidget *spin, gpointer data)
156 c_options->image.zoom_increment = (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) * 100.0 + 0.01);
159 static void slideshow_delay_hours_cb(GtkWidget *spin, gpointer data)
161 gint mins_secs_tenths, delay;
163 mins_secs_tenths = c_options->slideshow.delay %
164 (3600 * SLIDESHOW_SUBSECOND_PRECISION);
166 delay = (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
167 (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
170 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
171 SLIDESHOW_SUBSECOND_PRECISION;
174 static void slideshow_delay_minutes_cb(GtkWidget *spin, gpointer data)
176 gint hours, secs_tenths, delay;
178 hours = c_options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
179 secs_tenths = c_options->slideshow.delay % (60 * SLIDESHOW_SUBSECOND_PRECISION);
181 delay = hours * (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
182 (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
183 (60 * SLIDESHOW_SUBSECOND_PRECISION) + secs_tenths);
185 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
186 SLIDESHOW_SUBSECOND_PRECISION;
189 static void slideshow_delay_seconds_cb(GtkWidget *spin, gpointer data)
191 gint hours_mins, delay;
193 hours_mins = c_options->slideshow.delay / (60 * SLIDESHOW_SUBSECOND_PRECISION);
195 delay = (hours_mins * (60 * SLIDESHOW_SUBSECOND_PRECISION)) +
196 (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
197 (gdouble)(SLIDESHOW_SUBSECOND_PRECISION) + 0.01);
199 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
200 SLIDESHOW_SUBSECOND_PRECISION;
204 *-----------------------------------------------------------------------------
205 * sync program 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)
248 gboolean refresh = FALSE;
253 config_entry_to_option(safe_delete_path_entry, &options->file_ops.safe_delete_path, remove_trailing_slash);
255 if (options->file_filter.show_hidden_files != c_options->file_filter.show_hidden_files) refresh = TRUE;
256 if (options->file_filter.show_parent_directory != c_options->file_filter.show_parent_directory) refresh = TRUE;
257 if (options->file_filter.show_dot_directory != c_options->file_filter.show_dot_directory) refresh = TRUE;
258 if (options->file_sort.case_sensitive != c_options->file_sort.case_sensitive) refresh = TRUE;
259 if (options->file_sort.natural != c_options->file_sort.natural) refresh = TRUE;
260 if (options->file_filter.disable_file_extension_checks != c_options->file_filter.disable_file_extension_checks) refresh = TRUE;
261 if (options->file_filter.disable != c_options->file_filter.disable) refresh = TRUE;
263 options->file_ops.confirm_delete = c_options->file_ops.confirm_delete;
264 options->file_ops.enable_delete_key = c_options->file_ops.enable_delete_key;
265 options->file_ops.confirm_move_to_trash = c_options->file_ops.confirm_move_to_trash;
266 options->file_ops.use_system_trash = c_options->file_ops.use_system_trash;
267 options->file_ops.no_trash = c_options->file_ops.no_trash;
268 options->file_ops.safe_delete_folder_maxsize = c_options->file_ops.safe_delete_folder_maxsize;
269 options->tools_restore_state = c_options->tools_restore_state;
270 options->save_window_positions = c_options->save_window_positions;
271 options->use_saved_window_positions_for_new_windows = c_options->use_saved_window_positions_for_new_windows;
272 options->save_window_workspace = c_options->save_window_workspace;
273 options->save_dialog_window_positions = c_options->save_dialog_window_positions;
274 options->show_window_ids = c_options->show_window_ids;
275 options->image.scroll_reset_method = c_options->image.scroll_reset_method;
276 options->image.zoom_2pass = c_options->image.zoom_2pass;
277 options->image.fit_window_to_image = c_options->image.fit_window_to_image;
278 options->image.limit_window_size = c_options->image.limit_window_size;
279 options->image.zoom_to_fit_allow_expand = c_options->image.zoom_to_fit_allow_expand;
280 options->image.max_window_size = c_options->image.max_window_size;
281 options->image.limit_autofit_size = c_options->image.limit_autofit_size;
282 options->image.max_autofit_size = c_options->image.max_autofit_size;
283 options->image.max_enlargement_size = c_options->image.max_enlargement_size;
284 options->image.use_clutter_renderer = c_options->image.use_clutter_renderer;
285 options->progressive_key_scrolling = c_options->progressive_key_scrolling;
286 options->keyboard_scroll_step = c_options->keyboard_scroll_step;
288 if (options->thumbnails.max_width != c_options->thumbnails.max_width
289 || options->thumbnails.max_height != c_options->thumbnails.max_height
290 || options->thumbnails.quality != c_options->thumbnails.quality)
292 thumb_format_changed = TRUE;
294 options->thumbnails.max_width = c_options->thumbnails.max_width;
295 options->thumbnails.max_height = c_options->thumbnails.max_height;
296 options->thumbnails.quality = c_options->thumbnails.quality;
298 options->thumbnails.enable_caching = c_options->thumbnails.enable_caching;
299 options->thumbnails.cache_into_dirs = c_options->thumbnails.cache_into_dirs;
300 options->thumbnails.use_exif = c_options->thumbnails.use_exif;
301 options->thumbnails.use_color_management = c_options->thumbnails.use_color_management;
302 options->thumbnails.collection_preview = c_options->thumbnails.collection_preview;
303 options->thumbnails.use_ft_metadata = c_options->thumbnails.use_ft_metadata;
304 // options->thumbnails.use_ft_metadata_small = c_options->thumbnails.use_ft_metadata_small;
305 options->thumbnails.spec_standard = c_options->thumbnails.spec_standard;
306 options->metadata.enable_metadata_dirs = c_options->metadata.enable_metadata_dirs;
307 options->file_filter.show_hidden_files = c_options->file_filter.show_hidden_files;
308 options->file_filter.show_parent_directory = c_options->file_filter.show_parent_directory;
309 options->file_filter.show_dot_directory = c_options->file_filter.show_dot_directory;
310 options->file_filter.disable_file_extension_checks = c_options->file_filter.disable_file_extension_checks;
312 options->file_sort.case_sensitive = c_options->file_sort.case_sensitive;
313 options->file_sort.natural = c_options->file_sort.natural;
314 options->file_filter.disable = c_options->file_filter.disable;
316 config_entry_to_option(sidecar_ext_entry, &options->sidecar.ext, NULL);
317 sidecar_ext_parse(options->sidecar.ext);
319 options->slideshow.random = c_options->slideshow.random;
320 options->slideshow.repeat = c_options->slideshow.repeat;
321 options->slideshow.delay = c_options->slideshow.delay;
323 options->mousewheel_scrolls = c_options->mousewheel_scrolls;
324 options->image_lm_click_nav = c_options->image_lm_click_nav;
325 options->image_l_click_video = c_options->image_l_click_video;
326 options->image_l_click_video_editor = c_options->image_l_click_video_editor;
328 options->file_ops.enable_in_place_rename = c_options->file_ops.enable_in_place_rename;
330 options->image.tile_cache_max = c_options->image.tile_cache_max;
331 options->image.image_cache_max = c_options->image.image_cache_max;
333 options->image.zoom_quality = c_options->image.zoom_quality;
335 options->image.zoom_increment = c_options->image.zoom_increment;
337 options->image.enable_read_ahead = c_options->image.enable_read_ahead;
340 if (options->image.use_custom_border_color != c_options->image.use_custom_border_color
341 || options->image.use_custom_border_color_in_fullscreen != c_options->image.use_custom_border_color_in_fullscreen
342 || !gdk_color_equal(&options->image.border_color, &c_options->image.border_color))
344 options->image.use_custom_border_color_in_fullscreen = c_options->image.use_custom_border_color_in_fullscreen;
345 options->image.use_custom_border_color = c_options->image.use_custom_border_color;
346 options->image.border_color = c_options->image.border_color;
347 layout_colors_update();
348 view_window_colors_update();
351 options->image.alpha_color_1 = c_options->image.alpha_color_1;
352 options->image.alpha_color_2 = c_options->image.alpha_color_2;
354 options->fullscreen.screen = c_options->fullscreen.screen;
355 options->fullscreen.clean_flip = c_options->fullscreen.clean_flip;
356 options->fullscreen.disable_saver = c_options->fullscreen.disable_saver;
357 options->fullscreen.above = c_options->fullscreen.above;
358 if (c_options->image_overlay.template_string)
359 set_image_overlay_template_string(&options->image_overlay.template_string,
360 c_options->image_overlay.template_string);
361 if (c_options->image_overlay.font)
362 set_image_overlay_font_string(&options->image_overlay.font,
363 c_options->image_overlay.font);
364 options->image_overlay.text_red = c_options->image_overlay.text_red;
365 options->image_overlay.text_green = c_options->image_overlay.text_green;
366 options->image_overlay.text_blue = c_options->image_overlay.text_blue;
367 options->image_overlay.text_alpha = c_options->image_overlay.text_alpha;
368 options->image_overlay.background_red = c_options->image_overlay.background_red;
369 options->image_overlay.background_green = c_options->image_overlay.background_green;
370 options->image_overlay.background_blue = c_options->image_overlay.background_blue;
371 options->image_overlay.background_alpha = c_options->image_overlay.background_alpha;
372 options->update_on_time_change = c_options->update_on_time_change;
373 options->image.exif_proof_rotate_enable = c_options->image.exif_proof_rotate_enable;
375 options->duplicates_similarity_threshold = c_options->duplicates_similarity_threshold;
376 options->rot_invariant_sim = c_options->rot_invariant_sim;
378 options->tree_descend_subdirs = c_options->tree_descend_subdirs;
380 options->view_dir_list_single_click_enter = c_options->view_dir_list_single_click_enter;
381 options->circular_selection_lists = c_options->circular_selection_lists;
383 options->open_recent_list_maxsize = c_options->open_recent_list_maxsize;
384 options->dnd_icon_size = c_options->dnd_icon_size;
385 options->clipboard_selection = c_options->clipboard_selection;
386 options->dnd_default_action = c_options->dnd_default_action;
388 options->metadata.save_in_image_file = c_options->metadata.save_in_image_file;
389 options->metadata.save_legacy_IPTC = c_options->metadata.save_legacy_IPTC;
390 options->metadata.warn_on_write_problems = c_options->metadata.warn_on_write_problems;
391 options->metadata.save_legacy_format = c_options->metadata.save_legacy_format;
392 options->metadata.sync_grouped_files = c_options->metadata.sync_grouped_files;
393 options->metadata.confirm_write = c_options->metadata.confirm_write;
394 options->metadata.sidecar_extended_name = c_options->metadata.sidecar_extended_name;
395 options->metadata.confirm_timeout = c_options->metadata.confirm_timeout;
396 options->metadata.confirm_after_timeout = c_options->metadata.confirm_after_timeout;
397 options->metadata.confirm_on_image_change = c_options->metadata.confirm_on_image_change;
398 options->metadata.confirm_on_dir_change = c_options->metadata.confirm_on_dir_change;
399 options->metadata.keywords_case_sensitive = c_options->metadata.keywords_case_sensitive;
400 options->metadata.write_orientation = c_options->metadata.write_orientation;
401 options->stereo.mode = (c_options->stereo.mode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
402 (c_options->stereo.tmp.mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
403 (c_options->stereo.tmp.flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
404 (c_options->stereo.tmp.mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
405 (c_options->stereo.tmp.flip_left ? PR_STEREO_FLIP_LEFT : 0) |
406 (c_options->stereo.tmp.swap ? PR_STEREO_SWAP : 0) |
407 (c_options->stereo.tmp.temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
408 options->stereo.fsmode = (c_options->stereo.fsmode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
409 (c_options->stereo.tmp.fs_mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
410 (c_options->stereo.tmp.fs_flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
411 (c_options->stereo.tmp.fs_mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
412 (c_options->stereo.tmp.fs_flip_left ? PR_STEREO_FLIP_LEFT : 0) |
413 (c_options->stereo.tmp.fs_swap ? PR_STEREO_SWAP : 0) |
414 (c_options->stereo.tmp.fs_temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
415 options->stereo.enable_fsmode = c_options->stereo.enable_fsmode;
416 options->stereo.fixed_w = c_options->stereo.fixed_w;
417 options->stereo.fixed_h = c_options->stereo.fixed_h;
418 options->stereo.fixed_x1 = c_options->stereo.fixed_x1;
419 options->stereo.fixed_y1 = c_options->stereo.fixed_y1;
420 options->stereo.fixed_x2 = c_options->stereo.fixed_x2;
421 options->stereo.fixed_y2 = c_options->stereo.fixed_y2;
423 options->info_keywords.height = c_options->info_keywords.height;
424 options->info_title.height = c_options->info_title.height;
425 options->info_comment.height = c_options->info_comment.height;
426 options->info_rating.height = c_options->info_rating.height;
428 options->show_predefined_keyword_tree = c_options->show_predefined_keyword_tree;
429 options->expand_menu_toolbar = c_options->expand_menu_toolbar;
431 options->marks_save = c_options->marks_save;
432 options->with_rename = c_options->with_rename;
433 options->collections_on_top = c_options->collections_on_top;
434 options->hide_window_in_fullscreen = c_options->hide_window_in_fullscreen;
435 config_entry_to_option(help_search_engine_entry, &options->help_search_engine, NULL);
437 options->read_metadata_in_idle = c_options->read_metadata_in_idle;
439 options->star_rating.star = c_options->star_rating.star;
440 options->star_rating.rejected = c_options->star_rating.rejected;
442 set_debug_level(debug_c);
446 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
448 config_entry_to_option(color_profile_input_name_entry[i], &options->color_profile.input_name[i], NULL);
449 config_entry_to_option(color_profile_input_file_entry[i], &options->color_profile.input_file[i], NULL);
451 config_entry_to_option(color_profile_screen_file_entry, &options->color_profile.screen_file, NULL);
452 options->color_profile.use_x11_screen_profile = c_options->color_profile.use_x11_screen_profile;
453 if (options->color_profile.render_intent != c_options->color_profile.render_intent)
455 options->color_profile.render_intent = c_options->color_profile.render_intent;
460 options->mouse_button_8 = c_options->mouse_button_8;
461 options->mouse_button_9 = c_options->mouse_button_9;
463 options->override_disable_gpu = c_options->override_disable_gpu;
465 config_tab_keywords_save();
467 image_options_sync();
472 layout_refresh(NULL);
475 if (accel_store) gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_apply_cb, NULL);
477 toolbar_apply(TOOLBAR_MAIN);
478 toolbar_apply(TOOLBAR_STATUS);
482 *-----------------------------------------------------------------------------
483 * config window main button callbacks (private)
484 *-----------------------------------------------------------------------------
487 static void config_window_close_cb(GtkWidget *widget, gpointer data)
489 gtk_widget_destroy(configwindow);
494 static void config_window_help_cb(GtkWidget *widget, gpointer data)
496 GtkWidget *notebook = data;
499 static gchar *html_section[] =
501 "GuideOptionsGeneral.html",
502 "GuideOptionsImage.html",
503 "GuideOptionsOSD.html",
504 "GuideOptionsWindow.html",
505 "GuideOptionsKeyboard.html",
506 "GuideOptionsFiltering.html",
507 "GuideOptionsMetadata.html",
508 "GuideOptionsKeywords.html",
509 "GuideOptionsColor.html",
510 "GuideOptionsStereo.html",
511 "GuideOptionsBehavior.html",
512 "GuideOptionsToolbar.html",
513 "GuideOptionsToolbar.html"
516 i = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
517 help_window_show(html_section[i]);
520 static gboolean config_window_delete(GtkWidget *widget, GdkEventAny *event, gpointer data)
522 config_window_close_cb(NULL, NULL);
526 static void config_window_ok_cb(GtkWidget *widget, gpointer data)
529 GtkNotebook *notebook = data;
537 lw = layout_window_list->data;
539 window = gtk_widget_get_window(widget);
540 gdk_window_get_root_origin(window, &x, &y);
541 w = gdk_window_get_width(window);
542 h = gdk_window_get_height(window);
543 page_number = gtk_notebook_get_current_page(notebook);
545 lw->options.preferences_window.x = x;
546 lw->options.preferences_window.y = y;
547 lw->options.preferences_window.w = w;
548 lw->options.preferences_window.h = h;
549 lw->options.preferences_window.page_number = page_number;
551 config_window_apply();
552 layout_util_sync(lw);
553 save_options(options);
554 config_window_close_cb(NULL, NULL);
558 *-----------------------------------------------------------------------------
559 * config window setup (private)
560 *-----------------------------------------------------------------------------
563 static void quality_menu_cb(GtkWidget *combo, gpointer data)
567 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
571 *option = GDK_INTERP_NEAREST;
574 *option = GDK_INTERP_TILES;
577 *option = GDK_INTERP_BILINEAR;
582 static void dnd_default_action_selection_menu_cb(GtkWidget *combo, gpointer data)
586 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
590 *option = DND_ACTION_ASK;
593 *option = DND_ACTION_COPY;
596 *option = DND_ACTION_MOVE;
600 static void clipboard_selection_menu_cb(GtkWidget *combo, gpointer data)
604 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
607 *option = CLIPBOARD_PRIMARY;
610 *option = CLIPBOARD_CLIPBOARD;
613 *option = CLIPBOARD_BOTH;
616 *option = CLIPBOARD_BOTH;
620 static void add_quality_menu(GtkWidget *table, gint column, gint row, const gchar *text,
621 guint option, guint *option_c)
628 pref_table_label(table, column, row, text, 0.0);
630 combo = gtk_combo_box_text_new();
632 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Nearest (worst, but fastest)"));
633 if (option == GDK_INTERP_NEAREST) current = 0;
634 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Tiles"));
635 if (option == GDK_INTERP_TILES) current = 1;
636 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Bilinear (best, but slowest)"));
637 if (option == GDK_INTERP_BILINEAR) current = 2;
639 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
641 g_signal_connect(G_OBJECT(combo), "changed",
642 G_CALLBACK(quality_menu_cb), option_c);
644 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
645 gtk_widget_show(combo);
648 static void add_dnd_default_action_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text, DnDAction option, DnDAction *option_c)
655 pref_table_label(table, column, row, text, 0.0);
657 combo = gtk_combo_box_text_new();
659 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Ask"));
660 if (option == DND_ACTION_ASK) current = 0;
661 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Copy"));
662 if (option == DND_ACTION_COPY) current = 1;
663 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Move"));
664 if (option == DND_ACTION_MOVE) current = 2;
666 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
668 g_signal_connect(G_OBJECT(combo), "changed",
669 G_CALLBACK(dnd_default_action_selection_menu_cb), option_c);
671 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
672 gtk_widget_show(combo);
675 static void add_clipboard_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
676 gint option, gint *option_c)
683 pref_table_label(table, column, row, text, 0.0);
685 combo = gtk_combo_box_text_new();
687 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Primary"));
688 if (option == CLIPBOARD_PRIMARY) current = 0;
689 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Clipboard"));
690 if (option == CLIPBOARD_CLIPBOARD) current = 1;
691 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Both"));
692 if (option == CLIPBOARD_BOTH) current = 2;
694 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
696 g_signal_connect(G_OBJECT(combo), "changed",
697 G_CALLBACK(clipboard_selection_menu_cb), option_c);
699 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
700 gtk_widget_show(combo);
703 typedef struct _UseableMouseItems UseableMouseItems;
704 struct _UseableMouseItems
706 gchar *name; /* GtkActionEntry terminology */
711 static const UseableMouseItems useable_mouse_items[] = {
713 {"FirstImage", N_("First Image"), GTK_STOCK_GOTO_TOP},
714 {"PrevImage", N_("Previous Image"), GTK_STOCK_GO_UP},
715 {"NextImage", N_("Next Image"), GTK_STOCK_GO_DOWN},
716 {"LastImage", N_("Last Image"), GTK_STOCK_GOTO_BOTTOM},
717 {"Back", N_("Back"), GTK_STOCK_GO_BACK},
718 {"Forward", N_("Forward"), GTK_STOCK_GO_FORWARD},
719 {"Home", N_("Home"), GTK_STOCK_HOME},
720 {"Up", N_("Up"), GTK_STOCK_GO_UP},
721 {"FirstPage", N_("First page"), GTK_STOCK_MEDIA_PREVIOUS},
722 {"LastPage", N_("Last Page"), GTK_STOCK_MEDIA_NEXT},
723 {"NextPage", N_("Next page"), GTK_STOCK_MEDIA_FORWARD},
724 {"PrevPage", N_("Previous Page"), GTK_STOCK_MEDIA_REWIND},
725 {"NewWindow", N_("New _window"), GTK_STOCK_NEW},
726 {"NewCollection", N_("New collection"), GTK_STOCK_INDEX},
727 {"OpenCollection", N_("Open collection"), GTK_STOCK_OPEN},
728 {"Search", N_("Search"), GTK_STOCK_FIND},
729 {"FindDupes", N_("Find duplicates"), GTK_STOCK_FIND},
730 {"NewFolder", N_("New folder"),GTK_STOCK_DIRECTORY},
731 {"Copy", N_("Copy"), GTK_STOCK_COPY},
732 {"Move", N_("Move"), PIXBUF_INLINE_ICON_MOVE},
733 {"Rename", N_("Rename"), PIXBUF_INLINE_ICON_RENAME},
734 {"Delete", N_("Delete"), GTK_STOCK_DELETE},
735 {"CloseWindow", N_("Close Window"), GTK_STOCK_CLOSE},
736 {"PanView", N_("Pan view"), PIXBUF_INLINE_ICON_PANORAMA},
737 {"SelectAll", N_("Select all"), PIXBUF_INLINE_ICON_SELECT_ALL},
738 {"SelectNone", N_("Select none"), PIXBUF_INLINE_ICON_SELECT_NONE},
739 {"SelectInvert", N_("Select invert"), PIXBUF_INLINE_ICON_SELECT_INVERT},
740 {"ShowFileFilter", N_("Show file filter"), PIXBUF_INLINE_ICON_FILE_FILTER},
741 {"RectangularSelection", N_("Select rectangle"), PIXBUF_INLINE_ICON_SELECT_RECTANGLE},
742 {"Print", N_("Print"), GTK_STOCK_PRINT},
743 {"Preferences", N_("Preferences"), GTK_STOCK_PREFERENCES},
744 {"LayoutConfig", N_("Configure this window"), GTK_STOCK_PREFERENCES},
745 {"Maintenance", N_("Cache maintenance"), PIXBUF_INLINE_ICON_MAINTENANCE},
746 {"RotateCW", N_("Rotate clockwise 90°"), PIXBUF_INLINE_ICON_CW},
747 {"RotateCCW", N_("Rotate counterclockwise 90°"), PIXBUF_INLINE_ICON_CCW},
748 {"Rotate180", N_("Rotate 180°"), PIXBUF_INLINE_ICON_180},
749 {"Mirror", N_("Mirror"), PIXBUF_INLINE_ICON_MIRROR},
750 {"Flip", N_("Flip"), PIXBUF_INLINE_ICON_FLIP},
751 {"AlterNone", N_("Original state"), PIXBUF_INLINE_ICON_ORIGINAL},
752 {"ZoomIn", N_("Zoom in"), GTK_STOCK_ZOOM_IN},
753 {"ZoomOut", N_("Zoom out"), GTK_STOCK_ZOOM_OUT},
754 {"Zoom100", N_("Zoom 1:1"), GTK_STOCK_ZOOM_100},
755 {"ZoomFit", N_("Zoom to fit"), GTK_STOCK_ZOOM_FIT},
756 {"ZoomFillHor", N_("Fit Horizontaly"), PIXBUF_INLINE_ICON_ZOOMFILLHOR},
757 {"ZoomFillVert", N_("Fit vertically"), PIXBUF_INLINE_ICON_ZOOMFILLVERT},
758 {"Zoom200", N_("Zoom 2:1"), GTK_STOCK_FILE},
759 {"Zoom300", N_("Zoom 3:1"), GTK_STOCK_FILE},
760 {"Zoom400", N_("Zoom 4:1"), GTK_STOCK_FILE},
761 {"Zoom50", N_("Zoom 1:2"), GTK_STOCK_FILE},
762 {"Zoom33", N_("Zoom1:3"), GTK_STOCK_FILE},
763 {"Zoom25", N_("Zoom 1:4"), GTK_STOCK_FILE},
764 {"ConnectZoomIn", N_("Connected Zoom in"), GTK_STOCK_ZOOM_IN},
765 {"SplitPaneSync", N_("Split Pane Sync"), PIXBUF_INLINE_SPLIT_PANE_SYNC},
766 {"Grayscale", N_("Grayscale"), PIXBUF_INLINE_ICON_GRAYSCALE},
767 {"OverUnderExposed", N_("Over Under Exposed"), PIXBUF_INLINE_ICON_EXPOSURE},
768 {"HideTools", N_("Hide file list"), PIXBUF_INLINE_ICON_HIDETOOLS},
769 {"SlideShowPause", N_("Pause slideshow"), GTK_STOCK_MEDIA_PAUSE},
770 {"SlideShowFaster", N_("Slideshow Faster"), GTK_STOCK_FILE},
771 {"SlideShowSlower", N_("Slideshow Slower"), GTK_STOCK_FILE},
772 {"Refresh", N_("Refresh"), GTK_STOCK_REFRESH},
773 {"HelpContents", N_("Help"), GTK_STOCK_HELP},
774 {"ExifWin", N_("Exif window"), PIXBUF_INLINE_ICON_EXIF},
775 {"Thumbnails", N_("Show thumbnails"), PIXBUF_INLINE_ICON_THUMB},
776 {"ShowMarks", N_("Show marks"), PIXBUF_INLINE_ICON_MARKS},
777 {"ImageGuidelines", N_("Show guidelines"), PIXBUF_INLINE_ICON_GUIDELINES},
778 {"DrawRectangle", N_("Draw Rectangle"), PIXBUF_INLINE_ICON_DRAW_RECTANGLE},
779 {"FloatTools", N_("Float file list"), PIXBUF_INLINE_ICON_FLOAT},
780 {"SBar", N_("Info sidebar"), PIXBUF_INLINE_ICON_INFO},
781 {"SBarSort", N_("Sort manager"), PIXBUF_INLINE_ICON_SORT},
782 {"Quit", N_("Quit"), GTK_STOCK_QUIT},
786 static void mouse_buttons_selection_menu_cb(GtkWidget *combo, gpointer data)
788 gchar **option = data;
791 label = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(combo));
793 const UseableMouseItems *list = useable_mouse_items;
797 if (g_strcmp0(list->label, label) == 0)
805 *option = g_strdup(list->name);
809 static void add_mouse_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
810 gchar *option, gchar **option_c)
818 pref_table_label(table, column, row, text, 0.0);
820 combo = gtk_combo_box_text_new();
822 const UseableMouseItems *list = useable_mouse_items;
826 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), list->label);
827 if (g_strcmp0(list->name, option) == 0)
835 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
837 g_signal_connect(G_OBJECT(combo), "changed",
838 G_CALLBACK(mouse_buttons_selection_menu_cb), option_c);
840 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
841 gtk_widget_show(combo);
844 static void thumb_size_menu_cb(GtkWidget *combo, gpointer data)
848 n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
851 if ((guint) n < sizeof(thumb_size_list) / sizeof(ThumbSize))
853 c_options->thumbnails.max_width = thumb_size_list[n].w;
854 c_options->thumbnails.max_height = thumb_size_list[n].h;
858 c_options->thumbnails.max_width = options->thumbnails.max_width;
859 c_options->thumbnails.max_height = options->thumbnails.max_height;
863 static void add_thumb_size_menu(GtkWidget *table, gint column, gint row, gchar *text)
869 c_options->thumbnails.max_width = options->thumbnails.max_width;
870 c_options->thumbnails.max_height = options->thumbnails.max_height;
872 pref_table_label(table, column, row, text, 0.0);
874 combo = gtk_combo_box_text_new();
877 for (i = 0; (guint) i < sizeof(thumb_size_list) / sizeof(ThumbSize); i++)
882 w = thumb_size_list[i].w;
883 h = thumb_size_list[i].h;
885 buf = g_strdup_printf("%d x %d", w, h);
886 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
889 if (w == options->thumbnails.max_width && h == options->thumbnails.max_height) current = i;
896 buf = g_strdup_printf("%s %d x %d", _("Custom"), options->thumbnails.max_width, options->thumbnails.max_height);
897 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
903 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
904 g_signal_connect(G_OBJECT(combo), "changed",
905 G_CALLBACK(thumb_size_menu_cb), NULL);
907 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
908 gtk_widget_show(combo);
911 static void stereo_mode_menu_cb(GtkWidget *combo, gpointer data)
915 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
919 *option = PR_STEREO_NONE;
922 *option = PR_STEREO_ANAGLYPH_RC;
925 *option = PR_STEREO_ANAGLYPH_GM;
928 *option = PR_STEREO_ANAGLYPH_YB;
931 *option = PR_STEREO_ANAGLYPH_GRAY_RC;
934 *option = PR_STEREO_ANAGLYPH_GRAY_GM;
937 *option = PR_STEREO_ANAGLYPH_GRAY_YB;
940 *option = PR_STEREO_ANAGLYPH_DB_RC;
943 *option = PR_STEREO_ANAGLYPH_DB_GM;
946 *option = PR_STEREO_ANAGLYPH_DB_YB;
949 *option = PR_STEREO_HORIZ;
952 *option = PR_STEREO_HORIZ | PR_STEREO_HALF;
955 *option = PR_STEREO_VERT;
958 *option = PR_STEREO_VERT | PR_STEREO_HALF;
961 *option = PR_STEREO_FIXED;
966 static void add_stereo_mode_menu(GtkWidget *table, gint column, gint row, const gchar *text,
967 gint option, gint *option_c, gboolean add_fixed)
974 pref_table_label(table, column, row, text, 0.0);
976 combo = gtk_combo_box_text_new();
978 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Single image"));
980 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Red-Cyan"));
981 if (option & PR_STEREO_ANAGLYPH_RC) current = 1;
982 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Green-Magenta"));
983 if (option & PR_STEREO_ANAGLYPH_GM) current = 2;
984 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Yellow-Blue"));
985 if (option & PR_STEREO_ANAGLYPH_YB) current = 3;
986 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Red-Cyan"));
987 if (option & PR_STEREO_ANAGLYPH_GRAY_RC) current = 4;
988 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Green-Magenta"));
989 if (option & PR_STEREO_ANAGLYPH_GRAY_GM) current = 5;
990 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Yellow-Blue"));
991 if (option & PR_STEREO_ANAGLYPH_GRAY_YB) current = 6;
992 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Red-Cyan"));
993 if (option & PR_STEREO_ANAGLYPH_DB_RC) current = 7;
994 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Green-Magenta"));
995 if (option & PR_STEREO_ANAGLYPH_DB_GM) current = 8;
996 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Yellow-Blue"));
997 if (option & PR_STEREO_ANAGLYPH_DB_YB) current = 9;
999 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side"));
1000 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side Half size"));
1001 if (option & PR_STEREO_HORIZ)
1004 if (option & PR_STEREO_HALF) current = 11;
1007 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom"));
1008 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom Half size"));
1009 if (option & PR_STEREO_VERT)
1012 if (option & PR_STEREO_HALF) current = 13;
1017 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Fixed position"));
1018 if (option & PR_STEREO_FIXED) current = 14;
1021 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
1023 g_signal_connect(G_OBJECT(combo), "changed",
1024 G_CALLBACK(stereo_mode_menu_cb), option_c);
1026 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
1027 gtk_widget_show(combo);
1030 static void video_menu_cb(GtkWidget *combo, gpointer data)
1032 gchar **option = data;
1034 EditorDescription *ed = g_list_nth_data(editor_list_get(), gtk_combo_box_get_active(GTK_COMBO_BOX(combo)));
1038 static void video_menu_populate(gpointer data, gpointer user_data)
1040 GtkWidget *combo = user_data;
1041 EditorDescription *ed = data;
1043 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), ed->name);
1046 static void add_video_menu(GtkWidget *table, gint column, gint row, const gchar *text,
1047 gchar *option, gchar **option_c)
1051 /* use lists since they are sorted */
1052 GList *eds = editor_list_get();
1056 pref_table_label(table, column, row, text, 0.0);
1058 combo = gtk_combo_box_text_new();
1059 g_list_foreach(eds,video_menu_populate,(gpointer)combo);
1060 current = option ? g_list_index(eds,g_hash_table_lookup(editors,option)): -1;
1062 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
1064 g_signal_connect(G_OBJECT(combo), "changed",
1065 G_CALLBACK(video_menu_cb), option_c);
1067 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
1068 gtk_widget_show(combo);
1071 static void filter_store_populate(void)
1075 if (!filter_store) return;
1077 gtk_list_store_clear(filter_store);
1079 work = filter_get_list();
1088 gtk_list_store_append(filter_store, &iter);
1089 gtk_list_store_set(filter_store, &iter, 0, fe, -1);
1093 static void filter_store_ext_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1094 gchar *new_text, gpointer data)
1096 GtkWidget *model = data;
1097 FilterEntry *fe = data;
1101 if (!new_text || strlen(new_text) < 1) return;
1103 tpath = gtk_tree_path_new_from_string(path_str);
1104 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1105 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1107 g_free(fe->extensions);
1108 fe->extensions = g_strdup(new_text);
1110 gtk_tree_path_free(tpath);
1114 static void filter_store_class_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1115 gchar *new_text, gpointer data)
1117 GtkWidget *model = data;
1118 FilterEntry *fe = data;
1123 if (!new_text || !new_text[0]) return;
1125 tpath = gtk_tree_path_new_from_string(path_str);
1126 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1127 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1129 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
1131 if (strcmp(new_text, _(format_class_list[i])) == 0)
1138 gtk_tree_path_free(tpath);
1142 static void filter_store_desc_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1143 gchar *new_text, gpointer data)
1145 GtkWidget *model = data;
1150 if (!new_text || !new_text[0]) return;
1152 tpath = gtk_tree_path_new_from_string(path_str);
1153 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1154 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1156 g_free(fe->description);
1157 fe->description = g_strdup(new_text);
1159 gtk_tree_path_free(tpath);
1162 static void filter_store_enable_cb(GtkCellRendererToggle *renderer,
1163 gchar *path_str, gpointer data)
1165 GtkWidget *model = data;
1170 tpath = gtk_tree_path_new_from_string(path_str);
1171 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1172 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1174 fe->enabled = !fe->enabled;
1176 gtk_tree_path_free(tpath);
1180 static void filter_store_writable_cb(GtkCellRendererToggle *renderer,
1181 gchar *path_str, gpointer data)
1183 GtkWidget *model = data;
1188 tpath = gtk_tree_path_new_from_string(path_str);
1189 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1190 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1192 fe->writable = !fe->writable;
1193 if (fe->writable) fe->allow_sidecar = FALSE;
1195 gtk_tree_path_free(tpath);
1199 static void filter_store_sidecar_cb(GtkCellRendererToggle *renderer,
1200 gchar *path_str, gpointer data)
1202 GtkWidget *model = data;
1207 tpath = gtk_tree_path_new_from_string(path_str);
1208 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1209 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1211 fe->allow_sidecar = !fe->allow_sidecar;
1212 if (fe->allow_sidecar) fe->writable = FALSE;
1214 gtk_tree_path_free(tpath);
1218 static void filter_set_func(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
1219 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
1223 gtk_tree_model_get(tree_model, iter, 0, &fe, -1);
1225 switch (GPOINTER_TO_INT(data))
1228 g_object_set(GTK_CELL_RENDERER(cell),
1229 "active", fe->enabled, NULL);
1232 g_object_set(GTK_CELL_RENDERER(cell),
1233 "text", fe->extensions, NULL);
1235 case FE_DESCRIPTION:
1236 g_object_set(GTK_CELL_RENDERER(cell),
1237 "text", fe->description, NULL);
1240 g_object_set(GTK_CELL_RENDERER(cell),
1241 "text", _(format_class_list[fe->file_class]), NULL);
1244 g_object_set(GTK_CELL_RENDERER(cell),
1245 "active", fe->writable, NULL);
1247 case FE_ALLOW_SIDECAR:
1248 g_object_set(GTK_CELL_RENDERER(cell),
1249 "active", fe->allow_sidecar, NULL);
1254 static gboolean filter_add_scroll(gpointer data)
1258 GtkCellRenderer *cell;
1259 GtkTreeViewColumn *column;
1262 rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(filter_store), NULL);
1263 path = gtk_tree_path_new_from_indices(rows-1, -1);
1265 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data), 0);
1267 list_cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column));
1268 cell = g_list_last(list_cells)->data;
1270 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1271 path, column, FALSE, 0.0, 0.0 );
1272 gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(data),
1273 path, column, cell, TRUE);
1275 gtk_tree_path_free(path);
1276 g_list_free(list_cells);
1281 static void filter_add_cb(GtkWidget *widget, gpointer data)
1283 filter_add_unique("description", ".new", FORMAT_CLASS_IMAGE, TRUE, FALSE, TRUE);
1284 filter_store_populate();
1286 g_idle_add((GSourceFunc)filter_add_scroll, data);
1289 static void filter_remove_cb(GtkWidget *widget, gpointer data)
1291 GtkWidget *filter_view = data;
1292 GtkTreeSelection *selection;
1296 if (!filter_store) return;
1297 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1298 if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) return;
1299 gtk_tree_model_get(GTK_TREE_MODEL(filter_store), &iter, 0, &fe, -1);
1302 filter_remove_entry(fe);
1304 filter_store_populate();
1307 static gboolean filter_default_ok_scroll(GtkTreeView *data)
1311 GtkTreeViewColumn *column;
1313 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(filter_store), &iter);
1314 path = gtk_tree_model_get_path(GTK_TREE_MODEL(filter_store), &iter);
1315 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1317 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1321 gtk_tree_path_free(path);
1326 static void filter_default_ok_cb(GenericDialog *gd, gpointer data)
1329 filter_add_defaults();
1331 filter_store_populate();
1333 g_idle_add((GSourceFunc)filter_default_ok_scroll, gd->data);
1336 static void dummy_cancel_cb(GenericDialog *gd, gpointer data)
1338 /* no op, only so cancel button appears */
1341 static void filter_default_cb(GtkWidget *widget, gpointer data)
1345 gd = generic_dialog_new(_("Reset filters"),
1346 "reset_filter", widget, TRUE,
1347 dummy_cancel_cb, data);
1348 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset filters"),
1349 _("This will reset the file filters to the defaults.\nContinue?"), TRUE);
1350 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, filter_default_ok_cb, TRUE);
1351 gtk_widget_show(gd->dialog);
1354 static void filter_disable_cb(GtkWidget *widget, gpointer data)
1356 GtkWidget *frame = data;
1358 gtk_widget_set_sensitive(frame,
1359 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
1362 static void safe_delete_view_cb(GtkWidget *widget, gpointer data)
1364 layout_set_path(NULL, gtk_entry_get_text(GTK_ENTRY(safe_delete_path_entry)));
1367 static void safe_delete_clear_ok_cb(GenericDialog *gd, gpointer data)
1369 file_util_trash_clear();
1372 static void safe_delete_clear_cb(GtkWidget *widget, gpointer data)
1376 gd = generic_dialog_new(_("Clear trash"),
1377 "clear_trash", widget, TRUE,
1378 dummy_cancel_cb, NULL);
1379 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear trash"),
1380 _("This will remove the trash contents."), FALSE);
1381 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, safe_delete_clear_ok_cb, TRUE);
1382 entry = gtk_entry_new();
1383 gtk_widget_set_can_focus(entry, FALSE);
1384 gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE);
1385 if (options->file_ops.safe_delete_path) gtk_entry_set_text(GTK_ENTRY(entry), options->file_ops.safe_delete_path);
1386 gtk_box_pack_start(GTK_BOX(gd->vbox), entry, FALSE, FALSE, 0);
1387 gtk_widget_show(entry);
1388 gtk_widget_show(gd->dialog);
1391 static void image_overlay_template_view_changed_cb(GtkWidget *widget, gpointer data)
1393 GtkWidget *pTextView;
1394 GtkTextBuffer *pTextBuffer;
1398 pTextView = GTK_WIDGET(data);
1400 pTextBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pTextView));
1401 gtk_text_buffer_get_start_iter(pTextBuffer, &iStart);
1402 gtk_text_buffer_get_end_iter(pTextBuffer, &iEnd);
1404 set_image_overlay_template_string(&c_options->image_overlay.template_string,
1405 gtk_text_buffer_get_text(pTextBuffer, &iStart, &iEnd, TRUE));
1408 static void image_overlay_default_template_ok_cb(GenericDialog *gd, gpointer data)
1410 GtkTextView *text_view = data;
1411 GtkTextBuffer *buffer;
1413 set_default_image_overlay_template_string(&options->image_overlay.template_string);
1414 if (!configwindow) return;
1416 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
1417 gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1420 static void image_overlay_default_template_cb(GtkWidget *widget, gpointer data)
1424 gd = generic_dialog_new(_("Reset image overlay template string"),
1425 "reset_image_overlay_template_string", widget, TRUE,
1426 dummy_cancel_cb, data);
1427 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset image overlay template string"),
1428 _("This will reset the image overlay template string to the default.\nContinue?"), TRUE);
1429 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, image_overlay_default_template_ok_cb, TRUE);
1430 gtk_widget_show(gd->dialog);
1433 static void image_overlay_help_cb(GtkWidget *widget, gpointer data)
1435 help_window_show("GuideOptionsOSD.html");
1438 static void image_overlay_set_font_cb(GtkWidget *widget, gpointer data)
1440 #if GTK_CHECK_VERSION(3,4,0)
1443 PangoFontDescription *font_desc;
1445 dialog = gtk_font_chooser_dialog_new("Image Overlay Font", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1446 gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), options->image_overlay.font);
1448 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1450 font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
1451 font = pango_font_description_to_string(font_desc);
1452 g_free(c_options->image_overlay.font);
1453 c_options->image_overlay.font = g_strdup(font);
1457 gtk_widget_destroy(dialog);
1461 font = gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget));
1462 c_options->image_overlay.font = g_strdup(font);
1466 static void image_overlay_set_text_colour_cb(GtkWidget *widget, gpointer data)
1469 #if GTK_CHECK_VERSION(3,4,0)
1472 dialog = gtk_color_chooser_dialog_new("Image Overlay Text Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1473 colour.red = options->image_overlay.text_red;
1474 colour.green = options->image_overlay.text_green;
1475 colour.blue = options->image_overlay.text_blue;
1476 colour.alpha = options->image_overlay.text_alpha;
1477 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1478 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1480 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1482 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1483 c_options->image_overlay.text_red = colour.red*255;
1484 c_options->image_overlay.text_green = colour.green*255;
1485 c_options->image_overlay.text_blue = colour.blue*255;
1486 c_options->image_overlay.text_alpha = colour.alpha*255;
1488 gtk_widget_destroy(dialog);
1491 GtkColorSelection *colorsel;
1493 dialog = gtk_color_selection_dialog_new("Image Overlay Text Colour");
1494 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1495 colour.red = options->image_overlay.text_red*257;
1496 colour.green = options->image_overlay.text_green*257;
1497 colour.blue = options->image_overlay.text_blue*257;
1498 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1499 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1500 gtk_color_selection_set_current_color(colorsel, &colour);
1501 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.text_alpha*257);
1503 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1505 gtk_color_selection_get_current_color(colorsel, &colour);
1506 c_options->image_overlay.text_red = colour.red/257;
1507 c_options->image_overlay.text_green = colour.green/257;
1508 c_options->image_overlay.text_blue = colour.blue/257;
1509 c_options->image_overlay.text_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1511 gtk_widget_destroy (dialog);
1516 static void image_overlay_set_background_colour_cb(GtkWidget *widget, gpointer data)
1519 #if GTK_CHECK_VERSION(3,4,0)
1522 dialog = gtk_color_chooser_dialog_new("Image Overlay Background Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1523 colour.red = options->image_overlay.background_red;
1524 colour.green = options->image_overlay.background_green;
1525 colour.blue = options->image_overlay.background_blue;
1526 colour.alpha = options->image_overlay.background_alpha;
1527 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1528 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1530 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1532 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1533 c_options->image_overlay.background_red = colour.red*255;
1534 c_options->image_overlay.background_green = colour.green*255;
1535 c_options->image_overlay.background_blue = colour.blue*255;
1536 c_options->image_overlay.background_alpha = colour.alpha*255;
1538 gtk_widget_destroy(dialog);
1541 GtkColorSelection *colorsel;
1543 dialog = gtk_color_selection_dialog_new("Image Overlay Background Colour");
1544 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1545 colour.red = options->image_overlay.background_red*257;
1546 colour.green = options->image_overlay.background_green*257;
1547 colour.blue = options->image_overlay.background_blue*257;
1548 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1549 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1550 gtk_color_selection_set_current_color(colorsel, &colour);
1551 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.background_alpha*257);
1553 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1555 gtk_color_selection_get_current_color(colorsel, &colour);
1556 c_options->image_overlay.background_red = colour.red/257;
1557 c_options->image_overlay.background_green = colour.green/257;
1558 c_options->image_overlay.background_blue = colour.blue/257;
1559 c_options->image_overlay.background_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1561 gtk_widget_destroy(dialog);
1565 static void accel_store_populate(void)
1568 GList *groups, *actions;
1570 const gchar *accel_path;
1574 if (!accel_store || !layout_window_list || !layout_window_list->data) return;
1576 gtk_tree_store_clear(accel_store);
1577 lw = layout_window_list->data; /* get the actions from the first window, it should not matter, they should be the same in all windows */
1579 g_assert(lw && lw->ui_manager);
1580 groups = gtk_ui_manager_get_action_groups(lw->ui_manager);
1583 actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
1586 action = GTK_ACTION(actions->data);
1587 accel_path = gtk_action_get_accel_path(action);
1588 if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
1590 gchar *label, *label2, *tooltip, *accel;
1591 g_object_get(action,
1592 "tooltip", &tooltip,
1596 if (pango_parse_markup(label, -1, '_', NULL, &label2, NULL, NULL) && label2)
1602 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1606 gtk_tree_store_append(accel_store, &iter, NULL);
1607 gtk_tree_store_set(accel_store, &iter,
1610 AE_TOOLTIP, tooltip ? tooltip : "",
1611 AE_ACCEL, accel_path,
1619 actions = actions->next;
1622 groups = groups->next;
1626 static void accel_store_cleared_cb(GtkCellRendererAccel *accel, gchar *path_string, gpointer user_data)
1631 static gboolean accel_remove_key_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1633 gchar *accel1 = data;
1638 gtk_tree_model_get(model, iter, AE_KEY, &accel2, -1);
1640 gtk_accelerator_parse(accel1, &key1.accel_key, &key1.accel_mods);
1641 gtk_accelerator_parse(accel2, &key2.accel_key, &key2.accel_mods);
1643 if (key1.accel_key == key2.accel_key && key1.accel_mods == key2.accel_mods)
1645 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1646 DEBUG_1("accelerator key '%s' is already used, removing.", accel1);
1655 static void accel_store_edited_cb(GtkCellRendererAccel *accel, gchar *path_string, guint accel_key, GdkModifierType accel_mods, guint hardware_keycode, gpointer user_data)
1657 GtkTreeModel *model = (GtkTreeModel *)accel_store;
1661 GtkAccelKey old_key, key;
1662 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
1664 gtk_tree_model_get_iter(model, &iter, path);
1665 gtk_tree_model_get(model, &iter, AE_ACCEL, &accel_path, -1);
1667 /* test if the accelerator can be stored without conflicts*/
1668 gtk_accel_map_lookup_entry(accel_path, &old_key);
1670 /* change the key and read it back (change may fail on keys hardcoded in gtk)*/
1671 gtk_accel_map_change_entry(accel_path, accel_key, accel_mods, TRUE);
1672 gtk_accel_map_lookup_entry(accel_path, &key);
1674 /* restore the original for now, the key will be really changed when the changes are confirmed */
1675 gtk_accel_map_change_entry(accel_path, old_key.accel_key, old_key.accel_mods, TRUE);
1677 acc = gtk_accelerator_name(key.accel_key, key.accel_mods);
1678 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, acc);
1680 gtk_tree_store_set(accel_store, &iter, AE_KEY, acc, -1);
1681 gtk_tree_path_free(path);
1685 static gboolean accel_default_scroll(GtkTreeView *data)
1689 GtkTreeViewColumn *column;
1691 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(accel_store), &iter);
1692 path = gtk_tree_model_get_path(GTK_TREE_MODEL(accel_store), &iter);
1693 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1695 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1699 gtk_tree_path_free(path);
1704 static void accel_default_cb(GtkWidget *widget, gpointer data)
1706 accel_store_populate();
1708 g_idle_add((GSourceFunc)accel_default_scroll, data);
1711 void accel_remove_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1713 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1716 void accel_reset_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1719 gchar *accel_path, *accel;
1721 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, -1);
1722 gtk_accel_map_lookup_entry(accel_path, &key);
1723 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1725 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, accel);
1727 gtk_tree_store_set(accel_store, iter, AE_KEY, accel, -1);
1732 static void accel_reset_cb(GtkWidget *widget, gpointer data)
1734 GtkTreeSelection *selection;
1736 if (!accel_store) return;
1737 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data));
1738 gtk_tree_selection_selected_foreach(selection, &accel_reset_selection, NULL);
1743 static GtkWidget *scrolled_notebook_page(GtkWidget *notebook, const gchar *title)
1747 GtkWidget *scrolled;
1748 GtkWidget *viewport;
1750 scrolled = gtk_scrolled_window_new(NULL, NULL);
1751 gtk_container_set_border_width(GTK_CONTAINER(scrolled), PREF_PAD_BORDER);
1752 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1753 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1754 label = gtk_label_new(title);
1755 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, label);
1756 gtk_widget_show(scrolled);
1758 viewport = gtk_viewport_new(NULL, NULL);
1759 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1760 gtk_container_add(GTK_CONTAINER(scrolled), viewport);
1761 gtk_widget_show(viewport);
1763 vbox = gtk_vbox_new(FALSE, 0);
1764 gtk_container_add(GTK_CONTAINER(viewport), vbox);
1765 gtk_widget_show(vbox);
1770 static void cache_standard_cb(GtkWidget *widget, gpointer data)
1772 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1774 c_options->thumbnails.spec_standard =TRUE;
1775 c_options->thumbnails.cache_into_dirs = FALSE;
1779 static void cache_geeqie_cb(GtkWidget *widget, gpointer data)
1781 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1783 c_options->thumbnails.spec_standard =FALSE;
1784 c_options->thumbnails.cache_into_dirs = FALSE;
1788 static void cache_local_cb(GtkWidget *widget, gpointer data)
1790 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1792 c_options->thumbnails.cache_into_dirs = TRUE;
1793 c_options->thumbnails.spec_standard =FALSE;
1797 static void help_search_engine_entry_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1798 GdkEvent *event, gpointer userdata)
1800 if (pos == GTK_ENTRY_ICON_PRIMARY)
1802 gtk_entry_set_text(GTK_ENTRY(userdata), HELP_SEARCH_ENGINE);
1806 gtk_entry_set_text(GTK_ENTRY(userdata), "");
1810 static void star_rating_star_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1811 GdkEvent *event, gpointer userdata)
1813 gchar *rating_symbol;
1815 if (pos == GTK_ENTRY_ICON_PRIMARY)
1817 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_STAR);
1818 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1819 g_free(rating_symbol);
1823 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1824 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1825 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1829 static void star_rating_rejected_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1830 GdkEvent *event, gpointer userdata)
1832 gchar *rating_symbol;
1834 if (pos == GTK_ENTRY_ICON_PRIMARY)
1836 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_REJECTED);
1837 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1838 g_free(rating_symbol);
1842 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1843 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1844 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1848 static guint star_rating_symbol_test(GtkWidget *widget, gpointer data)
1850 GtkContainer *hbox = data;
1851 GString *str = g_string_new(NULL);
1852 GtkEntry *hex_code_entry;
1853 gchar *hex_code_full;
1856 guint64 hex_value = 0;
1858 list = gtk_container_get_children(hbox);
1860 hex_code_entry = g_list_nth_data(list, 2);
1861 hex_code_full = g_strdup(gtk_entry_get_text(hex_code_entry));
1863 hex_code = g_strsplit(hex_code_full, "+", 2);
1864 if (hex_code[0] && hex_code[1])
1866 hex_value = strtoull(hex_code[1], NULL, 16);
1868 if (!hex_value || hex_value > 0x10FFFF)
1870 hex_value = 0x003F; // Unicode 'Question Mark'
1872 str = g_string_append_unichar(str, (gunichar)hex_value);
1873 gtk_label_set_text(g_list_nth_data(list, 1), str->str);
1875 g_strfreev(hex_code);
1876 g_string_free(str, TRUE);
1877 g_free(hex_code_full);
1882 static void star_rating_star_test_cb(GtkWidget *widget, gpointer data)
1884 guint64 star_symbol;
1886 star_symbol = star_rating_symbol_test(widget, data);
1887 c_options->star_rating.star = star_symbol;
1890 static void star_rating_rejected_test_cb(GtkWidget *widget, gpointer data)
1892 guint64 rejected_symbol;
1894 rejected_symbol = star_rating_symbol_test(widget, data);
1895 c_options->star_rating.rejected = rejected_symbol;
1898 /* general options tab */
1899 static void timezone_database_install_cb(GtkWidget *widget, gpointer data);
1900 typedef struct _TZData TZData;
1904 GCancellable *cancellable;
1906 GtkWidget *progress;
1908 GFile *timezone_database_gq;
1909 gchar *timezone_database_user;
1912 static void config_tab_general(GtkWidget *notebook)
1917 GtkWidget *group_frame;
1918 GtkWidget *subgroup;
1920 GtkWidget *ct_button;
1923 gint hours, minutes, remainder;
1925 GtkWidget *star_rating_entry;
1927 gchar *rating_symbol;
1930 GNetworkMonitor *net_mon;
1931 GSocketConnectable *geeqie_org;
1932 gboolean internet_available;
1935 vbox = scrolled_notebook_page(notebook, _("General"));
1937 group = pref_group_new(vbox, FALSE, _("Thumbnails"), GTK_ORIENTATION_VERTICAL);
1939 table = pref_table_new(group, 2, 2, FALSE, FALSE);
1940 add_thumb_size_menu(table, 0, 0, _("Size:"));
1941 add_quality_menu(table, 0, 1, _("Quality:"), options->thumbnails.quality, &c_options->thumbnails.quality);
1943 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1944 pref_label_new(hbox, _("Custom size: "));
1945 pref_spin_new_int(hbox, _("Width:"), NULL, 1, 512, 1, options->thumbnails.max_width, &c_options->thumbnails.max_width);
1946 pref_spin_new_int(hbox, _("Height:"), NULL, 1, 512, 1, options->thumbnails.max_height, &c_options->thumbnails.max_height);
1948 ct_button = pref_checkbox_new_int(group, _("Cache thumbnails and sim. files"),
1949 options->thumbnails.enable_caching, &c_options->thumbnails.enable_caching);
1951 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1952 pref_checkbox_link_sensitivity(ct_button, subgroup);
1954 c_options->thumbnails.spec_standard = options->thumbnails.spec_standard;
1955 c_options->thumbnails.cache_into_dirs = options->thumbnails.cache_into_dirs;
1956 group_frame = pref_frame_new(subgroup, TRUE, _("Use Geeqie thumbnail style and cache"),
1957 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1958 button = pref_radiobutton_new(group_frame, NULL, get_thumbnails_cache_dir(),
1959 !options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1960 G_CALLBACK(cache_geeqie_cb), NULL);
1962 group_frame = pref_frame_new(subgroup, TRUE,
1963 _("Store thumbnails local to image folder (non-standard)"),
1964 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1965 pref_radiobutton_new(group_frame, button, "*/.thumbnails",
1966 !options->thumbnails.spec_standard && options->thumbnails.cache_into_dirs,
1967 G_CALLBACK(cache_local_cb), NULL);
1969 group_frame = pref_frame_new(subgroup, TRUE,
1970 _("Use standard thumbnail style and cache, shared with other applications"),
1971 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1972 pref_radiobutton_new(group_frame, button, get_thumbnails_standard_cache_dir(),
1973 options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1974 G_CALLBACK(cache_standard_cb), NULL);
1976 pref_checkbox_new_int(group, _("Use EXIF thumbnails when available (EXIF thumbnails may be outdated)"),
1977 options->thumbnails.use_exif, &c_options->thumbnails.use_exif);
1979 pref_checkbox_new_int(group, _("Thumbnail color management"),
1980 options->thumbnails.use_color_management, &c_options->thumbnails.use_color_management);
1982 spin = pref_spin_new_int(group, _("Collection preview:"), NULL,
1984 options->thumbnails.collection_preview, &c_options->thumbnails.collection_preview);
1985 gtk_widget_set_tooltip_text(spin, _("The maximum number of thumbnails shown in a Collection preview montage"));
1987 #ifdef HAVE_FFMPEGTHUMBNAILER_METADATA
1988 pref_checkbox_new_int(group, _("Use embedded metadata in video files as thumbnails when available"),
1989 options->thumbnails.use_ft_metadata, &c_options->thumbnails.use_ft_metadata);
1991 // pref_checkbox_new_int(group, _("Ignore embedded metadata if size is too small"),
1992 // options->thumbnails.use_ft_metadata_small, &c_options->thumbnails.use_ft_metadata_small);
1995 pref_spacer(group, PREF_PAD_GROUP);
1997 group = pref_group_new(vbox, FALSE, _("Star Rating"), GTK_ORIENTATION_VERTICAL);
1999 c_options->star_rating.star = options->star_rating.star;
2000 c_options->star_rating.rejected = options->star_rating.rejected;
2002 str = g_string_new(NULL);
2003 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2004 pref_label_new(hbox, _("Star character: "));
2005 str = g_string_append_unichar(str, options->star_rating.star);
2006 pref_label_new(hbox, g_strdup(str->str));
2007 rating_symbol = g_strdup_printf("U+%X", options->star_rating.star);
2008 star_rating_entry = gtk_entry_new();
2009 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
2010 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
2011 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
2012 gtk_widget_show(star_rating_entry);
2013 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
2014 G_CALLBACK(star_rating_star_test_cb), hbox);
2015 gtk_widget_set_tooltip_text(button, _("Display selected character"));
2016 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2017 gtk_widget_show(button);
2018 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."));
2019 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2020 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2021 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2022 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2023 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2024 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2025 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2026 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2027 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
2028 G_CALLBACK(star_rating_star_icon_cb),
2031 g_string_free(str, TRUE);
2032 g_free(rating_symbol);
2034 str = g_string_new(NULL);
2035 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2036 pref_label_new(hbox, _("Rejected character: "));
2037 str = g_string_append_unichar(str, options->star_rating.rejected);
2038 pref_label_new(hbox, g_strdup(str->str));
2039 rating_symbol = g_strdup_printf("U+%X", options->star_rating.rejected);
2040 star_rating_entry = gtk_entry_new();
2041 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
2042 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
2043 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
2044 gtk_widget_show(star_rating_entry);
2045 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
2046 G_CALLBACK(star_rating_rejected_test_cb), hbox);
2047 gtk_widget_set_tooltip_text(button, _("Display selected character"));
2048 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2049 gtk_widget_show(button);
2050 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."));
2051 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2052 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2053 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2054 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2055 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2056 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2057 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2058 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2059 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
2060 G_CALLBACK(star_rating_rejected_icon_cb),
2063 g_string_free(str, TRUE);
2064 g_free(rating_symbol);
2066 pref_spacer(group, PREF_PAD_GROUP);
2068 group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
2070 c_options->slideshow.delay = options->slideshow.delay;
2071 hours = options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2072 remainder = options->slideshow.delay % (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2073 minutes = remainder / (60 * SLIDESHOW_SUBSECOND_PRECISION);
2074 seconds = (gdouble)(remainder % (60 * SLIDESHOW_SUBSECOND_PRECISION)) /
2075 SLIDESHOW_SUBSECOND_PRECISION;
2077 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2079 spin = pref_spin_new(hbox, _("Delay between image change hrs:mins:secs.dec"), NULL,
2081 options->slideshow.delay ? hours : 0.0,
2082 G_CALLBACK(slideshow_delay_hours_cb), NULL);
2083 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2084 spin = pref_spin_new(hbox, ":" , NULL,
2086 options->slideshow.delay ? minutes: 0.0,
2087 G_CALLBACK(slideshow_delay_minutes_cb), NULL);
2088 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2089 spin = pref_spin_new(hbox, ":", NULL,
2090 SLIDESHOW_MIN_SECONDS, 59, 1.0, 1,
2091 options->slideshow.delay ? seconds : 10.0,
2092 G_CALLBACK(slideshow_delay_seconds_cb), NULL);
2093 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2095 pref_checkbox_new_int(group, _("Random"), options->slideshow.random, &c_options->slideshow.random);
2096 pref_checkbox_new_int(group, _("Repeat"), options->slideshow.repeat, &c_options->slideshow.repeat);
2098 pref_spacer(group, PREF_PAD_GROUP);
2100 group = pref_group_new(vbox, FALSE, _("Image loading and caching"), GTK_ORIENTATION_VERTICAL);
2102 pref_spin_new_int(group, _("Decoded image cache size (MiB):"), NULL,
2103 0, 99999, 1, options->image.image_cache_max, &c_options->image.image_cache_max);
2104 pref_checkbox_new_int(group, _("Preload next image"),
2105 options->image.enable_read_ahead, &c_options->image.enable_read_ahead);
2107 pref_checkbox_new_int(group, _("Refresh on file change"),
2108 options->update_on_time_change, &c_options->update_on_time_change);
2111 pref_spacer(group, PREF_PAD_GROUP);
2113 group = pref_group_new(vbox, FALSE, _("Expand menu and toolbar"), GTK_ORIENTATION_VERTICAL);
2115 pref_checkbox_new_int(group, _("Expand menu and toolbar (NOTE! Geeqie must be restarted for change to take effect)"),
2116 options->expand_menu_toolbar, &c_options->expand_menu_toolbar);
2117 gtk_widget_set_tooltip_text(group, _("Expand the menu and toolbar to the full width of the window"));
2119 pref_spacer(group, PREF_PAD_GROUP);
2121 group = pref_group_new(vbox, FALSE, _("Info sidebar heights"), GTK_ORIENTATION_VERTICAL);
2122 pref_label_new(group, _("NOTE! Geeqie must be restarted for changes to take effect"));
2123 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2124 pref_spin_new_int(hbox, _("Keywords:"), NULL,
2126 options->info_keywords.height, &c_options->info_keywords.height);
2127 pref_spin_new_int(hbox, _("Title:"), NULL,
2129 options->info_title.height, &c_options->info_title.height);
2130 pref_spin_new_int(hbox, _("Comment:"), NULL,
2132 options->info_comment.height, &c_options->info_comment.height);
2133 pref_spin_new_int(hbox, _("Rating:"), NULL,
2135 options->info_rating.height, &c_options->info_rating.height);
2137 pref_spacer(group, PREF_PAD_GROUP);
2139 group = pref_group_new(vbox, FALSE, _("Show predefined keyword tree"), GTK_ORIENTATION_VERTICAL);
2141 pref_checkbox_new_int(group, _("Show predefined keyword tree (NOTE! Geeqie must be restarted for change to take effect)"),
2142 options->show_predefined_keyword_tree, &c_options->show_predefined_keyword_tree);
2144 pref_spacer(group, PREF_PAD_GROUP);
2146 net_mon = g_network_monitor_get_default();
2147 geeqie_org = g_network_address_parse_uri(GQ_WEBSITE, 80, NULL);
2148 internet_available = g_network_monitor_can_reach(net_mon, geeqie_org, NULL, NULL);
2149 g_object_unref(geeqie_org);
2151 group = pref_group_new(vbox, FALSE, _("Timezone database"), GTK_ORIENTATION_VERTICAL);
2152 hbox = pref_box_new(group, TRUE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2154 if (!internet_available)
2156 gtk_widget_set_sensitive(group, FALSE);
2159 tz = g_new0(TZData, 1);
2161 path = path_from_utf8(TIMEZONE_DATABASE);
2162 basename = g_path_get_basename(path);
2163 tz->timezone_database_user = g_build_filename(get_rc_dir(), basename, NULL);
2167 if (isfile(tz->timezone_database_user))
2169 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Update"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2173 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Install"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2176 if (!internet_available)
2178 gtk_widget_set_tooltip_text(button, _("No Internet connection!\nThe timezone database is used to display exif time and date\ncorrected for UTC offset and Daylight Saving Time"));
2182 gtk_widget_set_tooltip_text(button, _("The timezone database is used to display exif time and date\ncorrected for UTC offset and Daylight Saving Time"));
2184 gtk_widget_show(button);
2186 pref_spacer(group, PREF_PAD_GROUP);
2188 group = pref_group_new(vbox, FALSE, _("On-line help search engine"), GTK_ORIENTATION_VERTICAL);
2190 help_search_engine_entry = gtk_entry_new();
2191 gtk_entry_set_text(GTK_ENTRY(help_search_engine_entry), options->help_search_engine);
2192 gtk_box_pack_start(GTK_BOX(group), help_search_engine_entry, FALSE, FALSE, 0);
2193 gtk_widget_show(help_search_engine_entry);
2195 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"));
2197 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2198 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2199 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2200 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2201 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2202 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2203 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2204 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2205 g_signal_connect(GTK_ENTRY(help_search_engine_entry), "icon-press",
2206 G_CALLBACK(help_search_engine_entry_icon_cb),
2207 help_search_engine_entry);
2211 static void config_tab_image(GtkWidget *notebook)
2216 GtkWidget *ct_button;
2217 GtkWidget *enlargement_button;
2220 GtkWidget *two_pass;
2222 GtkWidget *gpu_accel;
2225 vbox = scrolled_notebook_page(notebook, _("Image"));
2227 group = pref_group_new(vbox, FALSE, _("Zoom"), GTK_ORIENTATION_VERTICAL);
2229 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2230 add_quality_menu(table, 0, 0, _("Quality:"), options->image.zoom_quality, &c_options->image.zoom_quality);
2231 if (options->image.use_clutter_renderer && !options->disable_gpu)
2233 gtk_widget_set_sensitive(table, FALSE);
2237 gpu_accel = pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library (Requires restart)"),
2238 options->image.use_clutter_renderer, &c_options->image.use_clutter_renderer);
2239 if (options->disable_gpu && !options->override_disable_gpu)
2241 gtk_widget_set_sensitive(gpu_accel, FALSE);
2245 two_pass = pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"),
2246 options->image.zoom_2pass, &c_options->image.zoom_2pass);
2247 if (options->image.use_clutter_renderer && !options->disable_gpu)
2249 gtk_widget_set_sensitive(two_pass, FALSE);
2252 c_options->image.zoom_increment = options->image.zoom_increment;
2253 spin = pref_spin_new(group, _("Zoom increment:"), NULL,
2254 0.01, 4.0, 0.01, 2, (gdouble)options->image.zoom_increment / 100.0,
2255 G_CALLBACK(zoom_increment_cb), NULL);
2256 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2258 group = pref_group_new(vbox, FALSE, _("Fit image to window"), GTK_ORIENTATION_VERTICAL);
2260 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2261 enlargement_button = pref_checkbox_new_int(hbox, _("Allow enlargement of image (max. size in %)"),
2262 options->image.zoom_to_fit_allow_expand, &c_options->image.zoom_to_fit_allow_expand);
2263 spin = pref_spin_new_int(hbox, NULL, NULL,
2265 options->image.max_enlargement_size, &c_options->image.max_enlargement_size);
2266 pref_checkbox_link_sensitivity(enlargement_button, spin);
2267 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."));
2269 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2270 ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (% of actual window):"),
2271 options->image.limit_autofit_size, &c_options->image.limit_autofit_size);
2272 spin = pref_spin_new_int(hbox, NULL, NULL,
2274 options->image.max_autofit_size, &c_options->image.max_autofit_size);
2275 pref_checkbox_link_sensitivity(ct_button, spin);
2276 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."));
2278 group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
2280 pref_checkbox_new_int(group, _("Use custom border color in window mode"),
2281 options->image.use_custom_border_color, &c_options->image.use_custom_border_color);
2283 pref_checkbox_new_int(group, _("Use custom border color in fullscreen mode"),
2284 options->image.use_custom_border_color_in_fullscreen, &c_options->image.use_custom_border_color_in_fullscreen);
2286 pref_color_button_new(group, _("Border color"), &options->image.border_color,
2287 G_CALLBACK(pref_color_button_set_cb), &c_options->image.border_color);
2289 c_options->image.border_color = options->image.border_color;
2291 pref_color_button_new(group, _("Alpha channel color 1"), &options->image.alpha_color_1,
2292 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_1);
2294 pref_color_button_new(group, _("Alpha channel color 2"), &options->image.alpha_color_2,
2295 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_2);
2297 c_options->image.alpha_color_1 = options->image.alpha_color_1;
2298 c_options->image.alpha_color_2 = options->image.alpha_color_2;
2300 group = pref_group_new(vbox, FALSE, _("Convenience"), GTK_ORIENTATION_VERTICAL);
2302 pref_checkbox_new_int(group, _("Auto rotate proofs using Exif information"),
2303 options->image.exif_proof_rotate_enable, &c_options->image.exif_proof_rotate_enable);
2307 static void config_tab_windows(GtkWidget *notebook)
2313 GtkWidget *ct_button;
2316 vbox = scrolled_notebook_page(notebook, _("Windows"));
2318 group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
2320 ct_button = pref_checkbox_new_int(group, _("Remember window positions"),
2321 options->save_window_positions, &c_options->save_window_positions);
2323 button = pref_checkbox_new_int(group, _("Use saved window positions also for new windows"),
2324 options->use_saved_window_positions_for_new_windows, &c_options->use_saved_window_positions_for_new_windows);
2325 pref_checkbox_link_sensitivity(ct_button, button);
2327 button = pref_checkbox_new_int(group, _("Remember window workspace"),
2328 options->save_window_workspace, &c_options->save_window_workspace);
2329 pref_checkbox_link_sensitivity(ct_button, button);
2331 pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
2332 options->tools_restore_state, &c_options->tools_restore_state);
2334 pref_checkbox_new_int(group, _("Remember dialog window positions"),
2335 options->save_dialog_window_positions, &c_options->save_dialog_window_positions);
2337 pref_checkbox_new_int(group, _("Show window IDs"),
2338 options->show_window_ids, &c_options->show_window_ids);
2340 group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
2342 pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
2343 options->image.fit_window_to_image, &c_options->image.fit_window_to_image);
2345 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2346 ct_button = pref_checkbox_new_int(hbox, _("Limit size when auto-sizing window (%):"),
2347 options->image.limit_window_size, &c_options->image.limit_window_size);
2348 spin = pref_spin_new_int(hbox, NULL, NULL,
2350 options->image.max_window_size, &c_options->image.max_window_size);
2351 pref_checkbox_link_sensitivity(ct_button, spin);
2353 group = pref_group_new(vbox, FALSE, _("Full screen"), GTK_ORIENTATION_VERTICAL);
2355 c_options->fullscreen.screen = options->fullscreen.screen;
2356 c_options->fullscreen.above = options->fullscreen.above;
2357 hbox = fullscreen_prefs_selection_new(_("Location:"), &c_options->fullscreen.screen, &c_options->fullscreen.above);
2358 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2359 gtk_widget_show(hbox);
2361 pref_checkbox_new_int(group, _("Smooth image flip"),
2362 options->fullscreen.clean_flip, &c_options->fullscreen.clean_flip);
2363 pref_checkbox_new_int(group, _("Disable screen saver"),
2364 options->fullscreen.disable_saver, &c_options->fullscreen.disable_saver);
2367 #define PRE_FORMATTED_COLUMNS 5
2368 static void config_tab_osd(GtkWidget *notebook)
2374 GtkWidget *image_overlay_template_view;
2375 GtkWidget *scrolled;
2376 GtkWidget *scrolled_pre_formatted;
2377 GtkTextBuffer *buffer;
2379 GtkWidget *subgroup;
2381 vbox = scrolled_notebook_page(notebook, _("OSD"));
2383 image_overlay_template_view = gtk_text_view_new();
2385 group = pref_group_new(vbox, FALSE, _("Overlay Screen Display"), GTK_ORIENTATION_VERTICAL);
2387 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2389 scrolled_pre_formatted = osd_new(PRE_FORMATTED_COLUMNS, image_overlay_template_view);
2390 gtk_widget_set_size_request(scrolled_pre_formatted, 200, 150);
2391 gtk_box_pack_start(GTK_BOX(subgroup), scrolled_pre_formatted, FALSE, FALSE, 0);
2392 gtk_widget_show(scrolled_pre_formatted);
2393 gtk_widget_show(subgroup);
2395 pref_line(group, PREF_PAD_GAP);
2397 pref_label_new(group, _("Image overlay template"));
2399 scrolled = gtk_scrolled_window_new(NULL, NULL);
2400 gtk_widget_set_size_request(scrolled, 200, 150);
2401 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2402 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
2403 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2404 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 5);
2405 gtk_widget_show(scrolled);
2407 gtk_widget_set_tooltip_markup(image_overlay_template_view,
2408 _("Extensive formatting options are shown in the Help file"));
2410 gtk_container_add(GTK_CONTAINER(scrolled), image_overlay_template_view);
2411 gtk_widget_show(image_overlay_template_view);
2413 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2415 #if GTK_CHECK_VERSION(3,4,0)
2416 button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
2417 G_CALLBACK(image_overlay_set_font_cb), notebook);
2419 button = gtk_font_button_new();
2420 gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Image Overlay Font");
2421 gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->image_overlay.font);
2422 g_signal_connect(G_OBJECT(button), "font-set",
2423 G_CALLBACK(image_overlay_set_font_cb),NULL);
2425 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2426 gtk_widget_show(button);
2428 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Text"), FALSE,
2429 G_CALLBACK(image_overlay_set_text_colour_cb), NULL);
2430 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2431 gtk_widget_show(button);
2433 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Background"), FALSE,
2434 G_CALLBACK(image_overlay_set_background_colour_cb), NULL);
2435 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2436 gtk_widget_show(button);
2437 image_overlay_set_text_colours();
2439 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2440 G_CALLBACK(image_overlay_default_template_cb), image_overlay_template_view);
2441 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2442 gtk_widget_show(button);
2444 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
2445 G_CALLBACK(image_overlay_help_cb), NULL);
2446 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2447 gtk_widget_show(button);
2449 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_overlay_template_view));
2450 if (options->image_overlay.template_string) gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
2451 g_signal_connect(G_OBJECT(buffer), "changed",
2452 G_CALLBACK(image_overlay_template_view_changed_cb), image_overlay_template_view);
2454 pref_line(group, PREF_PAD_GAP);
2456 group = pref_group_new(vbox, FALSE, _("Exif, XMP or IPTC tags"), GTK_ORIENTATION_VERTICAL);
2457 hbox = gtk_hbox_new(FALSE, 0);
2458 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2459 gtk_widget_show(hbox);
2460 label = gtk_label_new(_("%Exif.Image.Orientation%"));
2461 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2462 gtk_widget_show(label);
2463 pref_spacer(group,TRUE);
2465 group = pref_group_new(vbox, FALSE, _("Field separators"), GTK_ORIENTATION_VERTICAL);
2466 hbox = gtk_hbox_new(FALSE, 0);
2467 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2468 gtk_widget_show(hbox);
2469 label = gtk_label_new(_("Separator shown only if both fields are non-null:\n%formatted.ShutterSpeed%|%formatted.ISOSpeedRating%"));
2470 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2471 gtk_widget_show(label);
2472 pref_spacer(group,TRUE);
2474 group = pref_group_new(vbox, FALSE, _("Field maximum length"), GTK_ORIENTATION_VERTICAL);
2475 hbox = gtk_hbox_new(FALSE, 0);
2476 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2477 gtk_widget_show(hbox);
2478 label = gtk_label_new(_("%path:39%"));
2479 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2480 gtk_widget_show(label);
2481 pref_spacer(group,TRUE);
2483 group = pref_group_new(vbox, FALSE, _("Pre- and post- text"), GTK_ORIENTATION_VERTICAL);
2484 hbox = gtk_hbox_new(FALSE, 0);
2485 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2486 gtk_widget_show(hbox);
2487 label = gtk_label_new(_("Text shown only if the field is non-null:\n%formatted.Aperture:F no. * setting%\n %formatted.Aperture:10:F no. * setting%"));
2488 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2489 gtk_widget_show(label);
2490 pref_spacer(group,TRUE);
2492 group = pref_group_new(vbox, FALSE, _("Pango markup"), GTK_ORIENTATION_VERTICAL);
2493 hbox = gtk_hbox_new(FALSE, 0);
2494 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2495 gtk_widget_show(hbox);
2496 label = gtk_label_new(_("<b>bold</b>\n<u>underline</u>\n<i>italic</i>\n<s>strikethrough</s>"));
2497 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2498 gtk_widget_show(label);
2501 static GtkTreeModel *create_class_model(void)
2503 GtkListStore *model;
2507 /* create list store */
2508 model = gtk_list_store_new(1, G_TYPE_STRING);
2509 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
2511 gtk_list_store_append(model, &iter);
2512 gtk_list_store_set(model, &iter, 0, _(format_class_list[i]), -1);
2514 return GTK_TREE_MODEL (model);
2519 static void config_tab_files(GtkWidget *notebook)
2526 GtkWidget *ct_button;
2527 GtkWidget *scrolled;
2528 GtkWidget *filter_view;
2529 GtkCellRenderer *renderer;
2530 GtkTreeSelection *selection;
2531 GtkTreeViewColumn *column;
2533 vbox = scrolled_notebook_page(notebook, _("Files"));
2535 group = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2537 pref_checkbox_new_int(group, _("Show hidden files or folders"),
2538 options->file_filter.show_hidden_files, &c_options->file_filter.show_hidden_files);
2539 pref_checkbox_new_int(group, _("Show parent folder (..)"),
2540 options->file_filter.show_parent_directory, &c_options->file_filter.show_parent_directory);
2541 pref_checkbox_new_int(group, _("Case sensitive sort"),
2542 options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
2543 pref_checkbox_new_int(group, _("Natural sort order"),
2544 options->file_sort.natural, &c_options->file_sort.natural);
2545 pref_checkbox_new_int(group, _("Disable file extension checks"),
2546 options->file_filter.disable_file_extension_checks, &c_options->file_filter.disable_file_extension_checks);
2548 ct_button = pref_checkbox_new_int(group, _("Disable File Filtering"),
2549 options->file_filter.disable, &c_options->file_filter.disable);
2552 group = pref_group_new(vbox, FALSE, _("Grouping sidecar extensions"), GTK_ORIENTATION_VERTICAL);
2554 sidecar_ext_entry = gtk_entry_new();
2555 gtk_entry_set_text(GTK_ENTRY(sidecar_ext_entry), options->sidecar.ext);
2556 gtk_box_pack_start(GTK_BOX(group), sidecar_ext_entry, FALSE, FALSE, 0);
2557 gtk_widget_show(sidecar_ext_entry);
2559 group = pref_group_new(vbox, TRUE, _("File types"), GTK_ORIENTATION_VERTICAL);
2561 frame = pref_group_parent(group);
2562 g_signal_connect(G_OBJECT(ct_button), "toggled",
2563 G_CALLBACK(filter_disable_cb), frame);
2564 gtk_widget_set_sensitive(frame, !options->file_filter.disable);
2566 scrolled = gtk_scrolled_window_new(NULL, NULL);
2567 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2568 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2569 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2570 gtk_widget_show(scrolled);
2572 filter_store = gtk_list_store_new(1, G_TYPE_POINTER);
2573 filter_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(filter_store));
2574 g_object_unref(filter_store);
2575 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
2576 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
2578 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), FALSE);
2580 column = gtk_tree_view_column_new();
2581 gtk_tree_view_column_set_title(column, _("Filter"));
2582 gtk_tree_view_column_set_resizable(column, TRUE);
2584 renderer = gtk_cell_renderer_toggle_new();
2585 g_signal_connect(G_OBJECT(renderer), "toggled",
2586 G_CALLBACK(filter_store_enable_cb), filter_store);
2587 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2588 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2589 GINT_TO_POINTER(FE_ENABLE), NULL);
2591 renderer = gtk_cell_renderer_text_new();
2592 g_signal_connect(G_OBJECT(renderer), "edited",
2593 G_CALLBACK(filter_store_ext_edit_cb), filter_store);
2594 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2595 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2596 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2597 GINT_TO_POINTER(FE_EXTENSION), NULL);
2598 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2600 column = gtk_tree_view_column_new();
2601 gtk_tree_view_column_set_title(column, _("Description"));
2602 gtk_tree_view_column_set_resizable(column, TRUE);
2603 gtk_tree_view_column_set_fixed_width(column, 200);
2604 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
2606 renderer = gtk_cell_renderer_text_new();
2607 g_signal_connect(G_OBJECT(renderer), "edited",
2608 G_CALLBACK(filter_store_desc_edit_cb), filter_store);
2609 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2610 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2611 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2612 GINT_TO_POINTER(FE_DESCRIPTION), NULL);
2613 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2615 column = gtk_tree_view_column_new();
2616 gtk_tree_view_column_set_title(column, _("Class"));
2617 gtk_tree_view_column_set_resizable(column, TRUE);
2618 renderer = gtk_cell_renderer_combo_new();
2619 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE,
2620 "model", create_class_model(),
2625 g_signal_connect(G_OBJECT(renderer), "edited",
2626 G_CALLBACK(filter_store_class_edit_cb), filter_store);
2627 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2628 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2629 GINT_TO_POINTER(FE_CLASS), NULL);
2630 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2632 column = gtk_tree_view_column_new();
2633 gtk_tree_view_column_set_title(column, _("Writable"));
2634 gtk_tree_view_column_set_resizable(column, FALSE);
2635 renderer = gtk_cell_renderer_toggle_new();
2636 g_signal_connect(G_OBJECT(renderer), "toggled",
2637 G_CALLBACK(filter_store_writable_cb), filter_store);
2638 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2639 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2640 GINT_TO_POINTER(FE_WRITABLE), NULL);
2641 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2643 column = gtk_tree_view_column_new();
2644 gtk_tree_view_column_set_title(column, _("Sidecar is allowed"));
2645 gtk_tree_view_column_set_resizable(column, FALSE);
2646 renderer = gtk_cell_renderer_toggle_new();
2647 g_signal_connect(G_OBJECT(renderer), "toggled",
2648 G_CALLBACK(filter_store_sidecar_cb), filter_store);
2649 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2650 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2651 GINT_TO_POINTER(FE_ALLOW_SIDECAR), NULL);
2652 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2655 filter_store_populate();
2656 gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
2657 gtk_widget_show(filter_view);
2659 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2661 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2662 G_CALLBACK(filter_default_cb), filter_view);
2663 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2664 gtk_widget_show(button);
2666 button = pref_button_new(NULL, GTK_STOCK_REMOVE, NULL, FALSE,
2667 G_CALLBACK(filter_remove_cb), filter_view);
2668 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2669 gtk_widget_show(button);
2671 button = pref_button_new(NULL, GTK_STOCK_ADD, NULL, FALSE,
2672 G_CALLBACK(filter_add_cb), filter_view);
2673 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2674 gtk_widget_show(button);
2678 static void config_tab_metadata(GtkWidget *notebook)
2683 GtkWidget *ct_button;
2687 vbox = scrolled_notebook_page(notebook, _("Metadata"));
2690 group = pref_group_new(vbox, FALSE, _("Metadata writing process"), GTK_ORIENTATION_VERTICAL);
2692 label = pref_label_new(group, _("Warning: Geeqie is built without Exiv2. Some options are disabled."));
2694 label = pref_label_new(group, _("Metadata are written in the following order. The process ends after first success."));
2695 #if GTK_CHECK_VERSION(3,16,0)
2696 gtk_label_set_xalign(GTK_LABEL(label), 0.0);
2697 gtk_label_set_yalign(GTK_LABEL(label), 0.5);
2699 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2702 ct_button = pref_checkbox_new_int(group, _("1) Save metadata in image files, or sidecar files, according to the XMP standard"),
2703 options->metadata.save_in_image_file, &c_options->metadata.save_in_image_file);
2705 gtk_widget_set_sensitive(ct_button, FALSE);
2708 pref_checkbox_new_int(group, _("2) Save metadata in '.metadata' folder, local to image folder (non-standard)"),
2709 options->metadata.enable_metadata_dirs, &c_options->metadata.enable_metadata_dirs);
2711 text = g_strdup_printf(_("3) Save metadata in Geeqie private directory '%s'"), get_metadata_cache_dir());
2712 label = pref_label_new(group, text);
2713 #if GTK_CHECK_VERSION(3,16,0)
2714 gtk_label_set_xalign(GTK_LABEL(label), 0.0);
2715 gtk_label_set_yalign(GTK_LABEL(label), 0.5);
2717 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2719 gtk_misc_set_padding(GTK_MISC(label), 22, 0);
2722 group = pref_group_new(vbox, FALSE, _("Step 1: Write to image files"), GTK_ORIENTATION_VERTICAL);
2724 gtk_widget_set_sensitive(group, FALSE);
2727 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2728 pref_checkbox_link_sensitivity(ct_button, hbox);
2730 pref_checkbox_new_int(hbox, _("Store metadata also in legacy IPTC tags (converted according to IPTC4XMP standard)"),
2731 options->metadata.save_legacy_IPTC, &c_options->metadata.save_legacy_IPTC);
2733 pref_checkbox_new_int(hbox, _("Warn if the image files are unwritable"),
2734 options->metadata.warn_on_write_problems, &c_options->metadata.warn_on_write_problems);
2736 pref_checkbox_new_int(hbox, _("Ask before writing to image files"),
2737 options->metadata.confirm_write, &c_options->metadata.confirm_write);
2739 pref_checkbox_new_int(hbox, _("Create sidecar files named image.ext.xmp (as opposed to image.xmp)"),
2740 options->metadata.sidecar_extended_name, &c_options->metadata.sidecar_extended_name);
2742 group = pref_group_new(vbox, FALSE, _("Step 2 and 3: write to Geeqie private files"), GTK_ORIENTATION_VERTICAL);
2744 gtk_widget_set_sensitive(group, FALSE);
2747 pref_checkbox_new_int(group, _("Use GQview legacy metadata format (supports only keywords and comments) instead of XMP"),
2748 options->metadata.save_legacy_format, &c_options->metadata.save_legacy_format);
2751 group = pref_group_new(vbox, FALSE, _("Miscellaneous"), GTK_ORIENTATION_VERTICAL);
2752 pref_checkbox_new_int(group, _("Write the same description tags (keywords, comment, etc.) to all grouped sidecars"),
2753 options->metadata.sync_grouped_files, &c_options->metadata.sync_grouped_files);
2755 pref_checkbox_new_int(group, _("Allow keywords to differ only in case"),
2756 options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
2758 ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"),
2759 options->metadata.write_orientation, &c_options->metadata.write_orientation);
2761 gtk_widget_set_sensitive(ct_button, FALSE);
2764 group = pref_group_new(vbox, FALSE, _("Auto-save options"), GTK_ORIENTATION_VERTICAL);
2766 ct_button = pref_checkbox_new_int(group, _("Write metadata after timeout"),
2767 options->metadata.confirm_after_timeout, &c_options->metadata.confirm_after_timeout);
2769 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2770 pref_checkbox_link_sensitivity(ct_button, hbox);
2772 pref_spin_new_int(hbox, _("Timeout (seconds):"), NULL, 0, 900, 1,
2773 options->metadata.confirm_timeout, &c_options->metadata.confirm_timeout);
2775 pref_checkbox_new_int(group, _("Write metadata on image change"),
2776 options->metadata.confirm_on_image_change, &c_options->metadata.confirm_on_image_change);
2778 pref_checkbox_new_int(group, _("Write metadata on directory change"),
2779 options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
2781 group = pref_group_new(vbox, FALSE, _("Pre-load metadata"), GTK_ORIENTATION_VERTICAL);
2783 ct_button = pref_checkbox_new_int(group, _("Read metadata in background"),
2784 options->read_metadata_in_idle, &c_options->read_metadata_in_idle);
2785 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");
2790 typedef struct _KeywordFindData KeywordFindData;
2791 struct _KeywordFindData
2798 GtkWidget *button_close;
2799 GtkWidget *button_stop;
2800 GtkWidget *button_start;
2801 GtkWidget *progress;
2809 guint idle_id; /* event source id */
2812 #define KEYWORD_DIALOG_WIDTH 400
2814 static void keywords_find_folder(KeywordFindData *kfd, FileData *dir_fd)
2816 GList *list_d = NULL;
2817 GList *list_f = NULL;
2821 filelist_read(dir_fd, &list_f, &list_d);
2825 filelist_read(dir_fd, &list_f, NULL);
2828 list_f = filelist_filter(list_f, FALSE);
2829 list_d = filelist_filter(list_d, TRUE);
2831 kfd->list = g_list_concat(list_f, kfd->list);
2832 kfd->list_dir = g_list_concat(list_d, kfd->list_dir);
2835 static void keywords_find_reset(KeywordFindData *kfd)
2837 filelist_free(kfd->list);
2840 filelist_free(kfd->list_dir);
2841 kfd->list_dir = NULL;
2844 static void keywords_find_close_cb(GenericDialog *fd, gpointer data)
2846 KeywordFindData *kfd = data;
2848 if (!gtk_widget_get_sensitive(kfd->button_close)) return;
2850 keywords_find_reset(kfd);
2851 generic_dialog_close(kfd->gd);
2855 static void keywords_find_finish(KeywordFindData *kfd)
2857 keywords_find_reset(kfd);
2859 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("done"));
2860 spinner_set_interval(kfd->spinner, -1);
2862 gtk_widget_set_sensitive(kfd->group, TRUE);
2863 gtk_widget_set_sensitive(kfd->button_start, TRUE);
2864 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2865 gtk_widget_set_sensitive(kfd->button_close, TRUE);
2868 static void keywords_find_stop_cb(GenericDialog *fd, gpointer data)
2870 KeywordFindData *kfd = data;
2872 g_idle_remove_by_data(kfd);
2874 keywords_find_finish(kfd);
2877 static gboolean keywords_find_file(gpointer data)
2879 KeywordFindData *kfd = data;
2881 GtkTextBuffer *buffer;
2889 fd = kfd->list->data;
2890 kfd->list = g_list_remove(kfd->list, fd);
2892 keywords = metadata_read_list(fd, KEYWORD_KEY, METADATA_PLAIN);
2893 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2897 gtk_text_buffer_get_end_iter(buffer, &iter);
2898 tmp = g_strconcat(keywords->data, "\n", NULL);
2899 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
2901 keywords = keywords->next;
2904 gtk_entry_set_text(GTK_ENTRY(kfd->progress), fd->path);
2905 file_data_unref(fd);
2906 string_list_free(keywords);
2910 else if (kfd->list_dir)
2914 fd = kfd->list_dir->data;
2915 kfd->list_dir = g_list_remove(kfd->list_dir, fd);
2917 keywords_find_folder(kfd, fd);
2919 file_data_unref(fd);
2924 keywords_find_finish(kfd);
2929 static void keywords_find_start_cb(GenericDialog *fd, gpointer data)
2931 KeywordFindData *kfd = data;
2934 if (kfd->list || !gtk_widget_get_sensitive(kfd->button_start)) return;
2936 path = remove_trailing_slash((gtk_entry_get_text(GTK_ENTRY(kfd->entry))));
2937 parse_out_relatives(path);
2941 warning_dialog(_("Invalid folder"),
2942 _("The specified folder can not be found."),
2943 GTK_STOCK_DIALOG_WARNING, kfd->gd->dialog);
2949 gtk_widget_set_sensitive(kfd->group, FALSE);
2950 gtk_widget_set_sensitive(kfd->button_start, FALSE);
2951 gtk_widget_set_sensitive(kfd->button_stop, TRUE);
2952 gtk_widget_set_sensitive(kfd->button_close, FALSE);
2953 spinner_set_interval(kfd->spinner, SPINNER_SPEED);
2955 dir_fd = file_data_new_dir(path);
2956 keywords_find_folder(kfd, dir_fd);
2957 file_data_unref(dir_fd);
2958 kfd->idle_id = g_idle_add(keywords_find_file, kfd);
2964 static void keywords_find_dialog(GtkWidget *widget, const gchar *path)
2966 KeywordFindData *kfd;
2970 kfd = g_new0(KeywordFindData, 1);
2972 kfd->gd = generic_dialog_new(_("Search for keywords"),
2973 "search_for_keywords",
2976 gtk_window_set_default_size(GTK_WINDOW(kfd->gd->dialog), KEYWORD_DIALOG_WIDTH, -1);
2977 kfd->gd->cancel_cb = keywords_find_close_cb;
2978 kfd->button_close = generic_dialog_add_button(kfd->gd, GTK_STOCK_CLOSE, NULL,
2979 keywords_find_close_cb, FALSE);
2980 kfd->button_start = generic_dialog_add_button(kfd->gd, GTK_STOCK_OK, _("S_tart"),
2981 keywords_find_start_cb, FALSE);
2982 kfd->button_stop = generic_dialog_add_button(kfd->gd, GTK_STOCK_STOP, NULL,
2983 keywords_find_stop_cb, FALSE);
2984 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2986 generic_dialog_add_message(kfd->gd, NULL, _("Search for keywords"), NULL, FALSE);
2988 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0);
2989 pref_spacer(hbox, PREF_PAD_INDENT);
2990 kfd->group = pref_box_new(hbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2992 hbox = pref_box_new(kfd->group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2993 pref_label_new(hbox, _("Folder:"));
2995 label = tab_completion_new(&kfd->entry, path, NULL, NULL, NULL, NULL);
2996 tab_completion_add_select_button(kfd->entry,_("Select folder") , TRUE);
2997 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
2998 gtk_widget_show(label);
3000 pref_checkbox_new_int(kfd->group, _("Include subfolders"), FALSE, &kfd->recurse);
3002 pref_line(kfd->gd->vbox, PREF_PAD_SPACE);
3003 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3005 kfd->progress = gtk_entry_new();
3006 gtk_widget_set_can_focus(kfd->progress, FALSE);
3007 gtk_editable_set_editable(GTK_EDITABLE(kfd->progress), FALSE);
3008 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("click start to begin"));
3009 gtk_box_pack_start(GTK_BOX(hbox), kfd->progress, TRUE, TRUE, 0);
3010 gtk_widget_show(kfd->progress);
3012 kfd->spinner = spinner_new(NULL, -1);
3013 gtk_box_pack_start(GTK_BOX(hbox), kfd->spinner, FALSE, FALSE, 0);
3014 gtk_widget_show(kfd->spinner);
3018 gtk_widget_show(kfd->gd->dialog);
3021 static void keywords_find_cb(GtkWidget *widget, gpointer data)
3023 const gchar *path = layout_get_path(NULL);
3025 if (!path || !*path) path = homedir();
3026 keywords_find_dialog(widget, path);
3029 static void config_tab_keywords_save()
3031 GtkTextIter start, end;
3032 GtkTextBuffer *buffer;
3033 GList *kw_list = NULL;
3039 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3040 gtk_text_buffer_get_bounds(buffer, &start, &end);
3042 buffer_text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
3044 kw_split = strtok(buffer_text, "\n");
3045 while (kw_split != NULL)
3051 if (g_strcmp0(work->data, kw_split) == 0)
3060 kw_list = g_list_append(kw_list, g_strdup(kw_split));
3062 kw_split = strtok(NULL, "\n");
3065 keyword_list_set(kw_list);
3067 string_list_free(kw_list);
3068 g_free(buffer_text);
3071 static void config_tab_keywords(GtkWidget *notebook)
3077 GtkWidget *scrolled;
3079 GtkTextBuffer *buffer;
3082 vbox = scrolled_notebook_page(notebook, _("Keywords"));
3084 group = pref_group_new(vbox, TRUE, _("Edit keywords autocompletion list"), GTK_ORIENTATION_VERTICAL);
3086 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3088 button = pref_button_new(hbox, GTK_STOCK_EXECUTE, _("Search"), FALSE,
3089 G_CALLBACK(keywords_find_cb), keyword_text);
3090 gtk_widget_set_tooltip_text(button, "Search for existing keywords");
3093 keyword_text = gtk_text_view_new();
3094 gtk_widget_set_size_request(keyword_text, 20, 20);
3095 scrolled = gtk_scrolled_window_new(NULL, NULL);
3096 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3097 gtk_widget_show(scrolled);
3099 gtk_container_add(GTK_CONTAINER(scrolled), keyword_text);
3100 gtk_widget_show(keyword_text);
3102 gtk_text_view_set_editable(GTK_TEXT_VIEW(keyword_text), TRUE);
3104 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3105 gtk_text_buffer_create_tag(buffer, "monospace",
3106 "family", "monospace", NULL);
3108 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(keyword_text), GTK_WRAP_WORD);
3109 gtk_text_buffer_get_start_iter(buffer, &iter);
3110 gtk_text_buffer_create_mark(buffer, "end", &iter, FALSE);
3113 path = g_build_filename(get_rc_dir(), "keywords", NULL);
3115 GList *kwl = keyword_list_get();
3116 kwl = g_list_first(kwl);
3119 gtk_text_buffer_get_end_iter (buffer, &iter);
3120 tmp = g_strconcat(kwl->data, "\n", NULL);
3121 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
3126 gtk_text_buffer_set_modified(buffer, FALSE);
3133 static void intent_menu_cb(GtkWidget *combo, gpointer data)
3135 gint *option = data;
3137 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
3141 *option = INTENT_PERCEPTUAL;
3144 *option = INTENT_RELATIVE_COLORIMETRIC;
3147 *option = INTENT_SATURATION;
3150 *option = INTENT_ABSOLUTE_COLORIMETRIC;
3155 static void add_intent_menu(GtkWidget *table, gint column, gint row, const gchar *text,
3156 gint option, gint *option_c)
3163 pref_table_label(table, column, row, text, 0.0);
3165 combo = gtk_combo_box_text_new();
3167 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Perceptual"));
3168 if (option == INTENT_PERCEPTUAL) current = 0;
3169 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Relative Colorimetric"));
3170 if (option == INTENT_RELATIVE_COLORIMETRIC) current = 1;
3171 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Saturation"));
3172 if (option == INTENT_SATURATION) current = 2;
3173 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Absolute Colorimetric"));
3174 if (option == INTENT_ABSOLUTE_COLORIMETRIC) current = 3;
3176 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
3178 gtk_widget_set_tooltip_text(combo,"Refer to the lcms documentation for the defaults used when the selected Intent is not available");
3180 g_signal_connect(G_OBJECT(combo), "changed",
3181 G_CALLBACK(intent_menu_cb), option_c);
3183 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
3184 gtk_widget_show(combo);
3188 static void config_tab_color(GtkWidget *notebook)
3197 vbox = scrolled_notebook_page(notebook, _("Color management"));
3199 group = pref_group_new(vbox, FALSE, _("Input profiles"), GTK_ORIENTATION_VERTICAL);
3201 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3204 table = pref_table_new(group, 3, COLOR_PROFILE_INPUTS + 1, FALSE, FALSE);
3205 gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
3207 label = pref_table_label(table, 0, 0, _("Type"), 0.0);
3208 pref_label_bold(label, TRUE, FALSE);
3210 label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
3211 pref_label_bold(label, TRUE, FALSE);
3213 label = pref_table_label(table, 2, 0, _("File"), 0.0);
3214 pref_label_bold(label, TRUE, FALSE);
3216 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
3221 buf = g_strdup_printf(_("Input %d:"), i + COLOR_PROFILE_FILE);
3222 pref_table_label(table, 0, i + 1, buf, 1.0);
3225 entry = gtk_entry_new();
3226 gtk_entry_set_max_length(GTK_ENTRY(entry), EDITOR_NAME_MAX_LENGTH);
3227 if (options->color_profile.input_name[i])
3229 gtk_entry_set_text(GTK_ENTRY(entry), options->color_profile.input_name[i]);
3231 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, i + 1, i + 2,
3232 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3233 gtk_widget_show(entry);
3234 color_profile_input_name_entry[i] = entry;
3236 tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, ".icc", "ICC Files", NULL);
3237 tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
3238 gtk_widget_set_size_request(entry, 160, -1);
3239 gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
3240 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3241 gtk_widget_show(tabcomp);
3242 color_profile_input_file_entry[i] = entry;
3245 group = pref_group_new(vbox, FALSE, _("Screen profile"), GTK_ORIENTATION_VERTICAL);
3247 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3249 pref_checkbox_new_int(group, _("Use system screen profile if available"),
3250 options->color_profile.use_x11_screen_profile, &c_options->color_profile.use_x11_screen_profile);
3252 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3254 pref_table_label(table, 0, 0, _("Screen:"), 1.0);
3255 tabcomp = tab_completion_new(&color_profile_screen_file_entry,
3256 options->color_profile.screen_file, NULL, ".icc", "ICC Files", NULL);
3257 tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
3258 gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
3260 add_intent_menu(table, 0, 1, _("Render Intent:"), options->color_profile.render_intent, &c_options->color_profile.render_intent);
3262 gtk_table_attach(GTK_TABLE(table), tabcomp, 1, 2,
3264 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3266 gtk_widget_show(tabcomp);
3269 /* advanced entry tab */
3270 static void use_geeqie_trash_cb(GtkWidget *widget, gpointer data)
3272 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3274 c_options->file_ops.use_system_trash = FALSE;
3275 c_options->file_ops.no_trash = FALSE;
3279 static void use_system_trash_cb(GtkWidget *widget, gpointer data)
3281 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3283 c_options->file_ops.use_system_trash = TRUE;
3284 c_options->file_ops.no_trash = FALSE;
3288 static void use_no_cache_cb(GtkWidget *widget, gpointer data)
3290 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3292 c_options->file_ops.no_trash = TRUE;
3296 static void config_tab_behavior(GtkWidget *notebook)
3303 GtkWidget *ct_button;
3307 GtkWidget *with_rename;
3308 GtkWidget *collections_on_top;
3309 GtkWidget *hide_window_in_fullscreen;
3310 GtkWidget *checkbox;
3313 vbox = scrolled_notebook_page(notebook, _("Behavior"));
3315 group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
3317 pref_checkbox_new_int(group, _("Confirm permanent file delete"),
3318 options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
3319 pref_checkbox_new_int(group, _("Confirm move file to Trash"),
3320 options->file_ops.confirm_move_to_trash, &c_options->file_ops.confirm_move_to_trash);
3321 pref_checkbox_new_int(group, _("Enable Delete key"),
3322 options->file_ops.enable_delete_key, &c_options->file_ops.enable_delete_key);
3324 ct_button = pref_radiobutton_new(group, NULL, _("Use Geeqie trash location"),
3325 !options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_geeqie_trash_cb),NULL);
3327 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3328 pref_checkbox_link_sensitivity(ct_button, hbox);
3330 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
3331 pref_label_new(hbox, _("Folder:"));
3333 tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL, NULL, NULL);
3334 tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
3335 gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
3336 gtk_widget_show(tabcomp);
3338 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3339 pref_checkbox_link_sensitivity(ct_button, hbox);
3341 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
3342 spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MiB"),
3343 0, 2048, 1, options->file_ops.safe_delete_folder_maxsize, &c_options->file_ops.safe_delete_folder_maxsize);
3344 gtk_widget_set_tooltip_markup(spin, _("Set to 0 for unlimited size"));
3345 button = pref_button_new(NULL, NULL, _("View"), FALSE,
3346 G_CALLBACK(safe_delete_view_cb), NULL);
3347 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3348 gtk_widget_show(button);
3350 button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
3351 G_CALLBACK(safe_delete_clear_cb), NULL);
3352 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3353 pref_radiobutton_new(group, ct_button, _("Use system Trash bin"),
3354 options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_system_trash_cb), NULL);
3356 pref_radiobutton_new(group, ct_button, _("Use no trash at all"),
3357 options->file_ops.no_trash, G_CALLBACK(use_no_cache_cb), NULL);
3359 gtk_widget_show(button);
3361 pref_spacer(group, PREF_PAD_GROUP);
3364 group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
3366 pref_checkbox_new_int(group, _("Descend folders in tree view"),
3367 options->tree_descend_subdirs, &c_options->tree_descend_subdirs);
3369 pref_checkbox_new_int(group, _("In place renaming"),
3370 options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
3372 pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
3373 options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
3375 tmp = pref_checkbox_new_int(group, _("Circular selection lists"),
3376 options->circular_selection_lists, &c_options->circular_selection_lists);
3377 gtk_widget_set_tooltip_text(tmp, _("Traverse selection lists in a circular manner"));
3379 marks = pref_checkbox_new_int(group, _("Save marks on exit"),
3380 options->marks_save, &c_options->marks_save);
3381 gtk_widget_set_tooltip_text(marks,"Note that marks linked to a keyword will be saved irrespective of this setting");
3383 with_rename = pref_checkbox_new_int(group, _("Use \"With Rename\" as default for Copy/Move dialogs"),
3384 options->with_rename, &c_options->with_rename);
3385 gtk_widget_set_tooltip_text(with_rename,"Change the default button for Copy/Move dialogs");
3387 collections_on_top = pref_checkbox_new_int(group, _("Open collections on top"),
3388 options->collections_on_top, &c_options->collections_on_top);
3389 gtk_widget_set_tooltip_text(collections_on_top,"Open collections window on top");
3391 hide_window_in_fullscreen = pref_checkbox_new_int(group, _("Hide window in fullscreen"),
3392 options->hide_window_in_fullscreen, &c_options->hide_window_in_fullscreen);
3393 gtk_widget_set_tooltip_text(hide_window_in_fullscreen,"When alt-tabbing, prevent Geeqie window showing twice");
3395 pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
3396 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
3398 pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
3399 16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
3401 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3402 add_dnd_default_action_selection_menu(table, 0, 0, _("Drag`n drop default action:"), options->dnd_default_action, &c_options->dnd_default_action);
3404 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3405 add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
3407 pref_spacer(group, PREF_PAD_GROUP);
3409 group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
3411 pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
3412 options->progressive_key_scrolling, &c_options->progressive_key_scrolling);
3413 pref_spin_new_int(group, _("Keyboard scrolling step multiplier:"), NULL,
3414 1, 32, 1, options->keyboard_scroll_step, (int *)&c_options->keyboard_scroll_step);
3415 pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
3416 options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
3417 pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
3418 options->image_lm_click_nav, &c_options->image_lm_click_nav);
3419 pref_checkbox_new_int(group, _("Play video by left click on image"),
3420 options->image_l_click_video, &c_options->image_l_click_video);
3421 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3422 add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
3424 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3425 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3426 add_mouse_selection_menu(table, 0, 0, _("Mouse button Back:"), options->mouse_button_8, &c_options->mouse_button_8);
3427 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3428 add_mouse_selection_menu(table, 0, 0, _("Mouse button Forward:"), options->mouse_button_9, &c_options->mouse_button_9);
3430 pref_spacer(group, PREF_PAD_GROUP);
3432 group = pref_group_new(vbox, FALSE, _("GPU"), GTK_ORIENTATION_VERTICAL);
3434 checkbox = pref_checkbox_new_int(group, _("Override disable GPU"),
3435 options->override_disable_gpu, &c_options->override_disable_gpu);
3436 gtk_widget_set_tooltip_text(checkbox, "Contact the developers for usage");
3439 pref_spacer(group, PREF_PAD_GROUP);
3441 group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
3443 pref_spin_new_int(group, _("Debug level:"), NULL,
3444 DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
3446 pref_checkbox_new_int(group, _("Timer data"),
3447 options->log_window.timer_data, &c_options->log_window.timer_data);
3449 pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
3450 1, 99999, 1, options->log_window_lines, &options->log_window_lines);
3454 /* accelerators tab */
3455 static void config_tab_accelerators(GtkWidget *notebook)
3461 GtkWidget *scrolled;
3462 GtkWidget *accel_view;
3463 GtkCellRenderer *renderer;
3464 GtkTreeSelection *selection;
3465 GtkTreeViewColumn *column;
3467 vbox = scrolled_notebook_page(notebook, _("Keyboard"));
3469 group = pref_group_new(vbox, TRUE, _("Accelerators"), GTK_ORIENTATION_VERTICAL);
3471 scrolled = gtk_scrolled_window_new(NULL, NULL);
3472 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
3473 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
3474 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3475 gtk_widget_show(scrolled);
3477 accel_store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
3479 accel_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(accel_store));
3480 g_object_unref(accel_store);
3481 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(accel_view));
3482 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
3484 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(accel_view), FALSE);
3486 renderer = gtk_cell_renderer_text_new();
3488 column = gtk_tree_view_column_new_with_attributes(_("Action"),
3493 gtk_tree_view_column_set_sort_column_id(column, AE_ACTION);
3494 gtk_tree_view_column_set_resizable(column, TRUE);
3495 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3498 renderer = gtk_cell_renderer_accel_new();
3499 g_signal_connect(G_OBJECT(renderer), "accel-cleared",
3500 G_CALLBACK(accel_store_cleared_cb), accel_store);
3501 g_signal_connect(G_OBJECT(renderer), "accel-edited",
3502 G_CALLBACK(accel_store_edited_cb), accel_store);
3505 g_object_set (renderer,
3507 "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
3510 column = gtk_tree_view_column_new_with_attributes(_("KEY"),
3515 gtk_tree_view_column_set_sort_column_id(column, AE_KEY);
3516 gtk_tree_view_column_set_resizable(column, TRUE);
3517 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3519 renderer = gtk_cell_renderer_text_new();
3521 column = gtk_tree_view_column_new_with_attributes(_("Tooltip"),
3526 gtk_tree_view_column_set_sort_column_id(column, AE_TOOLTIP);
3527 gtk_tree_view_column_set_resizable(column, TRUE);
3528 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3530 renderer = gtk_cell_renderer_text_new();
3532 column = gtk_tree_view_column_new_with_attributes("Accel",
3537 gtk_tree_view_column_set_sort_column_id(column, AE_ACCEL);
3538 gtk_tree_view_column_set_resizable(column, TRUE);
3539 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3541 accel_store_populate();
3542 gtk_container_add(GTK_CONTAINER(scrolled), accel_view);
3543 gtk_widget_show(accel_view);
3545 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3547 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
3548 G_CALLBACK(accel_default_cb), accel_view);
3549 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3550 gtk_widget_show(button);
3552 button = pref_button_new(NULL, NULL, _("Reset selected"), FALSE,
3553 G_CALLBACK(accel_reset_cb), accel_view);
3554 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3555 gtk_widget_show(button);
3558 /* toolbar main tab */
3559 static void config_tab_toolbar_main(GtkWidget *notebook)
3562 GtkWidget *toolbardata;
3565 lw = layout_window_list->data;
3567 vbox = scrolled_notebook_page(notebook, _("Toolbar Main"));
3569 toolbardata = toolbar_select_new(lw, TOOLBAR_MAIN);
3570 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3571 gtk_widget_show(vbox);
3574 /* toolbar status tab */
3575 static void config_tab_toolbar_status(GtkWidget *notebook)
3578 GtkWidget *toolbardata;
3581 lw = layout_window_list->data;
3583 vbox = scrolled_notebook_page(notebook, _("Toolbar Status"));
3585 toolbardata = toolbar_select_new(lw, TOOLBAR_STATUS);
3586 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3587 gtk_widget_show(vbox);
3591 static void config_tab_stereo(GtkWidget *notebook)
3599 GtkWidget *fs_button;
3600 vbox = scrolled_notebook_page(notebook, _("Stereo"));
3602 group = pref_group_new(vbox, FALSE, _("Windowed stereo mode"), GTK_ORIENTATION_VERTICAL);
3604 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3605 add_stereo_mode_menu(table, 0, 0, _("Windowed stereo mode"), options->stereo.mode, &c_options->stereo.mode, FALSE);
3607 table = pref_table_new(group, 2, 2, TRUE, FALSE);
3608 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3609 pref_checkbox_new_int(box, _("Mirror left image"),
3610 options->stereo.mode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.mirror_left);
3611 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3612 pref_checkbox_new_int(box, _("Flip left image"),
3613 options->stereo.mode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.flip_left);
3614 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3615 pref_checkbox_new_int(box, _("Mirror right image"),
3616 options->stereo.mode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.mirror_right);
3617 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3618 pref_checkbox_new_int(box, _("Flip right image"),
3619 options->stereo.mode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.flip_right);
3620 pref_checkbox_new_int(group, _("Swap left and right images"),
3621 options->stereo.mode & PR_STEREO_SWAP, &c_options->stereo.tmp.swap);
3622 pref_checkbox_new_int(group, _("Disable stereo mode on single image source"),
3623 options->stereo.mode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.temp_disable);
3625 group = pref_group_new(vbox, FALSE, _("Fullscreen stereo mode"), GTK_ORIENTATION_VERTICAL);
3626 fs_button = pref_checkbox_new_int(group, _("Use different settings for fullscreen"),
3627 options->stereo.enable_fsmode, &c_options->stereo.enable_fsmode);
3628 box2 = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
3629 pref_checkbox_link_sensitivity(fs_button, box2);
3630 table = pref_table_new(box2, 2, 1, FALSE, FALSE);
3631 add_stereo_mode_menu(table, 0, 0, _("Fullscreen stereo mode"), options->stereo.fsmode, &c_options->stereo.fsmode, TRUE);
3632 table = pref_table_new(box2, 2, 2, TRUE, FALSE);
3633 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3634 pref_checkbox_new_int(box, _("Mirror left image"),
3635 options->stereo.fsmode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.fs_mirror_left);
3636 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3637 pref_checkbox_new_int(box, _("Flip left image"),
3638 options->stereo.fsmode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.fs_flip_left);
3639 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3640 pref_checkbox_new_int(box, _("Mirror right image"),
3641 options->stereo.fsmode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.fs_mirror_right);
3642 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3643 pref_checkbox_new_int(box, _("Flip right image"),
3644 options->stereo.fsmode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.fs_flip_right);
3645 pref_checkbox_new_int(box2, _("Swap left and right images"),
3646 options->stereo.fsmode & PR_STEREO_SWAP, &c_options->stereo.tmp.fs_swap);
3647 pref_checkbox_new_int(box2, _("Disable stereo mode on single image source"),
3648 options->stereo.fsmode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.fs_temp_disable);
3650 group2 = pref_group_new(box2, FALSE, _("Fixed position"), GTK_ORIENTATION_VERTICAL);
3651 table = pref_table_new(group2, 5, 3, FALSE, FALSE);
3652 pref_table_spin_new_int(table, 0, 0, _("Width"), NULL,
3653 1, 5000, 1, options->stereo.fixed_w, &c_options->stereo.fixed_w);
3654 pref_table_spin_new_int(table, 3, 0, _("Height"), NULL,
3655 1, 5000, 1, options->stereo.fixed_h, &c_options->stereo.fixed_h);
3656 pref_table_spin_new_int(table, 0, 1, _("Left X"), NULL,
3657 0, 5000, 1, options->stereo.fixed_x1, &c_options->stereo.fixed_x1);
3658 pref_table_spin_new_int(table, 3, 1, _("Left Y"), NULL,
3659 0, 5000, 1, options->stereo.fixed_y1, &c_options->stereo.fixed_y1);
3660 pref_table_spin_new_int(table, 0, 2, _("Right X"), NULL,
3661 0, 5000, 1, options->stereo.fixed_x2, &c_options->stereo.fixed_x2);
3662 pref_table_spin_new_int(table, 3, 2, _("Right Y"), NULL,
3663 0, 5000, 1, options->stereo.fixed_y2, &c_options->stereo.fixed_y2);
3667 /* Main preferences window */
3668 static void config_window_create(LayoutWindow *lw)
3670 GtkWidget *win_vbox;
3672 GtkWidget *notebook;
3674 GtkWidget *ct_button;
3676 if (!c_options) c_options = init_options(NULL);
3678 configwindow = window_new(GTK_WINDOW_TOPLEVEL, "preferences", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Preferences"));
3679 DEBUG_NAME(configwindow);
3680 gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
3681 g_signal_connect(G_OBJECT(configwindow), "delete_event",
3682 G_CALLBACK(config_window_delete), NULL);
3683 if (options->save_dialog_window_positions)
3685 gtk_window_resize(GTK_WINDOW(configwindow), lw->options.preferences_window.w, lw->options.preferences_window.h);
3686 gtk_window_move(GTK_WINDOW(configwindow), lw->options.preferences_window.x, lw->options.preferences_window.y);
3690 gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
3692 gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
3693 gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
3695 win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
3696 gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
3697 gtk_widget_show(win_vbox);
3699 notebook = gtk_notebook_new();
3700 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_LEFT);
3701 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE);
3702 gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
3704 config_tab_general(notebook);
3705 config_tab_image(notebook);
3706 config_tab_osd(notebook);
3707 config_tab_windows(notebook);
3708 config_tab_accelerators(notebook);
3709 config_tab_files(notebook);
3710 config_tab_metadata(notebook);
3711 config_tab_keywords(notebook);
3712 config_tab_color(notebook);
3713 config_tab_stereo(notebook);
3714 config_tab_behavior(notebook);
3715 config_tab_toolbar_main(notebook);
3716 config_tab_toolbar_status(notebook);
3718 gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), lw->options.preferences_window.page_number);
3720 hbox = gtk_hbutton_box_new();
3721 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
3722 gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
3723 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
3724 gtk_widget_show(hbox);
3726 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
3727 G_CALLBACK(config_window_help_cb), notebook);
3728 gtk_container_add(GTK_CONTAINER(hbox), button);
3729 gtk_widget_set_can_default(button, TRUE);
3730 gtk_widget_show(button);
3732 button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
3733 G_CALLBACK(config_window_ok_cb), notebook);
3734 gtk_container_add(GTK_CONTAINER(hbox), button);
3735 gtk_widget_set_can_default(button, TRUE);
3736 gtk_widget_grab_default(button);
3737 gtk_widget_show(button);
3741 button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
3742 G_CALLBACK(config_window_close_cb), NULL);
3743 gtk_container_add(GTK_CONTAINER(hbox), button);
3744 gtk_widget_set_can_default(button, TRUE);
3745 gtk_widget_show(button);
3747 if (!generic_dialog_get_alternative_button_order(configwindow))
3749 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
3752 gtk_widget_show(notebook);
3754 gtk_widget_show(configwindow);
3758 *-----------------------------------------------------------------------------
3759 * config window show (public)
3760 *-----------------------------------------------------------------------------
3763 void show_config_window(LayoutWindow *lw)
3767 gtk_window_present(GTK_WINDOW(configwindow));
3771 config_window_create(lw);
3780 void show_about_window(LayoutWindow *lw)
3782 GdkPixbuf *pixbuf_logo;
3783 GdkPixbuf *pixbuf_icon;
3784 gchar *authors[1000];
3789 gchar *timezone_path;
3793 #define LINE_LENGTH 1000
3794 gchar line[LINE_LENGTH];
3796 copyright = g_string_new(NULL);
3797 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");
3799 path = path_from_utf8(TIMEZONE_DATABASE);
3800 basename = g_path_get_basename(path);
3801 timezone_path = g_build_filename(get_rc_dir(), basename, NULL);
3802 if (g_file_test(timezone_path, G_FILE_TEST_EXISTS))
3804 cd = ZDOpenDatabase(timezone_path);
3807 copyright = g_string_append(copyright, ZDGetNotice(cd));
3808 ZDCloseDatabase(cd);
3812 g_free(timezone_path);
3816 path = g_build_filename(GQ_HELPDIR, "AUTHORS", NULL);
3817 fp = fopen(path, "r");
3820 while(fgets(line, LINE_LENGTH, fp))
3822 /* get rid of ending \n from fgets */
3823 line[strlen(line) - 1] = '\0';
3824 authors[i_authors] = g_strdup(line);
3827 authors[i_authors] = NULL;
3832 comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
3833 "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
3835 pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
3836 pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
3837 gtk_show_about_dialog(GTK_WINDOW(lw->window),
3838 "title", _("About Geeqie"),
3840 "program-name", GQ_APPNAME,
3842 "logo", pixbuf_logo,
3843 "icon", pixbuf_icon,
3844 "website", GQ_WEBSITE,
3845 "website-label", "Website",
3846 "comments", comment,
3848 "translator-credits", _("translator-credits"),
3849 "wrap-license", TRUE,
3850 "license", copyright->str,
3853 g_string_free(copyright, TRUE);
3856 while(n < i_authors)
3866 static void image_overlay_set_text_colours()
3868 c_options->image_overlay.text_red = options->image_overlay.text_red;
3869 c_options->image_overlay.text_green = options->image_overlay.text_green;
3870 c_options->image_overlay.text_blue = options->image_overlay.text_blue;
3871 c_options->image_overlay.text_alpha = options->image_overlay.text_alpha;
3872 c_options->image_overlay.background_red = options->image_overlay.background_red;
3873 c_options->image_overlay.background_green = options->image_overlay.background_green;
3874 c_options->image_overlay.background_blue = options->image_overlay.background_blue;
3875 c_options->image_overlay.background_alpha = options->image_overlay.background_alpha;
3879 *-----------------------------------------------------------------------------
3880 * timezone database routines
3881 *-----------------------------------------------------------------------------
3884 static void timezone_async_ready_cb(GObject *source_object, GAsyncResult *res, gpointer data)
3886 GError *error = NULL;
3888 gchar *tmp_filename;
3890 if (!g_cancellable_is_cancelled(tz->cancellable))
3892 generic_dialog_close(tz->gd);
3896 if (g_file_copy_finish(G_FILE(source_object), res, &error))
3898 tmp_filename = g_file_get_parse_name(tz->tmp_g_file);
3899 move_file(tmp_filename, tz->timezone_database_user);
3900 g_free(tmp_filename);
3904 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
3907 g_file_delete(tz->tmp_g_file, NULL, &error);
3908 g_object_unref(tz->tmp_g_file);
3909 tz->tmp_g_file = NULL;
3910 g_object_unref(tz->cancellable);
3911 g_object_unref(tz->timezone_database_gq);
3914 static void timezone_progress_cb(goffset current_num_bytes, goffset total_num_bytes, gpointer data)
3918 if (!g_cancellable_is_cancelled(tz->cancellable))
3920 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(tz->progress), (gdouble)current_num_bytes / total_num_bytes);
3924 static void timezone_cancel_button_cb(GenericDialog *gd, gpointer data)
3928 g_cancellable_cancel(tz->cancellable);
3931 static void timezone_database_install_cb(GtkWidget *widget, gpointer data)
3934 GError *error = NULL;
3935 GFileIOStream *io_stream;
3942 tz->tmp_g_file = g_file_new_tmp("geeqie_timezone_XXXXXX", &io_stream, &error);
3946 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
3947 log_printf("Error: Download timezone database failed:\n%s", error->message);
3948 g_error_free(error);
3949 g_object_unref(tz->tmp_g_file);
3953 tz->timezone_database_gq = g_file_new_for_uri(TIMEZONE_DATABASE);
3955 tz->gd = generic_dialog_new(_("Timezone database"), "download_timezone_database", NULL, TRUE, timezone_cancel_button_cb, tz);
3957 generic_dialog_add_message(tz->gd, GTK_STOCK_DIALOG_INFO, _("Downloading timezone database"), NULL, FALSE);
3959 tz->progress = gtk_progress_bar_new();
3960 gtk_box_pack_start(GTK_BOX(tz->gd->vbox), tz->progress, FALSE, FALSE, 0);
3961 gtk_widget_show(tz->progress);
3963 gtk_widget_show(tz->gd->dialog);
3964 tz->cancellable = g_cancellable_new();
3965 g_file_copy_async(tz->timezone_database_gq, tz->tmp_g_file, G_FILE_COPY_OVERWRITE, G_PRIORITY_LOW, tz->cancellable, timezone_progress_cb, tz, timezone_async_ready_cb, tz);
3967 gtk_button_set_label(GTK_BUTTON(widget), _("Update"));
3970 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */