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"
44 #include "pixbuf_util.h"
46 #include "slideshow.h"
50 #include "ui_fileops.h"
52 #include "ui_spinner.h"
53 #include "ui_tabcomp.h"
54 #include "ui_utildlg.h"
56 #include "zonedetect.h"
67 #include <gspell/gspell.h>
70 #define EDITOR_NAME_MAX_LENGTH 32
71 #define EDITOR_COMMAND_MAX_LENGTH 1024
73 static void image_overlay_set_text_colours();
75 GtkWidget *keyword_text;
76 static void config_tab_keywords_save();
78 typedef struct _ThumbSize ThumbSize;
85 static ThumbSize thumb_size_list[] =
120 FILETYPES_COLUMN_FILTER = 0,
121 FILETYPES_COLUMN_DESCRIPTION,
122 FILETYPES_COLUMN_CLASS,
123 FILETYPES_COLUMN_WRITABLE,
124 FILETYPES_COLUMN_SIDECAR,
125 FILETYPES_COLUMN_COUNT
128 gchar *format_class_list[] = {
139 /* config memory values */
140 static ConfOptions *c_options = NULL;
147 static GtkWidget *configwindow = NULL;
148 static GtkListStore *filter_store = NULL;
149 static GtkTreeStore *accel_store = NULL;
151 static GtkWidget *safe_delete_path_entry;
153 static GtkWidget *color_profile_input_file_entry[COLOR_PROFILE_INPUTS];
154 static GtkWidget *color_profile_input_name_entry[COLOR_PROFILE_INPUTS];
155 static GtkWidget *color_profile_screen_file_entry;
156 static GtkWidget *external_preview_select_entry;
157 static GtkWidget *external_preview_extract_entry;
159 static GtkWidget *sidecar_ext_entry;
160 static GtkWidget *help_search_engine_entry;
163 #define CONFIG_WINDOW_DEF_WIDTH 700
164 #define CONFIG_WINDOW_DEF_HEIGHT 600
167 *-----------------------------------------------------------------------------
168 * option widget callbacks (private)
169 *-----------------------------------------------------------------------------
172 static void zoom_increment_cb(GtkWidget *spin, gpointer data)
174 c_options->image.zoom_increment = (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) * 100.0 + 0.01);
177 static void slideshow_delay_hours_cb(GtkWidget *spin, gpointer data)
179 gint mins_secs_tenths, delay;
181 mins_secs_tenths = c_options->slideshow.delay %
182 (3600 * SLIDESHOW_SUBSECOND_PRECISION);
184 delay = (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
185 (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
188 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
189 SLIDESHOW_SUBSECOND_PRECISION;
192 static void slideshow_delay_minutes_cb(GtkWidget *spin, gpointer data)
194 gint hours, secs_tenths, delay;
196 hours = c_options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
197 secs_tenths = c_options->slideshow.delay % (60 * SLIDESHOW_SUBSECOND_PRECISION);
199 delay = hours * (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
200 (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
201 (60 * SLIDESHOW_SUBSECOND_PRECISION) + secs_tenths);
203 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
204 SLIDESHOW_SUBSECOND_PRECISION;
207 static void slideshow_delay_seconds_cb(GtkWidget *spin, gpointer data)
209 gint hours_mins, delay;
211 hours_mins = c_options->slideshow.delay / (60 * SLIDESHOW_SUBSECOND_PRECISION);
213 delay = (hours_mins * (60 * SLIDESHOW_SUBSECOND_PRECISION)) +
214 (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
215 (gdouble)(SLIDESHOW_SUBSECOND_PRECISION) + 0.01);
217 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
218 SLIDESHOW_SUBSECOND_PRECISION;
222 *-----------------------------------------------------------------------------
223 * sync program to config window routine (private)
224 *-----------------------------------------------------------------------------
227 void config_entry_to_option(GtkWidget *entry, gchar **option, gchar *(*func)(const gchar *))
233 buf = gtk_entry_get_text(GTK_ENTRY(entry));
234 if (buf && strlen(buf) > 0)
239 *option = g_strdup(buf);
244 static gboolean accel_apply_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
246 gchar *accel_path, *accel;
248 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, AE_KEY, &accel, -1);
250 if (accel_path && accel_path[0])
253 gtk_accelerator_parse(accel, &key.accel_key, &key.accel_mods);
254 gtk_accel_map_change_entry(accel_path, key.accel_key, key.accel_mods, TRUE);
264 static void config_window_apply(void)
266 gboolean refresh = FALSE;
271 config_entry_to_option(safe_delete_path_entry, &options->file_ops.safe_delete_path, remove_trailing_slash);
273 if (options->file_filter.show_hidden_files != c_options->file_filter.show_hidden_files) refresh = TRUE;
274 if (options->file_filter.show_parent_directory != c_options->file_filter.show_parent_directory) refresh = TRUE;
275 if (options->file_filter.show_dot_directory != c_options->file_filter.show_dot_directory) refresh = TRUE;
276 if (options->file_sort.case_sensitive != c_options->file_sort.case_sensitive) refresh = TRUE;
277 if (options->file_sort.natural != c_options->file_sort.natural) refresh = TRUE;
278 if (options->file_filter.disable_file_extension_checks != c_options->file_filter.disable_file_extension_checks) refresh = TRUE;
279 if (options->file_filter.disable != c_options->file_filter.disable) refresh = TRUE;
281 options->file_ops.confirm_delete = c_options->file_ops.confirm_delete;
282 options->file_ops.enable_delete_key = c_options->file_ops.enable_delete_key;
283 options->file_ops.confirm_move_to_trash = c_options->file_ops.confirm_move_to_trash;
284 options->file_ops.use_system_trash = c_options->file_ops.use_system_trash;
285 options->file_ops.no_trash = c_options->file_ops.no_trash;
286 options->file_ops.safe_delete_folder_maxsize = c_options->file_ops.safe_delete_folder_maxsize;
287 options->tools_restore_state = c_options->tools_restore_state;
288 options->save_window_positions = c_options->save_window_positions;
289 options->use_saved_window_positions_for_new_windows = c_options->use_saved_window_positions_for_new_windows;
290 options->save_window_workspace = c_options->save_window_workspace;
291 options->save_dialog_window_positions = c_options->save_dialog_window_positions;
292 options->show_window_ids = c_options->show_window_ids;
293 options->image.scroll_reset_method = c_options->image.scroll_reset_method;
294 options->image.zoom_2pass = c_options->image.zoom_2pass;
295 options->image.fit_window_to_image = c_options->image.fit_window_to_image;
296 options->image.limit_window_size = c_options->image.limit_window_size;
297 options->image.zoom_to_fit_allow_expand = c_options->image.zoom_to_fit_allow_expand;
298 options->image.max_window_size = c_options->image.max_window_size;
299 options->image.limit_autofit_size = c_options->image.limit_autofit_size;
300 options->image.max_autofit_size = c_options->image.max_autofit_size;
301 options->image.max_enlargement_size = c_options->image.max_enlargement_size;
302 options->image.use_clutter_renderer = c_options->image.use_clutter_renderer;
303 options->image.tile_size = c_options->image.tile_size;
304 options->progressive_key_scrolling = c_options->progressive_key_scrolling;
305 options->keyboard_scroll_step = c_options->keyboard_scroll_step;
307 if (options->thumbnails.max_width != c_options->thumbnails.max_width
308 || options->thumbnails.max_height != c_options->thumbnails.max_height
309 || options->thumbnails.quality != c_options->thumbnails.quality)
311 thumb_format_changed = TRUE;
313 options->thumbnails.max_width = c_options->thumbnails.max_width;
314 options->thumbnails.max_height = c_options->thumbnails.max_height;
315 options->thumbnails.quality = c_options->thumbnails.quality;
317 options->thumbnails.enable_caching = c_options->thumbnails.enable_caching;
318 options->thumbnails.cache_into_dirs = c_options->thumbnails.cache_into_dirs;
319 options->thumbnails.use_exif = c_options->thumbnails.use_exif;
320 options->thumbnails.use_color_management = c_options->thumbnails.use_color_management;
321 options->thumbnails.collection_preview = c_options->thumbnails.collection_preview;
322 options->thumbnails.use_ft_metadata = c_options->thumbnails.use_ft_metadata;
323 // options->thumbnails.use_ft_metadata_small = c_options->thumbnails.use_ft_metadata_small;
324 options->thumbnails.spec_standard = c_options->thumbnails.spec_standard;
325 options->metadata.enable_metadata_dirs = c_options->metadata.enable_metadata_dirs;
326 options->file_filter.show_hidden_files = c_options->file_filter.show_hidden_files;
327 options->file_filter.show_parent_directory = c_options->file_filter.show_parent_directory;
328 options->file_filter.show_dot_directory = c_options->file_filter.show_dot_directory;
329 options->file_filter.disable_file_extension_checks = c_options->file_filter.disable_file_extension_checks;
331 options->file_sort.case_sensitive = c_options->file_sort.case_sensitive;
332 options->file_sort.natural = c_options->file_sort.natural;
333 options->file_filter.disable = c_options->file_filter.disable;
335 config_entry_to_option(sidecar_ext_entry, &options->sidecar.ext, NULL);
336 sidecar_ext_parse(options->sidecar.ext);
338 options->slideshow.random = c_options->slideshow.random;
339 options->slideshow.repeat = c_options->slideshow.repeat;
340 options->slideshow.delay = c_options->slideshow.delay;
342 options->mousewheel_scrolls = c_options->mousewheel_scrolls;
343 options->image_lm_click_nav = c_options->image_lm_click_nav;
344 options->image_l_click_archive = c_options->image_l_click_archive;
345 options->image_l_click_video = c_options->image_l_click_video;
346 options->image_l_click_video_editor = c_options->image_l_click_video_editor;
348 options->file_ops.enable_in_place_rename = c_options->file_ops.enable_in_place_rename;
350 options->image.tile_cache_max = c_options->image.tile_cache_max;
351 options->image.image_cache_max = c_options->image.image_cache_max;
353 options->image.zoom_quality = c_options->image.zoom_quality;
355 options->image.zoom_increment = c_options->image.zoom_increment;
357 options->image.zoom_style = c_options->image.zoom_style;
359 options->image.enable_read_ahead = c_options->image.enable_read_ahead;
362 if (options->image.use_custom_border_color != c_options->image.use_custom_border_color
363 || options->image.use_custom_border_color_in_fullscreen != c_options->image.use_custom_border_color_in_fullscreen
364 || !gdk_color_equal(&options->image.border_color, &c_options->image.border_color))
366 options->image.use_custom_border_color_in_fullscreen = c_options->image.use_custom_border_color_in_fullscreen;
367 options->image.use_custom_border_color = c_options->image.use_custom_border_color;
368 options->image.border_color = c_options->image.border_color;
369 layout_colors_update();
370 view_window_colors_update();
373 options->image.alpha_color_1 = c_options->image.alpha_color_1;
374 options->image.alpha_color_2 = c_options->image.alpha_color_2;
376 options->fullscreen.screen = c_options->fullscreen.screen;
377 options->fullscreen.clean_flip = c_options->fullscreen.clean_flip;
378 options->fullscreen.disable_saver = c_options->fullscreen.disable_saver;
379 options->fullscreen.above = c_options->fullscreen.above;
380 if (c_options->image_overlay.template_string)
381 set_image_overlay_template_string(&options->image_overlay.template_string,
382 c_options->image_overlay.template_string);
383 if (c_options->image_overlay.font)
384 set_image_overlay_font_string(&options->image_overlay.font,
385 c_options->image_overlay.font);
386 options->image_overlay.text_red = c_options->image_overlay.text_red;
387 options->image_overlay.text_green = c_options->image_overlay.text_green;
388 options->image_overlay.text_blue = c_options->image_overlay.text_blue;
389 options->image_overlay.text_alpha = c_options->image_overlay.text_alpha;
390 options->image_overlay.background_red = c_options->image_overlay.background_red;
391 options->image_overlay.background_green = c_options->image_overlay.background_green;
392 options->image_overlay.background_blue = c_options->image_overlay.background_blue;
393 options->image_overlay.background_alpha = c_options->image_overlay.background_alpha;
394 options->update_on_time_change = c_options->update_on_time_change;
396 options->duplicates_similarity_threshold = c_options->duplicates_similarity_threshold;
397 options->rot_invariant_sim = c_options->rot_invariant_sim;
399 options->tree_descend_subdirs = c_options->tree_descend_subdirs;
401 options->view_dir_list_single_click_enter = c_options->view_dir_list_single_click_enter;
402 options->circular_selection_lists = c_options->circular_selection_lists;
404 options->open_recent_list_maxsize = c_options->open_recent_list_maxsize;
405 options->recent_folder_image_list_maxsize = c_options->recent_folder_image_list_maxsize;
406 options->dnd_icon_size = c_options->dnd_icon_size;
407 options->clipboard_selection = c_options->clipboard_selection;
408 options->dnd_default_action = c_options->dnd_default_action;
410 options->metadata.save_in_image_file = c_options->metadata.save_in_image_file;
411 options->metadata.save_legacy_IPTC = c_options->metadata.save_legacy_IPTC;
412 options->metadata.warn_on_write_problems = c_options->metadata.warn_on_write_problems;
413 options->metadata.save_legacy_format = c_options->metadata.save_legacy_format;
414 options->metadata.sync_grouped_files = c_options->metadata.sync_grouped_files;
415 options->metadata.confirm_write = c_options->metadata.confirm_write;
416 options->metadata.sidecar_extended_name = c_options->metadata.sidecar_extended_name;
417 options->metadata.confirm_timeout = c_options->metadata.confirm_timeout;
418 options->metadata.confirm_after_timeout = c_options->metadata.confirm_after_timeout;
419 options->metadata.confirm_on_image_change = c_options->metadata.confirm_on_image_change;
420 options->metadata.confirm_on_dir_change = c_options->metadata.confirm_on_dir_change;
421 options->metadata.keywords_case_sensitive = c_options->metadata.keywords_case_sensitive;
422 options->metadata.write_orientation = c_options->metadata.write_orientation;
423 options->metadata.check_spelling = c_options->metadata.check_spelling;
424 options->stereo.mode = (c_options->stereo.mode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
425 (c_options->stereo.tmp.mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
426 (c_options->stereo.tmp.flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
427 (c_options->stereo.tmp.mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
428 (c_options->stereo.tmp.flip_left ? PR_STEREO_FLIP_LEFT : 0) |
429 (c_options->stereo.tmp.swap ? PR_STEREO_SWAP : 0) |
430 (c_options->stereo.tmp.temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
431 options->stereo.fsmode = (c_options->stereo.fsmode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
432 (c_options->stereo.tmp.fs_mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
433 (c_options->stereo.tmp.fs_flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
434 (c_options->stereo.tmp.fs_mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
435 (c_options->stereo.tmp.fs_flip_left ? PR_STEREO_FLIP_LEFT : 0) |
436 (c_options->stereo.tmp.fs_swap ? PR_STEREO_SWAP : 0) |
437 (c_options->stereo.tmp.fs_temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
438 options->stereo.enable_fsmode = c_options->stereo.enable_fsmode;
439 options->stereo.fixed_w = c_options->stereo.fixed_w;
440 options->stereo.fixed_h = c_options->stereo.fixed_h;
441 options->stereo.fixed_x1 = c_options->stereo.fixed_x1;
442 options->stereo.fixed_y1 = c_options->stereo.fixed_y1;
443 options->stereo.fixed_x2 = c_options->stereo.fixed_x2;
444 options->stereo.fixed_y2 = c_options->stereo.fixed_y2;
446 options->info_keywords.height = c_options->info_keywords.height;
447 options->info_title.height = c_options->info_title.height;
448 options->info_comment.height = c_options->info_comment.height;
449 options->info_rating.height = c_options->info_rating.height;
451 options->show_predefined_keyword_tree = c_options->show_predefined_keyword_tree;
452 options->expand_menu_toolbar = c_options->expand_menu_toolbar;
454 options->marks_save = c_options->marks_save;
455 options->with_rename = c_options->with_rename;
456 options->collections_on_top = c_options->collections_on_top;
457 options->hide_window_in_fullscreen = c_options->hide_window_in_fullscreen;
458 config_entry_to_option(help_search_engine_entry, &options->help_search_engine, NULL);
460 options->external_preview.enable = c_options->external_preview.enable;
461 config_entry_to_option(external_preview_select_entry, &options->external_preview.select, NULL);
462 config_entry_to_option(external_preview_extract_entry, &options->external_preview.extract, NULL);
464 options->read_metadata_in_idle = c_options->read_metadata_in_idle;
466 options->star_rating.star = c_options->star_rating.star;
467 options->star_rating.rejected = c_options->star_rating.rejected;
469 options->threads.duplicates = c_options->threads.duplicates > 0 ? c_options->threads.duplicates : -1;
472 set_debug_level(debug_c);
476 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
478 config_entry_to_option(color_profile_input_name_entry[i], &options->color_profile.input_name[i], NULL);
479 config_entry_to_option(color_profile_input_file_entry[i], &options->color_profile.input_file[i], NULL);
481 config_entry_to_option(color_profile_screen_file_entry, &options->color_profile.screen_file, NULL);
482 options->color_profile.use_x11_screen_profile = c_options->color_profile.use_x11_screen_profile;
483 if (options->color_profile.render_intent != c_options->color_profile.render_intent)
485 options->color_profile.render_intent = c_options->color_profile.render_intent;
490 options->mouse_button_8 = c_options->mouse_button_8;
491 options->mouse_button_9 = c_options->mouse_button_9;
493 options->override_disable_gpu = c_options->override_disable_gpu;
495 config_tab_keywords_save();
497 image_options_sync();
502 layout_refresh(NULL);
505 if (accel_store) gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_apply_cb, NULL);
507 toolbar_apply(TOOLBAR_MAIN);
508 toolbar_apply(TOOLBAR_STATUS);
512 *-----------------------------------------------------------------------------
513 * config window main button callbacks (private)
514 *-----------------------------------------------------------------------------
517 static void config_window_close_cb(GtkWidget *widget, gpointer data)
519 gtk_widget_destroy(configwindow);
524 static void config_window_help_cb(GtkWidget *widget, gpointer data)
526 GtkWidget *notebook = data;
529 static gchar *html_section[] =
531 "GuideOptionsGeneral.html",
532 "GuideOptionsImage.html",
533 "GuideOptionsOSD.html",
534 "GuideOptionsWindow.html",
535 "GuideOptionsKeyboard.html",
536 "GuideOptionsFiltering.html",
537 "GuideOptionsMetadata.html",
538 "GuideOptionsKeywords.html",
539 "GuideOptionsColor.html",
540 "GuideOptionsStereo.html",
541 "GuideOptionsBehavior.html",
542 "GuideOptionsToolbar.html",
543 "GuideOptionsToolbar.html",
544 "GuideOptionsAdvanced.html"
547 i = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
548 help_window_show(html_section[i]);
551 static gboolean config_window_delete(GtkWidget *widget, GdkEventAny *event, gpointer data)
553 config_window_close_cb(NULL, NULL);
557 static void config_window_ok_cb(GtkWidget *widget, gpointer data)
560 GtkNotebook *notebook = data;
568 lw = layout_window_list->data;
570 window = gtk_widget_get_window(widget);
571 gdk_window_get_root_origin(window, &x, &y);
572 w = gdk_window_get_width(window);
573 h = gdk_window_get_height(window);
574 page_number = gtk_notebook_get_current_page(notebook);
576 lw->options.preferences_window.x = x;
577 lw->options.preferences_window.y = y;
578 lw->options.preferences_window.w = w;
579 lw->options.preferences_window.h = h;
580 lw->options.preferences_window.page_number = page_number;
582 config_window_apply();
583 layout_util_sync(lw);
584 save_options(options);
585 config_window_close_cb(NULL, NULL);
589 *-----------------------------------------------------------------------------
590 * config window setup (private)
591 *-----------------------------------------------------------------------------
594 static void quality_menu_cb(GtkWidget *combo, gpointer data)
598 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
602 *option = GDK_INTERP_NEAREST;
605 *option = GDK_INTERP_TILES;
608 *option = GDK_INTERP_BILINEAR;
613 static void dnd_default_action_selection_menu_cb(GtkWidget *combo, gpointer data)
617 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
621 *option = DND_ACTION_ASK;
624 *option = DND_ACTION_COPY;
627 *option = DND_ACTION_MOVE;
631 static void clipboard_selection_menu_cb(GtkWidget *combo, gpointer data)
635 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
638 *option = CLIPBOARD_PRIMARY;
641 *option = CLIPBOARD_CLIPBOARD;
644 *option = CLIPBOARD_BOTH;
647 *option = CLIPBOARD_BOTH;
651 static void add_quality_menu(GtkWidget *table, gint column, gint row, const gchar *text,
652 guint option, guint *option_c)
659 pref_table_label(table, column, row, text, 0.0);
661 combo = gtk_combo_box_text_new();
663 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Nearest (worst, but fastest)"));
664 if (option == GDK_INTERP_NEAREST) current = 0;
665 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Tiles"));
666 if (option == GDK_INTERP_TILES) current = 1;
667 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Bilinear (best, but slowest)"));
668 if (option == GDK_INTERP_BILINEAR) current = 2;
670 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
672 g_signal_connect(G_OBJECT(combo), "changed",
673 G_CALLBACK(quality_menu_cb), option_c);
675 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
676 gtk_widget_show(combo);
679 static void add_dnd_default_action_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text, DnDAction option, DnDAction *option_c)
686 pref_table_label(table, column, row, text, 0.0);
688 combo = gtk_combo_box_text_new();
690 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Ask"));
691 if (option == DND_ACTION_ASK) current = 0;
692 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Copy"));
693 if (option == DND_ACTION_COPY) current = 1;
694 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Move"));
695 if (option == DND_ACTION_MOVE) current = 2;
697 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
699 g_signal_connect(G_OBJECT(combo), "changed",
700 G_CALLBACK(dnd_default_action_selection_menu_cb), option_c);
702 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
703 gtk_widget_show(combo);
706 static void add_clipboard_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
707 gint option, gint *option_c)
714 pref_table_label(table, column, row, text, 0.0);
716 combo = gtk_combo_box_text_new();
718 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Primary"));
719 if (option == CLIPBOARD_PRIMARY) current = 0;
720 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Clipboard"));
721 if (option == CLIPBOARD_CLIPBOARD) current = 1;
722 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Both"));
723 if (option == CLIPBOARD_BOTH) current = 2;
725 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
727 g_signal_connect(G_OBJECT(combo), "changed",
728 G_CALLBACK(clipboard_selection_menu_cb), option_c);
730 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
731 gtk_widget_show(combo);
734 static void zoom_style_selection_menu_cb(GtkWidget *combo, gpointer data)
738 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
741 *option = ZOOM_GEOMETRIC;
744 *option = ZOOM_ARITHMETIC;
747 *option = ZOOM_GEOMETRIC;
751 static void add_zoom_style_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text, ZoomStyle option, ZoomStyle *option_c)
758 pref_table_label(table, column, row, text, 0.0);
760 combo = gtk_combo_box_text_new();
762 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Geometric"));
763 if (option == ZOOM_GEOMETRIC) current = 0;
764 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Arithmetic"));
765 if (option == ZOOM_ARITHMETIC) current = 1;
767 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
769 g_signal_connect(G_OBJECT(combo), "changed", G_CALLBACK(zoom_style_selection_menu_cb), option_c);
771 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
772 gtk_widget_show(combo);
775 typedef struct _UseableMouseItems UseableMouseItems;
776 struct _UseableMouseItems
778 gchar *name; /* GtkActionEntry terminology */
783 static const UseableMouseItems useable_mouse_items[] = {
785 {"FirstImage", N_("First Image"), GTK_STOCK_GOTO_TOP},
786 {"PrevImage", N_("Previous Image"), GTK_STOCK_GO_UP},
787 {"NextImage", N_("Next Image"), GTK_STOCK_GO_DOWN},
788 {"LastImage", N_("Last Image"), GTK_STOCK_GOTO_BOTTOM},
789 {"Back", N_("Back"), GTK_STOCK_GO_BACK},
790 {"Forward", N_("Forward"), GTK_STOCK_GO_FORWARD},
791 {"Home", N_("Home"), GTK_STOCK_HOME},
792 {"Up", N_("Up"), GTK_STOCK_GO_UP},
793 {"FirstPage", N_("First page"), GTK_STOCK_MEDIA_PREVIOUS},
794 {"LastPage", N_("Last Page"), GTK_STOCK_MEDIA_NEXT},
795 {"NextPage", N_("Next page"), GTK_STOCK_MEDIA_FORWARD},
796 {"PrevPage", N_("Previous Page"), GTK_STOCK_MEDIA_REWIND},
797 {"NewWindow", N_("New _window"), GTK_STOCK_NEW},
798 {"NewCollection", N_("New collection"), GTK_STOCK_INDEX},
799 {"OpenCollection", N_("Open collection"), GTK_STOCK_OPEN},
800 {"Search", N_("Search"), GTK_STOCK_FIND},
801 {"FindDupes", N_("Find duplicates"), GTK_STOCK_FIND},
802 {"NewFolder", N_("New folder"),GTK_STOCK_DIRECTORY},
803 {"Copy", N_("Copy"), GTK_STOCK_COPY},
804 {"Move", N_("Move"), PIXBUF_INLINE_ICON_MOVE},
805 {"Rename", N_("Rename"), PIXBUF_INLINE_ICON_RENAME},
806 {"Delete", N_("Delete"), GTK_STOCK_DELETE},
807 {"CloseWindow", N_("Close Window"), GTK_STOCK_CLOSE},
808 {"PanView", N_("Pan view"), PIXBUF_INLINE_ICON_PANORAMA},
809 {"SelectAll", N_("Select all"), PIXBUF_INLINE_ICON_SELECT_ALL},
810 {"SelectNone", N_("Select none"), PIXBUF_INLINE_ICON_SELECT_NONE},
811 {"SelectInvert", N_("Select invert"), PIXBUF_INLINE_ICON_SELECT_INVERT},
812 {"ShowFileFilter", N_("Show file filter"), PIXBUF_INLINE_ICON_FILE_FILTER},
813 {"RectangularSelection", N_("Select rectangle"), PIXBUF_INLINE_ICON_SELECT_RECTANGLE},
814 {"Print", N_("Print"), GTK_STOCK_PRINT},
815 {"Preferences", N_("Preferences"), GTK_STOCK_PREFERENCES},
816 {"LayoutConfig", N_("Configure this window"), GTK_STOCK_PREFERENCES},
817 {"Maintenance", N_("Cache maintenance"), PIXBUF_INLINE_ICON_MAINTENANCE},
818 {"RotateCW", N_("Rotate clockwise 90°"), PIXBUF_INLINE_ICON_CW},
819 {"RotateCCW", N_("Rotate counterclockwise 90°"), PIXBUF_INLINE_ICON_CCW},
820 {"Rotate180", N_("Rotate 180°"), PIXBUF_INLINE_ICON_180},
821 {"Mirror", N_("Mirror"), PIXBUF_INLINE_ICON_MIRROR},
822 {"Flip", N_("Flip"), PIXBUF_INLINE_ICON_FLIP},
823 {"AlterNone", N_("Original state"), PIXBUF_INLINE_ICON_ORIGINAL},
824 {"ZoomIn", N_("Zoom in"), GTK_STOCK_ZOOM_IN},
825 {"ZoomOut", N_("Zoom out"), GTK_STOCK_ZOOM_OUT},
826 {"Zoom100", N_("Zoom 1:1"), GTK_STOCK_ZOOM_100},
827 {"ZoomFit", N_("Zoom to fit"), GTK_STOCK_ZOOM_FIT},
828 {"ZoomFillHor", N_("Fit Horizontaly"), PIXBUF_INLINE_ICON_ZOOMFILLHOR},
829 {"ZoomFillVert", N_("Fit vertically"), PIXBUF_INLINE_ICON_ZOOMFILLVERT},
830 {"Zoom200", N_("Zoom 2:1"), GTK_STOCK_FILE},
831 {"Zoom300", N_("Zoom 3:1"), GTK_STOCK_FILE},
832 {"Zoom400", N_("Zoom 4:1"), GTK_STOCK_FILE},
833 {"Zoom50", N_("Zoom 1:2"), GTK_STOCK_FILE},
834 {"Zoom33", N_("Zoom1:3"), GTK_STOCK_FILE},
835 {"Zoom25", N_("Zoom 1:4"), GTK_STOCK_FILE},
836 {"ConnectZoomIn", N_("Connected Zoom in"), GTK_STOCK_ZOOM_IN},
837 {"SplitPaneSync", N_("Split Pane Sync"), PIXBUF_INLINE_SPLIT_PANE_SYNC},
838 {"Grayscale", N_("Grayscale"), PIXBUF_INLINE_ICON_GRAYSCALE},
839 {"OverUnderExposed", N_("Over Under Exposed"), PIXBUF_INLINE_ICON_EXPOSURE},
840 {"HideTools", N_("Hide file list"), PIXBUF_INLINE_ICON_HIDETOOLS},
841 {"SlideShowPause", N_("Pause slideshow"), GTK_STOCK_MEDIA_PAUSE},
842 {"SlideShowFaster", N_("Slideshow Faster"), GTK_STOCK_FILE},
843 {"SlideShowSlower", N_("Slideshow Slower"), GTK_STOCK_FILE},
844 {"Refresh", N_("Refresh"), GTK_STOCK_REFRESH},
845 {"HelpContents", N_("Help"), GTK_STOCK_HELP},
846 {"ExifWin", N_("Exif window"), PIXBUF_INLINE_ICON_EXIF},
847 {"Thumbnails", N_("Show thumbnails"), PIXBUF_INLINE_ICON_THUMB},
848 {"ShowMarks", N_("Show marks"), PIXBUF_INLINE_ICON_MARKS},
849 {"DrawRectangle", N_("Draw Rectangle"), PIXBUF_INLINE_ICON_DRAW_RECTANGLE},
850 {"FloatTools", N_("Float file list"), PIXBUF_INLINE_ICON_FLOAT},
851 {"SBar", N_("Info sidebar"), PIXBUF_INLINE_ICON_INFO},
852 {"SBarSort", N_("Sort manager"), PIXBUF_INLINE_ICON_SORT},
853 {"Quit", N_("Quit"), GTK_STOCK_QUIT},
857 static void mouse_buttons_selection_menu_cb(GtkWidget *combo, gpointer data)
859 gchar **option = data;
862 label = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(combo));
864 const UseableMouseItems *list = useable_mouse_items;
868 if (g_strcmp0(list->label, label) == 0)
876 *option = g_strdup(list->name);
880 static void add_mouse_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
881 gchar *option, gchar **option_c)
889 pref_table_label(table, column, row, text, 0.0);
891 combo = gtk_combo_box_text_new();
893 const UseableMouseItems *list = useable_mouse_items;
897 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), list->label);
898 if (g_strcmp0(list->name, option) == 0)
906 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
908 g_signal_connect(G_OBJECT(combo), "changed",
909 G_CALLBACK(mouse_buttons_selection_menu_cb), option_c);
911 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
912 gtk_widget_show(combo);
915 static void thumb_size_menu_cb(GtkWidget *combo, gpointer data)
919 n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
922 if ((guint) n < sizeof(thumb_size_list) / sizeof(ThumbSize))
924 c_options->thumbnails.max_width = thumb_size_list[n].w;
925 c_options->thumbnails.max_height = thumb_size_list[n].h;
929 c_options->thumbnails.max_width = options->thumbnails.max_width;
930 c_options->thumbnails.max_height = options->thumbnails.max_height;
934 static void add_thumb_size_menu(GtkWidget *table, gint column, gint row, gchar *text)
940 c_options->thumbnails.max_width = options->thumbnails.max_width;
941 c_options->thumbnails.max_height = options->thumbnails.max_height;
943 pref_table_label(table, column, row, text, 0.0);
945 combo = gtk_combo_box_text_new();
948 for (i = 0; (guint) i < sizeof(thumb_size_list) / sizeof(ThumbSize); i++)
953 w = thumb_size_list[i].w;
954 h = thumb_size_list[i].h;
956 buf = g_strdup_printf("%d x %d", w, h);
957 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
960 if (w == options->thumbnails.max_width && h == options->thumbnails.max_height) current = i;
967 buf = g_strdup_printf("%s %d x %d", _("Custom"), options->thumbnails.max_width, options->thumbnails.max_height);
968 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
974 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
975 g_signal_connect(G_OBJECT(combo), "changed",
976 G_CALLBACK(thumb_size_menu_cb), NULL);
978 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
979 gtk_widget_show(combo);
982 static void stereo_mode_menu_cb(GtkWidget *combo, gpointer data)
986 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
990 *option = PR_STEREO_NONE;
993 *option = PR_STEREO_ANAGLYPH_RC;
996 *option = PR_STEREO_ANAGLYPH_GM;
999 *option = PR_STEREO_ANAGLYPH_YB;
1002 *option = PR_STEREO_ANAGLYPH_GRAY_RC;
1005 *option = PR_STEREO_ANAGLYPH_GRAY_GM;
1008 *option = PR_STEREO_ANAGLYPH_GRAY_YB;
1011 *option = PR_STEREO_ANAGLYPH_DB_RC;
1014 *option = PR_STEREO_ANAGLYPH_DB_GM;
1017 *option = PR_STEREO_ANAGLYPH_DB_YB;
1020 *option = PR_STEREO_HORIZ;
1023 *option = PR_STEREO_HORIZ | PR_STEREO_HALF;
1026 *option = PR_STEREO_VERT;
1029 *option = PR_STEREO_VERT | PR_STEREO_HALF;
1032 *option = PR_STEREO_FIXED;
1037 static void add_stereo_mode_menu(GtkWidget *table, gint column, gint row, const gchar *text,
1038 gint option, gint *option_c, gboolean add_fixed)
1045 pref_table_label(table, column, row, text, 0.0);
1047 combo = gtk_combo_box_text_new();
1049 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Single image"));
1051 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Red-Cyan"));
1052 if (option & PR_STEREO_ANAGLYPH_RC) current = 1;
1053 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Green-Magenta"));
1054 if (option & PR_STEREO_ANAGLYPH_GM) current = 2;
1055 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Yellow-Blue"));
1056 if (option & PR_STEREO_ANAGLYPH_YB) current = 3;
1057 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Red-Cyan"));
1058 if (option & PR_STEREO_ANAGLYPH_GRAY_RC) current = 4;
1059 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Green-Magenta"));
1060 if (option & PR_STEREO_ANAGLYPH_GRAY_GM) current = 5;
1061 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Yellow-Blue"));
1062 if (option & PR_STEREO_ANAGLYPH_GRAY_YB) current = 6;
1063 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Red-Cyan"));
1064 if (option & PR_STEREO_ANAGLYPH_DB_RC) current = 7;
1065 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Green-Magenta"));
1066 if (option & PR_STEREO_ANAGLYPH_DB_GM) current = 8;
1067 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Yellow-Blue"));
1068 if (option & PR_STEREO_ANAGLYPH_DB_YB) current = 9;
1070 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side"));
1071 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side Half size"));
1072 if (option & PR_STEREO_HORIZ)
1075 if (option & PR_STEREO_HALF) current = 11;
1078 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom"));
1079 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom Half size"));
1080 if (option & PR_STEREO_VERT)
1083 if (option & PR_STEREO_HALF) current = 13;
1088 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Fixed position"));
1089 if (option & PR_STEREO_FIXED) current = 14;
1092 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
1094 g_signal_connect(G_OBJECT(combo), "changed",
1095 G_CALLBACK(stereo_mode_menu_cb), option_c);
1097 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
1098 gtk_widget_show(combo);
1101 static void video_menu_cb(GtkWidget *combo, gpointer data)
1103 gchar **option = data;
1105 EditorDescription *ed = g_list_nth_data(editor_list_get(), gtk_combo_box_get_active(GTK_COMBO_BOX(combo)));
1109 static void video_menu_populate(gpointer data, gpointer user_data)
1111 GtkWidget *combo = user_data;
1112 EditorDescription *ed = data;
1114 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), ed->name);
1117 static void add_video_menu(GtkWidget *table, gint column, gint row, const gchar *text,
1118 gchar *option, gchar **option_c)
1122 /* use lists since they are sorted */
1123 GList *eds = editor_list_get();
1127 pref_table_label(table, column, row, text, 0.0);
1129 combo = gtk_combo_box_text_new();
1130 g_list_foreach(eds,video_menu_populate,(gpointer)combo);
1131 current = option ? g_list_index(eds,g_hash_table_lookup(editors,option)): -1;
1133 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
1135 g_signal_connect(G_OBJECT(combo), "changed",
1136 G_CALLBACK(video_menu_cb), option_c);
1138 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
1139 gtk_widget_show(combo);
1142 static void filter_store_populate(void)
1146 if (!filter_store) return;
1148 gtk_list_store_clear(filter_store);
1150 work = filter_get_list();
1159 gtk_list_store_append(filter_store, &iter);
1160 gtk_list_store_set(filter_store, &iter, 0, fe, -1);
1164 static void filter_store_ext_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1165 gchar *new_text, gpointer data)
1167 GtkWidget *model = data;
1168 FilterEntry *fe = data;
1172 if (!new_text || strlen(new_text) < 1) return;
1174 tpath = gtk_tree_path_new_from_string(path_str);
1175 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1176 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1178 g_free(fe->extensions);
1179 fe->extensions = g_strdup(new_text);
1181 gtk_tree_path_free(tpath);
1185 static void filter_store_class_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1186 gchar *new_text, gpointer data)
1188 GtkWidget *model = data;
1189 FilterEntry *fe = data;
1194 if (!new_text || !new_text[0]) return;
1196 tpath = gtk_tree_path_new_from_string(path_str);
1197 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1198 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1200 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
1202 if (strcmp(new_text, _(format_class_list[i])) == 0)
1209 gtk_tree_path_free(tpath);
1213 static void filter_store_desc_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1214 gchar *new_text, gpointer data)
1216 GtkWidget *model = data;
1221 if (!new_text || !new_text[0]) return;
1223 tpath = gtk_tree_path_new_from_string(path_str);
1224 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1225 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1227 g_free(fe->description);
1228 fe->description = g_strdup(new_text);
1230 gtk_tree_path_free(tpath);
1233 static void filter_store_enable_cb(GtkCellRendererToggle *renderer,
1234 gchar *path_str, gpointer data)
1236 GtkWidget *model = data;
1241 tpath = gtk_tree_path_new_from_string(path_str);
1242 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1243 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1245 fe->enabled = !fe->enabled;
1247 gtk_tree_path_free(tpath);
1251 static void filter_store_writable_cb(GtkCellRendererToggle *renderer,
1252 gchar *path_str, gpointer data)
1254 GtkWidget *model = data;
1259 tpath = gtk_tree_path_new_from_string(path_str);
1260 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1261 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1263 fe->writable = !fe->writable;
1264 if (fe->writable) fe->allow_sidecar = FALSE;
1266 gtk_tree_path_free(tpath);
1270 static void filter_store_sidecar_cb(GtkCellRendererToggle *renderer,
1271 gchar *path_str, gpointer data)
1273 GtkWidget *model = data;
1278 tpath = gtk_tree_path_new_from_string(path_str);
1279 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1280 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1282 fe->allow_sidecar = !fe->allow_sidecar;
1283 if (fe->allow_sidecar) fe->writable = FALSE;
1285 gtk_tree_path_free(tpath);
1289 static void filter_set_func(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
1290 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
1294 gtk_tree_model_get(tree_model, iter, 0, &fe, -1);
1296 switch (GPOINTER_TO_INT(data))
1299 g_object_set(GTK_CELL_RENDERER(cell),
1300 "active", fe->enabled, NULL);
1303 g_object_set(GTK_CELL_RENDERER(cell),
1304 "text", fe->extensions, NULL);
1306 case FE_DESCRIPTION:
1307 g_object_set(GTK_CELL_RENDERER(cell),
1308 "text", fe->description, NULL);
1311 g_object_set(GTK_CELL_RENDERER(cell),
1312 "text", _(format_class_list[fe->file_class]), NULL);
1315 g_object_set(GTK_CELL_RENDERER(cell),
1316 "active", fe->writable, NULL);
1318 case FE_ALLOW_SIDECAR:
1319 g_object_set(GTK_CELL_RENDERER(cell),
1320 "active", fe->allow_sidecar, NULL);
1325 static gboolean filter_add_scroll(gpointer data)
1329 GtkCellRenderer *cell;
1330 GtkTreeViewColumn *column;
1333 rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(filter_store), NULL);
1334 path = gtk_tree_path_new_from_indices(rows-1, -1);
1336 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data), 0);
1338 list_cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column));
1339 cell = g_list_last(list_cells)->data;
1341 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1342 path, column, FALSE, 0.0, 0.0 );
1343 gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(data),
1344 path, column, cell, TRUE);
1346 gtk_tree_path_free(path);
1347 g_list_free(list_cells);
1352 static void filter_add_cb(GtkWidget *widget, gpointer data)
1354 filter_add_unique("description", ".new", FORMAT_CLASS_IMAGE, TRUE, FALSE, TRUE);
1355 filter_store_populate();
1357 g_idle_add((GSourceFunc)filter_add_scroll, data);
1360 static void filter_remove_cb(GtkWidget *widget, gpointer data)
1362 GtkWidget *filter_view = data;
1363 GtkTreeSelection *selection;
1367 if (!filter_store) return;
1368 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1369 if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) return;
1370 gtk_tree_model_get(GTK_TREE_MODEL(filter_store), &iter, 0, &fe, -1);
1373 filter_remove_entry(fe);
1375 filter_store_populate();
1378 static gboolean filter_default_ok_scroll(GtkTreeView *data)
1382 GtkTreeViewColumn *column;
1384 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(filter_store), &iter);
1385 path = gtk_tree_model_get_path(GTK_TREE_MODEL(filter_store), &iter);
1386 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1388 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1392 gtk_tree_path_free(path);
1397 static void filter_default_ok_cb(GenericDialog *gd, gpointer data)
1400 filter_add_defaults();
1402 filter_store_populate();
1404 g_idle_add((GSourceFunc)filter_default_ok_scroll, gd->data);
1407 static void dummy_cancel_cb(GenericDialog *gd, gpointer data)
1409 /* no op, only so cancel button appears */
1412 static void filter_default_cb(GtkWidget *widget, gpointer data)
1416 gd = generic_dialog_new(_("Reset filters"),
1417 "reset_filter", widget, TRUE,
1418 dummy_cancel_cb, data);
1419 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset filters"),
1420 _("This will reset the file filters to the defaults.\nContinue?"), TRUE);
1421 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, filter_default_ok_cb, TRUE);
1422 gtk_widget_show(gd->dialog);
1425 static void filter_disable_cb(GtkWidget *widget, gpointer data)
1427 GtkWidget *frame = data;
1429 gtk_widget_set_sensitive(frame,
1430 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
1433 static void safe_delete_view_cb(GtkWidget *widget, gpointer data)
1435 layout_set_path(NULL, gtk_entry_get_text(GTK_ENTRY(safe_delete_path_entry)));
1438 static void safe_delete_clear_ok_cb(GenericDialog *gd, gpointer data)
1440 file_util_trash_clear();
1443 static void safe_delete_clear_cb(GtkWidget *widget, gpointer data)
1447 gd = generic_dialog_new(_("Clear trash"),
1448 "clear_trash", widget, TRUE,
1449 dummy_cancel_cb, NULL);
1450 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear trash"),
1451 _("This will remove the trash contents."), FALSE);
1452 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, safe_delete_clear_ok_cb, TRUE);
1453 entry = gtk_entry_new();
1454 gtk_widget_set_can_focus(entry, FALSE);
1455 gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE);
1456 if (options->file_ops.safe_delete_path) gtk_entry_set_text(GTK_ENTRY(entry), options->file_ops.safe_delete_path);
1457 gtk_box_pack_start(GTK_BOX(gd->vbox), entry, FALSE, FALSE, 0);
1458 gtk_widget_show(entry);
1459 gtk_widget_show(gd->dialog);
1462 static void image_overlay_template_view_changed_cb(GtkWidget *widget, gpointer data)
1464 GtkWidget *pTextView;
1465 GtkTextBuffer *pTextBuffer;
1469 pTextView = GTK_WIDGET(data);
1471 pTextBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pTextView));
1472 gtk_text_buffer_get_start_iter(pTextBuffer, &iStart);
1473 gtk_text_buffer_get_end_iter(pTextBuffer, &iEnd);
1475 set_image_overlay_template_string(&c_options->image_overlay.template_string,
1476 gtk_text_buffer_get_text(pTextBuffer, &iStart, &iEnd, TRUE));
1479 static void image_overlay_default_template_ok_cb(GenericDialog *gd, gpointer data)
1481 GtkTextView *text_view = data;
1482 GtkTextBuffer *buffer;
1484 set_default_image_overlay_template_string(&options->image_overlay.template_string);
1485 if (!configwindow) return;
1487 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
1488 gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1491 static void image_overlay_default_template_cb(GtkWidget *widget, gpointer data)
1495 gd = generic_dialog_new(_("Reset image overlay template string"),
1496 "reset_image_overlay_template_string", widget, TRUE,
1497 dummy_cancel_cb, data);
1498 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset image overlay template string"),
1499 _("This will reset the image overlay template string to the default.\nContinue?"), TRUE);
1500 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, image_overlay_default_template_ok_cb, TRUE);
1501 gtk_widget_show(gd->dialog);
1504 static void image_overlay_help_cb(GtkWidget *widget, gpointer data)
1506 help_window_show("GuideOptionsOSD.html");
1509 static void image_overlay_set_font_cb(GtkWidget *widget, gpointer data)
1511 #if GTK_CHECK_VERSION(3,4,0)
1514 PangoFontDescription *font_desc;
1516 dialog = gtk_font_chooser_dialog_new("Image Overlay Font", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1517 gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), options->image_overlay.font);
1519 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1521 font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
1522 font = pango_font_description_to_string(font_desc);
1523 g_free(c_options->image_overlay.font);
1524 c_options->image_overlay.font = g_strdup(font);
1528 gtk_widget_destroy(dialog);
1532 font = gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget));
1533 c_options->image_overlay.font = g_strdup(font);
1537 static void image_overlay_set_text_colour_cb(GtkWidget *widget, gpointer data)
1540 #if GTK_CHECK_VERSION(3,4,0)
1543 dialog = gtk_color_chooser_dialog_new("Image Overlay Text Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1544 colour.red = options->image_overlay.text_red;
1545 colour.green = options->image_overlay.text_green;
1546 colour.blue = options->image_overlay.text_blue;
1547 colour.alpha = options->image_overlay.text_alpha;
1548 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1549 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1551 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1553 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1554 c_options->image_overlay.text_red = colour.red*255;
1555 c_options->image_overlay.text_green = colour.green*255;
1556 c_options->image_overlay.text_blue = colour.blue*255;
1557 c_options->image_overlay.text_alpha = colour.alpha*255;
1559 gtk_widget_destroy(dialog);
1562 GtkColorSelection *colorsel;
1564 dialog = gtk_color_selection_dialog_new("Image Overlay Text Colour");
1565 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1566 colour.red = options->image_overlay.text_red*257;
1567 colour.green = options->image_overlay.text_green*257;
1568 colour.blue = options->image_overlay.text_blue*257;
1569 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1570 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1571 gtk_color_selection_set_current_color(colorsel, &colour);
1572 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.text_alpha*257);
1574 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1576 gtk_color_selection_get_current_color(colorsel, &colour);
1577 c_options->image_overlay.text_red = colour.red/257;
1578 c_options->image_overlay.text_green = colour.green/257;
1579 c_options->image_overlay.text_blue = colour.blue/257;
1580 c_options->image_overlay.text_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1582 gtk_widget_destroy (dialog);
1587 static void image_overlay_set_background_colour_cb(GtkWidget *widget, gpointer data)
1590 #if GTK_CHECK_VERSION(3,4,0)
1593 dialog = gtk_color_chooser_dialog_new("Image Overlay Background Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1594 colour.red = options->image_overlay.background_red;
1595 colour.green = options->image_overlay.background_green;
1596 colour.blue = options->image_overlay.background_blue;
1597 colour.alpha = options->image_overlay.background_alpha;
1598 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1599 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1601 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1603 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1604 c_options->image_overlay.background_red = colour.red*255;
1605 c_options->image_overlay.background_green = colour.green*255;
1606 c_options->image_overlay.background_blue = colour.blue*255;
1607 c_options->image_overlay.background_alpha = colour.alpha*255;
1609 gtk_widget_destroy(dialog);
1612 GtkColorSelection *colorsel;
1614 dialog = gtk_color_selection_dialog_new("Image Overlay Background Colour");
1615 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1616 colour.red = options->image_overlay.background_red*257;
1617 colour.green = options->image_overlay.background_green*257;
1618 colour.blue = options->image_overlay.background_blue*257;
1619 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1620 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1621 gtk_color_selection_set_current_color(colorsel, &colour);
1622 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.background_alpha*257);
1624 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1626 gtk_color_selection_get_current_color(colorsel, &colour);
1627 c_options->image_overlay.background_red = colour.red/257;
1628 c_options->image_overlay.background_green = colour.green/257;
1629 c_options->image_overlay.background_blue = colour.blue/257;
1630 c_options->image_overlay.background_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1632 gtk_widget_destroy(dialog);
1636 static void accel_store_populate(void)
1639 GList *groups, *actions;
1641 const gchar *accel_path;
1645 if (!accel_store || !layout_window_list || !layout_window_list->data) return;
1647 gtk_tree_store_clear(accel_store);
1648 lw = layout_window_list->data; /* get the actions from the first window, it should not matter, they should be the same in all windows */
1650 g_assert(lw && lw->ui_manager);
1651 groups = gtk_ui_manager_get_action_groups(lw->ui_manager);
1654 actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
1657 action = GTK_ACTION(actions->data);
1658 accel_path = gtk_action_get_accel_path(action);
1659 if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
1661 gchar *label, *label2, *tooltip, *accel;
1662 g_object_get(action,
1663 "tooltip", &tooltip,
1667 if (pango_parse_markup(label, -1, '_', NULL, &label2, NULL, NULL) && label2)
1673 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1677 gtk_tree_store_append(accel_store, &iter, NULL);
1678 gtk_tree_store_set(accel_store, &iter,
1681 AE_TOOLTIP, tooltip ? tooltip : "",
1682 AE_ACCEL, accel_path,
1690 actions = actions->next;
1693 groups = groups->next;
1697 static void accel_store_cleared_cb(GtkCellRendererAccel *accel, gchar *path_string, gpointer user_data)
1702 static gboolean accel_remove_key_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1704 gchar *accel1 = data;
1709 gtk_tree_model_get(model, iter, AE_KEY, &accel2, -1);
1711 gtk_accelerator_parse(accel1, &key1.accel_key, &key1.accel_mods);
1712 gtk_accelerator_parse(accel2, &key2.accel_key, &key2.accel_mods);
1714 if (key1.accel_key == key2.accel_key && key1.accel_mods == key2.accel_mods)
1716 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1717 DEBUG_1("accelerator key '%s' is already used, removing.", accel1);
1726 static void accel_store_edited_cb(GtkCellRendererAccel *accel, gchar *path_string, guint accel_key, GdkModifierType accel_mods, guint hardware_keycode, gpointer user_data)
1728 GtkTreeModel *model = (GtkTreeModel *)accel_store;
1732 GtkAccelKey old_key, key;
1733 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
1735 gtk_tree_model_get_iter(model, &iter, path);
1736 gtk_tree_model_get(model, &iter, AE_ACCEL, &accel_path, -1);
1738 /* test if the accelerator can be stored without conflicts*/
1739 gtk_accel_map_lookup_entry(accel_path, &old_key);
1741 /* change the key and read it back (change may fail on keys hardcoded in gtk)*/
1742 gtk_accel_map_change_entry(accel_path, accel_key, accel_mods, TRUE);
1743 gtk_accel_map_lookup_entry(accel_path, &key);
1745 /* restore the original for now, the key will be really changed when the changes are confirmed */
1746 gtk_accel_map_change_entry(accel_path, old_key.accel_key, old_key.accel_mods, TRUE);
1748 acc = gtk_accelerator_name(key.accel_key, key.accel_mods);
1749 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, acc);
1751 gtk_tree_store_set(accel_store, &iter, AE_KEY, acc, -1);
1752 gtk_tree_path_free(path);
1756 static gboolean accel_default_scroll(GtkTreeView *data)
1760 GtkTreeViewColumn *column;
1762 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(accel_store), &iter);
1763 path = gtk_tree_model_get_path(GTK_TREE_MODEL(accel_store), &iter);
1764 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1766 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1770 gtk_tree_path_free(path);
1775 static void accel_default_cb(GtkWidget *widget, gpointer data)
1777 accel_store_populate();
1779 g_idle_add((GSourceFunc)accel_default_scroll, data);
1782 void accel_remove_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1784 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1787 void accel_reset_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1790 gchar *accel_path, *accel;
1792 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, -1);
1793 gtk_accel_map_lookup_entry(accel_path, &key);
1794 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1796 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, accel);
1798 gtk_tree_store_set(accel_store, iter, AE_KEY, accel, -1);
1803 static void accel_reset_cb(GtkWidget *widget, gpointer data)
1805 GtkTreeSelection *selection;
1807 if (!accel_store) return;
1808 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data));
1809 gtk_tree_selection_selected_foreach(selection, &accel_reset_selection, NULL);
1814 static GtkWidget *scrolled_notebook_page(GtkWidget *notebook, const gchar *title)
1818 GtkWidget *scrolled;
1819 GtkWidget *viewport;
1821 scrolled = gtk_scrolled_window_new(NULL, NULL);
1822 gtk_container_set_border_width(GTK_CONTAINER(scrolled), PREF_PAD_BORDER);
1823 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1824 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1825 label = gtk_label_new(title);
1826 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, label);
1827 gtk_widget_show(scrolled);
1829 viewport = gtk_viewport_new(NULL, NULL);
1830 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1831 gtk_container_add(GTK_CONTAINER(scrolled), viewport);
1832 gtk_widget_show(viewport);
1834 vbox = gtk_vbox_new(FALSE, 0);
1835 gtk_container_add(GTK_CONTAINER(viewport), vbox);
1836 gtk_widget_show(vbox);
1841 static void cache_standard_cb(GtkWidget *widget, gpointer data)
1843 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1845 c_options->thumbnails.spec_standard =TRUE;
1846 c_options->thumbnails.cache_into_dirs = FALSE;
1850 static void cache_geeqie_cb(GtkWidget *widget, gpointer data)
1852 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1854 c_options->thumbnails.spec_standard =FALSE;
1855 c_options->thumbnails.cache_into_dirs = FALSE;
1859 static void cache_local_cb(GtkWidget *widget, gpointer data)
1861 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1863 c_options->thumbnails.cache_into_dirs = TRUE;
1864 c_options->thumbnails.spec_standard =FALSE;
1868 static void help_search_engine_entry_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1869 GdkEvent *event, gpointer userdata)
1871 if (pos == GTK_ENTRY_ICON_PRIMARY)
1873 gtk_entry_set_text(GTK_ENTRY(userdata), HELP_SEARCH_ENGINE);
1877 gtk_entry_set_text(GTK_ENTRY(userdata), "");
1881 static void star_rating_star_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1882 GdkEvent *event, gpointer userdata)
1884 gchar *rating_symbol;
1886 if (pos == GTK_ENTRY_ICON_PRIMARY)
1888 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_STAR);
1889 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1890 g_free(rating_symbol);
1894 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1895 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1896 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1900 static void star_rating_rejected_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1901 GdkEvent *event, gpointer userdata)
1903 gchar *rating_symbol;
1905 if (pos == GTK_ENTRY_ICON_PRIMARY)
1907 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_REJECTED);
1908 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1909 g_free(rating_symbol);
1913 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1914 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1915 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1919 static guint star_rating_symbol_test(GtkWidget *widget, gpointer data)
1921 GtkContainer *hbox = data;
1922 GString *str = g_string_new(NULL);
1923 GtkEntry *hex_code_entry;
1924 gchar *hex_code_full;
1927 guint64 hex_value = 0;
1929 list = gtk_container_get_children(hbox);
1931 hex_code_entry = g_list_nth_data(list, 2);
1932 hex_code_full = g_strdup(gtk_entry_get_text(hex_code_entry));
1934 hex_code = g_strsplit(hex_code_full, "+", 2);
1935 if (hex_code[0] && hex_code[1])
1937 hex_value = strtoull(hex_code[1], NULL, 16);
1939 if (!hex_value || hex_value > 0x10FFFF)
1941 hex_value = 0x003F; // Unicode 'Question Mark'
1943 str = g_string_append_unichar(str, (gunichar)hex_value);
1944 gtk_label_set_text(g_list_nth_data(list, 1), str->str);
1946 g_strfreev(hex_code);
1947 g_string_free(str, TRUE);
1948 g_free(hex_code_full);
1953 static void star_rating_star_test_cb(GtkWidget *widget, gpointer data)
1955 guint64 star_symbol;
1957 star_symbol = star_rating_symbol_test(widget, data);
1958 c_options->star_rating.star = star_symbol;
1961 static void star_rating_rejected_test_cb(GtkWidget *widget, gpointer data)
1963 guint64 rejected_symbol;
1965 rejected_symbol = star_rating_symbol_test(widget, data);
1966 c_options->star_rating.rejected = rejected_symbol;
1969 /* general options tab */
1970 static void timezone_database_install_cb(GtkWidget *widget, gpointer data);
1971 typedef struct _TZData TZData;
1975 GCancellable *cancellable;
1977 GtkWidget *progress;
1979 GFile *timezone_database_gq;
1980 gchar *timezone_database_user;
1983 static void config_tab_general(GtkWidget *notebook)
1988 GtkWidget *group_frame;
1989 GtkWidget *subgroup;
1991 GtkWidget *ct_button;
1994 gint hours, minutes, remainder;
1996 GtkWidget *star_rating_entry;
1998 gchar *rating_symbol;
2001 gchar *download_locn;
2002 GNetworkMonitor *net_mon;
2003 GSocketConnectable *tz_org;
2004 gboolean internet_available = FALSE;
2007 vbox = scrolled_notebook_page(notebook, _("General"));
2009 group = pref_group_new(vbox, FALSE, _("Thumbnails"), GTK_ORIENTATION_VERTICAL);
2011 table = pref_table_new(group, 2, 2, FALSE, FALSE);
2012 add_thumb_size_menu(table, 0, 0, _("Size:"));
2013 add_quality_menu(table, 0, 1, _("Quality:"), options->thumbnails.quality, &c_options->thumbnails.quality);
2015 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2016 pref_label_new(hbox, _("Custom size: "));
2017 pref_spin_new_int(hbox, _("Width:"), NULL, 1, 512, 1, options->thumbnails.max_width, &c_options->thumbnails.max_width);
2018 pref_spin_new_int(hbox, _("Height:"), NULL, 1, 512, 1, options->thumbnails.max_height, &c_options->thumbnails.max_height);
2020 ct_button = pref_checkbox_new_int(group, _("Cache thumbnails and sim. files"),
2021 options->thumbnails.enable_caching, &c_options->thumbnails.enable_caching);
2023 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2024 pref_checkbox_link_sensitivity(ct_button, subgroup);
2026 c_options->thumbnails.spec_standard = options->thumbnails.spec_standard;
2027 c_options->thumbnails.cache_into_dirs = options->thumbnails.cache_into_dirs;
2028 group_frame = pref_frame_new(subgroup, TRUE, _("Use Geeqie thumbnail style and cache"),
2029 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2030 button = pref_radiobutton_new(group_frame, NULL, get_thumbnails_cache_dir(),
2031 !options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
2032 G_CALLBACK(cache_geeqie_cb), NULL);
2034 group_frame = pref_frame_new(subgroup, TRUE,
2035 _("Store thumbnails local to image folder (non-standard)"),
2036 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2037 pref_radiobutton_new(group_frame, button, "*/.thumbnails",
2038 !options->thumbnails.spec_standard && options->thumbnails.cache_into_dirs,
2039 G_CALLBACK(cache_local_cb), NULL);
2041 group_frame = pref_frame_new(subgroup, TRUE,
2042 _("Use standard thumbnail style and cache, shared with other applications"),
2043 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2044 pref_radiobutton_new(group_frame, button, get_thumbnails_standard_cache_dir(),
2045 options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
2046 G_CALLBACK(cache_standard_cb), NULL);
2048 pref_checkbox_new_int(group, _("Use EXIF thumbnails when available (EXIF thumbnails may be outdated)"),
2049 options->thumbnails.use_exif, &c_options->thumbnails.use_exif);
2051 pref_checkbox_new_int(group, _("Thumbnail color management"),
2052 options->thumbnails.use_color_management, &c_options->thumbnails.use_color_management);
2054 spin = pref_spin_new_int(group, _("Collection preview:"), NULL,
2056 options->thumbnails.collection_preview, &c_options->thumbnails.collection_preview);
2057 gtk_widget_set_tooltip_text(spin, _("The maximum number of thumbnails shown in a Collection preview montage"));
2059 #ifdef HAVE_FFMPEGTHUMBNAILER_METADATA
2060 pref_checkbox_new_int(group, _("Use embedded metadata in video files as thumbnails when available"),
2061 options->thumbnails.use_ft_metadata, &c_options->thumbnails.use_ft_metadata);
2063 // pref_checkbox_new_int(group, _("Ignore embedded metadata if size is too small"),
2064 // options->thumbnails.use_ft_metadata_small, &c_options->thumbnails.use_ft_metadata_small);
2067 pref_spacer(group, PREF_PAD_GROUP);
2069 group = pref_group_new(vbox, FALSE, _("Star Rating"), GTK_ORIENTATION_VERTICAL);
2071 c_options->star_rating.star = options->star_rating.star;
2072 c_options->star_rating.rejected = options->star_rating.rejected;
2074 str = g_string_new(NULL);
2075 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2076 pref_label_new(hbox, _("Star character: "));
2077 str = g_string_append_unichar(str, options->star_rating.star);
2078 pref_label_new(hbox, g_strdup(str->str));
2079 rating_symbol = g_strdup_printf("U+%X", options->star_rating.star);
2080 star_rating_entry = gtk_entry_new();
2081 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
2082 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
2083 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
2084 gtk_widget_show(star_rating_entry);
2085 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
2086 G_CALLBACK(star_rating_star_test_cb), hbox);
2087 gtk_widget_set_tooltip_text(button, _("Display selected character"));
2088 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2089 gtk_widget_show(button);
2090 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."));
2091 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2092 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2093 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2094 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2095 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2096 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2097 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2098 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2099 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
2100 G_CALLBACK(star_rating_star_icon_cb),
2103 g_string_free(str, TRUE);
2104 g_free(rating_symbol);
2106 str = g_string_new(NULL);
2107 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2108 pref_label_new(hbox, _("Rejected character: "));
2109 str = g_string_append_unichar(str, options->star_rating.rejected);
2110 pref_label_new(hbox, g_strdup(str->str));
2111 rating_symbol = g_strdup_printf("U+%X", options->star_rating.rejected);
2112 star_rating_entry = gtk_entry_new();
2113 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
2114 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
2115 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
2116 gtk_widget_show(star_rating_entry);
2117 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
2118 G_CALLBACK(star_rating_rejected_test_cb), hbox);
2119 gtk_widget_set_tooltip_text(button, _("Display selected character"));
2120 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2121 gtk_widget_show(button);
2122 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."));
2123 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2124 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2125 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2126 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2127 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2128 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2129 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2130 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2131 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
2132 G_CALLBACK(star_rating_rejected_icon_cb),
2135 g_string_free(str, TRUE);
2136 g_free(rating_symbol);
2138 pref_spacer(group, PREF_PAD_GROUP);
2140 group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
2142 c_options->slideshow.delay = options->slideshow.delay;
2143 hours = options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2144 remainder = options->slideshow.delay % (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2145 minutes = remainder / (60 * SLIDESHOW_SUBSECOND_PRECISION);
2146 seconds = (gdouble)(remainder % (60 * SLIDESHOW_SUBSECOND_PRECISION)) /
2147 SLIDESHOW_SUBSECOND_PRECISION;
2149 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2151 spin = pref_spin_new(hbox, _("Delay between image change hrs:mins:secs.dec"), NULL,
2153 options->slideshow.delay ? hours : 0.0,
2154 G_CALLBACK(slideshow_delay_hours_cb), NULL);
2155 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2156 spin = pref_spin_new(hbox, ":" , NULL,
2158 options->slideshow.delay ? minutes: 0.0,
2159 G_CALLBACK(slideshow_delay_minutes_cb), NULL);
2160 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2161 spin = pref_spin_new(hbox, ":", NULL,
2162 SLIDESHOW_MIN_SECONDS, 59, 1.0, 1,
2163 options->slideshow.delay ? seconds : 10.0,
2164 G_CALLBACK(slideshow_delay_seconds_cb), NULL);
2165 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2167 pref_checkbox_new_int(group, _("Random"), options->slideshow.random, &c_options->slideshow.random);
2168 pref_checkbox_new_int(group, _("Repeat"), options->slideshow.repeat, &c_options->slideshow.repeat);
2170 pref_spacer(group, PREF_PAD_GROUP);
2172 group = pref_group_new(vbox, FALSE, _("Image loading and caching"), GTK_ORIENTATION_VERTICAL);
2174 pref_spin_new_int(group, _("Decoded image cache size (MiB):"), NULL,
2175 0, 99999, 1, options->image.image_cache_max, &c_options->image.image_cache_max);
2176 pref_checkbox_new_int(group, _("Preload next image"),
2177 options->image.enable_read_ahead, &c_options->image.enable_read_ahead);
2179 pref_checkbox_new_int(group, _("Refresh on file change"),
2180 options->update_on_time_change, &c_options->update_on_time_change);
2183 pref_spacer(group, PREF_PAD_GROUP);
2185 group = pref_group_new(vbox, FALSE, _("Expand menu and toolbar"), GTK_ORIENTATION_VERTICAL);
2187 pref_checkbox_new_int(group, _("Expand menu and toolbar (NOTE! Geeqie must be restarted for change to take effect)"),
2188 options->expand_menu_toolbar, &c_options->expand_menu_toolbar);
2189 gtk_widget_set_tooltip_text(group, _("Expand the menu and toolbar to the full width of the window"));
2191 pref_spacer(group, PREF_PAD_GROUP);
2193 net_mon = g_network_monitor_get_default();
2194 tz_org = g_network_address_parse_uri(TIMEZONE_DATABASE_WEB, 80, NULL);
2197 internet_available = g_network_monitor_can_reach(net_mon, tz_org, NULL, NULL);
2198 g_object_unref(tz_org);
2201 group = pref_group_new(vbox, FALSE, _("Timezone database"), GTK_ORIENTATION_VERTICAL);
2202 hbox = pref_box_new(group, TRUE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2204 if (!internet_available)
2206 gtk_widget_set_sensitive(group, FALSE);
2209 tz = g_new0(TZData, 1);
2211 path = path_from_utf8(TIMEZONE_DATABASE_WEB);
2212 basename = g_path_get_basename(path);
2213 tz->timezone_database_user = g_build_filename(get_rc_dir(), TIMEZONE_DATABASE_FILE, NULL);
2217 if (isfile(tz->timezone_database_user))
2219 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Update"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2223 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Install"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2226 download_locn = g_strconcat(_("Download database from: "), TIMEZONE_DATABASE_WEB, NULL);
2227 pref_label_new(GTK_WIDGET(hbox), download_locn);
2228 g_free(download_locn);
2230 if (!internet_available)
2232 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"));
2236 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"));
2238 gtk_widget_show(button);
2240 pref_spacer(group, PREF_PAD_GROUP);
2242 group = pref_group_new(vbox, FALSE, _("On-line help search engine"), GTK_ORIENTATION_VERTICAL);
2244 help_search_engine_entry = gtk_entry_new();
2245 gtk_entry_set_text(GTK_ENTRY(help_search_engine_entry), options->help_search_engine);
2246 gtk_box_pack_start(GTK_BOX(group), help_search_engine_entry, FALSE, FALSE, 0);
2247 gtk_widget_show(help_search_engine_entry);
2249 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"));
2251 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2252 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2253 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2254 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2255 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2256 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2257 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2258 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2259 g_signal_connect(GTK_ENTRY(help_search_engine_entry), "icon-press",
2260 G_CALLBACK(help_search_engine_entry_icon_cb),
2261 help_search_engine_entry);
2265 static void config_tab_image(GtkWidget *notebook)
2270 GtkWidget *ct_button;
2271 GtkWidget *enlargement_button;
2274 GtkWidget *two_pass;
2276 GtkWidget *gpu_accel;
2279 vbox = scrolled_notebook_page(notebook, _("Image"));
2281 group = pref_group_new(vbox, FALSE, _("Zoom"), GTK_ORIENTATION_VERTICAL);
2283 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2284 add_quality_menu(table, 0, 0, _("Quality:"), options->image.zoom_quality, &c_options->image.zoom_quality);
2285 if (options->image.use_clutter_renderer && !options->disable_gpu)
2287 gtk_widget_set_sensitive(table, FALSE);
2291 gpu_accel = pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library (Requires restart)"),
2292 options->image.use_clutter_renderer, &c_options->image.use_clutter_renderer);
2293 if (options->disable_gpu && !options->override_disable_gpu)
2295 gtk_widget_set_sensitive(gpu_accel, FALSE);
2299 two_pass = pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"),
2300 options->image.zoom_2pass, &c_options->image.zoom_2pass);
2301 if (options->image.use_clutter_renderer && !options->disable_gpu)
2303 gtk_widget_set_sensitive(two_pass, FALSE);
2306 c_options->image.zoom_increment = options->image.zoom_increment;
2307 spin = pref_spin_new(group, _("Zoom increment:"), NULL,
2308 0.01, 4.0, 0.01, 2, (gdouble)options->image.zoom_increment / 100.0,
2309 G_CALLBACK(zoom_increment_cb), NULL);
2310 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2312 c_options->image.zoom_style = options->image.zoom_style;
2313 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2314 add_zoom_style_selection_menu(table, 0, 0, _("Zoom style:"), options->image.zoom_style, &c_options->image.zoom_style);
2316 group = pref_group_new(vbox, FALSE, _("Fit image to window"), GTK_ORIENTATION_VERTICAL);
2318 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2319 enlargement_button = pref_checkbox_new_int(hbox, _("Allow enlargement of image (max. size in %)"),
2320 options->image.zoom_to_fit_allow_expand, &c_options->image.zoom_to_fit_allow_expand);
2321 spin = pref_spin_new_int(hbox, NULL, NULL,
2323 options->image.max_enlargement_size, &c_options->image.max_enlargement_size);
2324 pref_checkbox_link_sensitivity(enlargement_button, spin);
2325 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."));
2327 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2328 ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (% of actual window):"),
2329 options->image.limit_autofit_size, &c_options->image.limit_autofit_size);
2330 spin = pref_spin_new_int(hbox, NULL, NULL,
2332 options->image.max_autofit_size, &c_options->image.max_autofit_size);
2333 pref_checkbox_link_sensitivity(ct_button, spin);
2334 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."));
2336 group = pref_group_new(vbox, FALSE, _("Tile size"), GTK_ORIENTATION_VERTICAL);
2337 gtk_widget_set_sensitive(group, !options->image.use_clutter_renderer);
2339 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2340 spin = pref_spin_new_int(hbox, _("Pixels"), _("(Requires restart)"),
2342 options->image.tile_size, &c_options->image.tile_size);
2343 gtk_widget_set_tooltip_text(GTK_WIDGET(hbox), _("This value changes the size of the tiles large images are split into. Increasing the size of the tiles will reduce the tiling effect seen on image changes, but will also slightly increase the delay before the first part of a large image is seen."));
2345 group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
2347 pref_checkbox_new_int(group, _("Use custom border color in window mode"),
2348 options->image.use_custom_border_color, &c_options->image.use_custom_border_color);
2350 pref_checkbox_new_int(group, _("Use custom border color in fullscreen mode"),
2351 options->image.use_custom_border_color_in_fullscreen, &c_options->image.use_custom_border_color_in_fullscreen);
2353 pref_color_button_new(group, _("Border color"), &options->image.border_color,
2354 G_CALLBACK(pref_color_button_set_cb), &c_options->image.border_color);
2356 c_options->image.border_color = options->image.border_color;
2358 pref_color_button_new(group, _("Alpha channel color 1"), &options->image.alpha_color_1,
2359 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_1);
2361 pref_color_button_new(group, _("Alpha channel color 2"), &options->image.alpha_color_2,
2362 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_2);
2364 c_options->image.alpha_color_1 = options->image.alpha_color_1;
2365 c_options->image.alpha_color_2 = options->image.alpha_color_2;
2370 static void save_default_window_layout_cb(GtkWidget *widget, gpointer data)
2372 LayoutWindow *lw = NULL;
2373 gchar *default_path;
2376 /* Get current lw */
2379 tmp_id = lw->options.id;
2380 lw->options.id = g_strdup("lw_default");
2382 default_path = g_build_filename(get_rc_dir(), DEFAULT_WINDOW_LAYOUT, NULL);
2383 save_default_layout_options_to_file(default_path, options, lw);
2384 g_free(lw->options.id);
2385 lw->options.id = tmp_id;
2386 g_free(default_path);
2389 #if GTK_CHECK_VERSION(3,22,0)
2390 static gboolean popover_cb(gpointer data)
2392 GtkPopover *popover = data;
2394 gtk_popover_popdown(popover);
2399 static void default_layout_changed_cb(GtkWidget *button, GtkPopover *popover)
2401 gtk_popover_popup(popover);
2403 g_timeout_add(2000, popover_cb, popover);
2406 static GtkWidget *create_popover(GtkWidget *parent, GtkWidget *child, GtkPositionType pos)
2410 popover = gtk_popover_new(parent);
2411 gtk_popover_set_position(GTK_POPOVER (popover), pos);
2412 gtk_container_add (GTK_CONTAINER(popover), child);
2413 gtk_container_set_border_width(GTK_CONTAINER (popover), 6);
2414 gtk_widget_show (child);
2420 static void config_tab_windows(GtkWidget *notebook)
2425 GtkWidget *subgroup;
2427 GtkWidget *ct_button;
2430 vbox = scrolled_notebook_page(notebook, _("Windows"));
2432 group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
2434 ct_button = pref_checkbox_new_int(group, _("Remember session"),
2435 options->save_window_positions, &c_options->save_window_positions);
2437 button = pref_checkbox_new_int(group, _("Use saved window positions also for new windows"),
2438 options->use_saved_window_positions_for_new_windows, &c_options->use_saved_window_positions_for_new_windows);
2439 pref_checkbox_link_sensitivity(ct_button, button);
2441 button = pref_checkbox_new_int(group, _("Remember window workspace"),
2442 options->save_window_workspace, &c_options->save_window_workspace);
2443 pref_checkbox_link_sensitivity(ct_button, button);
2445 pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
2446 options->tools_restore_state, &c_options->tools_restore_state);
2448 pref_checkbox_new_int(group, _("Remember dialog window positions"),
2449 options->save_dialog_window_positions, &c_options->save_dialog_window_positions);
2451 pref_checkbox_new_int(group, _("Show window IDs"),
2452 options->show_window_ids, &c_options->show_window_ids);
2454 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2455 pref_label_new(subgroup, _("Use current layout for default: "));
2456 button = pref_button_new(subgroup, NULL, _("Set"), FALSE, G_CALLBACK(save_default_window_layout_cb), NULL);
2458 #if GTK_CHECK_VERSION(3,22,0)
2461 popover = create_popover(button, gtk_label_new(_("Current window layout\nhas been set as default")), GTK_POS_TOP);
2462 gtk_popover_set_modal(GTK_POPOVER (popover), FALSE);
2463 g_signal_connect(button, "clicked", G_CALLBACK(default_layout_changed_cb), popover);
2466 group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
2468 pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
2469 options->image.fit_window_to_image, &c_options->image.fit_window_to_image);
2471 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2472 ct_button = pref_checkbox_new_int(hbox, _("Limit size when auto-sizing window (%):"),
2473 options->image.limit_window_size, &c_options->image.limit_window_size);
2474 spin = pref_spin_new_int(hbox, NULL, NULL,
2476 options->image.max_window_size, &c_options->image.max_window_size);
2477 pref_checkbox_link_sensitivity(ct_button, spin);
2479 group = pref_group_new(vbox, FALSE, _("Full screen"), GTK_ORIENTATION_VERTICAL);
2481 c_options->fullscreen.screen = options->fullscreen.screen;
2482 c_options->fullscreen.above = options->fullscreen.above;
2483 hbox = fullscreen_prefs_selection_new(_("Location:"), &c_options->fullscreen.screen, &c_options->fullscreen.above);
2484 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2485 gtk_widget_show(hbox);
2487 pref_checkbox_new_int(group, _("Smooth image flip"),
2488 options->fullscreen.clean_flip, &c_options->fullscreen.clean_flip);
2489 pref_checkbox_new_int(group, _("Disable screen saver"),
2490 options->fullscreen.disable_saver, &c_options->fullscreen.disable_saver);
2493 #define PRE_FORMATTED_COLUMNS 5
2494 static void config_tab_osd(GtkWidget *notebook)
2500 GtkWidget *image_overlay_template_view;
2501 GtkWidget *scrolled;
2502 GtkWidget *scrolled_pre_formatted;
2503 GtkTextBuffer *buffer;
2505 GtkWidget *subgroup;
2507 vbox = scrolled_notebook_page(notebook, _("OSD"));
2509 image_overlay_template_view = gtk_text_view_new();
2511 group = pref_group_new(vbox, FALSE, _("Overlay Screen Display"), GTK_ORIENTATION_VERTICAL);
2513 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2515 scrolled_pre_formatted = osd_new(PRE_FORMATTED_COLUMNS, image_overlay_template_view);
2516 gtk_widget_set_size_request(scrolled_pre_formatted, 200, 150);
2517 gtk_box_pack_start(GTK_BOX(subgroup), scrolled_pre_formatted, FALSE, FALSE, 0);
2518 gtk_widget_show(scrolled_pre_formatted);
2519 gtk_widget_show(subgroup);
2521 pref_line(group, PREF_PAD_GAP);
2523 pref_label_new(group, _("Image overlay template"));
2525 scrolled = gtk_scrolled_window_new(NULL, NULL);
2526 gtk_widget_set_size_request(scrolled, 200, 150);
2527 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2528 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
2529 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2530 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 5);
2531 gtk_widget_show(scrolled);
2533 gtk_widget_set_tooltip_markup(image_overlay_template_view,
2534 _("Extensive formatting options are shown in the Help file"));
2536 gtk_container_add(GTK_CONTAINER(scrolled), image_overlay_template_view);
2537 gtk_widget_show(image_overlay_template_view);
2539 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2541 #if GTK_CHECK_VERSION(3,4,0)
2542 button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
2543 G_CALLBACK(image_overlay_set_font_cb), notebook);
2545 button = gtk_font_button_new();
2546 gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Image Overlay Font");
2547 gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->image_overlay.font);
2548 g_signal_connect(G_OBJECT(button), "font-set",
2549 G_CALLBACK(image_overlay_set_font_cb),NULL);
2551 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2552 gtk_widget_show(button);
2554 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Text"), FALSE,
2555 G_CALLBACK(image_overlay_set_text_colour_cb), NULL);
2556 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2557 gtk_widget_show(button);
2559 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Background"), FALSE,
2560 G_CALLBACK(image_overlay_set_background_colour_cb), NULL);
2561 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2562 gtk_widget_show(button);
2563 image_overlay_set_text_colours();
2565 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2566 G_CALLBACK(image_overlay_default_template_cb), image_overlay_template_view);
2567 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2568 gtk_widget_show(button);
2570 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
2571 G_CALLBACK(image_overlay_help_cb), NULL);
2572 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2573 gtk_widget_show(button);
2575 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_overlay_template_view));
2576 if (options->image_overlay.template_string) gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
2577 g_signal_connect(G_OBJECT(buffer), "changed",
2578 G_CALLBACK(image_overlay_template_view_changed_cb), image_overlay_template_view);
2580 pref_line(group, PREF_PAD_GAP);
2582 group = pref_group_new(vbox, FALSE, _("Exif, XMP or IPTC tags"), GTK_ORIENTATION_VERTICAL);
2583 hbox = gtk_hbox_new(FALSE, 0);
2584 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2585 gtk_widget_show(hbox);
2586 label = gtk_label_new(_("%Exif.Image.Orientation%"));
2587 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2588 gtk_widget_show(label);
2589 pref_spacer(group,TRUE);
2591 group = pref_group_new(vbox, FALSE, _("Field separators"), GTK_ORIENTATION_VERTICAL);
2592 hbox = gtk_hbox_new(FALSE, 0);
2593 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2594 gtk_widget_show(hbox);
2595 label = gtk_label_new(_("Separator shown only if both fields are non-null:\n%formatted.ShutterSpeed%|%formatted.ISOSpeedRating%"));
2596 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2597 gtk_widget_show(label);
2598 pref_spacer(group,TRUE);
2600 group = pref_group_new(vbox, FALSE, _("Field maximum length"), GTK_ORIENTATION_VERTICAL);
2601 hbox = gtk_hbox_new(FALSE, 0);
2602 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2603 gtk_widget_show(hbox);
2604 label = gtk_label_new(_("%path:39%"));
2605 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2606 gtk_widget_show(label);
2607 pref_spacer(group,TRUE);
2609 group = pref_group_new(vbox, FALSE, _("Pre- and post- text"), GTK_ORIENTATION_VERTICAL);
2610 hbox = gtk_hbox_new(FALSE, 0);
2611 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2612 gtk_widget_show(hbox);
2613 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%"));
2614 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2615 gtk_widget_show(label);
2616 pref_spacer(group,TRUE);
2618 group = pref_group_new(vbox, FALSE, _("Pango markup"), GTK_ORIENTATION_VERTICAL);
2619 hbox = gtk_hbox_new(FALSE, 0);
2620 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2621 gtk_widget_show(hbox);
2622 label = gtk_label_new(_("<b>bold</b>\n<u>underline</u>\n<i>italic</i>\n<s>strikethrough</s>"));
2623 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2624 gtk_widget_show(label);
2627 static GtkTreeModel *create_class_model(void)
2629 GtkListStore *model;
2633 /* create list store */
2634 model = gtk_list_store_new(1, G_TYPE_STRING);
2635 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
2637 gtk_list_store_append(model, &iter);
2638 gtk_list_store_set(model, &iter, 0, _(format_class_list[i]), -1);
2640 return GTK_TREE_MODEL (model);
2645 static gint filter_table_sort_cb(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer data)
2647 gint n = GPOINTER_TO_INT(data);
2649 FilterEntry *filter_a;
2650 FilterEntry *filter_b;
2652 gtk_tree_model_get(model, a, 0, &filter_a, -1);
2653 gtk_tree_model_get(model, b, 0, &filter_b, -1);
2657 case FILETYPES_COLUMN_DESCRIPTION:
2659 ret = g_utf8_collate(filter_a->description, filter_b->description);
2662 case FILETYPES_COLUMN_CLASS:
2664 ret = g_strcmp0(format_class_list[filter_a->file_class], format_class_list[filter_b->file_class]);
2667 case FILETYPES_COLUMN_WRITABLE:
2669 ret = filter_a->writable - filter_b->writable;
2672 case FILETYPES_COLUMN_SIDECAR:
2674 ret = filter_a->allow_sidecar - filter_b->allow_sidecar;
2678 g_return_val_if_reached(0);
2684 static gboolean search_function_cb(GtkTreeModel *model, gint column, const gchar *key, GtkTreeIter *iter, gpointer search_data)
2687 gboolean ret = TRUE;
2689 gtk_tree_model_get(model, iter, 0, &fe, -1);
2691 if (g_strstr_len(fe->extensions, -1, key))
2699 static void config_tab_files(GtkWidget *notebook)
2706 GtkWidget *ct_button;
2707 GtkWidget *scrolled;
2708 GtkWidget *filter_view;
2709 GtkCellRenderer *renderer;
2710 GtkTreeSelection *selection;
2711 GtkTreeViewColumn *column;
2713 vbox = scrolled_notebook_page(notebook, _("Files"));
2715 group = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2717 pref_checkbox_new_int(group, _("Show hidden files or folders"),
2718 options->file_filter.show_hidden_files, &c_options->file_filter.show_hidden_files);
2719 pref_checkbox_new_int(group, _("Show parent folder (..)"),
2720 options->file_filter.show_parent_directory, &c_options->file_filter.show_parent_directory);
2721 pref_checkbox_new_int(group, _("Case sensitive sort"),
2722 options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
2723 pref_checkbox_new_int(group, _("Natural sort order"),
2724 options->file_sort.natural, &c_options->file_sort.natural);
2725 pref_checkbox_new_int(group, _("Disable file extension checks"),
2726 options->file_filter.disable_file_extension_checks, &c_options->file_filter.disable_file_extension_checks);
2728 ct_button = pref_checkbox_new_int(group, _("Disable File Filtering"),
2729 options->file_filter.disable, &c_options->file_filter.disable);
2732 group = pref_group_new(vbox, FALSE, _("Grouping sidecar extensions"), GTK_ORIENTATION_VERTICAL);
2734 sidecar_ext_entry = gtk_entry_new();
2735 gtk_entry_set_text(GTK_ENTRY(sidecar_ext_entry), options->sidecar.ext);
2736 gtk_box_pack_start(GTK_BOX(group), sidecar_ext_entry, FALSE, FALSE, 0);
2737 gtk_widget_show(sidecar_ext_entry);
2739 group = pref_group_new(vbox, TRUE, _("File types"), GTK_ORIENTATION_VERTICAL);
2741 frame = pref_group_parent(group);
2742 g_signal_connect(G_OBJECT(ct_button), "toggled",
2743 G_CALLBACK(filter_disable_cb), frame);
2744 gtk_widget_set_sensitive(frame, !options->file_filter.disable);
2746 scrolled = gtk_scrolled_window_new(NULL, NULL);
2747 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2748 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2749 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2750 gtk_widget_show(scrolled);
2752 filter_store = gtk_list_store_new(1, G_TYPE_POINTER);
2753 filter_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(filter_store));
2754 g_object_unref(filter_store);
2755 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
2756 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
2758 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), FALSE);
2760 column = gtk_tree_view_column_new();
2761 gtk_tree_view_column_set_title(column, _("Filter"));
2762 gtk_tree_view_column_set_resizable(column, TRUE);
2764 renderer = gtk_cell_renderer_toggle_new();
2765 g_signal_connect(G_OBJECT(renderer), "toggled",
2766 G_CALLBACK(filter_store_enable_cb), filter_store);
2767 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2768 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2769 GINT_TO_POINTER(FE_ENABLE), NULL);
2771 renderer = gtk_cell_renderer_text_new();
2772 g_signal_connect(G_OBJECT(renderer), "edited",
2773 G_CALLBACK(filter_store_ext_edit_cb), filter_store);
2774 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2775 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2776 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2777 GINT_TO_POINTER(FE_EXTENSION), NULL);
2778 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2780 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), TRUE);
2781 gtk_tree_view_set_search_column(GTK_TREE_VIEW(filter_view), FILETYPES_COLUMN_FILTER);
2782 gtk_tree_view_set_search_equal_func(GTK_TREE_VIEW(filter_view), search_function_cb, NULL, NULL);
2784 column = gtk_tree_view_column_new();
2785 gtk_tree_view_column_set_title(column, _("Description"));
2786 gtk_tree_view_column_set_resizable(column, TRUE);
2787 gtk_tree_view_column_set_fixed_width(column, 200);
2788 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
2790 renderer = gtk_cell_renderer_text_new();
2791 g_signal_connect(G_OBJECT(renderer), "edited",
2792 G_CALLBACK(filter_store_desc_edit_cb), filter_store);
2793 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2794 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2795 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2796 GINT_TO_POINTER(FE_DESCRIPTION), NULL);
2797 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2798 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(filter_store), FILETYPES_COLUMN_DESCRIPTION, filter_table_sort_cb, GINT_TO_POINTER(FILETYPES_COLUMN_DESCRIPTION), NULL);
2799 gtk_tree_view_column_set_sort_column_id(column, FILETYPES_COLUMN_DESCRIPTION);
2801 column = gtk_tree_view_column_new();
2802 gtk_tree_view_column_set_title(column, _("Class"));
2803 gtk_tree_view_column_set_resizable(column, TRUE);
2804 renderer = gtk_cell_renderer_combo_new();
2805 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE,
2806 "model", create_class_model(),
2811 g_signal_connect(G_OBJECT(renderer), "edited",
2812 G_CALLBACK(filter_store_class_edit_cb), filter_store);
2813 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2814 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2815 GINT_TO_POINTER(FE_CLASS), NULL);
2816 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2817 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(filter_store), FILETYPES_COLUMN_CLASS, filter_table_sort_cb, GINT_TO_POINTER(FILETYPES_COLUMN_CLASS), NULL);
2818 gtk_tree_view_column_set_sort_column_id(column, FILETYPES_COLUMN_CLASS);
2820 column = gtk_tree_view_column_new();
2821 gtk_tree_view_column_set_title(column, _("Writable"));
2822 gtk_tree_view_column_set_resizable(column, FALSE);
2823 renderer = gtk_cell_renderer_toggle_new();
2824 g_signal_connect(G_OBJECT(renderer), "toggled",
2825 G_CALLBACK(filter_store_writable_cb), filter_store);
2826 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2827 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2828 GINT_TO_POINTER(FE_WRITABLE), NULL);
2829 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2830 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(filter_store), FILETYPES_COLUMN_WRITABLE, filter_table_sort_cb, GINT_TO_POINTER(FILETYPES_COLUMN_WRITABLE), NULL);
2831 gtk_tree_view_column_set_sort_column_id(column, FILETYPES_COLUMN_WRITABLE);
2833 column = gtk_tree_view_column_new();
2834 gtk_tree_view_column_set_title(column, _("Sidecar is allowed"));
2835 gtk_tree_view_column_set_resizable(column, FALSE);
2836 renderer = gtk_cell_renderer_toggle_new();
2837 g_signal_connect(G_OBJECT(renderer), "toggled",
2838 G_CALLBACK(filter_store_sidecar_cb), filter_store);
2839 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2840 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2841 GINT_TO_POINTER(FE_ALLOW_SIDECAR), NULL);
2842 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2843 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(filter_store), FILETYPES_COLUMN_SIDECAR, filter_table_sort_cb, GINT_TO_POINTER(FILETYPES_COLUMN_SIDECAR), NULL);
2844 gtk_tree_view_column_set_sort_column_id(column, FILETYPES_COLUMN_SIDECAR);
2846 filter_store_populate();
2847 gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
2848 gtk_widget_show(filter_view);
2850 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2852 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2853 G_CALLBACK(filter_default_cb), filter_view);
2854 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2855 gtk_widget_show(button);
2857 button = pref_button_new(NULL, GTK_STOCK_REMOVE, NULL, FALSE,
2858 G_CALLBACK(filter_remove_cb), filter_view);
2859 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2860 gtk_widget_show(button);
2862 button = pref_button_new(NULL, GTK_STOCK_ADD, NULL, FALSE,
2863 G_CALLBACK(filter_add_cb), filter_view);
2864 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2865 gtk_widget_show(button);
2869 static void config_tab_metadata(GtkWidget *notebook)
2874 GtkWidget *ct_button;
2878 vbox = scrolled_notebook_page(notebook, _("Metadata"));
2881 group = pref_group_new(vbox, FALSE, _("Metadata writing process"), GTK_ORIENTATION_VERTICAL);
2883 label = pref_label_new(group, _("Warning: Geeqie is built without Exiv2. Some options are disabled."));
2885 label = pref_label_new(group, _("Metadata are written in the following order. The process ends after first success."));
2886 #if GTK_CHECK_VERSION(3,16,0)
2887 gtk_label_set_xalign(GTK_LABEL(label), 0.0);
2888 gtk_label_set_yalign(GTK_LABEL(label), 0.5);
2890 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2893 ct_button = pref_checkbox_new_int(group, _("1) Save metadata in image files, or sidecar files, according to the XMP standard"),
2894 options->metadata.save_in_image_file, &c_options->metadata.save_in_image_file);
2896 gtk_widget_set_sensitive(ct_button, FALSE);
2899 pref_checkbox_new_int(group, _("2) Save metadata in '.metadata' folder, local to image folder (non-standard)"),
2900 options->metadata.enable_metadata_dirs, &c_options->metadata.enable_metadata_dirs);
2902 text = g_strdup_printf(_("3) Save metadata in Geeqie private directory '%s'"), get_metadata_cache_dir());
2903 label = pref_label_new(group, text);
2904 #if GTK_CHECK_VERSION(3,16,0)
2905 gtk_label_set_xalign(GTK_LABEL(label), 0.0);
2906 gtk_label_set_yalign(GTK_LABEL(label), 0.5);
2908 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2910 gtk_misc_set_padding(GTK_MISC(label), 22, 0);
2913 group = pref_group_new(vbox, FALSE, _("Step 1: Write to image files"), GTK_ORIENTATION_VERTICAL);
2915 gtk_widget_set_sensitive(group, FALSE);
2918 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2919 pref_checkbox_link_sensitivity(ct_button, hbox);
2921 pref_checkbox_new_int(hbox, _("Store metadata also in legacy IPTC tags (converted according to IPTC4XMP standard)"),
2922 options->metadata.save_legacy_IPTC, &c_options->metadata.save_legacy_IPTC);
2924 pref_checkbox_new_int(hbox, _("Warn if the image files are unwritable"),
2925 options->metadata.warn_on_write_problems, &c_options->metadata.warn_on_write_problems);
2927 pref_checkbox_new_int(hbox, _("Ask before writing to image files"),
2928 options->metadata.confirm_write, &c_options->metadata.confirm_write);
2930 pref_checkbox_new_int(hbox, _("Create sidecar files named image.ext.xmp (as opposed to image.xmp)"),
2931 options->metadata.sidecar_extended_name, &c_options->metadata.sidecar_extended_name);
2933 group = pref_group_new(vbox, FALSE, _("Step 2 and 3: write to Geeqie private files"), GTK_ORIENTATION_VERTICAL);
2935 gtk_widget_set_sensitive(group, FALSE);
2938 pref_checkbox_new_int(group, _("Use GQview legacy metadata format (supports only keywords and comments) instead of XMP"),
2939 options->metadata.save_legacy_format, &c_options->metadata.save_legacy_format);
2942 group = pref_group_new(vbox, FALSE, _("Miscellaneous"), GTK_ORIENTATION_VERTICAL);
2943 pref_checkbox_new_int(group, _("Write the same description tags (keywords, comment, etc.) to all grouped sidecars"),
2944 options->metadata.sync_grouped_files, &c_options->metadata.sync_grouped_files);
2946 pref_checkbox_new_int(group, _("Allow keywords to differ only in case"),
2947 options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
2949 ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"),
2950 options->metadata.write_orientation, &c_options->metadata.write_orientation);
2952 gtk_widget_set_sensitive(ct_button, FALSE);
2955 group = pref_group_new(vbox, FALSE, _("Auto-save options"), GTK_ORIENTATION_VERTICAL);
2957 ct_button = pref_checkbox_new_int(group, _("Write metadata after timeout"),
2958 options->metadata.confirm_after_timeout, &c_options->metadata.confirm_after_timeout);
2960 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2961 pref_checkbox_link_sensitivity(ct_button, hbox);
2963 pref_spin_new_int(hbox, _("Timeout (seconds):"), NULL, 0, 900, 1,
2964 options->metadata.confirm_timeout, &c_options->metadata.confirm_timeout);
2966 pref_checkbox_new_int(group, _("Write metadata on image change"),
2967 options->metadata.confirm_on_image_change, &c_options->metadata.confirm_on_image_change);
2969 pref_checkbox_new_int(group, _("Write metadata on directory change"),
2970 options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
2973 #if GTK_CHECK_VERSION(3,20,0)
2974 group = pref_group_new(vbox, FALSE, _("Spelling checks"), GTK_ORIENTATION_VERTICAL);
2976 ct_button = pref_checkbox_new_int(group, _("Check spelling -Requires restart"), options->metadata.check_spelling, &c_options->metadata.check_spelling);
2980 group = pref_group_new(vbox, FALSE, _("Pre-load metadata"), GTK_ORIENTATION_VERTICAL);
2982 ct_button = pref_checkbox_new_int(group, _("Read metadata in background"),
2983 options->read_metadata_in_idle, &c_options->read_metadata_in_idle);
2984 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");
2989 typedef struct _KeywordFindData KeywordFindData;
2990 struct _KeywordFindData
2997 GtkWidget *button_close;
2998 GtkWidget *button_stop;
2999 GtkWidget *button_start;
3000 GtkWidget *progress;
3008 guint idle_id; /* event source id */
3011 #define KEYWORD_DIALOG_WIDTH 400
3013 static void keywords_find_folder(KeywordFindData *kfd, FileData *dir_fd)
3015 GList *list_d = NULL;
3016 GList *list_f = NULL;
3020 filelist_read(dir_fd, &list_f, &list_d);
3024 filelist_read(dir_fd, &list_f, NULL);
3027 list_f = filelist_filter(list_f, FALSE);
3028 list_d = filelist_filter(list_d, TRUE);
3030 kfd->list = g_list_concat(list_f, kfd->list);
3031 kfd->list_dir = g_list_concat(list_d, kfd->list_dir);
3034 static void keywords_find_reset(KeywordFindData *kfd)
3036 filelist_free(kfd->list);
3039 filelist_free(kfd->list_dir);
3040 kfd->list_dir = NULL;
3043 static void keywords_find_close_cb(GenericDialog *fd, gpointer data)
3045 KeywordFindData *kfd = data;
3047 if (!gtk_widget_get_sensitive(kfd->button_close)) return;
3049 keywords_find_reset(kfd);
3050 generic_dialog_close(kfd->gd);
3054 static void keywords_find_finish(KeywordFindData *kfd)
3056 keywords_find_reset(kfd);
3058 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("done"));
3059 spinner_set_interval(kfd->spinner, -1);
3061 gtk_widget_set_sensitive(kfd->group, TRUE);
3062 gtk_widget_set_sensitive(kfd->button_start, TRUE);
3063 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
3064 gtk_widget_set_sensitive(kfd->button_close, TRUE);
3067 static void keywords_find_stop_cb(GenericDialog *fd, gpointer data)
3069 KeywordFindData *kfd = data;
3071 g_idle_remove_by_data(kfd);
3073 keywords_find_finish(kfd);
3076 static gboolean keywords_find_file(gpointer data)
3078 KeywordFindData *kfd = data;
3080 GtkTextBuffer *buffer;
3088 fd = kfd->list->data;
3089 kfd->list = g_list_remove(kfd->list, fd);
3091 keywords = metadata_read_list(fd, KEYWORD_KEY, METADATA_PLAIN);
3092 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3096 gtk_text_buffer_get_end_iter(buffer, &iter);
3097 tmp = g_strconcat(keywords->data, "\n", NULL);
3098 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
3100 keywords = keywords->next;
3103 gtk_entry_set_text(GTK_ENTRY(kfd->progress), fd->path);
3104 file_data_unref(fd);
3105 string_list_free(keywords);
3109 else if (kfd->list_dir)
3113 fd = kfd->list_dir->data;
3114 kfd->list_dir = g_list_remove(kfd->list_dir, fd);
3116 keywords_find_folder(kfd, fd);
3118 file_data_unref(fd);
3123 keywords_find_finish(kfd);
3128 static void keywords_find_start_cb(GenericDialog *fd, gpointer data)
3130 KeywordFindData *kfd = data;
3133 if (kfd->list || !gtk_widget_get_sensitive(kfd->button_start)) return;
3135 path = remove_trailing_slash((gtk_entry_get_text(GTK_ENTRY(kfd->entry))));
3136 parse_out_relatives(path);
3140 warning_dialog(_("Invalid folder"),
3141 _("The specified folder can not be found."),
3142 GTK_STOCK_DIALOG_WARNING, kfd->gd->dialog);
3148 gtk_widget_set_sensitive(kfd->group, FALSE);
3149 gtk_widget_set_sensitive(kfd->button_start, FALSE);
3150 gtk_widget_set_sensitive(kfd->button_stop, TRUE);
3151 gtk_widget_set_sensitive(kfd->button_close, FALSE);
3152 spinner_set_interval(kfd->spinner, SPINNER_SPEED);
3154 dir_fd = file_data_new_dir(path);
3155 keywords_find_folder(kfd, dir_fd);
3156 file_data_unref(dir_fd);
3157 kfd->idle_id = g_idle_add(keywords_find_file, kfd);
3163 static void keywords_find_dialog(GtkWidget *widget, const gchar *path)
3165 KeywordFindData *kfd;
3169 kfd = g_new0(KeywordFindData, 1);
3171 kfd->gd = generic_dialog_new(_("Search for keywords"),
3172 "search_for_keywords",
3175 gtk_window_set_default_size(GTK_WINDOW(kfd->gd->dialog), KEYWORD_DIALOG_WIDTH, -1);
3176 kfd->gd->cancel_cb = keywords_find_close_cb;
3177 kfd->button_close = generic_dialog_add_button(kfd->gd, GTK_STOCK_CLOSE, NULL,
3178 keywords_find_close_cb, FALSE);
3179 kfd->button_start = generic_dialog_add_button(kfd->gd, GTK_STOCK_OK, _("S_tart"),
3180 keywords_find_start_cb, FALSE);
3181 kfd->button_stop = generic_dialog_add_button(kfd->gd, GTK_STOCK_STOP, NULL,
3182 keywords_find_stop_cb, FALSE);
3183 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
3185 generic_dialog_add_message(kfd->gd, NULL, _("Search for keywords"), NULL, FALSE);
3187 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0);
3188 pref_spacer(hbox, PREF_PAD_INDENT);
3189 kfd->group = pref_box_new(hbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
3191 hbox = pref_box_new(kfd->group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3192 pref_label_new(hbox, _("Folder:"));
3194 label = tab_completion_new(&kfd->entry, path, NULL, NULL, NULL, NULL);
3195 tab_completion_add_select_button(kfd->entry,_("Select folder") , TRUE);
3196 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
3197 gtk_widget_show(label);
3199 pref_checkbox_new_int(kfd->group, _("Include subfolders"), FALSE, &kfd->recurse);
3201 pref_line(kfd->gd->vbox, PREF_PAD_SPACE);
3202 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3204 kfd->progress = gtk_entry_new();
3205 gtk_widget_set_can_focus(kfd->progress, FALSE);
3206 gtk_editable_set_editable(GTK_EDITABLE(kfd->progress), FALSE);
3207 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("click start to begin"));
3208 gtk_box_pack_start(GTK_BOX(hbox), kfd->progress, TRUE, TRUE, 0);
3209 gtk_widget_show(kfd->progress);
3211 kfd->spinner = spinner_new(NULL, -1);
3212 gtk_box_pack_start(GTK_BOX(hbox), kfd->spinner, FALSE, FALSE, 0);
3213 gtk_widget_show(kfd->spinner);
3217 gtk_widget_show(kfd->gd->dialog);
3220 static void keywords_find_cb(GtkWidget *widget, gpointer data)
3222 const gchar *path = layout_get_path(NULL);
3224 if (!path || !*path) path = homedir();
3225 keywords_find_dialog(widget, path);
3228 static void config_tab_keywords_save()
3230 GtkTextIter start, end;
3231 GtkTextBuffer *buffer;
3232 GList *kw_list = NULL;
3238 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3239 gtk_text_buffer_get_bounds(buffer, &start, &end);
3241 buffer_text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
3243 kw_split = strtok(buffer_text, "\n");
3244 while (kw_split != NULL)
3250 if (g_strcmp0(work->data, kw_split) == 0)
3259 kw_list = g_list_append(kw_list, g_strdup(kw_split));
3261 kw_split = strtok(NULL, "\n");
3264 keyword_list_set(kw_list);
3266 string_list_free(kw_list);
3267 g_free(buffer_text);
3270 static void config_tab_keywords(GtkWidget *notebook)
3276 GtkWidget *scrolled;
3278 GtkTextBuffer *buffer;
3281 GspellTextView *gspell_view;
3284 vbox = scrolled_notebook_page(notebook, _("Keywords"));
3286 group = pref_group_new(vbox, TRUE, _("Edit keywords autocompletion list"), GTK_ORIENTATION_VERTICAL);
3288 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3290 button = pref_button_new(hbox, GTK_STOCK_EXECUTE, _("Search"), FALSE,
3291 G_CALLBACK(keywords_find_cb), keyword_text);
3292 gtk_widget_set_tooltip_text(button, "Search for existing keywords");
3295 keyword_text = gtk_text_view_new();
3296 gtk_widget_set_size_request(keyword_text, 20, 20);
3297 scrolled = gtk_scrolled_window_new(NULL, NULL);
3298 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3299 gtk_widget_show(scrolled);
3302 #if GTK_CHECK_VERSION(3,20,0)
3303 if (options->metadata.check_spelling)
3305 gspell_view = gspell_text_view_get_from_gtk_text_view(GTK_TEXT_VIEW(keyword_text));
3306 gspell_text_view_basic_setup(gspell_view);
3311 gtk_container_add(GTK_CONTAINER(scrolled), keyword_text);
3312 gtk_widget_show(keyword_text);
3314 gtk_text_view_set_editable(GTK_TEXT_VIEW(keyword_text), TRUE);
3316 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3317 gtk_text_buffer_create_tag(buffer, "monospace",
3318 "family", "monospace", NULL);
3320 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(keyword_text), GTK_WRAP_WORD);
3321 gtk_text_buffer_get_start_iter(buffer, &iter);
3322 gtk_text_buffer_create_mark(buffer, "end", &iter, FALSE);
3325 path = g_build_filename(get_rc_dir(), "keywords", NULL);
3327 GList *kwl = keyword_list_get();
3328 kwl = g_list_first(kwl);
3331 gtk_text_buffer_get_end_iter (buffer, &iter);
3332 tmp = g_strconcat(kwl->data, "\n", NULL);
3333 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
3338 gtk_text_buffer_set_modified(buffer, FALSE);
3345 static void intent_menu_cb(GtkWidget *combo, gpointer data)
3347 gint *option = data;
3349 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
3353 *option = INTENT_PERCEPTUAL;
3356 *option = INTENT_RELATIVE_COLORIMETRIC;
3359 *option = INTENT_SATURATION;
3362 *option = INTENT_ABSOLUTE_COLORIMETRIC;
3367 static void add_intent_menu(GtkWidget *table, gint column, gint row, const gchar *text,
3368 gint option, gint *option_c)
3375 pref_table_label(table, column, row, text, 0.0);
3377 combo = gtk_combo_box_text_new();
3379 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Perceptual"));
3380 if (option == INTENT_PERCEPTUAL) current = 0;
3381 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Relative Colorimetric"));
3382 if (option == INTENT_RELATIVE_COLORIMETRIC) current = 1;
3383 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Saturation"));
3384 if (option == INTENT_SATURATION) current = 2;
3385 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Absolute Colorimetric"));
3386 if (option == INTENT_ABSOLUTE_COLORIMETRIC) current = 3;
3388 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
3390 gtk_widget_set_tooltip_text(combo,"Refer to the lcms documentation for the defaults used when the selected Intent is not available");
3392 g_signal_connect(G_OBJECT(combo), "changed",
3393 G_CALLBACK(intent_menu_cb), option_c);
3395 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
3396 gtk_widget_show(combo);
3400 static void config_tab_color(GtkWidget *notebook)
3409 vbox = scrolled_notebook_page(notebook, _("Color management"));
3411 group = pref_group_new(vbox, FALSE, _("Input profiles"), GTK_ORIENTATION_VERTICAL);
3413 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3416 table = pref_table_new(group, 3, COLOR_PROFILE_INPUTS + 1, FALSE, FALSE);
3417 gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
3419 label = pref_table_label(table, 0, 0, _("Type"), 0.0);
3420 pref_label_bold(label, TRUE, FALSE);
3422 label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
3423 pref_label_bold(label, TRUE, FALSE);
3425 label = pref_table_label(table, 2, 0, _("File"), 0.0);
3426 pref_label_bold(label, TRUE, FALSE);
3428 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
3433 buf = g_strdup_printf(_("Input %d:"), i + COLOR_PROFILE_FILE);
3434 pref_table_label(table, 0, i + 1, buf, 1.0);
3437 entry = gtk_entry_new();
3438 gtk_entry_set_max_length(GTK_ENTRY(entry), EDITOR_NAME_MAX_LENGTH);
3439 if (options->color_profile.input_name[i])
3441 gtk_entry_set_text(GTK_ENTRY(entry), options->color_profile.input_name[i]);
3443 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, i + 1, i + 2,
3444 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3445 gtk_widget_show(entry);
3446 color_profile_input_name_entry[i] = entry;
3448 tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, ".icc", "ICC Files", NULL);
3449 tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
3450 gtk_widget_set_size_request(entry, 160, -1);
3451 gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
3452 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3453 gtk_widget_show(tabcomp);
3454 color_profile_input_file_entry[i] = entry;
3457 group = pref_group_new(vbox, FALSE, _("Screen profile"), GTK_ORIENTATION_VERTICAL);
3459 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3461 pref_checkbox_new_int(group, _("Use system screen profile if available"),
3462 options->color_profile.use_x11_screen_profile, &c_options->color_profile.use_x11_screen_profile);
3464 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3466 pref_table_label(table, 0, 0, _("Screen:"), 1.0);
3467 tabcomp = tab_completion_new(&color_profile_screen_file_entry,
3468 options->color_profile.screen_file, NULL, ".icc", "ICC Files", NULL);
3469 tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
3470 gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
3472 add_intent_menu(table, 0, 1, _("Render Intent:"), options->color_profile.render_intent, &c_options->color_profile.render_intent);
3474 gtk_table_attach(GTK_TABLE(table), tabcomp, 1, 2,
3476 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3478 gtk_widget_show(tabcomp);
3481 /* advanced entry tab */
3482 static void use_geeqie_trash_cb(GtkWidget *widget, gpointer data)
3484 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3486 c_options->file_ops.use_system_trash = FALSE;
3487 c_options->file_ops.no_trash = FALSE;
3491 static void use_system_trash_cb(GtkWidget *widget, gpointer data)
3493 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3495 c_options->file_ops.use_system_trash = TRUE;
3496 c_options->file_ops.no_trash = FALSE;
3500 static void use_no_cache_cb(GtkWidget *widget, gpointer data)
3502 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3504 c_options->file_ops.no_trash = TRUE;
3508 static void config_tab_behavior(GtkWidget *notebook)
3515 GtkWidget *ct_button;
3519 GtkWidget *with_rename;
3520 GtkWidget *collections_on_top;
3521 GtkWidget *hide_window_in_fullscreen;
3522 GtkWidget *checkbox;
3525 vbox = scrolled_notebook_page(notebook, _("Behavior"));
3527 group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
3529 pref_checkbox_new_int(group, _("Confirm permanent file delete"),
3530 options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
3531 pref_checkbox_new_int(group, _("Confirm move file to Trash"),
3532 options->file_ops.confirm_move_to_trash, &c_options->file_ops.confirm_move_to_trash);
3533 pref_checkbox_new_int(group, _("Enable Delete key"),
3534 options->file_ops.enable_delete_key, &c_options->file_ops.enable_delete_key);
3536 ct_button = pref_radiobutton_new(group, NULL, _("Use Geeqie trash location"),
3537 !options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_geeqie_trash_cb),NULL);
3539 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3540 pref_checkbox_link_sensitivity(ct_button, hbox);
3542 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
3543 pref_label_new(hbox, _("Folder:"));
3545 tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL, NULL, NULL);
3546 tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
3547 gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
3548 gtk_widget_show(tabcomp);
3550 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3551 pref_checkbox_link_sensitivity(ct_button, hbox);
3553 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
3554 spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MiB"),
3555 0, 2048, 1, options->file_ops.safe_delete_folder_maxsize, &c_options->file_ops.safe_delete_folder_maxsize);
3556 gtk_widget_set_tooltip_markup(spin, _("Set to 0 for unlimited size"));
3557 button = pref_button_new(NULL, NULL, _("View"), FALSE,
3558 G_CALLBACK(safe_delete_view_cb), NULL);
3559 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3560 gtk_widget_show(button);
3562 button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
3563 G_CALLBACK(safe_delete_clear_cb), NULL);
3564 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3566 c_options->file_ops.no_trash = options->file_ops.no_trash;
3567 c_options->file_ops.use_system_trash = options->file_ops.use_system_trash;
3569 pref_radiobutton_new(group, ct_button, _("Use system Trash bin"),
3570 options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_system_trash_cb), NULL);
3572 pref_radiobutton_new(group, ct_button, _("Use no trash at all"),
3573 options->file_ops.no_trash, G_CALLBACK(use_no_cache_cb), NULL);
3575 gtk_widget_show(button);
3577 pref_spacer(group, PREF_PAD_GROUP);
3580 group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
3582 pref_checkbox_new_int(group, _("Descend folders in tree view"),
3583 options->tree_descend_subdirs, &c_options->tree_descend_subdirs);
3585 pref_checkbox_new_int(group, _("In place renaming"),
3586 options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
3588 pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
3589 options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
3591 tmp = pref_checkbox_new_int(group, _("Circular selection lists"),
3592 options->circular_selection_lists, &c_options->circular_selection_lists);
3593 gtk_widget_set_tooltip_text(tmp, _("Traverse selection lists in a circular manner"));
3595 marks = pref_checkbox_new_int(group, _("Save marks on exit"),
3596 options->marks_save, &c_options->marks_save);
3597 gtk_widget_set_tooltip_text(marks,"Note that marks linked to a keyword will be saved irrespective of this setting");
3599 with_rename = pref_checkbox_new_int(group, _("Use \"With Rename\" as default for Copy/Move dialogs"),
3600 options->with_rename, &c_options->with_rename);
3601 gtk_widget_set_tooltip_text(with_rename,"Change the default button for Copy/Move dialogs");
3603 collections_on_top = pref_checkbox_new_int(group, _("Open collections on top"),
3604 options->collections_on_top, &c_options->collections_on_top);
3605 gtk_widget_set_tooltip_text(collections_on_top,"Open collections window on top");
3607 hide_window_in_fullscreen = pref_checkbox_new_int(group, _("Hide window in fullscreen"),
3608 options->hide_window_in_fullscreen, &c_options->hide_window_in_fullscreen);
3609 gtk_widget_set_tooltip_text(hide_window_in_fullscreen,"When alt-tabbing, prevent Geeqie window showing twice");
3611 pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
3612 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
3614 tmp = pref_spin_new_int(group, _("Recent folder-image list maximum size"), NULL, 0, 50, 1, options->recent_folder_image_list_maxsize, &c_options->recent_folder_image_list_maxsize);
3615 gtk_widget_set_tooltip_text(tmp, _("List of the last image viewed in each recent folder.\nRe-opening a folder will set focus to the last image viewed."));
3617 pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
3618 16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
3620 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3621 add_dnd_default_action_selection_menu(table, 0, 0, _("Drag`n drop default action:"), options->dnd_default_action, &c_options->dnd_default_action);
3623 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3624 add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
3626 pref_spacer(group, PREF_PAD_GROUP);
3628 group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
3630 pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
3631 options->progressive_key_scrolling, &c_options->progressive_key_scrolling);
3632 pref_spin_new_int(group, _("Keyboard scrolling step multiplier:"), NULL,
3633 1, 32, 1, options->keyboard_scroll_step, (int *)&c_options->keyboard_scroll_step);
3634 pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
3635 options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
3636 pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
3637 options->image_lm_click_nav, &c_options->image_lm_click_nav);
3638 pref_checkbox_new_int(group, _("Open archive by left click on image"),
3639 options->image_l_click_archive, &c_options->image_l_click_archive);
3640 pref_checkbox_new_int(group, _("Play video by left click on image"),
3641 options->image_l_click_video, &c_options->image_l_click_video);
3642 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3643 add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
3645 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3646 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3647 add_mouse_selection_menu(table, 0, 0, _("Mouse button Back:"), options->mouse_button_8, &c_options->mouse_button_8);
3648 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3649 add_mouse_selection_menu(table, 0, 0, _("Mouse button Forward:"), options->mouse_button_9, &c_options->mouse_button_9);
3651 pref_spacer(group, PREF_PAD_GROUP);
3653 group = pref_group_new(vbox, FALSE, _("GPU"), GTK_ORIENTATION_VERTICAL);
3655 checkbox = pref_checkbox_new_int(group, _("Override disable GPU"),
3656 options->override_disable_gpu, &c_options->override_disable_gpu);
3657 gtk_widget_set_tooltip_text(checkbox, "Contact the developers for usage");
3660 pref_spacer(group, PREF_PAD_GROUP);
3662 group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
3664 pref_spin_new_int(group, _("Debug level:"), NULL,
3665 DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
3667 pref_checkbox_new_int(group, _("Timer data"),
3668 options->log_window.timer_data, &c_options->log_window.timer_data);
3670 pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
3671 1, 99999, 1, options->log_window_lines, &options->log_window_lines);
3675 /* accelerators tab */
3676 static void config_tab_accelerators(GtkWidget *notebook)
3682 GtkWidget *scrolled;
3683 GtkWidget *accel_view;
3684 GtkCellRenderer *renderer;
3685 GtkTreeSelection *selection;
3686 GtkTreeViewColumn *column;
3688 vbox = scrolled_notebook_page(notebook, _("Keyboard"));
3690 group = pref_group_new(vbox, TRUE, _("Accelerators"), GTK_ORIENTATION_VERTICAL);
3692 scrolled = gtk_scrolled_window_new(NULL, NULL);
3693 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
3694 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
3695 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3696 gtk_widget_show(scrolled);
3698 accel_store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
3700 accel_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(accel_store));
3701 g_object_unref(accel_store);
3702 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(accel_view));
3703 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
3705 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(accel_view), FALSE);
3707 renderer = gtk_cell_renderer_text_new();
3709 column = gtk_tree_view_column_new_with_attributes(_("Action"),
3714 gtk_tree_view_column_set_sort_column_id(column, AE_ACTION);
3715 gtk_tree_view_column_set_resizable(column, TRUE);
3716 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3719 renderer = gtk_cell_renderer_accel_new();
3720 g_signal_connect(G_OBJECT(renderer), "accel-cleared",
3721 G_CALLBACK(accel_store_cleared_cb), accel_store);
3722 g_signal_connect(G_OBJECT(renderer), "accel-edited",
3723 G_CALLBACK(accel_store_edited_cb), accel_store);
3726 g_object_set (renderer,
3728 "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
3731 column = gtk_tree_view_column_new_with_attributes(_("KEY"),
3736 gtk_tree_view_column_set_sort_column_id(column, AE_KEY);
3737 gtk_tree_view_column_set_resizable(column, TRUE);
3738 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3740 renderer = gtk_cell_renderer_text_new();
3742 column = gtk_tree_view_column_new_with_attributes(_("Tooltip"),
3747 gtk_tree_view_column_set_sort_column_id(column, AE_TOOLTIP);
3748 gtk_tree_view_column_set_resizable(column, TRUE);
3749 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3751 renderer = gtk_cell_renderer_text_new();
3753 column = gtk_tree_view_column_new_with_attributes("Accel",
3758 gtk_tree_view_column_set_sort_column_id(column, AE_ACCEL);
3759 gtk_tree_view_column_set_resizable(column, TRUE);
3760 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3762 accel_store_populate();
3763 gtk_container_add(GTK_CONTAINER(scrolled), accel_view);
3764 gtk_widget_show(accel_view);
3766 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3768 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
3769 G_CALLBACK(accel_default_cb), accel_view);
3770 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3771 gtk_widget_show(button);
3773 button = pref_button_new(NULL, NULL, _("Reset selected"), FALSE,
3774 G_CALLBACK(accel_reset_cb), accel_view);
3775 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3776 gtk_widget_show(button);
3779 /* toolbar main tab */
3780 static void config_tab_toolbar_main(GtkWidget *notebook)
3783 GtkWidget *toolbardata;
3786 lw = layout_window_list->data;
3788 vbox = scrolled_notebook_page(notebook, _("Toolbar Main"));
3790 toolbardata = toolbar_select_new(lw, TOOLBAR_MAIN);
3791 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3792 gtk_widget_show(vbox);
3795 /* toolbar status tab */
3796 static void config_tab_toolbar_status(GtkWidget *notebook)
3799 GtkWidget *toolbardata;
3802 lw = layout_window_list->data;
3804 vbox = scrolled_notebook_page(notebook, _("Toolbar Status"));
3806 toolbardata = toolbar_select_new(lw, TOOLBAR_STATUS);
3807 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3808 gtk_widget_show(vbox);
3812 static gint extension_sort_cb(gconstpointer a, gconstpointer b)
3814 return g_strcmp0((gchar *)a, (gchar *)b);
3817 static void config_tab_advanced(GtkWidget *notebook)
3821 GSList *formats_list;
3822 GList *extensions_list = NULL;
3825 GdkPixbufFormat *fm;
3827 GString *types_string = g_string_new(NULL);
3828 GtkWidget *types_string_label;
3829 GtkWidget *threads_string_label;
3830 GtkWidget *dupes_threads_spin;
3832 vbox = scrolled_notebook_page(notebook, _("Advanced"));
3833 group = pref_group_new(vbox, FALSE, _("External preview extraction"), GTK_ORIENTATION_VERTICAL);
3835 pref_checkbox_new_int(group, _("Use external preview extraction - Requires restart"), options->external_preview.enable, &c_options->external_preview.enable);
3837 pref_spacer(group, PREF_PAD_GROUP);
3839 formats_list = gdk_pixbuf_get_formats();
3841 while (formats_list)
3843 fm = formats_list->data;
3844 extensions = gdk_pixbuf_format_get_extensions(fm);
3847 while (extensions[i])
3849 extensions_list = g_list_insert_sorted(extensions_list, g_strdup(extensions[i]), extension_sort_cb);
3853 g_strfreev(extensions);
3854 formats_list = formats_list->next;
3857 while (extensions_list)
3859 if (types_string->len == 0)
3861 types_string = g_string_append(types_string, extensions_list->data);
3865 types_string = g_string_append(types_string, ", ");
3866 types_string = g_string_append(types_string, extensions_list->data);
3869 extensions_list = extensions_list->next;
3872 types_string = g_string_prepend(types_string, _("Usable file types:\n"));
3873 types_string_label = pref_label_new(group, types_string->str);
3874 gtk_label_set_line_wrap(GTK_LABEL(types_string_label), TRUE);
3876 pref_spacer(group, PREF_PAD_GROUP);
3878 group = pref_group_new(vbox, FALSE, _("File identification tool"), GTK_ORIENTATION_VERTICAL);
3879 external_preview_select_entry = gtk_entry_new();
3880 tabcomp = tab_completion_new(&external_preview_select_entry, options->external_preview.select, NULL, NULL, NULL, NULL);
3881 tab_completion_add_select_button(external_preview_select_entry, _("Select file identification tool"), FALSE);
3882 gtk_box_pack_start(GTK_BOX(group), tabcomp, TRUE, TRUE, 0);
3883 gtk_widget_show(tabcomp);
3885 group = pref_group_new(vbox, FALSE, _("Preview extraction tool"), GTK_ORIENTATION_VERTICAL);
3886 external_preview_extract_entry = gtk_entry_new();
3887 tabcomp = tab_completion_new(&external_preview_extract_entry, options->external_preview.extract, NULL, NULL, NULL, NULL);
3888 tab_completion_add_select_button(external_preview_extract_entry, _("Select preview extraction tool"), FALSE);
3889 gtk_box_pack_start(GTK_BOX(group), tabcomp, TRUE, TRUE, 0);
3890 gtk_widget_show(tabcomp);
3892 gtk_widget_show(vbox);
3894 g_slist_free(formats_list);
3895 string_list_free(extensions_list);
3896 g_string_free(types_string, TRUE);
3898 pref_spacer(group, PREF_PAD_GROUP);
3900 pref_line(vbox, PREF_PAD_SPACE);
3901 group = pref_group_new(vbox, FALSE, _("Thread pool limits"), GTK_ORIENTATION_VERTICAL);
3903 threads_string_label = pref_label_new(group, "This option limits the number of threads (or cpu cores)\nthat Geeqie will use when running duplicate checks. The default value is 0, which means all available cores will be used.");
3904 gtk_label_set_line_wrap(GTK_LABEL(threads_string_label), TRUE);
3906 pref_spacer(vbox, PREF_PAD_GROUP);
3908 dupes_threads_spin = pref_spin_new_int(vbox, _("Duplicate check:"), _("max. threads"), 0, get_cpu_cores(), 1, options->threads.duplicates, &c_options->threads.duplicates);
3909 gtk_widget_set_tooltip_markup(dupes_threads_spin, _("Set to 0 for unlimited"));
3913 static void config_tab_stereo(GtkWidget *notebook)
3921 GtkWidget *fs_button;
3922 vbox = scrolled_notebook_page(notebook, _("Stereo"));
3924 group = pref_group_new(vbox, FALSE, _("Windowed stereo mode"), GTK_ORIENTATION_VERTICAL);
3926 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3927 add_stereo_mode_menu(table, 0, 0, _("Windowed stereo mode"), options->stereo.mode, &c_options->stereo.mode, FALSE);
3929 table = pref_table_new(group, 2, 2, TRUE, FALSE);
3930 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3931 pref_checkbox_new_int(box, _("Mirror left image"),
3932 options->stereo.mode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.mirror_left);
3933 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3934 pref_checkbox_new_int(box, _("Flip left image"),
3935 options->stereo.mode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.flip_left);
3936 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3937 pref_checkbox_new_int(box, _("Mirror right image"),
3938 options->stereo.mode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.mirror_right);
3939 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3940 pref_checkbox_new_int(box, _("Flip right image"),
3941 options->stereo.mode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.flip_right);
3942 pref_checkbox_new_int(group, _("Swap left and right images"),
3943 options->stereo.mode & PR_STEREO_SWAP, &c_options->stereo.tmp.swap);
3944 pref_checkbox_new_int(group, _("Disable stereo mode on single image source"),
3945 options->stereo.mode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.temp_disable);
3947 group = pref_group_new(vbox, FALSE, _("Fullscreen stereo mode"), GTK_ORIENTATION_VERTICAL);
3948 fs_button = pref_checkbox_new_int(group, _("Use different settings for fullscreen"),
3949 options->stereo.enable_fsmode, &c_options->stereo.enable_fsmode);
3950 box2 = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
3951 pref_checkbox_link_sensitivity(fs_button, box2);
3952 table = pref_table_new(box2, 2, 1, FALSE, FALSE);
3953 add_stereo_mode_menu(table, 0, 0, _("Fullscreen stereo mode"), options->stereo.fsmode, &c_options->stereo.fsmode, TRUE);
3954 table = pref_table_new(box2, 2, 2, TRUE, FALSE);
3955 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3956 pref_checkbox_new_int(box, _("Mirror left image"),
3957 options->stereo.fsmode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.fs_mirror_left);
3958 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3959 pref_checkbox_new_int(box, _("Flip left image"),
3960 options->stereo.fsmode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.fs_flip_left);
3961 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3962 pref_checkbox_new_int(box, _("Mirror right image"),
3963 options->stereo.fsmode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.fs_mirror_right);
3964 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3965 pref_checkbox_new_int(box, _("Flip right image"),
3966 options->stereo.fsmode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.fs_flip_right);
3967 pref_checkbox_new_int(box2, _("Swap left and right images"),
3968 options->stereo.fsmode & PR_STEREO_SWAP, &c_options->stereo.tmp.fs_swap);
3969 pref_checkbox_new_int(box2, _("Disable stereo mode on single image source"),
3970 options->stereo.fsmode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.fs_temp_disable);
3972 group2 = pref_group_new(box2, FALSE, _("Fixed position"), GTK_ORIENTATION_VERTICAL);
3973 table = pref_table_new(group2, 5, 3, FALSE, FALSE);
3974 pref_table_spin_new_int(table, 0, 0, _("Width"), NULL,
3975 1, 5000, 1, options->stereo.fixed_w, &c_options->stereo.fixed_w);
3976 pref_table_spin_new_int(table, 3, 0, _("Height"), NULL,
3977 1, 5000, 1, options->stereo.fixed_h, &c_options->stereo.fixed_h);
3978 pref_table_spin_new_int(table, 0, 1, _("Left X"), NULL,
3979 0, 5000, 1, options->stereo.fixed_x1, &c_options->stereo.fixed_x1);
3980 pref_table_spin_new_int(table, 3, 1, _("Left Y"), NULL,
3981 0, 5000, 1, options->stereo.fixed_y1, &c_options->stereo.fixed_y1);
3982 pref_table_spin_new_int(table, 0, 2, _("Right X"), NULL,
3983 0, 5000, 1, options->stereo.fixed_x2, &c_options->stereo.fixed_x2);
3984 pref_table_spin_new_int(table, 3, 2, _("Right Y"), NULL,
3985 0, 5000, 1, options->stereo.fixed_y2, &c_options->stereo.fixed_y2);
3989 /* Main preferences window */
3990 static void config_window_create(LayoutWindow *lw)
3992 GtkWidget *win_vbox;
3994 GtkWidget *notebook;
3996 GtkWidget *ct_button;
3998 if (!c_options) c_options = init_options(NULL);
4000 configwindow = window_new(GTK_WINDOW_TOPLEVEL, "preferences", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Preferences"));
4001 DEBUG_NAME(configwindow);
4002 gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
4003 g_signal_connect(G_OBJECT(configwindow), "delete_event",
4004 G_CALLBACK(config_window_delete), NULL);
4005 if (options->save_dialog_window_positions)
4007 gtk_window_resize(GTK_WINDOW(configwindow), lw->options.preferences_window.w, lw->options.preferences_window.h);
4008 gtk_window_move(GTK_WINDOW(configwindow), lw->options.preferences_window.x, lw->options.preferences_window.y);
4012 gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
4014 gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
4015 gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
4017 win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
4018 gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
4019 gtk_widget_show(win_vbox);
4021 notebook = gtk_notebook_new();
4022 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_LEFT);
4023 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE);
4024 gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
4026 config_tab_general(notebook);
4027 config_tab_image(notebook);
4028 config_tab_osd(notebook);
4029 config_tab_windows(notebook);
4030 config_tab_accelerators(notebook);
4031 config_tab_files(notebook);
4032 config_tab_metadata(notebook);
4033 config_tab_keywords(notebook);
4034 config_tab_color(notebook);
4035 config_tab_stereo(notebook);
4036 config_tab_behavior(notebook);
4037 config_tab_toolbar_main(notebook);
4038 config_tab_toolbar_status(notebook);
4039 config_tab_advanced(notebook);
4041 gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), lw->options.preferences_window.page_number);
4043 hbox = gtk_hbutton_box_new();
4044 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
4045 gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
4046 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
4047 gtk_widget_show(hbox);
4049 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
4050 G_CALLBACK(config_window_help_cb), notebook);
4051 gtk_container_add(GTK_CONTAINER(hbox), button);
4052 gtk_widget_set_can_default(button, TRUE);
4053 gtk_widget_show(button);
4055 button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
4056 G_CALLBACK(config_window_ok_cb), notebook);
4057 gtk_container_add(GTK_CONTAINER(hbox), button);
4058 gtk_widget_set_can_default(button, TRUE);
4059 gtk_widget_grab_default(button);
4060 gtk_widget_show(button);
4064 button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
4065 G_CALLBACK(config_window_close_cb), NULL);
4066 gtk_container_add(GTK_CONTAINER(hbox), button);
4067 gtk_widget_set_can_default(button, TRUE);
4068 gtk_widget_show(button);
4070 if (!generic_dialog_get_alternative_button_order(configwindow))
4072 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
4075 gtk_widget_show(notebook);
4077 gtk_widget_show(configwindow);
4081 *-----------------------------------------------------------------------------
4082 * config window show (public)
4083 *-----------------------------------------------------------------------------
4086 void show_config_window(LayoutWindow *lw)
4090 gtk_window_present(GTK_WINDOW(configwindow));
4094 config_window_create(lw);
4103 void show_about_window(LayoutWindow *lw)
4105 GdkPixbuf *pixbuf_logo;
4106 GdkPixbuf *pixbuf_icon;
4107 gchar *authors[1000];
4112 gchar *timezone_path;
4115 #define LINE_LENGTH 1000
4116 gchar line[LINE_LENGTH];
4118 copyright = g_string_new(NULL);
4119 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");
4121 timezone_path = g_build_filename(get_rc_dir(), TIMEZONE_DATABASE_FILE, NULL);
4122 if (g_file_test(timezone_path, G_FILE_TEST_EXISTS))
4124 cd = ZDOpenDatabase(timezone_path);
4127 copyright = g_string_append(copyright, ZDGetNotice(cd));
4131 log_printf("Error: Init of timezone database %s failed\n", timezone_path);
4133 ZDCloseDatabase(cd);
4135 g_free(timezone_path);
4138 path = g_build_filename(gq_helpdir, "AUTHORS", NULL);
4139 fp = fopen(path, "r");
4142 while(fgets(line, LINE_LENGTH, fp))
4144 /* get rid of ending \n from fgets */
4145 line[strlen(line) - 1] = '\0';
4146 authors[i_authors] = g_strdup(line);
4149 authors[i_authors] = NULL;
4154 comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
4155 "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
4157 pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
4158 pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
4159 gtk_show_about_dialog(GTK_WINDOW(lw->window),
4160 "title", _("About Geeqie"),
4162 "program-name", GQ_APPNAME,
4164 "logo", pixbuf_logo,
4165 "icon", pixbuf_icon,
4166 "website", GQ_WEBSITE,
4167 "website-label", "Website",
4168 "comments", comment,
4170 "translator-credits", _("translator-credits"),
4171 "wrap-license", TRUE,
4172 "license", copyright->str,
4175 g_string_free(copyright, TRUE);
4178 while(n < i_authors)
4188 static void image_overlay_set_text_colours()
4190 c_options->image_overlay.text_red = options->image_overlay.text_red;
4191 c_options->image_overlay.text_green = options->image_overlay.text_green;
4192 c_options->image_overlay.text_blue = options->image_overlay.text_blue;
4193 c_options->image_overlay.text_alpha = options->image_overlay.text_alpha;
4194 c_options->image_overlay.background_red = options->image_overlay.background_red;
4195 c_options->image_overlay.background_green = options->image_overlay.background_green;
4196 c_options->image_overlay.background_blue = options->image_overlay.background_blue;
4197 c_options->image_overlay.background_alpha = options->image_overlay.background_alpha;
4201 *-----------------------------------------------------------------------------
4202 * timezone database routines
4203 *-----------------------------------------------------------------------------
4206 static void timezone_async_ready_cb(GObject *source_object, GAsyncResult *res, gpointer data)
4208 GError *error = NULL;
4210 gchar *tmp_filename;
4211 gchar *timezone_bin;
4212 gchar *tmp_dir = NULL;
4215 if (!g_cancellable_is_cancelled(tz->cancellable))
4217 generic_dialog_close(tz->gd);
4221 if (g_file_copy_finish(G_FILE(source_object), res, &error))
4223 tmp_filename = g_file_get_path(tz->tmp_g_file);
4224 fd = file_data_new_simple(tmp_filename);
4225 tmp_dir = open_archive(fd);
4229 timezone_bin = g_build_filename(tmp_dir, TIMEZONE_DATABASE_VERSION, TIMEZONE_DATABASE_FILE, NULL);
4230 if (isfile(timezone_bin))
4232 move_file(timezone_bin, tz->timezone_database_user);
4236 warning_dialog(_("Warning: Cannot open timezone database file"), _("See the Log Window"), GTK_STOCK_DIALOG_WARNING, NULL);
4239 g_free(timezone_bin);
4240 g_free(tmp_dir); // The folder in /tmp is deleted in exit_program_final()
4244 warning_dialog(_("Warning: Cannot open timezone database file"), _("See the Log Window"), GTK_STOCK_DIALOG_WARNING, NULL);
4246 g_free(tmp_filename);
4247 file_data_unref(fd);
4251 file_util_warning_dialog(_("Error: Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
4254 g_file_delete(tz->tmp_g_file, NULL, &error);
4255 g_object_unref(tz->tmp_g_file);
4256 tz->tmp_g_file = NULL;
4257 g_object_unref(tz->cancellable);
4258 g_object_unref(tz->timezone_database_gq);
4261 static void timezone_progress_cb(goffset current_num_bytes, goffset total_num_bytes, gpointer data)
4265 if (!g_cancellable_is_cancelled(tz->cancellable))
4267 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(tz->progress), (gdouble)current_num_bytes / total_num_bytes);
4271 static void timezone_cancel_button_cb(GenericDialog *gd, gpointer data)
4275 g_cancellable_cancel(tz->cancellable);
4278 static void timezone_database_install_cb(GtkWidget *widget, gpointer data)
4281 GError *error = NULL;
4282 GFileIOStream *io_stream;
4289 tz->tmp_g_file = g_file_new_tmp("geeqie_timezone_XXXXXX", &io_stream, &error);
4293 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
4294 log_printf("Error: Download timezone database failed:\n%s", error->message);
4295 g_error_free(error);
4296 g_object_unref(tz->tmp_g_file);
4300 tz->timezone_database_gq = g_file_new_for_uri(TIMEZONE_DATABASE_WEB);
4302 tz->gd = generic_dialog_new(_("Timezone database"), "download_timezone_database", NULL, TRUE, timezone_cancel_button_cb, tz);
4304 generic_dialog_add_message(tz->gd, GTK_STOCK_DIALOG_INFO, _("Downloading timezone database"), NULL, FALSE);
4306 tz->progress = gtk_progress_bar_new();
4307 gtk_box_pack_start(GTK_BOX(tz->gd->vbox), tz->progress, FALSE, FALSE, 0);
4308 gtk_widget_show(tz->progress);
4310 gtk_widget_show(tz->gd->dialog);
4311 tz->cancellable = g_cancellable_new();
4312 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);
4314 gtk_button_set_label(GTK_BUTTON(widget), _("Update"));
4317 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */