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"
25 #include "bar-keywords.h"
29 #include "filefilter.h"
30 #include "fullscreen.h"
32 #include "image-overlay.h"
33 #include "color-man.h"
35 #include "layout-util.h"
39 #include "pixbuf-util.h"
41 #include "slideshow.h"
45 #include "ui-fileops.h"
47 #include "ui-spinner.h"
48 #include "ui-tabcomp.h"
50 #include "zonedetect.h"
61 #include <gspell/gspell.h>
64 #define EDITOR_NAME_MAX_LENGTH 32
65 #define EDITOR_COMMAND_MAX_LENGTH 1024
67 static void image_overlay_set_text_colours();
69 GtkWidget *keyword_text;
70 static void config_tab_keywords_save();
72 typedef struct _ThumbSize ThumbSize;
79 static ThumbSize thumb_size_list[] =
114 FILETYPES_COLUMN_ENABLED = 0,
115 FILETYPES_COLUMN_FILTER,
116 FILETYPES_COLUMN_DESCRIPTION,
117 FILETYPES_COLUMN_CLASS,
118 FILETYPES_COLUMN_WRITABLE,
119 FILETYPES_COLUMN_SIDECAR,
120 FILETYPES_COLUMN_COUNT
123 gchar *format_class_list[] = {
134 /* config memory values */
135 static ConfOptions *c_options = NULL;
142 static GtkWidget *configwindow = NULL;
143 static GtkListStore *filter_store = NULL;
144 static GtkTreeStore *accel_store = NULL;
146 static GtkWidget *safe_delete_path_entry;
148 static GtkWidget *color_profile_input_file_entry[COLOR_PROFILE_INPUTS];
149 static GtkWidget *color_profile_input_name_entry[COLOR_PROFILE_INPUTS];
150 static GtkWidget *color_profile_screen_file_entry;
151 static GtkWidget *external_preview_select_entry;
152 static GtkWidget *external_preview_extract_entry;
154 static GtkWidget *sidecar_ext_entry;
155 static GtkWidget *help_search_engine_entry;
158 #define CONFIG_WINDOW_DEF_WIDTH 700
159 #define CONFIG_WINDOW_DEF_HEIGHT 600
162 *-----------------------------------------------------------------------------
163 * option widget callbacks (private)
164 *-----------------------------------------------------------------------------
167 static void zoom_increment_cb(GtkWidget *spin, gpointer UNUSED(data))
169 c_options->image.zoom_increment = (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) * 100.0 + 0.01);
172 static void slideshow_delay_hours_cb(GtkWidget *spin, gpointer UNUSED(data))
174 gint mins_secs_tenths, delay;
176 mins_secs_tenths = c_options->slideshow.delay %
177 (3600 * SLIDESHOW_SUBSECOND_PRECISION);
179 delay = (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
180 (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
183 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
184 SLIDESHOW_SUBSECOND_PRECISION;
187 static void slideshow_delay_minutes_cb(GtkWidget *spin, gpointer UNUSED(data))
189 gint hours, secs_tenths, delay;
191 hours = c_options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
192 secs_tenths = c_options->slideshow.delay % (60 * SLIDESHOW_SUBSECOND_PRECISION);
194 delay = hours * (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
195 (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
196 (60 * SLIDESHOW_SUBSECOND_PRECISION) + secs_tenths);
198 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
199 SLIDESHOW_SUBSECOND_PRECISION;
202 static void slideshow_delay_seconds_cb(GtkWidget *spin, gpointer UNUSED(data))
204 gint hours_mins, delay;
206 hours_mins = c_options->slideshow.delay / (60 * SLIDESHOW_SUBSECOND_PRECISION);
208 delay = (hours_mins * (60 * SLIDESHOW_SUBSECOND_PRECISION)) +
209 (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
210 (gdouble)(SLIDESHOW_SUBSECOND_PRECISION) + 0.01);
212 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
213 SLIDESHOW_SUBSECOND_PRECISION;
217 *-----------------------------------------------------------------------------
218 * sync program to config window routine (private)
219 *-----------------------------------------------------------------------------
222 void config_entry_to_option(GtkWidget *entry, gchar **option, gchar *(*func)(const gchar *))
228 buf = gtk_entry_get_text(GTK_ENTRY(entry));
229 if (buf && strlen(buf) > 0)
234 *option = g_strdup(buf);
239 static gboolean accel_apply_cb(GtkTreeModel *model, GtkTreePath *UNUSED(path), GtkTreeIter *iter, gpointer UNUSED(data))
241 gchar *accel_path, *accel;
243 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, AE_KEY, &accel, -1);
245 if (accel_path && accel_path[0])
248 gtk_accelerator_parse(accel, &key.accel_key, &key.accel_mods);
249 gtk_accel_map_change_entry(accel_path, key.accel_key, key.accel_mods, TRUE);
259 static void config_window_apply(void)
261 gboolean refresh = FALSE;
266 config_entry_to_option(safe_delete_path_entry, &options->file_ops.safe_delete_path, remove_trailing_slash);
268 if (options->file_filter.show_hidden_files != c_options->file_filter.show_hidden_files) refresh = TRUE;
269 if (options->file_filter.show_parent_directory != c_options->file_filter.show_parent_directory) refresh = TRUE;
270 if (options->file_filter.show_dot_directory != c_options->file_filter.show_dot_directory) refresh = TRUE;
271 if (options->file_sort.case_sensitive != c_options->file_sort.case_sensitive) refresh = TRUE;
272 if (options->file_sort.natural != c_options->file_sort.natural) refresh = TRUE;
273 if (options->file_filter.disable_file_extension_checks != c_options->file_filter.disable_file_extension_checks) refresh = TRUE;
274 if (options->file_filter.disable != c_options->file_filter.disable) refresh = TRUE;
276 options->file_ops.confirm_delete = c_options->file_ops.confirm_delete;
277 options->file_ops.enable_delete_key = c_options->file_ops.enable_delete_key;
278 options->file_ops.confirm_move_to_trash = c_options->file_ops.confirm_move_to_trash;
279 options->file_ops.use_system_trash = c_options->file_ops.use_system_trash;
280 options->file_ops.no_trash = c_options->file_ops.no_trash;
281 options->file_ops.safe_delete_folder_maxsize = c_options->file_ops.safe_delete_folder_maxsize;
282 options->tools_restore_state = c_options->tools_restore_state;
283 options->save_window_positions = c_options->save_window_positions;
284 options->use_saved_window_positions_for_new_windows = c_options->use_saved_window_positions_for_new_windows;
285 options->save_window_workspace = c_options->save_window_workspace;
286 options->save_dialog_window_positions = c_options->save_dialog_window_positions;
287 options->show_window_ids = c_options->show_window_ids;
288 options->image.scroll_reset_method = c_options->image.scroll_reset_method;
289 options->image.zoom_2pass = c_options->image.zoom_2pass;
290 options->image.fit_window_to_image = c_options->image.fit_window_to_image;
291 options->image.limit_window_size = c_options->image.limit_window_size;
292 options->image.zoom_to_fit_allow_expand = c_options->image.zoom_to_fit_allow_expand;
293 options->image.max_window_size = c_options->image.max_window_size;
294 options->image.limit_autofit_size = c_options->image.limit_autofit_size;
295 options->image.max_autofit_size = c_options->image.max_autofit_size;
296 options->image.max_enlargement_size = c_options->image.max_enlargement_size;
297 //~ options->image.use_clutter_renderer = c_options->image.use_clutter_renderer;
298 options->image.tile_size = c_options->image.tile_size;
299 options->progressive_key_scrolling = c_options->progressive_key_scrolling;
300 options->keyboard_scroll_step = c_options->keyboard_scroll_step;
302 if (options->thumbnails.max_width != c_options->thumbnails.max_width
303 || options->thumbnails.max_height != c_options->thumbnails.max_height
304 || options->thumbnails.quality != c_options->thumbnails.quality)
306 thumb_format_changed = TRUE;
308 options->thumbnails.max_width = c_options->thumbnails.max_width;
309 options->thumbnails.max_height = c_options->thumbnails.max_height;
310 options->thumbnails.quality = c_options->thumbnails.quality;
312 options->thumbnails.enable_caching = c_options->thumbnails.enable_caching;
313 options->thumbnails.cache_into_dirs = c_options->thumbnails.cache_into_dirs;
314 options->thumbnails.use_exif = c_options->thumbnails.use_exif;
315 options->thumbnails.use_color_management = c_options->thumbnails.use_color_management;
316 options->thumbnails.collection_preview = c_options->thumbnails.collection_preview;
317 options->thumbnails.use_ft_metadata = c_options->thumbnails.use_ft_metadata;
318 // options->thumbnails.use_ft_metadata_small = c_options->thumbnails.use_ft_metadata_small;
319 options->thumbnails.spec_standard = c_options->thumbnails.spec_standard;
320 options->metadata.enable_metadata_dirs = c_options->metadata.enable_metadata_dirs;
321 options->file_filter.show_hidden_files = c_options->file_filter.show_hidden_files;
322 options->file_filter.show_parent_directory = c_options->file_filter.show_parent_directory;
323 options->file_filter.show_dot_directory = c_options->file_filter.show_dot_directory;
324 options->file_filter.disable_file_extension_checks = c_options->file_filter.disable_file_extension_checks;
326 options->file_sort.case_sensitive = c_options->file_sort.case_sensitive;
327 options->file_sort.natural = c_options->file_sort.natural;
328 options->file_filter.disable = c_options->file_filter.disable;
330 config_entry_to_option(sidecar_ext_entry, &options->sidecar.ext, NULL);
331 sidecar_ext_parse(options->sidecar.ext);
333 options->slideshow.random = c_options->slideshow.random;
334 options->slideshow.repeat = c_options->slideshow.repeat;
335 options->slideshow.delay = c_options->slideshow.delay;
337 options->mousewheel_scrolls = c_options->mousewheel_scrolls;
338 options->image_lm_click_nav = c_options->image_lm_click_nav;
339 options->image_l_click_archive = c_options->image_l_click_archive;
340 options->image_l_click_video = c_options->image_l_click_video;
341 options->image_l_click_video_editor = c_options->image_l_click_video_editor;
343 options->file_ops.enable_in_place_rename = c_options->file_ops.enable_in_place_rename;
345 options->image.tile_cache_max = c_options->image.tile_cache_max;
346 options->image.image_cache_max = c_options->image.image_cache_max;
348 options->image.zoom_quality = c_options->image.zoom_quality;
350 options->image.zoom_increment = c_options->image.zoom_increment;
352 options->image.zoom_style = c_options->image.zoom_style;
354 options->image.enable_read_ahead = c_options->image.enable_read_ahead;
357 if (options->image.use_custom_border_color != c_options->image.use_custom_border_color
358 || options->image.use_custom_border_color_in_fullscreen != c_options->image.use_custom_border_color_in_fullscreen
359 || !gdk_color_equal(&options->image.border_color, &c_options->image.border_color))
361 options->image.use_custom_border_color_in_fullscreen = c_options->image.use_custom_border_color_in_fullscreen;
362 options->image.use_custom_border_color = c_options->image.use_custom_border_color;
363 options->image.border_color = c_options->image.border_color;
364 layout_colors_update();
365 view_window_colors_update();
368 options->image.alpha_color_1 = c_options->image.alpha_color_1;
369 options->image.alpha_color_2 = c_options->image.alpha_color_2;
371 options->fullscreen.screen = c_options->fullscreen.screen;
372 options->fullscreen.clean_flip = c_options->fullscreen.clean_flip;
373 options->fullscreen.disable_saver = c_options->fullscreen.disable_saver;
374 options->fullscreen.above = c_options->fullscreen.above;
375 if (c_options->image_overlay.template_string)
376 set_image_overlay_template_string(&options->image_overlay.template_string,
377 c_options->image_overlay.template_string);
378 if (c_options->image_overlay.font)
379 set_image_overlay_font_string(&options->image_overlay.font,
380 c_options->image_overlay.font);
381 options->image_overlay.text_red = c_options->image_overlay.text_red;
382 options->image_overlay.text_green = c_options->image_overlay.text_green;
383 options->image_overlay.text_blue = c_options->image_overlay.text_blue;
384 options->image_overlay.text_alpha = c_options->image_overlay.text_alpha;
385 options->image_overlay.background_red = c_options->image_overlay.background_red;
386 options->image_overlay.background_green = c_options->image_overlay.background_green;
387 options->image_overlay.background_blue = c_options->image_overlay.background_blue;
388 options->image_overlay.background_alpha = c_options->image_overlay.background_alpha;
389 options->update_on_time_change = c_options->update_on_time_change;
391 options->duplicates_similarity_threshold = c_options->duplicates_similarity_threshold;
392 options->rot_invariant_sim = c_options->rot_invariant_sim;
394 options->tree_descend_subdirs = c_options->tree_descend_subdirs;
396 options->view_dir_list_single_click_enter = c_options->view_dir_list_single_click_enter;
397 options->circular_selection_lists = c_options->circular_selection_lists;
399 options->open_recent_list_maxsize = c_options->open_recent_list_maxsize;
400 options->recent_folder_image_list_maxsize = c_options->recent_folder_image_list_maxsize;
401 options->dnd_icon_size = c_options->dnd_icon_size;
402 options->clipboard_selection = c_options->clipboard_selection;
403 options->dnd_default_action = c_options->dnd_default_action;
405 options->metadata.save_in_image_file = c_options->metadata.save_in_image_file;
406 options->metadata.save_legacy_IPTC = c_options->metadata.save_legacy_IPTC;
407 options->metadata.warn_on_write_problems = c_options->metadata.warn_on_write_problems;
408 options->metadata.save_legacy_format = c_options->metadata.save_legacy_format;
409 options->metadata.sync_grouped_files = c_options->metadata.sync_grouped_files;
410 options->metadata.confirm_write = c_options->metadata.confirm_write;
411 options->metadata.sidecar_extended_name = c_options->metadata.sidecar_extended_name;
412 options->metadata.confirm_timeout = c_options->metadata.confirm_timeout;
413 options->metadata.confirm_after_timeout = c_options->metadata.confirm_after_timeout;
414 options->metadata.confirm_on_image_change = c_options->metadata.confirm_on_image_change;
415 options->metadata.confirm_on_dir_change = c_options->metadata.confirm_on_dir_change;
416 options->metadata.keywords_case_sensitive = c_options->metadata.keywords_case_sensitive;
417 options->metadata.write_orientation = c_options->metadata.write_orientation;
418 options->metadata.check_spelling = c_options->metadata.check_spelling;
419 options->stereo.mode = (c_options->stereo.mode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
420 (c_options->stereo.tmp.mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
421 (c_options->stereo.tmp.flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
422 (c_options->stereo.tmp.mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
423 (c_options->stereo.tmp.flip_left ? PR_STEREO_FLIP_LEFT : 0) |
424 (c_options->stereo.tmp.swap ? PR_STEREO_SWAP : 0) |
425 (c_options->stereo.tmp.temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
426 options->stereo.fsmode = (c_options->stereo.fsmode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
427 (c_options->stereo.tmp.fs_mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
428 (c_options->stereo.tmp.fs_flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
429 (c_options->stereo.tmp.fs_mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
430 (c_options->stereo.tmp.fs_flip_left ? PR_STEREO_FLIP_LEFT : 0) |
431 (c_options->stereo.tmp.fs_swap ? PR_STEREO_SWAP : 0) |
432 (c_options->stereo.tmp.fs_temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
433 options->stereo.enable_fsmode = c_options->stereo.enable_fsmode;
434 options->stereo.fixed_w = c_options->stereo.fixed_w;
435 options->stereo.fixed_h = c_options->stereo.fixed_h;
436 options->stereo.fixed_x1 = c_options->stereo.fixed_x1;
437 options->stereo.fixed_y1 = c_options->stereo.fixed_y1;
438 options->stereo.fixed_x2 = c_options->stereo.fixed_x2;
439 options->stereo.fixed_y2 = c_options->stereo.fixed_y2;
441 options->info_keywords.height = c_options->info_keywords.height;
442 options->info_title.height = c_options->info_title.height;
443 options->info_comment.height = c_options->info_comment.height;
444 options->info_rating.height = c_options->info_rating.height;
446 options->show_predefined_keyword_tree = c_options->show_predefined_keyword_tree;
447 options->expand_menu_toolbar = c_options->expand_menu_toolbar;
449 options->marks_save = c_options->marks_save;
450 options->with_rename = c_options->with_rename;
451 options->collections_on_top = c_options->collections_on_top;
452 options->hide_window_in_fullscreen = c_options->hide_window_in_fullscreen;
453 config_entry_to_option(help_search_engine_entry, &options->help_search_engine, NULL);
455 options->external_preview.enable = c_options->external_preview.enable;
456 config_entry_to_option(external_preview_select_entry, &options->external_preview.select, NULL);
457 config_entry_to_option(external_preview_extract_entry, &options->external_preview.extract, NULL);
459 options->read_metadata_in_idle = c_options->read_metadata_in_idle;
461 options->star_rating.star = c_options->star_rating.star;
462 options->star_rating.rejected = c_options->star_rating.rejected;
464 options->threads.duplicates = c_options->threads.duplicates > 0 ? c_options->threads.duplicates : -1;
467 set_debug_level(debug_c);
471 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
473 config_entry_to_option(color_profile_input_name_entry[i], &options->color_profile.input_name[i], NULL);
474 config_entry_to_option(color_profile_input_file_entry[i], &options->color_profile.input_file[i], NULL);
476 config_entry_to_option(color_profile_screen_file_entry, &options->color_profile.screen_file, NULL);
477 options->color_profile.use_x11_screen_profile = c_options->color_profile.use_x11_screen_profile;
478 if (options->color_profile.render_intent != c_options->color_profile.render_intent)
480 options->color_profile.render_intent = c_options->color_profile.render_intent;
485 options->mouse_button_8 = c_options->mouse_button_8;
486 options->mouse_button_9 = c_options->mouse_button_9;
488 options->override_disable_gpu = c_options->override_disable_gpu;
490 config_tab_keywords_save();
492 image_options_sync();
497 layout_refresh(NULL);
500 if (accel_store) gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_apply_cb, NULL);
502 toolbar_apply(TOOLBAR_MAIN);
503 toolbar_apply(TOOLBAR_STATUS);
507 *-----------------------------------------------------------------------------
508 * config window main button callbacks (private)
509 *-----------------------------------------------------------------------------
512 static void config_window_close_cb(GtkWidget *UNUSED(widget), gpointer UNUSED(data))
514 gtk_widget_destroy(configwindow);
519 static void config_window_help_cb(GtkWidget *UNUSED(widget), gpointer data)
521 GtkWidget *notebook = data;
524 static gchar *html_section[] =
526 "GuideOptionsGeneral.html",
527 "GuideOptionsImage.html",
528 "GuideOptionsOSD.html",
529 "GuideOptionsWindow.html",
530 "GuideOptionsKeyboard.html",
531 "GuideOptionsFiltering.html",
532 "GuideOptionsMetadata.html",
533 "GuideOptionsKeywords.html",
534 "GuideOptionsColor.html",
535 "GuideOptionsStereo.html",
536 "GuideOptionsBehavior.html",
537 "GuideOptionsToolbar.html",
538 "GuideOptionsToolbar.html",
539 "GuideOptionsAdvanced.html"
542 i = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
543 help_window_show(html_section[i]);
546 static gboolean config_window_delete(GtkWidget *UNUSED(widget), GdkEventAny *UNUSED(event), gpointer UNUSED(data))
548 config_window_close_cb(NULL, NULL);
552 static void config_window_ok_cb(GtkWidget *widget, gpointer data)
555 GtkNotebook *notebook = data;
563 lw = layout_window_list->data;
565 window = gtk_widget_get_window(widget);
566 gdk_window_get_root_origin(window, &x, &y);
567 w = gdk_window_get_width(window);
568 h = gdk_window_get_height(window);
569 page_number = gtk_notebook_get_current_page(notebook);
571 lw->options.preferences_window.x = x;
572 lw->options.preferences_window.y = y;
573 lw->options.preferences_window.w = w;
574 lw->options.preferences_window.h = h;
575 lw->options.preferences_window.page_number = page_number;
577 config_window_apply();
578 layout_util_sync(lw);
579 save_options(options);
580 config_window_close_cb(NULL, NULL);
584 *-----------------------------------------------------------------------------
585 * config window setup (private)
586 *-----------------------------------------------------------------------------
589 static void quality_menu_cb(GtkWidget *combo, gpointer data)
593 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
597 *option = GDK_INTERP_NEAREST;
600 *option = GDK_INTERP_TILES;
603 *option = GDK_INTERP_BILINEAR;
608 static void dnd_default_action_selection_menu_cb(GtkWidget *combo, gpointer data)
612 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
616 *option = DND_ACTION_ASK;
619 *option = DND_ACTION_COPY;
622 *option = DND_ACTION_MOVE;
626 static void clipboard_selection_menu_cb(GtkWidget *combo, gpointer data)
630 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
633 *option = CLIPBOARD_PRIMARY;
636 *option = CLIPBOARD_CLIPBOARD;
639 *option = CLIPBOARD_BOTH;
642 *option = CLIPBOARD_BOTH;
646 static void add_quality_menu(GtkWidget *table, gint column, gint row, const gchar *text,
647 guint option, guint *option_c)
654 pref_table_label(table, column, row, text, 0.0);
656 combo = gtk_combo_box_text_new();
658 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Nearest (worst, but fastest)"));
659 if (option == GDK_INTERP_NEAREST) current = 0;
660 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Tiles"));
661 if (option == GDK_INTERP_TILES) current = 1;
662 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Bilinear (best, but slowest)"));
663 if (option == GDK_INTERP_BILINEAR) current = 2;
665 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
667 g_signal_connect(G_OBJECT(combo), "changed",
668 G_CALLBACK(quality_menu_cb), option_c);
670 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
671 gtk_widget_show(combo);
674 static void add_dnd_default_action_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text, DnDAction option, DnDAction *option_c)
681 pref_table_label(table, column, row, text, 0.0);
683 combo = gtk_combo_box_text_new();
685 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Ask"));
686 if (option == DND_ACTION_ASK) current = 0;
687 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Copy"));
688 if (option == DND_ACTION_COPY) current = 1;
689 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Move"));
690 if (option == DND_ACTION_MOVE) current = 2;
692 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
694 g_signal_connect(G_OBJECT(combo), "changed",
695 G_CALLBACK(dnd_default_action_selection_menu_cb), option_c);
697 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
698 gtk_widget_show(combo);
701 static void add_clipboard_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
702 gint option, gint *option_c)
709 pref_table_label(table, column, row, text, 0.0);
711 combo = gtk_combo_box_text_new();
713 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Primary"));
714 if (option == CLIPBOARD_PRIMARY) current = 0;
715 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Clipboard"));
716 if (option == CLIPBOARD_CLIPBOARD) current = 1;
717 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Both"));
718 if (option == CLIPBOARD_BOTH) current = 2;
720 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
722 g_signal_connect(G_OBJECT(combo), "changed",
723 G_CALLBACK(clipboard_selection_menu_cb), option_c);
725 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
726 gtk_widget_show(combo);
729 static void zoom_style_selection_menu_cb(GtkWidget *combo, gpointer data)
733 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
736 *option = ZOOM_GEOMETRIC;
739 *option = ZOOM_ARITHMETIC;
742 *option = ZOOM_GEOMETRIC;
746 static void add_zoom_style_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text, ZoomStyle option, ZoomStyle *option_c)
753 pref_table_label(table, column, row, text, 0.0);
755 combo = gtk_combo_box_text_new();
757 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Geometric"));
758 if (option == ZOOM_GEOMETRIC) current = 0;
759 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Arithmetic"));
760 if (option == ZOOM_ARITHMETIC) current = 1;
762 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
764 g_signal_connect(G_OBJECT(combo), "changed", G_CALLBACK(zoom_style_selection_menu_cb), option_c);
766 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
767 gtk_widget_show(combo);
770 typedef struct _UseableMouseItems UseableMouseItems;
771 struct _UseableMouseItems
773 gchar *name; /* GtkActionEntry terminology */
778 static const UseableMouseItems useable_mouse_items[] = {
780 {"FirstImage", N_("First Image"), GTK_STOCK_GOTO_TOP},
781 {"PrevImage", N_("Previous Image"), GTK_STOCK_GO_UP},
782 {"NextImage", N_("Next Image"), GTK_STOCK_GO_DOWN},
783 {"LastImage", N_("Last Image"), GTK_STOCK_GOTO_BOTTOM},
784 {"Back", N_("Back"), GTK_STOCK_GO_BACK},
785 {"Forward", N_("Forward"), GTK_STOCK_GO_FORWARD},
786 {"Home", N_("Home"), GTK_STOCK_HOME},
787 {"Up", N_("Up"), GTK_STOCK_GO_UP},
788 {"FirstPage", N_("First page"), GTK_STOCK_MEDIA_PREVIOUS},
789 {"LastPage", N_("Last Page"), GTK_STOCK_MEDIA_NEXT},
790 {"NextPage", N_("Next page"), GTK_STOCK_MEDIA_FORWARD},
791 {"PrevPage", N_("Previous Page"), GTK_STOCK_MEDIA_REWIND},
792 {"NewWindow", N_("New _window"), GTK_STOCK_NEW},
793 {"NewCollection", N_("New collection"), GTK_STOCK_INDEX},
794 {"OpenCollection", N_("Open collection"), GTK_STOCK_OPEN},
795 {"Search", N_("Search"), GTK_STOCK_FIND},
796 {"FindDupes", N_("Find duplicates"), GTK_STOCK_FIND},
797 {"NewFolder", N_("New folder"),GTK_STOCK_DIRECTORY},
798 {"Copy", N_("Copy"), GTK_STOCK_COPY},
799 {"Move", N_("Move"), PIXBUF_INLINE_ICON_MOVE},
800 {"Rename", N_("Rename"), PIXBUF_INLINE_ICON_RENAME},
801 {"Delete", N_("Delete"), GTK_STOCK_DELETE},
802 {"CloseWindow", N_("Close Window"), GTK_STOCK_CLOSE},
803 {"PanView", N_("Pan view"), PIXBUF_INLINE_ICON_PANORAMA},
804 {"SelectAll", N_("Select all"), PIXBUF_INLINE_ICON_SELECT_ALL},
805 {"SelectNone", N_("Select none"), PIXBUF_INLINE_ICON_SELECT_NONE},
806 {"SelectInvert", N_("Select invert"), PIXBUF_INLINE_ICON_SELECT_INVERT},
807 {"ShowFileFilter", N_("Show file filter"), PIXBUF_INLINE_ICON_FILE_FILTER},
808 {"RectangularSelection", N_("Select rectangle"), PIXBUF_INLINE_ICON_SELECT_RECTANGLE},
809 {"Print", N_("Print"), GTK_STOCK_PRINT},
810 {"Preferences", N_("Preferences"), GTK_STOCK_PREFERENCES},
811 {"LayoutConfig", N_("Configure this window"), GTK_STOCK_PREFERENCES},
812 {"Maintenance", N_("Cache maintenance"), PIXBUF_INLINE_ICON_MAINTENANCE},
813 {"RotateCW", N_("Rotate clockwise 90°"), PIXBUF_INLINE_ICON_CW},
814 {"RotateCCW", N_("Rotate counterclockwise 90°"), PIXBUF_INLINE_ICON_CCW},
815 {"Rotate180", N_("Rotate 180°"), PIXBUF_INLINE_ICON_180},
816 {"Mirror", N_("Mirror"), PIXBUF_INLINE_ICON_MIRROR},
817 {"Flip", N_("Flip"), PIXBUF_INLINE_ICON_FLIP},
818 {"AlterNone", N_("Original state"), PIXBUF_INLINE_ICON_ORIGINAL},
819 {"ZoomIn", N_("Zoom in"), GTK_STOCK_ZOOM_IN},
820 {"ZoomOut", N_("Zoom out"), GTK_STOCK_ZOOM_OUT},
821 {"Zoom100", N_("Zoom 1:1"), GTK_STOCK_ZOOM_100},
822 {"ZoomFit", N_("Zoom to fit"), GTK_STOCK_ZOOM_FIT},
823 {"ZoomFillHor", N_("Fit Horizontaly"), PIXBUF_INLINE_ICON_ZOOMFILLHOR},
824 {"ZoomFillVert", N_("Fit vertically"), PIXBUF_INLINE_ICON_ZOOMFILLVERT},
825 {"Zoom200", N_("Zoom 2:1"), GTK_STOCK_FILE},
826 {"Zoom300", N_("Zoom 3:1"), GTK_STOCK_FILE},
827 {"Zoom400", N_("Zoom 4:1"), GTK_STOCK_FILE},
828 {"Zoom50", N_("Zoom 1:2"), GTK_STOCK_FILE},
829 {"Zoom33", N_("Zoom1:3"), GTK_STOCK_FILE},
830 {"Zoom25", N_("Zoom 1:4"), GTK_STOCK_FILE},
831 {"ConnectZoomIn", N_("Connected Zoom in"), GTK_STOCK_ZOOM_IN},
832 {"SplitPaneSync", N_("Split Pane Sync"), PIXBUF_INLINE_SPLIT_PANE_SYNC},
833 {"Grayscale", N_("Grayscale"), PIXBUF_INLINE_ICON_GRAYSCALE},
834 {"OverUnderExposed", N_("Over Under Exposed"), PIXBUF_INLINE_ICON_EXPOSURE},
835 {"HideTools", N_("Hide file list"), PIXBUF_INLINE_ICON_HIDETOOLS},
836 {"SlideShowPause", N_("Pause slideshow"), GTK_STOCK_MEDIA_PAUSE},
837 {"SlideShowFaster", N_("Slideshow Faster"), GTK_STOCK_FILE},
838 {"SlideShowSlower", N_("Slideshow Slower"), GTK_STOCK_FILE},
839 {"Refresh", N_("Refresh"), GTK_STOCK_REFRESH},
840 {"HelpContents", N_("Help"), GTK_STOCK_HELP},
841 {"ExifWin", N_("Exif window"), PIXBUF_INLINE_ICON_EXIF},
842 {"Thumbnails", N_("Show thumbnails"), PIXBUF_INLINE_ICON_THUMB},
843 {"ShowMarks", N_("Show marks"), PIXBUF_INLINE_ICON_MARKS},
844 {"DrawRectangle", N_("Draw Rectangle"), PIXBUF_INLINE_ICON_DRAW_RECTANGLE},
845 {"FloatTools", N_("Float file list"), PIXBUF_INLINE_ICON_FLOAT},
846 {"SBar", N_("Info sidebar"), PIXBUF_INLINE_ICON_INFO},
847 {"SBarSort", N_("Sort manager"), PIXBUF_INLINE_ICON_SORT},
848 {"Quit", N_("Quit"), GTK_STOCK_QUIT},
852 static void mouse_buttons_selection_menu_cb(GtkWidget *combo, gpointer data)
854 gchar **option = data;
857 label = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(combo));
859 const UseableMouseItems *list = useable_mouse_items;
863 if (g_strcmp0(list->label, label) == 0)
871 *option = g_strdup(list->name);
875 static void add_mouse_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
876 gchar *option, gchar **option_c)
884 pref_table_label(table, column, row, text, 0.0);
886 combo = gtk_combo_box_text_new();
888 const UseableMouseItems *list = useable_mouse_items;
892 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), list->label);
893 if (g_strcmp0(list->name, option) == 0)
901 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
903 g_signal_connect(G_OBJECT(combo), "changed",
904 G_CALLBACK(mouse_buttons_selection_menu_cb), option_c);
906 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
907 gtk_widget_show(combo);
910 static void thumb_size_menu_cb(GtkWidget *combo, gpointer UNUSED(data))
914 n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
917 if ((guint) n < sizeof(thumb_size_list) / sizeof(ThumbSize))
919 c_options->thumbnails.max_width = thumb_size_list[n].w;
920 c_options->thumbnails.max_height = thumb_size_list[n].h;
924 c_options->thumbnails.max_width = options->thumbnails.max_width;
925 c_options->thumbnails.max_height = options->thumbnails.max_height;
929 static void add_thumb_size_menu(GtkWidget *table, gint column, gint row, gchar *text)
935 c_options->thumbnails.max_width = options->thumbnails.max_width;
936 c_options->thumbnails.max_height = options->thumbnails.max_height;
938 pref_table_label(table, column, row, text, 0.0);
940 combo = gtk_combo_box_text_new();
943 for (i = 0; (guint) i < sizeof(thumb_size_list) / sizeof(ThumbSize); i++)
948 w = thumb_size_list[i].w;
949 h = thumb_size_list[i].h;
951 buf = g_strdup_printf("%d x %d", w, h);
952 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
955 if (w == options->thumbnails.max_width && h == options->thumbnails.max_height) current = i;
962 buf = g_strdup_printf("%s %d x %d", _("Custom"), options->thumbnails.max_width, options->thumbnails.max_height);
963 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
969 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
970 g_signal_connect(G_OBJECT(combo), "changed",
971 G_CALLBACK(thumb_size_menu_cb), NULL);
973 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
974 gtk_widget_show(combo);
977 static void stereo_mode_menu_cb(GtkWidget *combo, gpointer data)
981 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
985 *option = PR_STEREO_NONE;
988 *option = PR_STEREO_ANAGLYPH_RC;
991 *option = PR_STEREO_ANAGLYPH_GM;
994 *option = PR_STEREO_ANAGLYPH_YB;
997 *option = PR_STEREO_ANAGLYPH_GRAY_RC;
1000 *option = PR_STEREO_ANAGLYPH_GRAY_GM;
1003 *option = PR_STEREO_ANAGLYPH_GRAY_YB;
1006 *option = PR_STEREO_ANAGLYPH_DB_RC;
1009 *option = PR_STEREO_ANAGLYPH_DB_GM;
1012 *option = PR_STEREO_ANAGLYPH_DB_YB;
1015 *option = PR_STEREO_HORIZ;
1018 *option = PR_STEREO_HORIZ | PR_STEREO_HALF;
1021 *option = PR_STEREO_VERT;
1024 *option = PR_STEREO_VERT | PR_STEREO_HALF;
1027 *option = PR_STEREO_FIXED;
1032 static void add_stereo_mode_menu(GtkWidget *table, gint column, gint row, const gchar *text,
1033 gint option, gint *option_c, gboolean add_fixed)
1040 pref_table_label(table, column, row, text, 0.0);
1042 combo = gtk_combo_box_text_new();
1044 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Single image"));
1046 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Red-Cyan"));
1047 if (option & PR_STEREO_ANAGLYPH_RC) current = 1;
1048 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Green-Magenta"));
1049 if (option & PR_STEREO_ANAGLYPH_GM) current = 2;
1050 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Yellow-Blue"));
1051 if (option & PR_STEREO_ANAGLYPH_YB) current = 3;
1052 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Red-Cyan"));
1053 if (option & PR_STEREO_ANAGLYPH_GRAY_RC) current = 4;
1054 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Green-Magenta"));
1055 if (option & PR_STEREO_ANAGLYPH_GRAY_GM) current = 5;
1056 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Yellow-Blue"));
1057 if (option & PR_STEREO_ANAGLYPH_GRAY_YB) current = 6;
1058 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Red-Cyan"));
1059 if (option & PR_STEREO_ANAGLYPH_DB_RC) current = 7;
1060 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Green-Magenta"));
1061 if (option & PR_STEREO_ANAGLYPH_DB_GM) current = 8;
1062 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Yellow-Blue"));
1063 if (option & PR_STEREO_ANAGLYPH_DB_YB) current = 9;
1065 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side"));
1066 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side Half size"));
1067 if (option & PR_STEREO_HORIZ)
1070 if (option & PR_STEREO_HALF) current = 11;
1073 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom"));
1074 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom Half size"));
1075 if (option & PR_STEREO_VERT)
1078 if (option & PR_STEREO_HALF) current = 13;
1083 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Fixed position"));
1084 if (option & PR_STEREO_FIXED) current = 14;
1087 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
1089 g_signal_connect(G_OBJECT(combo), "changed",
1090 G_CALLBACK(stereo_mode_menu_cb), option_c);
1092 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
1093 gtk_widget_show(combo);
1096 static void video_menu_cb(GtkWidget *combo, gpointer data)
1098 gchar **option = data;
1100 EditorDescription *ed = g_list_nth_data(editor_list_get(), gtk_combo_box_get_active(GTK_COMBO_BOX(combo)));
1104 static void video_menu_populate(gpointer data, gpointer user_data)
1106 GtkWidget *combo = user_data;
1107 EditorDescription *ed = data;
1109 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), ed->name);
1112 static void add_video_menu(GtkWidget *table, gint column, gint row, const gchar *text,
1113 gchar *option, gchar **option_c)
1117 /* use lists since they are sorted */
1118 GList *eds = editor_list_get();
1122 pref_table_label(table, column, row, text, 0.0);
1124 combo = gtk_combo_box_text_new();
1125 g_list_foreach(eds,video_menu_populate,(gpointer)combo);
1126 current = option ? g_list_index(eds,g_hash_table_lookup(editors,option)): -1;
1128 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
1130 g_signal_connect(G_OBJECT(combo), "changed",
1131 G_CALLBACK(video_menu_cb), option_c);
1133 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
1134 gtk_widget_show(combo);
1137 static void filter_store_populate(void)
1141 if (!filter_store) return;
1143 gtk_list_store_clear(filter_store);
1145 work = filter_get_list();
1154 gtk_list_store_append(filter_store, &iter);
1155 gtk_list_store_set(filter_store, &iter, 0, fe, -1);
1159 static void filter_store_ext_edit_cb(GtkCellRendererText *UNUSED(cell), gchar *path_str,
1160 gchar *new_text, gpointer data)
1162 GtkWidget *model = data;
1163 FilterEntry *fe = data;
1167 if (!new_text || strlen(new_text) < 1) return;
1169 tpath = gtk_tree_path_new_from_string(path_str);
1170 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1171 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1173 g_free(fe->extensions);
1174 fe->extensions = g_strdup(new_text);
1176 gtk_tree_path_free(tpath);
1180 static void filter_store_class_edit_cb(GtkCellRendererText *UNUSED(cell), gchar *path_str,
1181 gchar *new_text, gpointer data)
1183 GtkWidget *model = data;
1184 FilterEntry *fe = data;
1189 if (!new_text || !new_text[0]) return;
1191 tpath = gtk_tree_path_new_from_string(path_str);
1192 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1193 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1195 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
1197 if (strcmp(new_text, _(format_class_list[i])) == 0)
1204 gtk_tree_path_free(tpath);
1208 static void filter_store_desc_edit_cb(GtkCellRendererText *UNUSED(cell), gchar *path_str,
1209 gchar *new_text, gpointer data)
1211 GtkWidget *model = data;
1216 if (!new_text || !new_text[0]) return;
1218 tpath = gtk_tree_path_new_from_string(path_str);
1219 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1220 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1222 g_free(fe->description);
1223 fe->description = g_strdup(new_text);
1225 gtk_tree_path_free(tpath);
1228 static void filter_store_enable_cb(GtkCellRendererToggle *UNUSED(renderer),
1229 gchar *path_str, gpointer data)
1231 GtkWidget *model = data;
1236 tpath = gtk_tree_path_new_from_string(path_str);
1237 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1238 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1240 fe->enabled = !fe->enabled;
1242 gtk_tree_path_free(tpath);
1246 static void filter_store_writable_cb(GtkCellRendererToggle *UNUSED(renderer),
1247 gchar *path_str, gpointer data)
1249 GtkWidget *model = data;
1254 tpath = gtk_tree_path_new_from_string(path_str);
1255 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1256 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1258 fe->writable = !fe->writable;
1259 if (fe->writable) fe->allow_sidecar = FALSE;
1261 gtk_tree_path_free(tpath);
1265 static void filter_store_sidecar_cb(GtkCellRendererToggle *UNUSED(renderer),
1266 gchar *path_str, gpointer data)
1268 GtkWidget *model = data;
1273 tpath = gtk_tree_path_new_from_string(path_str);
1274 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1275 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1277 fe->allow_sidecar = !fe->allow_sidecar;
1278 if (fe->allow_sidecar) fe->writable = FALSE;
1280 gtk_tree_path_free(tpath);
1284 static void filter_set_func(GtkTreeViewColumn *UNUSED(tree_column), GtkCellRenderer *cell,
1285 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
1289 gtk_tree_model_get(tree_model, iter, 0, &fe, -1);
1291 switch (GPOINTER_TO_INT(data))
1294 g_object_set(GTK_CELL_RENDERER(cell),
1295 "active", fe->enabled, NULL);
1298 g_object_set(GTK_CELL_RENDERER(cell),
1299 "text", fe->extensions, NULL);
1301 case FE_DESCRIPTION:
1302 g_object_set(GTK_CELL_RENDERER(cell),
1303 "text", fe->description, NULL);
1306 g_object_set(GTK_CELL_RENDERER(cell),
1307 "text", _(format_class_list[fe->file_class]), NULL);
1310 g_object_set(GTK_CELL_RENDERER(cell),
1311 "active", fe->writable, NULL);
1313 case FE_ALLOW_SIDECAR:
1314 g_object_set(GTK_CELL_RENDERER(cell),
1315 "active", fe->allow_sidecar, NULL);
1320 static gboolean filter_add_scroll(gpointer data)
1324 GtkCellRenderer *cell;
1325 GtkTreeViewColumn *column;
1328 GtkTreeModel *store;
1330 FilterEntry *filter;
1332 rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(filter_store), NULL);
1333 path = gtk_tree_path_new_from_indices(rows-1, -1);
1335 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data), 0);
1337 list_cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column));
1338 cell = g_list_last(list_cells)->data;
1340 store = gtk_tree_view_get_model(GTK_TREE_VIEW(data));
1341 valid = gtk_tree_model_get_iter_first(store, &iter);
1345 gtk_tree_model_get(store, &iter, 0, &filter, -1);
1347 if (g_strcmp0(filter->extensions, ".new") == 0)
1349 path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iter);
1353 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter);
1356 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1357 path, column, FALSE, 0.0, 0.0 );
1358 gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(data),
1359 path, column, cell, TRUE);
1361 gtk_tree_path_free(path);
1362 g_list_free(list_cells);
1367 static void filter_add_cb(GtkWidget *UNUSED(widget), gpointer data)
1369 filter_add_unique("description", ".new", FORMAT_CLASS_IMAGE, TRUE, FALSE, TRUE);
1370 filter_store_populate();
1372 g_idle_add((GSourceFunc)filter_add_scroll, data);
1375 static void filter_remove_cb(GtkWidget *UNUSED(widget), gpointer data)
1377 GtkWidget *filter_view = data;
1378 GtkTreeSelection *selection;
1382 if (!filter_store) return;
1383 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1384 if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) return;
1385 gtk_tree_model_get(GTK_TREE_MODEL(filter_store), &iter, 0, &fe, -1);
1388 filter_remove_entry(fe);
1390 filter_store_populate();
1393 static gboolean filter_default_ok_scroll(GtkTreeView *data)
1397 GtkTreeViewColumn *column;
1399 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(filter_store), &iter);
1400 path = gtk_tree_model_get_path(GTK_TREE_MODEL(filter_store), &iter);
1401 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1403 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1407 gtk_tree_path_free(path);
1412 static void filter_default_ok_cb(GenericDialog *gd, gpointer UNUSED(data))
1415 filter_add_defaults();
1417 filter_store_populate();
1419 g_idle_add((GSourceFunc)filter_default_ok_scroll, gd->data);
1422 static void dummy_cancel_cb(GenericDialog *UNUSED(gd), gpointer UNUSED(data))
1424 /* no op, only so cancel button appears */
1427 static void filter_default_cb(GtkWidget *widget, gpointer data)
1431 gd = generic_dialog_new(_("Reset filters"),
1432 "reset_filter", widget, TRUE,
1433 dummy_cancel_cb, data);
1434 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset filters"),
1435 _("This will reset the file filters to the defaults.\nContinue?"), TRUE);
1436 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, filter_default_ok_cb, TRUE);
1437 gtk_widget_show(gd->dialog);
1440 static void filter_disable_cb(GtkWidget *widget, gpointer data)
1442 GtkWidget *frame = data;
1444 gtk_widget_set_sensitive(frame,
1445 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
1448 static void safe_delete_view_cb(GtkWidget *UNUSED(widget), gpointer UNUSED(data))
1450 layout_set_path(NULL, gtk_entry_get_text(GTK_ENTRY(safe_delete_path_entry)));
1453 static void safe_delete_clear_ok_cb(GenericDialog *UNUSED(gd), gpointer UNUSED(data))
1455 file_util_trash_clear();
1458 static void safe_delete_clear_cb(GtkWidget *widget, gpointer UNUSED(data))
1462 gd = generic_dialog_new(_("Clear trash"),
1463 "clear_trash", widget, TRUE,
1464 dummy_cancel_cb, NULL);
1465 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear trash"),
1466 _("This will remove the trash contents."), FALSE);
1467 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, safe_delete_clear_ok_cb, TRUE);
1468 entry = gtk_entry_new();
1469 gtk_widget_set_can_focus(entry, FALSE);
1470 gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE);
1471 if (options->file_ops.safe_delete_path) gtk_entry_set_text(GTK_ENTRY(entry), options->file_ops.safe_delete_path);
1472 gtk_box_pack_start(GTK_BOX(gd->vbox), entry, FALSE, FALSE, 0);
1473 gtk_widget_show(entry);
1474 gtk_widget_show(gd->dialog);
1477 static void image_overlay_template_view_changed_cb(GtkWidget *UNUSED(widget), gpointer data)
1479 GtkWidget *pTextView;
1480 GtkTextBuffer *pTextBuffer;
1484 pTextView = GTK_WIDGET(data);
1486 pTextBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pTextView));
1487 gtk_text_buffer_get_start_iter(pTextBuffer, &iStart);
1488 gtk_text_buffer_get_end_iter(pTextBuffer, &iEnd);
1490 set_image_overlay_template_string(&c_options->image_overlay.template_string,
1491 gtk_text_buffer_get_text(pTextBuffer, &iStart, &iEnd, TRUE));
1494 static void image_overlay_default_template_ok_cb(GenericDialog *UNUSED(gd), gpointer data)
1496 GtkTextView *text_view = data;
1497 GtkTextBuffer *buffer;
1499 set_default_image_overlay_template_string(&options->image_overlay.template_string);
1500 if (!configwindow) return;
1502 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
1503 gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1506 static void image_overlay_default_template_cb(GtkWidget *widget, gpointer data)
1510 gd = generic_dialog_new(_("Reset image overlay template string"),
1511 "reset_image_overlay_template_string", widget, TRUE,
1512 dummy_cancel_cb, data);
1513 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset image overlay template string"),
1514 _("This will reset the image overlay template string to the default.\nContinue?"), TRUE);
1515 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, image_overlay_default_template_ok_cb, TRUE);
1516 gtk_widget_show(gd->dialog);
1519 static void image_overlay_help_cb(GtkWidget *UNUSED(widget), gpointer UNUSED(data))
1521 help_window_show("GuideOptionsOSD.html");
1524 static void image_overlay_set_font_cb(GtkWidget *widget, gpointer UNUSED(data))
1528 PangoFontDescription *font_desc;
1530 dialog = gtk_font_chooser_dialog_new("Image Overlay Font", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1531 gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), options->image_overlay.font);
1533 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1535 font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
1536 font = pango_font_description_to_string(font_desc);
1537 g_free(c_options->image_overlay.font);
1538 c_options->image_overlay.font = g_strdup(font);
1542 gtk_widget_destroy(dialog);
1545 static void image_overlay_set_text_colour_cb(GtkWidget *widget, gpointer UNUSED(data))
1550 dialog = gtk_color_chooser_dialog_new("Image Overlay Text Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1551 colour.red = options->image_overlay.text_red;
1552 colour.green = options->image_overlay.text_green;
1553 colour.blue = options->image_overlay.text_blue;
1554 colour.alpha = options->image_overlay.text_alpha;
1555 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1556 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1558 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1560 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1561 c_options->image_overlay.text_red = colour.red*255;
1562 c_options->image_overlay.text_green = colour.green*255;
1563 c_options->image_overlay.text_blue = colour.blue*255;
1564 c_options->image_overlay.text_alpha = colour.alpha*255;
1566 gtk_widget_destroy(dialog);
1570 static void image_overlay_set_background_colour_cb(GtkWidget *widget, gpointer UNUSED(data))
1575 dialog = gtk_color_chooser_dialog_new("Image Overlay Background Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1576 colour.red = options->image_overlay.background_red;
1577 colour.green = options->image_overlay.background_green;
1578 colour.blue = options->image_overlay.background_blue;
1579 colour.alpha = options->image_overlay.background_alpha;
1580 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1581 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1583 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1585 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1586 c_options->image_overlay.background_red = colour.red*255;
1587 c_options->image_overlay.background_green = colour.green*255;
1588 c_options->image_overlay.background_blue = colour.blue*255;
1589 c_options->image_overlay.background_alpha = colour.alpha*255;
1591 gtk_widget_destroy(dialog);
1594 static void accel_store_populate(void)
1597 GList *groups, *actions;
1599 const gchar *accel_path;
1603 if (!accel_store || !layout_window_list || !layout_window_list->data) return;
1605 gtk_tree_store_clear(accel_store);
1606 lw = layout_window_list->data; /* get the actions from the first window, it should not matter, they should be the same in all windows */
1608 g_assert(lw && lw->ui_manager);
1609 groups = gtk_ui_manager_get_action_groups(lw->ui_manager);
1612 actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
1615 action = GTK_ACTION(actions->data);
1616 accel_path = gtk_action_get_accel_path(action);
1617 if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
1619 gchar *label, *label2, *tooltip, *accel;
1620 g_object_get(action,
1621 "tooltip", &tooltip,
1625 if (pango_parse_markup(label, -1, '_', NULL, &label2, NULL, NULL) && label2)
1631 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1635 gtk_tree_store_append(accel_store, &iter, NULL);
1636 gtk_tree_store_set(accel_store, &iter,
1639 AE_TOOLTIP, tooltip ? tooltip : "",
1640 AE_ACCEL, accel_path,
1648 actions = actions->next;
1651 groups = groups->next;
1655 static void accel_store_cleared_cb(GtkCellRendererAccel *UNUSED(accel), gchar *UNUSED(path_string), gpointer UNUSED(user_data))
1660 static gboolean accel_remove_key_cb(GtkTreeModel *model, GtkTreePath *UNUSED(path), GtkTreeIter *iter, gpointer data)
1662 gchar *accel1 = data;
1667 gtk_tree_model_get(model, iter, AE_KEY, &accel2, -1);
1669 gtk_accelerator_parse(accel1, &key1.accel_key, &key1.accel_mods);
1670 gtk_accelerator_parse(accel2, &key2.accel_key, &key2.accel_mods);
1672 if (key1.accel_key == key2.accel_key && key1.accel_mods == key2.accel_mods)
1674 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1675 DEBUG_1("accelerator key '%s' is already used, removing.", accel1);
1684 static void accel_store_edited_cb(GtkCellRendererAccel *UNUSED(accel), gchar *path_string, guint accel_key, GdkModifierType accel_mods, guint UNUSED(hardware_keycode), gpointer UNUSED(user_data))
1686 GtkTreeModel *model = (GtkTreeModel *)accel_store;
1690 GtkAccelKey old_key, key;
1691 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
1693 gtk_tree_model_get_iter(model, &iter, path);
1694 gtk_tree_model_get(model, &iter, AE_ACCEL, &accel_path, -1);
1696 /* test if the accelerator can be stored without conflicts*/
1697 gtk_accel_map_lookup_entry(accel_path, &old_key);
1699 /* change the key and read it back (change may fail on keys hardcoded in gtk)*/
1700 gtk_accel_map_change_entry(accel_path, accel_key, accel_mods, TRUE);
1701 gtk_accel_map_lookup_entry(accel_path, &key);
1703 /* restore the original for now, the key will be really changed when the changes are confirmed */
1704 gtk_accel_map_change_entry(accel_path, old_key.accel_key, old_key.accel_mods, TRUE);
1706 acc = gtk_accelerator_name(key.accel_key, key.accel_mods);
1707 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, acc);
1709 gtk_tree_store_set(accel_store, &iter, AE_KEY, acc, -1);
1710 gtk_tree_path_free(path);
1714 static gboolean accel_default_scroll(GtkTreeView *data)
1718 GtkTreeViewColumn *column;
1720 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(accel_store), &iter);
1721 path = gtk_tree_model_get_path(GTK_TREE_MODEL(accel_store), &iter);
1722 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1724 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1728 gtk_tree_path_free(path);
1733 static void accel_default_cb(GtkWidget *UNUSED(widget), gpointer data)
1735 accel_store_populate();
1737 g_idle_add((GSourceFunc)accel_default_scroll, data);
1740 //void accel_remove_selection(GtkTreeModel *UNUSED(model), GtkTreePath *UNUSED(path), GtkTreeIter *iter, gpointer UNUSED(data))
1742 //gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1745 void accel_reset_selection(GtkTreeModel *model, GtkTreePath *UNUSED(path), GtkTreeIter *iter, gpointer UNUSED(data))
1748 gchar *accel_path, *accel;
1750 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, -1);
1751 gtk_accel_map_lookup_entry(accel_path, &key);
1752 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1754 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, accel);
1756 gtk_tree_store_set(accel_store, iter, AE_KEY, accel, -1);
1761 static void accel_reset_cb(GtkWidget *UNUSED(widget), gpointer data)
1763 GtkTreeSelection *selection;
1765 if (!accel_store) return;
1766 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data));
1767 gtk_tree_selection_selected_foreach(selection, &accel_reset_selection, NULL);
1772 static GtkWidget *scrolled_notebook_page(GtkWidget *notebook, const gchar *title)
1776 GtkWidget *scrolled;
1777 GtkWidget *viewport;
1779 scrolled = gtk_scrolled_window_new(NULL, NULL);
1780 gtk_container_set_border_width(GTK_CONTAINER(scrolled), PREF_PAD_BORDER);
1781 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1782 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1783 label = gtk_label_new(title);
1784 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, label);
1785 gtk_widget_show(scrolled);
1787 viewport = gtk_viewport_new(NULL, NULL);
1788 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1789 gtk_container_add(GTK_CONTAINER(scrolled), viewport);
1790 gtk_widget_show(viewport);
1792 vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
1793 gtk_container_add(GTK_CONTAINER(viewport), vbox);
1794 gtk_widget_show(vbox);
1799 static void cache_standard_cb(GtkWidget *widget, gpointer UNUSED(data))
1801 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1803 c_options->thumbnails.spec_standard =TRUE;
1804 c_options->thumbnails.cache_into_dirs = FALSE;
1808 static void cache_geeqie_cb(GtkWidget *widget, gpointer UNUSED(data))
1810 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1812 c_options->thumbnails.spec_standard =FALSE;
1813 c_options->thumbnails.cache_into_dirs = FALSE;
1817 static void cache_local_cb(GtkWidget *widget, gpointer UNUSED(data))
1819 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1821 c_options->thumbnails.cache_into_dirs = TRUE;
1822 c_options->thumbnails.spec_standard =FALSE;
1826 static void help_search_engine_entry_icon_cb(GtkEntry *UNUSED(entry), GtkEntryIconPosition pos,
1827 GdkEvent *UNUSED(event), gpointer userdata)
1829 if (pos == GTK_ENTRY_ICON_PRIMARY)
1831 gtk_entry_set_text(GTK_ENTRY(userdata), HELP_SEARCH_ENGINE);
1835 gtk_entry_set_text(GTK_ENTRY(userdata), "");
1839 static void star_rating_star_icon_cb(GtkEntry *UNUSED(entry), GtkEntryIconPosition pos,
1840 GdkEvent *UNUSED(event), gpointer userdata)
1842 gchar *rating_symbol;
1844 if (pos == GTK_ENTRY_ICON_PRIMARY)
1846 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_STAR);
1847 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1848 g_free(rating_symbol);
1852 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1853 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1854 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1858 static void star_rating_rejected_icon_cb(GtkEntry *UNUSED(entry), GtkEntryIconPosition pos,
1859 GdkEvent *UNUSED(event), gpointer userdata)
1861 gchar *rating_symbol;
1863 if (pos == GTK_ENTRY_ICON_PRIMARY)
1865 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_REJECTED);
1866 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1867 g_free(rating_symbol);
1871 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1872 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1873 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1877 static guint star_rating_symbol_test(GtkWidget *UNUSED(widget), gpointer data)
1879 GtkContainer *hbox = data;
1880 GString *str = g_string_new(NULL);
1881 GtkEntry *hex_code_entry;
1882 gchar *hex_code_full;
1885 guint64 hex_value = 0;
1887 list = gtk_container_get_children(hbox);
1889 hex_code_entry = g_list_nth_data(list, 2);
1890 hex_code_full = g_strdup(gtk_entry_get_text(hex_code_entry));
1892 hex_code = g_strsplit(hex_code_full, "+", 2);
1893 if (hex_code[0] && hex_code[1])
1895 hex_value = strtoull(hex_code[1], NULL, 16);
1897 if (!hex_value || hex_value > 0x10FFFF)
1899 hex_value = 0x003F; // Unicode 'Question Mark'
1901 str = g_string_append_unichar(str, (gunichar)hex_value);
1902 gtk_label_set_text(g_list_nth_data(list, 1), str->str);
1904 g_strfreev(hex_code);
1905 g_string_free(str, TRUE);
1906 g_free(hex_code_full);
1911 static void star_rating_star_test_cb(GtkWidget *widget, gpointer data)
1913 guint64 star_symbol;
1915 star_symbol = star_rating_symbol_test(widget, data);
1916 c_options->star_rating.star = star_symbol;
1919 static void star_rating_rejected_test_cb(GtkWidget *widget, gpointer data)
1921 guint64 rejected_symbol;
1923 rejected_symbol = star_rating_symbol_test(widget, data);
1924 c_options->star_rating.rejected = rejected_symbol;
1927 /* general options tab */
1928 static void timezone_database_install_cb(GtkWidget *widget, gpointer data);
1929 typedef struct _TZData TZData;
1933 GCancellable *cancellable;
1935 GtkWidget *progress;
1937 GFile *timezone_database_gq;
1938 gchar *timezone_database_user;
1941 static void config_tab_general(GtkWidget *notebook)
1946 GtkWidget *group_frame;
1947 GtkWidget *subgroup;
1949 GtkWidget *ct_button;
1952 gint hours, minutes, remainder;
1954 GtkWidget *star_rating_entry;
1956 gchar *rating_symbol;
1959 gchar *download_locn;
1960 GNetworkMonitor *net_mon;
1961 GSocketConnectable *tz_org;
1962 gboolean internet_available = FALSE;
1965 vbox = scrolled_notebook_page(notebook, _("General"));
1967 group = pref_group_new(vbox, FALSE, _("Thumbnails"), GTK_ORIENTATION_VERTICAL);
1969 table = pref_table_new(group, 2, 2, FALSE, FALSE);
1970 add_thumb_size_menu(table, 0, 0, _("Size:"));
1971 add_quality_menu(table, 0, 1, _("Quality:"), options->thumbnails.quality, &c_options->thumbnails.quality);
1973 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1974 pref_label_new(hbox, _("Custom size: "));
1975 pref_spin_new_int(hbox, _("Width:"), NULL, 1, 512, 1, options->thumbnails.max_width, &c_options->thumbnails.max_width);
1976 pref_spin_new_int(hbox, _("Height:"), NULL, 1, 512, 1, options->thumbnails.max_height, &c_options->thumbnails.max_height);
1978 ct_button = pref_checkbox_new_int(group, _("Cache thumbnails and sim. files"),
1979 options->thumbnails.enable_caching, &c_options->thumbnails.enable_caching);
1981 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1982 pref_checkbox_link_sensitivity(ct_button, subgroup);
1984 c_options->thumbnails.spec_standard = options->thumbnails.spec_standard;
1985 c_options->thumbnails.cache_into_dirs = options->thumbnails.cache_into_dirs;
1986 group_frame = pref_frame_new(subgroup, TRUE, _("Use Geeqie thumbnail style and cache"),
1987 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1988 button = pref_radiobutton_new(group_frame, NULL, get_thumbnails_cache_dir(),
1989 !options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1990 G_CALLBACK(cache_geeqie_cb), NULL);
1992 group_frame = pref_frame_new(subgroup, TRUE,
1993 _("Store thumbnails local to image folder (non-standard)"),
1994 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1995 pref_radiobutton_new(group_frame, button, "*/.thumbnails",
1996 !options->thumbnails.spec_standard && options->thumbnails.cache_into_dirs,
1997 G_CALLBACK(cache_local_cb), NULL);
1999 group_frame = pref_frame_new(subgroup, TRUE,
2000 _("Use standard thumbnail style and cache, shared with other applications"),
2001 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2002 pref_radiobutton_new(group_frame, button, get_thumbnails_standard_cache_dir(),
2003 options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
2004 G_CALLBACK(cache_standard_cb), NULL);
2006 pref_checkbox_new_int(group, _("Use EXIF thumbnails when available (EXIF thumbnails may be outdated)"),
2007 options->thumbnails.use_exif, &c_options->thumbnails.use_exif);
2009 pref_checkbox_new_int(group, _("Thumbnail color management"),
2010 options->thumbnails.use_color_management, &c_options->thumbnails.use_color_management);
2012 spin = pref_spin_new_int(group, _("Collection preview:"), NULL,
2014 options->thumbnails.collection_preview, &c_options->thumbnails.collection_preview);
2015 gtk_widget_set_tooltip_text(spin, _("The maximum number of thumbnails shown in a Collection preview montage"));
2017 #ifdef HAVE_FFMPEGTHUMBNAILER_METADATA
2018 pref_checkbox_new_int(group, _("Use embedded metadata in video files as thumbnails when available"),
2019 options->thumbnails.use_ft_metadata, &c_options->thumbnails.use_ft_metadata);
2021 // pref_checkbox_new_int(group, _("Ignore embedded metadata if size is too small"),
2022 // options->thumbnails.use_ft_metadata_small, &c_options->thumbnails.use_ft_metadata_small);
2025 pref_spacer(group, PREF_PAD_GROUP);
2027 group = pref_group_new(vbox, FALSE, _("Star Rating"), GTK_ORIENTATION_VERTICAL);
2029 c_options->star_rating.star = options->star_rating.star;
2030 c_options->star_rating.rejected = options->star_rating.rejected;
2032 str = g_string_new(NULL);
2033 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2034 pref_label_new(hbox, _("Star character: "));
2035 str = g_string_append_unichar(str, options->star_rating.star);
2036 pref_label_new(hbox, g_strdup(str->str));
2037 rating_symbol = g_strdup_printf("U+%X", options->star_rating.star);
2038 star_rating_entry = gtk_entry_new();
2039 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
2040 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
2041 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
2042 gtk_widget_show(star_rating_entry);
2043 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
2044 G_CALLBACK(star_rating_star_test_cb), hbox);
2045 gtk_widget_set_tooltip_text(button, _("Display selected character"));
2046 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2047 gtk_widget_show(button);
2048 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."));
2049 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2050 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2051 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2052 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2053 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2054 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2055 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2056 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2057 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
2058 G_CALLBACK(star_rating_star_icon_cb),
2061 g_string_free(str, TRUE);
2062 g_free(rating_symbol);
2064 str = g_string_new(NULL);
2065 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2066 pref_label_new(hbox, _("Rejected character: "));
2067 str = g_string_append_unichar(str, options->star_rating.rejected);
2068 pref_label_new(hbox, g_strdup(str->str));
2069 rating_symbol = g_strdup_printf("U+%X", options->star_rating.rejected);
2070 star_rating_entry = gtk_entry_new();
2071 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
2072 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
2073 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
2074 gtk_widget_show(star_rating_entry);
2075 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
2076 G_CALLBACK(star_rating_rejected_test_cb), hbox);
2077 gtk_widget_set_tooltip_text(button, _("Display selected character"));
2078 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2079 gtk_widget_show(button);
2080 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."));
2081 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2082 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2083 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2084 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2085 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2086 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2087 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2088 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2089 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
2090 G_CALLBACK(star_rating_rejected_icon_cb),
2093 g_string_free(str, TRUE);
2094 g_free(rating_symbol);
2096 pref_spacer(group, PREF_PAD_GROUP);
2098 group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
2100 c_options->slideshow.delay = options->slideshow.delay;
2101 hours = options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2102 remainder = options->slideshow.delay % (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2103 minutes = remainder / (60 * SLIDESHOW_SUBSECOND_PRECISION);
2104 seconds = (gdouble)(remainder % (60 * SLIDESHOW_SUBSECOND_PRECISION)) /
2105 SLIDESHOW_SUBSECOND_PRECISION;
2107 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2109 spin = pref_spin_new(hbox, _("Delay between image change hrs:mins:secs.dec"), NULL,
2111 options->slideshow.delay ? hours : 0.0,
2112 G_CALLBACK(slideshow_delay_hours_cb), NULL);
2113 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2114 spin = pref_spin_new(hbox, ":" , NULL,
2116 options->slideshow.delay ? minutes: 0.0,
2117 G_CALLBACK(slideshow_delay_minutes_cb), NULL);
2118 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2119 spin = pref_spin_new(hbox, ":", NULL,
2120 SLIDESHOW_MIN_SECONDS, 59, 1.0, 1,
2121 options->slideshow.delay ? seconds : 10.0,
2122 G_CALLBACK(slideshow_delay_seconds_cb), NULL);
2123 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2125 pref_checkbox_new_int(group, _("Random"), options->slideshow.random, &c_options->slideshow.random);
2126 pref_checkbox_new_int(group, _("Repeat"), options->slideshow.repeat, &c_options->slideshow.repeat);
2128 pref_spacer(group, PREF_PAD_GROUP);
2130 group = pref_group_new(vbox, FALSE, _("Image loading and caching"), GTK_ORIENTATION_VERTICAL);
2132 pref_spin_new_int(group, _("Decoded image cache size (MiB):"), NULL,
2133 0, 99999, 1, options->image.image_cache_max, &c_options->image.image_cache_max);
2134 pref_checkbox_new_int(group, _("Preload next image"),
2135 options->image.enable_read_ahead, &c_options->image.enable_read_ahead);
2137 pref_checkbox_new_int(group, _("Refresh on file change"),
2138 options->update_on_time_change, &c_options->update_on_time_change);
2141 pref_spacer(group, PREF_PAD_GROUP);
2143 group = pref_group_new(vbox, FALSE, _("Expand menu and toolbar"), GTK_ORIENTATION_VERTICAL);
2145 pref_checkbox_new_int(group, _("Expand menu and toolbar (NOTE! Geeqie must be restarted for change to take effect)"),
2146 options->expand_menu_toolbar, &c_options->expand_menu_toolbar);
2147 gtk_widget_set_tooltip_text(group, _("Expand the menu and toolbar to the full width of the window"));
2149 pref_spacer(group, PREF_PAD_GROUP);
2151 net_mon = g_network_monitor_get_default();
2152 tz_org = g_network_address_parse_uri(TIMEZONE_DATABASE_WEB, 80, NULL);
2155 internet_available = g_network_monitor_can_reach(net_mon, tz_org, NULL, NULL);
2156 g_object_unref(tz_org);
2159 group = pref_group_new(vbox, FALSE, _("Timezone database"), GTK_ORIENTATION_VERTICAL);
2160 hbox = pref_box_new(group, TRUE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2162 if (!internet_available)
2164 gtk_widget_set_sensitive(group, FALSE);
2167 tz = g_new0(TZData, 1);
2169 path = path_from_utf8(TIMEZONE_DATABASE_WEB);
2170 basename = g_path_get_basename(path);
2171 tz->timezone_database_user = g_build_filename(get_rc_dir(), TIMEZONE_DATABASE_FILE, NULL);
2175 if (isfile(tz->timezone_database_user))
2177 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Update"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2181 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Install"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2184 download_locn = g_strconcat(_("Download database from: "), TIMEZONE_DATABASE_WEB, NULL);
2185 pref_label_new(GTK_WIDGET(hbox), download_locn);
2186 g_free(download_locn);
2188 if (!internet_available)
2190 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"));
2194 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"));
2196 gtk_widget_show(button);
2198 pref_spacer(group, PREF_PAD_GROUP);
2200 group = pref_group_new(vbox, FALSE, _("On-line help search engine"), GTK_ORIENTATION_VERTICAL);
2202 help_search_engine_entry = gtk_entry_new();
2203 gtk_entry_set_text(GTK_ENTRY(help_search_engine_entry), options->help_search_engine);
2204 gtk_box_pack_start(GTK_BOX(group), help_search_engine_entry, FALSE, FALSE, 0);
2205 gtk_widget_show(help_search_engine_entry);
2207 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"));
2209 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2210 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2211 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2212 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2213 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2214 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2215 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2216 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2217 g_signal_connect(GTK_ENTRY(help_search_engine_entry), "icon-press",
2218 G_CALLBACK(help_search_engine_entry_icon_cb),
2219 help_search_engine_entry);
2223 static void config_tab_image(GtkWidget *notebook)
2228 GtkWidget *ct_button;
2229 GtkWidget *enlargement_button;
2232 //~ #ifdef HAVE_CLUTTER
2233 //~ GtkWidget *gpu_accel;
2236 vbox = scrolled_notebook_page(notebook, _("Image"));
2238 group = pref_group_new(vbox, FALSE, _("Zoom"), GTK_ORIENTATION_VERTICAL);
2240 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2241 add_quality_menu(table, 0, 0, _("Quality:"), options->image.zoom_quality, &c_options->image.zoom_quality);
2242 //~ if (options->image.use_clutter_renderer && !options->disable_gpu)
2244 //~ gtk_widget_set_sensitive(table, FALSE);
2247 //~ #ifdef HAVE_CLUTTER
2248 //~ gpu_accel = pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library (Requires restart)"),
2249 //~ options->image.use_clutter_renderer, &c_options->image.use_clutter_renderer);
2250 //~ if (options->disable_gpu && !options->override_disable_gpu)
2252 //~ gtk_widget_set_sensitive(gpu_accel, FALSE);
2256 pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"),
2257 options->image.zoom_2pass, &c_options->image.zoom_2pass);
2258 //~ if (options->image.use_clutter_renderer && !options->disable_gpu)
2260 //~ gtk_widget_set_sensitive(two_pass, FALSE);
2263 c_options->image.zoom_increment = options->image.zoom_increment;
2264 spin = pref_spin_new(group, _("Zoom increment:"), NULL,
2265 0.01, 4.0, 0.01, 2, (gdouble)options->image.zoom_increment / 100.0,
2266 G_CALLBACK(zoom_increment_cb), NULL);
2267 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2269 c_options->image.zoom_style = options->image.zoom_style;
2270 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2271 add_zoom_style_selection_menu(table, 0, 0, _("Zoom style:"), options->image.zoom_style, &c_options->image.zoom_style);
2273 group = pref_group_new(vbox, FALSE, _("Fit image to window"), GTK_ORIENTATION_VERTICAL);
2275 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2276 enlargement_button = pref_checkbox_new_int(hbox, _("Allow enlargement of image (max. size in %)"),
2277 options->image.zoom_to_fit_allow_expand, &c_options->image.zoom_to_fit_allow_expand);
2278 spin = pref_spin_new_int(hbox, NULL, NULL,
2280 options->image.max_enlargement_size, &c_options->image.max_enlargement_size);
2281 pref_checkbox_link_sensitivity(enlargement_button, spin);
2282 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."));
2284 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2285 ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (% of actual window):"),
2286 options->image.limit_autofit_size, &c_options->image.limit_autofit_size);
2287 spin = pref_spin_new_int(hbox, NULL, NULL,
2289 options->image.max_autofit_size, &c_options->image.max_autofit_size);
2290 pref_checkbox_link_sensitivity(ct_button, spin);
2291 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."));
2293 group = pref_group_new(vbox, FALSE, _("Tile size"), GTK_ORIENTATION_VERTICAL);
2294 //~ gtk_widget_set_sensitive(group, !options->image.use_clutter_renderer);
2296 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2297 spin = pref_spin_new_int(hbox, _("Pixels"), _("(Requires restart)"),
2299 options->image.tile_size, &c_options->image.tile_size);
2300 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."));
2302 group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
2304 pref_checkbox_new_int(group, _("Use custom border color in window mode"),
2305 options->image.use_custom_border_color, &c_options->image.use_custom_border_color);
2307 pref_checkbox_new_int(group, _("Use custom border color in fullscreen mode"),
2308 options->image.use_custom_border_color_in_fullscreen, &c_options->image.use_custom_border_color_in_fullscreen);
2310 pref_color_button_new(group, _("Border color"), &options->image.border_color,
2311 G_CALLBACK(pref_color_button_set_cb), &c_options->image.border_color);
2313 c_options->image.border_color = options->image.border_color;
2315 pref_color_button_new(group, _("Alpha channel color 1"), &options->image.alpha_color_1,
2316 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_1);
2318 pref_color_button_new(group, _("Alpha channel color 2"), &options->image.alpha_color_2,
2319 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_2);
2321 c_options->image.alpha_color_1 = options->image.alpha_color_1;
2322 c_options->image.alpha_color_2 = options->image.alpha_color_2;
2327 static void save_default_window_layout_cb(GtkWidget *UNUSED(widget), gpointer UNUSED(data))
2329 LayoutWindow *lw = NULL;
2330 gchar *default_path;
2333 /* Get current lw */
2336 tmp_id = lw->options.id;
2337 lw->options.id = g_strdup("lw_default");
2339 default_path = g_build_filename(get_rc_dir(), DEFAULT_WINDOW_LAYOUT, NULL);
2340 save_default_layout_options_to_file(default_path, options, lw);
2341 g_free(lw->options.id);
2342 lw->options.id = tmp_id;
2343 g_free(default_path);
2346 static gboolean popover_cb(gpointer data)
2348 GtkPopover *popover = data;
2350 gtk_popover_popdown(popover);
2355 static void default_layout_changed_cb(GtkWidget *UNUSED(button), GtkPopover *popover)
2357 gtk_popover_popup(popover);
2359 g_timeout_add(2000, popover_cb, popover);
2362 static GtkWidget *create_popover(GtkWidget *parent, GtkWidget *child, GtkPositionType pos)
2366 popover = gtk_popover_new(parent);
2367 gtk_popover_set_position(GTK_POPOVER (popover), pos);
2368 gtk_container_add (GTK_CONTAINER(popover), child);
2369 gtk_container_set_border_width(GTK_CONTAINER (popover), 6);
2370 gtk_widget_show (child);
2375 static void config_tab_windows(GtkWidget *notebook)
2380 GtkWidget *subgroup;
2382 GtkWidget *ct_button;
2385 vbox = scrolled_notebook_page(notebook, _("Windows"));
2387 group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
2389 ct_button = pref_checkbox_new_int(group, _("Remember session"),
2390 options->save_window_positions, &c_options->save_window_positions);
2392 button = pref_checkbox_new_int(group, _("Use saved window positions also for new windows"),
2393 options->use_saved_window_positions_for_new_windows, &c_options->use_saved_window_positions_for_new_windows);
2394 pref_checkbox_link_sensitivity(ct_button, button);
2396 button = pref_checkbox_new_int(group, _("Remember window workspace"),
2397 options->save_window_workspace, &c_options->save_window_workspace);
2398 pref_checkbox_link_sensitivity(ct_button, button);
2400 pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
2401 options->tools_restore_state, &c_options->tools_restore_state);
2403 pref_checkbox_new_int(group, _("Remember dialog window positions"),
2404 options->save_dialog_window_positions, &c_options->save_dialog_window_positions);
2406 pref_checkbox_new_int(group, _("Show window IDs"),
2407 options->show_window_ids, &c_options->show_window_ids);
2409 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2410 pref_label_new(subgroup, _("Use current layout for default: "));
2411 button = pref_button_new(subgroup, NULL, _("Set"), FALSE, G_CALLBACK(save_default_window_layout_cb), NULL);
2415 popover = create_popover(button, gtk_label_new(_("Current window layout\nhas been set as default")), GTK_POS_TOP);
2416 gtk_popover_set_modal(GTK_POPOVER (popover), FALSE);
2417 g_signal_connect(button, "clicked", G_CALLBACK(default_layout_changed_cb), popover);
2419 group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
2421 pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
2422 options->image.fit_window_to_image, &c_options->image.fit_window_to_image);
2424 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2425 ct_button = pref_checkbox_new_int(hbox, _("Limit size when auto-sizing window (%):"),
2426 options->image.limit_window_size, &c_options->image.limit_window_size);
2427 spin = pref_spin_new_int(hbox, NULL, NULL,
2429 options->image.max_window_size, &c_options->image.max_window_size);
2430 pref_checkbox_link_sensitivity(ct_button, spin);
2432 group = pref_group_new(vbox, FALSE, _("Full screen"), GTK_ORIENTATION_VERTICAL);
2434 c_options->fullscreen.screen = options->fullscreen.screen;
2435 c_options->fullscreen.above = options->fullscreen.above;
2436 hbox = fullscreen_prefs_selection_new(_("Location:"), &c_options->fullscreen.screen, &c_options->fullscreen.above);
2437 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2438 gtk_widget_show(hbox);
2440 pref_checkbox_new_int(group, _("Smooth image flip"),
2441 options->fullscreen.clean_flip, &c_options->fullscreen.clean_flip);
2442 pref_checkbox_new_int(group, _("Disable screen saver"),
2443 options->fullscreen.disable_saver, &c_options->fullscreen.disable_saver);
2446 #define PRE_FORMATTED_COLUMNS 5
2447 static void config_tab_osd(GtkWidget *notebook)
2453 GtkWidget *image_overlay_template_view;
2454 GtkWidget *scrolled;
2455 GtkWidget *scrolled_pre_formatted;
2456 GtkTextBuffer *buffer;
2458 GtkWidget *subgroup;
2460 vbox = scrolled_notebook_page(notebook, _("OSD"));
2462 image_overlay_template_view = gtk_text_view_new();
2464 group = pref_group_new(vbox, FALSE, _("Overlay Screen Display"), GTK_ORIENTATION_VERTICAL);
2466 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2468 scrolled_pre_formatted = osd_new(PRE_FORMATTED_COLUMNS, image_overlay_template_view);
2469 gtk_widget_set_size_request(scrolled_pre_formatted, 200, 150);
2470 gtk_box_pack_start(GTK_BOX(subgroup), scrolled_pre_formatted, FALSE, FALSE, 0);
2471 gtk_widget_show(scrolled_pre_formatted);
2472 gtk_widget_show(subgroup);
2474 pref_line(group, PREF_PAD_GAP);
2476 pref_label_new(group, _("Image overlay template"));
2478 scrolled = gtk_scrolled_window_new(NULL, NULL);
2479 gtk_widget_set_size_request(scrolled, 200, 150);
2480 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2481 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
2482 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2483 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 5);
2484 gtk_widget_show(scrolled);
2486 gtk_widget_set_tooltip_markup(image_overlay_template_view,
2487 _("Extensive formatting options are shown in the Help file"));
2489 gtk_container_add(GTK_CONTAINER(scrolled), image_overlay_template_view);
2490 gtk_widget_show(image_overlay_template_view);
2492 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2494 button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
2495 G_CALLBACK(image_overlay_set_font_cb), notebook);
2497 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2498 gtk_widget_show(button);
2500 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Text"), FALSE,
2501 G_CALLBACK(image_overlay_set_text_colour_cb), NULL);
2502 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2503 gtk_widget_show(button);
2505 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Background"), FALSE,
2506 G_CALLBACK(image_overlay_set_background_colour_cb), NULL);
2507 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2508 gtk_widget_show(button);
2509 image_overlay_set_text_colours();
2511 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2512 G_CALLBACK(image_overlay_default_template_cb), image_overlay_template_view);
2513 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2514 gtk_widget_show(button);
2516 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
2517 G_CALLBACK(image_overlay_help_cb), NULL);
2518 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2519 gtk_widget_show(button);
2521 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_overlay_template_view));
2522 if (options->image_overlay.template_string) gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
2523 g_signal_connect(G_OBJECT(buffer), "changed",
2524 G_CALLBACK(image_overlay_template_view_changed_cb), image_overlay_template_view);
2526 pref_line(group, PREF_PAD_GAP);
2528 group = pref_group_new(vbox, FALSE, _("Exif, XMP or IPTC tags"), GTK_ORIENTATION_VERTICAL);
2529 hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
2530 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2531 gtk_widget_show(hbox);
2532 label = gtk_label_new(_("%Exif.Image.Orientation%"));
2533 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2534 gtk_widget_show(label);
2535 pref_spacer(group,TRUE);
2537 group = pref_group_new(vbox, FALSE, _("Field separators"), GTK_ORIENTATION_VERTICAL);
2538 hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
2539 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2540 gtk_widget_show(hbox);
2541 label = gtk_label_new(_("Separator shown only if both fields are non-null:\n%formatted.ShutterSpeed%|%formatted.ISOSpeedRating%"));
2542 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2543 gtk_widget_show(label);
2544 pref_spacer(group,TRUE);
2546 group = pref_group_new(vbox, FALSE, _("Field maximum length"), GTK_ORIENTATION_VERTICAL);
2547 hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
2548 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2549 gtk_widget_show(hbox);
2550 label = gtk_label_new(_("%path:39%"));
2551 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2552 gtk_widget_show(label);
2553 pref_spacer(group,TRUE);
2555 group = pref_group_new(vbox, FALSE, _("Pre- and post- text"), GTK_ORIENTATION_VERTICAL);
2556 hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
2557 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2558 gtk_widget_show(hbox);
2559 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%"));
2560 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2561 gtk_widget_show(label);
2562 pref_spacer(group,TRUE);
2564 group = pref_group_new(vbox, FALSE, _("Pango markup"), GTK_ORIENTATION_VERTICAL);
2565 hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
2566 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2567 gtk_widget_show(hbox);
2568 label = gtk_label_new(_("<b>bold</b>\n<u>underline</u>\n<i>italic</i>\n<s>strikethrough</s>"));
2569 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2570 gtk_widget_show(label);
2573 static GtkTreeModel *create_class_model(void)
2575 GtkListStore *model;
2579 /* create list store */
2580 model = gtk_list_store_new(1, G_TYPE_STRING);
2581 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
2583 gtk_list_store_append(model, &iter);
2584 gtk_list_store_set(model, &iter, 0, _(format_class_list[i]), -1);
2586 return GTK_TREE_MODEL (model);
2591 static gint filter_table_sort_cb(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer data)
2593 gint n = GPOINTER_TO_INT(data);
2595 FilterEntry *filter_a;
2596 FilterEntry *filter_b;
2598 gtk_tree_model_get(model, a, 0, &filter_a, -1);
2599 gtk_tree_model_get(model, b, 0, &filter_b, -1);
2603 case FILETYPES_COLUMN_ENABLED:
2605 ret = filter_a->enabled - filter_b->enabled;
2608 case FILETYPES_COLUMN_FILTER:
2610 ret = g_utf8_collate(filter_a->extensions, filter_b->extensions);
2613 case FILETYPES_COLUMN_DESCRIPTION:
2615 ret = g_utf8_collate(filter_a->description, filter_b->description);
2618 case FILETYPES_COLUMN_CLASS:
2620 ret = g_strcmp0(format_class_list[filter_a->file_class], format_class_list[filter_b->file_class]);
2623 case FILETYPES_COLUMN_WRITABLE:
2625 ret = filter_a->writable - filter_b->writable;
2628 case FILETYPES_COLUMN_SIDECAR:
2630 ret = filter_a->allow_sidecar - filter_b->allow_sidecar;
2634 g_return_val_if_reached(0);
2640 static gboolean search_function_cb(GtkTreeModel *model, gint UNUSED(column), const gchar *key, GtkTreeIter *iter, gpointer UNUSED(search_data))
2643 gboolean ret = TRUE;
2645 gtk_tree_model_get(model, iter, 0, &fe, -1);
2647 if (g_strstr_len(fe->extensions, -1, key))
2655 static void config_tab_files(GtkWidget *notebook)
2662 GtkWidget *ct_button;
2663 GtkWidget *scrolled;
2664 GtkWidget *filter_view;
2665 GtkCellRenderer *renderer;
2666 GtkTreeSelection *selection;
2667 GtkTreeViewColumn *column;
2669 vbox = scrolled_notebook_page(notebook, _("File Filters"));
2671 group = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2673 pref_checkbox_new_int(group, _("Show hidden files or folders"),
2674 options->file_filter.show_hidden_files, &c_options->file_filter.show_hidden_files);
2675 pref_checkbox_new_int(group, _("Show parent folder (..)"),
2676 options->file_filter.show_parent_directory, &c_options->file_filter.show_parent_directory);
2677 pref_checkbox_new_int(group, _("Case sensitive sort"),
2678 options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
2679 pref_checkbox_new_int(group, _("Natural sort order"),
2680 options->file_sort.natural, &c_options->file_sort.natural);
2681 pref_checkbox_new_int(group, _("Disable file extension checks"),
2682 options->file_filter.disable_file_extension_checks, &c_options->file_filter.disable_file_extension_checks);
2684 ct_button = pref_checkbox_new_int(group, _("Disable File Filtering"),
2685 options->file_filter.disable, &c_options->file_filter.disable);
2688 group = pref_group_new(vbox, FALSE, _("Grouping sidecar extensions"), GTK_ORIENTATION_VERTICAL);
2690 sidecar_ext_entry = gtk_entry_new();
2691 gtk_entry_set_text(GTK_ENTRY(sidecar_ext_entry), options->sidecar.ext);
2692 gtk_box_pack_start(GTK_BOX(group), sidecar_ext_entry, FALSE, FALSE, 0);
2693 gtk_widget_show(sidecar_ext_entry);
2695 group = pref_group_new(vbox, TRUE, _("File types"), GTK_ORIENTATION_VERTICAL);
2697 frame = pref_group_parent(group);
2698 g_signal_connect(G_OBJECT(ct_button), "toggled",
2699 G_CALLBACK(filter_disable_cb), frame);
2700 gtk_widget_set_sensitive(frame, !options->file_filter.disable);
2702 scrolled = gtk_scrolled_window_new(NULL, NULL);
2703 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2704 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2705 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2706 gtk_widget_show(scrolled);
2708 filter_store = gtk_list_store_new(1, G_TYPE_POINTER);
2709 filter_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(filter_store));
2710 g_object_unref(filter_store);
2711 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
2712 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
2714 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), FALSE);
2716 column = gtk_tree_view_column_new();
2717 gtk_tree_view_column_set_title(column, _("Enabled"));
2718 gtk_tree_view_column_set_resizable(column, TRUE);
2720 renderer = gtk_cell_renderer_toggle_new();
2721 g_signal_connect(G_OBJECT(renderer), "toggled",
2722 G_CALLBACK(filter_store_enable_cb), filter_store);
2723 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2724 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2725 GINT_TO_POINTER(FE_ENABLE), NULL);
2726 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(filter_store), FILETYPES_COLUMN_ENABLED, filter_table_sort_cb, GINT_TO_POINTER(FILETYPES_COLUMN_ENABLED), NULL);
2727 gtk_tree_view_column_set_sort_column_id(column, FILETYPES_COLUMN_ENABLED);
2728 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2730 column = gtk_tree_view_column_new();
2731 gtk_tree_view_column_set_title(column, _("Filter"));
2732 gtk_tree_view_column_set_resizable(column, TRUE);
2733 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(filter_store), FILETYPES_COLUMN_FILTER, filter_table_sort_cb, GINT_TO_POINTER(FILETYPES_COLUMN_FILTER), NULL);
2734 gtk_tree_view_column_set_sort_column_id(column, FILETYPES_COLUMN_FILTER);
2736 renderer = gtk_cell_renderer_text_new();
2737 g_signal_connect(G_OBJECT(renderer), "edited",
2738 G_CALLBACK(filter_store_ext_edit_cb), filter_store);
2739 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2740 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2741 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2742 GINT_TO_POINTER(FE_EXTENSION), NULL);
2743 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2745 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), TRUE);
2746 gtk_tree_view_set_search_column(GTK_TREE_VIEW(filter_view), FILETYPES_COLUMN_FILTER);
2747 gtk_tree_view_set_search_equal_func(GTK_TREE_VIEW(filter_view), search_function_cb, NULL, NULL);
2749 column = gtk_tree_view_column_new();
2750 gtk_tree_view_column_set_title(column, _("Description"));
2751 gtk_tree_view_column_set_resizable(column, TRUE);
2752 gtk_tree_view_column_set_fixed_width(column, 200);
2753 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
2755 renderer = gtk_cell_renderer_text_new();
2756 g_signal_connect(G_OBJECT(renderer), "edited",
2757 G_CALLBACK(filter_store_desc_edit_cb), filter_store);
2758 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2759 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2760 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2761 GINT_TO_POINTER(FE_DESCRIPTION), NULL);
2762 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2763 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);
2764 gtk_tree_view_column_set_sort_column_id(column, FILETYPES_COLUMN_DESCRIPTION);
2766 column = gtk_tree_view_column_new();
2767 gtk_tree_view_column_set_title(column, _("Class"));
2768 gtk_tree_view_column_set_resizable(column, TRUE);
2769 renderer = gtk_cell_renderer_combo_new();
2770 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE,
2771 "model", create_class_model(),
2776 g_signal_connect(G_OBJECT(renderer), "edited",
2777 G_CALLBACK(filter_store_class_edit_cb), filter_store);
2778 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2779 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2780 GINT_TO_POINTER(FE_CLASS), NULL);
2781 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2782 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);
2783 gtk_tree_view_column_set_sort_column_id(column, FILETYPES_COLUMN_CLASS);
2785 column = gtk_tree_view_column_new();
2786 gtk_tree_view_column_set_title(column, _("Writable"));
2787 gtk_tree_view_column_set_resizable(column, FALSE);
2788 renderer = gtk_cell_renderer_toggle_new();
2789 g_signal_connect(G_OBJECT(renderer), "toggled",
2790 G_CALLBACK(filter_store_writable_cb), filter_store);
2791 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2792 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2793 GINT_TO_POINTER(FE_WRITABLE), NULL);
2794 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2795 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);
2796 gtk_tree_view_column_set_sort_column_id(column, FILETYPES_COLUMN_WRITABLE);
2798 column = gtk_tree_view_column_new();
2799 gtk_tree_view_column_set_title(column, _("Sidecar is allowed"));
2800 gtk_tree_view_column_set_resizable(column, FALSE);
2801 renderer = gtk_cell_renderer_toggle_new();
2802 g_signal_connect(G_OBJECT(renderer), "toggled",
2803 G_CALLBACK(filter_store_sidecar_cb), filter_store);
2804 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2805 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2806 GINT_TO_POINTER(FE_ALLOW_SIDECAR), NULL);
2807 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2808 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);
2809 gtk_tree_view_column_set_sort_column_id(column, FILETYPES_COLUMN_SIDECAR);
2811 filter_store_populate();
2812 gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
2813 gtk_widget_show(filter_view);
2815 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2817 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2818 G_CALLBACK(filter_default_cb), filter_view);
2819 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2820 gtk_widget_show(button);
2822 button = pref_button_new(NULL, GTK_STOCK_REMOVE, NULL, FALSE,
2823 G_CALLBACK(filter_remove_cb), filter_view);
2824 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2825 gtk_widget_show(button);
2827 button = pref_button_new(NULL, GTK_STOCK_ADD, NULL, FALSE,
2828 G_CALLBACK(filter_add_cb), filter_view);
2829 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2830 gtk_widget_show(button);
2834 static void config_tab_metadata(GtkWidget *notebook)
2839 GtkWidget *ct_button;
2841 GtkWidget *tmp_widget;
2843 GtkWidget *text_label;
2845 vbox = scrolled_notebook_page(notebook, _("Metadata"));
2848 group = pref_group_new(vbox, FALSE, _("Metadata writing sequence"), GTK_ORIENTATION_VERTICAL);
2850 label = pref_label_new(group, _("Warning: Geeqie is built without Exiv2. Some options are disabled."));
2852 label = pref_label_new(group, _("When writing metadata, Geeqie will follow these steps, if selected. This process will stop when the first successful write occurs."));
2853 gtk_label_set_xalign(GTK_LABEL(label), 0.0);
2854 gtk_label_set_yalign(GTK_LABEL(label), 0.5);
2856 gtk_widget_set_tooltip_text(label, _("A flowchart of the sequence is shown in the Help file"));
2858 ct_button = pref_checkbox_new_int(group, "", options->metadata.save_in_image_file, &c_options->metadata.save_in_image_file);
2859 text_label = gtk_bin_get_child(GTK_BIN(ct_button));
2860 markup = g_markup_printf_escaped ("<span weight=\"bold\">%s</span>%s", _("Step 1"), _(") Save metadata in either the image file or the sidecar file, according to the XMP standard"));
2861 gtk_label_set_markup (GTK_LABEL(text_label), markup);
2863 markup = g_markup_printf_escaped ("%s<span style=\"italic\">%s</span>%s<span style=\"italic\">%s</span>%s", _("The destination is dependent on the settings in the "), _("Writable"), _(" and "), _("Sidecar Is Allowed"), _(" columns of the File Filters tab)"));
2864 gtk_widget_set_tooltip_markup(ct_button, markup);
2868 gtk_widget_set_sensitive(ct_button, FALSE);
2871 tmp_widget = pref_checkbox_new_int(group, "", options->metadata.enable_metadata_dirs, &c_options->metadata.enable_metadata_dirs);
2872 text_label = gtk_bin_get_child(GTK_BIN(tmp_widget));
2873 markup = g_markup_printf_escaped ("<span weight=\"bold\">%s</span>%s<span style=\"italic\">%s</span>%s", _("Step 2"), _(") Save metadata in the folder "),".metadata,", _(" local to the image folder (non-standard)"));
2874 gtk_label_set_markup (GTK_LABEL(text_label), markup);
2877 label = pref_label_new(group, "");
2878 markup = g_markup_printf_escaped ("<span weight=\"bold\">%s</span>%s<span style=\"italic\">%s</span>%s", _("Step 3"), _(") Save metadata in Geeqie private directory "), get_metadata_cache_dir(), "/");
2879 gtk_label_set_markup (GTK_LABEL(label), markup);
2882 gtk_label_set_xalign(GTK_LABEL(label), 0.0);
2883 gtk_label_set_yalign(GTK_LABEL(label), 0.5);
2884 gtk_misc_set_padding(GTK_MISC(label), 22, 0);
2885 pref_spacer(group, PREF_PAD_GROUP);
2887 group = pref_group_new(vbox, FALSE, _("Step 1 Options:"), GTK_ORIENTATION_VERTICAL);
2889 gtk_widget_set_sensitive(group, FALSE);
2892 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2893 pref_checkbox_link_sensitivity(ct_button, hbox);
2895 tmp_widget= pref_checkbox_new_int(hbox, _("Store metadata also in IPTC tags (converted according to the IPTC4XMP standard)"), options->metadata.save_legacy_IPTC, &c_options->metadata.save_legacy_IPTC);
2896 gtk_widget_set_tooltip_text(tmp_widget, _("A simplified conversion list is in the Help file"));
2898 pref_checkbox_new_int(hbox, _("Warn if the image or sidecar file is not writable"), options->metadata.warn_on_write_problems, &c_options->metadata.warn_on_write_problems);
2900 pref_checkbox_new_int(hbox, _("Ask before writing to image files"), options->metadata.confirm_write, &c_options->metadata.confirm_write);
2902 tmp_widget= pref_checkbox_new_int(hbox, "", options->metadata.sidecar_extended_name, &c_options->metadata.sidecar_extended_name);
2903 gtk_widget_set_tooltip_text(tmp_widget, _("This file naming convention is used by Darktable"));
2904 text_label = gtk_bin_get_child(GTK_BIN(tmp_widget));
2905 markup = g_markup_printf_escaped ("%s<span style=\"italic\">%s</span>%s<span style=\"italic\">%s</span>%s", _("Create sidecar files named "), "image.ext.xmp", _(" (as opposed to the normal "), "image.xmp", ")");
2906 gtk_label_set_markup (GTK_LABEL(text_label), markup);
2909 pref_spacer(group, PREF_PAD_GROUP);
2911 group = pref_group_new(vbox, FALSE, _("Steps 2 and 3 Option:"), GTK_ORIENTATION_VERTICAL);
2913 gtk_widget_set_sensitive(group, FALSE);
2916 pref_checkbox_new_int(group, _("Use GQview legacy metadata format instead of XMP (supports only Keywords and Comments)"), options->metadata.save_legacy_format, &c_options->metadata.save_legacy_format);
2918 pref_spacer(group, PREF_PAD_GROUP);
2920 group = pref_group_new(vbox, FALSE, _("Miscellaneous"), GTK_ORIENTATION_VERTICAL);
2921 tmp_widget = pref_checkbox_new_int(group, _("Write the same description tags to all grouped sidecars"), options->metadata.sync_grouped_files, &c_options->metadata.sync_grouped_files);
2922 gtk_widget_set_tooltip_text(tmp_widget, _("See the Help file for a list of the tags used"));
2924 tmp_widget = pref_checkbox_new_int(group, _("Permit Keywords to be case-sensitive"), options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
2925 gtk_widget_set_tooltip_text(tmp_widget, _("When selected, \"Place\" and \"place\" are two different keywords"));
2927 ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"), options->metadata.write_orientation, &c_options->metadata.write_orientation);
2928 gtk_widget_set_tooltip_text(ct_button, _("If checked, the results of orientation commands (Rotate, Mirror and Flip) issued on an image will be written to metadata\nNote: If this option is not checked, the results of orientation commands will be lost when Geeqie closes"));
2931 gtk_widget_set_sensitive(ct_button, FALSE);
2934 pref_spacer(group, PREF_PAD_GROUP);
2936 group = pref_group_new(vbox, FALSE, _("Auto-save options"), GTK_ORIENTATION_VERTICAL);
2938 ct_button = pref_checkbox_new_int(group, _("Write metadata after timeout"), options->metadata.confirm_after_timeout, &c_options->metadata.confirm_after_timeout);
2940 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2941 pref_checkbox_link_sensitivity(ct_button, hbox);
2943 pref_spin_new_int(hbox, _("Timeout (seconds):"), NULL, 0, 900, 1, options->metadata.confirm_timeout, &c_options->metadata.confirm_timeout);
2945 pref_checkbox_new_int(group, _("Write metadata on image change"), options->metadata.confirm_on_image_change, &c_options->metadata.confirm_on_image_change);
2947 pref_checkbox_new_int(group, _("Write metadata on directory change"), options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
2949 pref_spacer(group, PREF_PAD_GROUP);
2952 group = pref_group_new(vbox, FALSE, _("Spelling checks"), GTK_ORIENTATION_VERTICAL);
2954 ct_button = pref_checkbox_new_int(group, _("Check spelling - Requires restart"), options->metadata.check_spelling, &c_options->metadata.check_spelling);
2955 gtk_widget_set_tooltip_text(ct_button, _("Spelling checks are performed on info sidebar panes Comment, Headline and Title"));
2958 pref_spacer(group, PREF_PAD_GROUP);
2960 group = pref_group_new(vbox, FALSE, _("Pre-load metadata"), GTK_ORIENTATION_VERTICAL);
2962 ct_button = pref_checkbox_new_int(group, _("Read metadata in background"), options->read_metadata_in_idle, &c_options->read_metadata_in_idle);
2963 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");
2968 typedef struct _KeywordFindData KeywordFindData;
2969 struct _KeywordFindData
2976 GtkWidget *button_close;
2977 GtkWidget *button_stop;
2978 GtkWidget *button_start;
2979 GtkWidget *progress;
2987 guint idle_id; /* event source id */
2990 #define KEYWORD_DIALOG_WIDTH 400
2992 static void keywords_find_folder(KeywordFindData *kfd, FileData *dir_fd)
2994 GList *list_d = NULL;
2995 GList *list_f = NULL;
2999 filelist_read(dir_fd, &list_f, &list_d);
3003 filelist_read(dir_fd, &list_f, NULL);
3006 list_f = filelist_filter(list_f, FALSE);
3007 list_d = filelist_filter(list_d, TRUE);
3009 kfd->list = g_list_concat(list_f, kfd->list);
3010 kfd->list_dir = g_list_concat(list_d, kfd->list_dir);
3013 static void keywords_find_reset(KeywordFindData *kfd)
3015 filelist_free(kfd->list);
3018 filelist_free(kfd->list_dir);
3019 kfd->list_dir = NULL;
3022 static void keywords_find_close_cb(GenericDialog *UNUSED(fd), gpointer data)
3024 KeywordFindData *kfd = data;
3026 if (!gtk_widget_get_sensitive(kfd->button_close)) return;
3028 keywords_find_reset(kfd);
3029 generic_dialog_close(kfd->gd);
3033 static void keywords_find_finish(KeywordFindData *kfd)
3035 keywords_find_reset(kfd);
3037 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("done"));
3038 spinner_set_interval(kfd->spinner, -1);
3040 gtk_widget_set_sensitive(kfd->group, TRUE);
3041 gtk_widget_set_sensitive(kfd->button_start, TRUE);
3042 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
3043 gtk_widget_set_sensitive(kfd->button_close, TRUE);
3046 static void keywords_find_stop_cb(GenericDialog *UNUSED(fd), gpointer data)
3048 KeywordFindData *kfd = data;
3050 g_idle_remove_by_data(kfd);
3052 keywords_find_finish(kfd);
3055 static gboolean keywords_find_file(gpointer data)
3057 KeywordFindData *kfd = data;
3059 GtkTextBuffer *buffer;
3067 fd = kfd->list->data;
3068 kfd->list = g_list_remove(kfd->list, fd);
3070 keywords = metadata_read_list(fd, KEYWORD_KEY, METADATA_PLAIN);
3071 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3075 gtk_text_buffer_get_end_iter(buffer, &iter);
3076 tmp = g_strconcat(keywords->data, "\n", NULL);
3077 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
3079 keywords = keywords->next;
3082 gtk_entry_set_text(GTK_ENTRY(kfd->progress), fd->path);
3083 file_data_unref(fd);
3084 string_list_free(keywords);
3088 else if (kfd->list_dir)
3092 fd = kfd->list_dir->data;
3093 kfd->list_dir = g_list_remove(kfd->list_dir, fd);
3095 keywords_find_folder(kfd, fd);
3097 file_data_unref(fd);
3102 keywords_find_finish(kfd);
3107 static void keywords_find_start_cb(GenericDialog *UNUSED(fd), gpointer data)
3109 KeywordFindData *kfd = data;
3112 if (kfd->list || !gtk_widget_get_sensitive(kfd->button_start)) return;
3114 path = remove_trailing_slash((gtk_entry_get_text(GTK_ENTRY(kfd->entry))));
3115 parse_out_relatives(path);
3119 warning_dialog(_("Invalid folder"),
3120 _("The specified folder can not be found."),
3121 GTK_STOCK_DIALOG_WARNING, kfd->gd->dialog);
3127 gtk_widget_set_sensitive(kfd->group, FALSE);
3128 gtk_widget_set_sensitive(kfd->button_start, FALSE);
3129 gtk_widget_set_sensitive(kfd->button_stop, TRUE);
3130 gtk_widget_set_sensitive(kfd->button_close, FALSE);
3131 spinner_set_interval(kfd->spinner, SPINNER_SPEED);
3133 dir_fd = file_data_new_dir(path);
3134 keywords_find_folder(kfd, dir_fd);
3135 file_data_unref(dir_fd);
3136 kfd->idle_id = g_idle_add(keywords_find_file, kfd);
3142 static void keywords_find_dialog(GtkWidget *widget, const gchar *path)
3144 KeywordFindData *kfd;
3148 kfd = g_new0(KeywordFindData, 1);
3150 kfd->gd = generic_dialog_new(_("Search for keywords"),
3151 "search_for_keywords",
3154 gtk_window_set_default_size(GTK_WINDOW(kfd->gd->dialog), KEYWORD_DIALOG_WIDTH, -1);
3155 kfd->gd->cancel_cb = keywords_find_close_cb;
3156 kfd->button_close = generic_dialog_add_button(kfd->gd, GTK_STOCK_CLOSE, NULL,
3157 keywords_find_close_cb, FALSE);
3158 kfd->button_start = generic_dialog_add_button(kfd->gd, GTK_STOCK_OK, _("S_tart"),
3159 keywords_find_start_cb, FALSE);
3160 kfd->button_stop = generic_dialog_add_button(kfd->gd, GTK_STOCK_STOP, NULL,
3161 keywords_find_stop_cb, FALSE);
3162 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
3164 generic_dialog_add_message(kfd->gd, NULL, _("Search for keywords"), NULL, FALSE);
3166 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0);
3167 pref_spacer(hbox, PREF_PAD_INDENT);
3168 kfd->group = pref_box_new(hbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
3170 hbox = pref_box_new(kfd->group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3171 pref_label_new(hbox, _("Folder:"));
3173 label = tab_completion_new(&kfd->entry, path, NULL, NULL, NULL, NULL);
3174 tab_completion_add_select_button(kfd->entry,_("Select folder") , TRUE);
3175 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
3176 gtk_widget_show(label);
3178 pref_checkbox_new_int(kfd->group, _("Include subfolders"), FALSE, &kfd->recurse);
3180 pref_line(kfd->gd->vbox, PREF_PAD_SPACE);
3181 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3183 kfd->progress = gtk_entry_new();
3184 gtk_widget_set_can_focus(kfd->progress, FALSE);
3185 gtk_editable_set_editable(GTK_EDITABLE(kfd->progress), FALSE);
3186 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("click start to begin"));
3187 gtk_box_pack_start(GTK_BOX(hbox), kfd->progress, TRUE, TRUE, 0);
3188 gtk_widget_show(kfd->progress);
3190 kfd->spinner = spinner_new(NULL, -1);
3191 gtk_box_pack_start(GTK_BOX(hbox), kfd->spinner, FALSE, FALSE, 0);
3192 gtk_widget_show(kfd->spinner);
3196 gtk_widget_show(kfd->gd->dialog);
3199 static void keywords_find_cb(GtkWidget *widget, gpointer UNUSED(data))
3201 const gchar *path = layout_get_path(NULL);
3203 if (!path || !*path) path = homedir();
3204 keywords_find_dialog(widget, path);
3207 static void config_tab_keywords_save()
3209 GtkTextIter start, end;
3210 GtkTextBuffer *buffer;
3211 GList *kw_list = NULL;
3217 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3218 gtk_text_buffer_get_bounds(buffer, &start, &end);
3220 buffer_text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
3222 kw_split = strtok(buffer_text, "\n");
3223 while (kw_split != NULL)
3229 if (g_strcmp0(work->data, kw_split) == 0)
3238 kw_list = g_list_append(kw_list, g_strdup(kw_split));
3240 kw_split = strtok(NULL, "\n");
3243 keyword_list_set(kw_list);
3245 string_list_free(kw_list);
3246 g_free(buffer_text);
3249 static void config_tab_keywords(GtkWidget *notebook)
3255 GtkWidget *scrolled;
3257 GtkTextBuffer *buffer;
3260 GspellTextView *gspell_view;
3263 vbox = scrolled_notebook_page(notebook, _("Keywords"));
3265 group = pref_group_new(vbox, TRUE, _("Edit keywords autocompletion list"), GTK_ORIENTATION_VERTICAL);
3267 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3269 button = pref_button_new(hbox, GTK_STOCK_EXECUTE, _("Search"), FALSE,
3270 G_CALLBACK(keywords_find_cb), keyword_text);
3271 gtk_widget_set_tooltip_text(button, "Search for existing keywords");
3274 keyword_text = gtk_text_view_new();
3275 gtk_widget_set_size_request(keyword_text, 20, 20);
3276 scrolled = gtk_scrolled_window_new(NULL, NULL);
3277 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3278 gtk_widget_show(scrolled);
3281 if (options->metadata.check_spelling)
3283 gspell_view = gspell_text_view_get_from_gtk_text_view(GTK_TEXT_VIEW(keyword_text));
3284 gspell_text_view_basic_setup(gspell_view);
3288 gtk_container_add(GTK_CONTAINER(scrolled), keyword_text);
3289 gtk_widget_show(keyword_text);
3291 gtk_text_view_set_editable(GTK_TEXT_VIEW(keyword_text), TRUE);
3293 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3294 gtk_text_buffer_create_tag(buffer, "monospace",
3295 "family", "monospace", NULL);
3297 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(keyword_text), GTK_WRAP_WORD);
3298 gtk_text_buffer_get_start_iter(buffer, &iter);
3299 gtk_text_buffer_create_mark(buffer, "end", &iter, FALSE);
3302 path = g_build_filename(get_rc_dir(), "keywords", NULL);
3304 GList *kwl = keyword_list_get();
3305 kwl = g_list_first(kwl);
3308 gtk_text_buffer_get_end_iter (buffer, &iter);
3309 tmp = g_strconcat(kwl->data, "\n", NULL);
3310 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
3315 gtk_text_buffer_set_modified(buffer, FALSE);
3322 static void intent_menu_cb(GtkWidget *combo, gpointer data)
3324 gint *option = data;
3326 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
3330 *option = INTENT_PERCEPTUAL;
3333 *option = INTENT_RELATIVE_COLORIMETRIC;
3336 *option = INTENT_SATURATION;
3339 *option = INTENT_ABSOLUTE_COLORIMETRIC;
3344 static void add_intent_menu(GtkWidget *table, gint column, gint row, const gchar *text,
3345 gint option, gint *option_c)
3352 pref_table_label(table, column, row, text, 0.0);
3354 combo = gtk_combo_box_text_new();
3356 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Perceptual"));
3357 if (option == INTENT_PERCEPTUAL) current = 0;
3358 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Relative Colorimetric"));
3359 if (option == INTENT_RELATIVE_COLORIMETRIC) current = 1;
3360 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Saturation"));
3361 if (option == INTENT_SATURATION) current = 2;
3362 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Absolute Colorimetric"));
3363 if (option == INTENT_ABSOLUTE_COLORIMETRIC) current = 3;
3365 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
3367 gtk_widget_set_tooltip_text(combo,"Refer to the lcms documentation for the defaults used when the selected Intent is not available");
3369 g_signal_connect(G_OBJECT(combo), "changed",
3370 G_CALLBACK(intent_menu_cb), option_c);
3372 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
3373 gtk_widget_show(combo);
3377 static void config_tab_color(GtkWidget *notebook)
3386 vbox = scrolled_notebook_page(notebook, _("Color management"));
3388 group = pref_group_new(vbox, FALSE, _("Input profiles"), GTK_ORIENTATION_VERTICAL);
3390 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3393 table = pref_table_new(group, 3, COLOR_PROFILE_INPUTS + 1, FALSE, FALSE);
3394 gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
3396 label = pref_table_label(table, 0, 0, _("Type"), 0.0);
3397 pref_label_bold(label, TRUE, FALSE);
3399 label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
3400 pref_label_bold(label, TRUE, FALSE);
3402 label = pref_table_label(table, 2, 0, _("File"), 0.0);
3403 pref_label_bold(label, TRUE, FALSE);
3405 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
3410 buf = g_strdup_printf(_("Input %d:"), i + COLOR_PROFILE_FILE);
3411 pref_table_label(table, 0, i + 1, buf, 1.0);
3414 entry = gtk_entry_new();
3415 gtk_entry_set_max_length(GTK_ENTRY(entry), EDITOR_NAME_MAX_LENGTH);
3416 if (options->color_profile.input_name[i])
3418 gtk_entry_set_text(GTK_ENTRY(entry), options->color_profile.input_name[i]);
3420 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, i + 1, i + 2,
3421 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3422 gtk_widget_show(entry);
3423 color_profile_input_name_entry[i] = entry;
3425 tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, ".icc", "ICC Files", NULL);
3426 tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
3427 gtk_widget_set_size_request(entry, 160, -1);
3428 gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
3429 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3430 gtk_widget_show(tabcomp);
3431 color_profile_input_file_entry[i] = entry;
3434 group = pref_group_new(vbox, FALSE, _("Screen profile"), GTK_ORIENTATION_VERTICAL);
3436 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3438 pref_checkbox_new_int(group, _("Use system screen profile if available"),
3439 options->color_profile.use_x11_screen_profile, &c_options->color_profile.use_x11_screen_profile);
3441 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3443 pref_table_label(table, 0, 0, _("Screen:"), 1.0);
3444 tabcomp = tab_completion_new(&color_profile_screen_file_entry,
3445 options->color_profile.screen_file, NULL, ".icc", "ICC Files", NULL);
3446 tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
3447 gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
3449 add_intent_menu(table, 0, 1, _("Render Intent:"), options->color_profile.render_intent, &c_options->color_profile.render_intent);
3451 gtk_table_attach(GTK_TABLE(table), tabcomp, 1, 2,
3453 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3455 gtk_widget_show(tabcomp);
3458 /* advanced entry tab */
3459 static void use_geeqie_trash_cb(GtkWidget *widget, gpointer UNUSED(data))
3461 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3463 c_options->file_ops.use_system_trash = FALSE;
3464 c_options->file_ops.no_trash = FALSE;
3468 static void use_system_trash_cb(GtkWidget *widget, gpointer UNUSED(data))
3470 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3472 c_options->file_ops.use_system_trash = TRUE;
3473 c_options->file_ops.no_trash = FALSE;
3477 static void use_no_cache_cb(GtkWidget *widget, gpointer UNUSED(data))
3479 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3481 c_options->file_ops.no_trash = TRUE;
3485 static void config_tab_behavior(GtkWidget *notebook)
3492 GtkWidget *ct_button;
3496 GtkWidget *with_rename;
3497 GtkWidget *collections_on_top;
3498 GtkWidget *hide_window_in_fullscreen;
3499 GtkWidget *checkbox;
3502 vbox = scrolled_notebook_page(notebook, _("Behavior"));
3504 group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
3506 pref_checkbox_new_int(group, _("Confirm permanent file delete"),
3507 options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
3508 pref_checkbox_new_int(group, _("Confirm move file to Trash"),
3509 options->file_ops.confirm_move_to_trash, &c_options->file_ops.confirm_move_to_trash);
3510 pref_checkbox_new_int(group, _("Enable Delete key"),
3511 options->file_ops.enable_delete_key, &c_options->file_ops.enable_delete_key);
3513 ct_button = pref_radiobutton_new(group, NULL, _("Use Geeqie trash location"),
3514 !options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_geeqie_trash_cb),NULL);
3516 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3517 pref_checkbox_link_sensitivity(ct_button, hbox);
3519 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
3520 pref_label_new(hbox, _("Folder:"));
3522 tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL, NULL, NULL);
3523 tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
3524 gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
3525 gtk_widget_show(tabcomp);
3527 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3528 pref_checkbox_link_sensitivity(ct_button, hbox);
3530 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
3531 spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MiB"),
3532 0, 2048, 1, options->file_ops.safe_delete_folder_maxsize, &c_options->file_ops.safe_delete_folder_maxsize);
3533 gtk_widget_set_tooltip_markup(spin, _("Set to 0 for unlimited size"));
3534 button = pref_button_new(NULL, NULL, _("View"), FALSE,
3535 G_CALLBACK(safe_delete_view_cb), NULL);
3536 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3537 gtk_widget_show(button);
3539 button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
3540 G_CALLBACK(safe_delete_clear_cb), NULL);
3541 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3543 c_options->file_ops.no_trash = options->file_ops.no_trash;
3544 c_options->file_ops.use_system_trash = options->file_ops.use_system_trash;
3546 pref_radiobutton_new(group, ct_button, _("Use system Trash bin"),
3547 options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_system_trash_cb), NULL);
3549 pref_radiobutton_new(group, ct_button, _("Use no trash at all"),
3550 options->file_ops.no_trash, G_CALLBACK(use_no_cache_cb), NULL);
3552 gtk_widget_show(button);
3554 pref_spacer(group, PREF_PAD_GROUP);
3557 group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
3559 pref_checkbox_new_int(group, _("Descend folders in tree view"),
3560 options->tree_descend_subdirs, &c_options->tree_descend_subdirs);
3562 pref_checkbox_new_int(group, _("In place renaming"),
3563 options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
3565 pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
3566 options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
3568 tmp = pref_checkbox_new_int(group, _("Circular selection lists"),
3569 options->circular_selection_lists, &c_options->circular_selection_lists);
3570 gtk_widget_set_tooltip_text(tmp, _("Traverse selection lists in a circular manner"));
3572 marks = pref_checkbox_new_int(group, _("Save marks on exit"),
3573 options->marks_save, &c_options->marks_save);
3574 gtk_widget_set_tooltip_text(marks,"Note that marks linked to a keyword will be saved irrespective of this setting");
3576 with_rename = pref_checkbox_new_int(group, _("Use \"With Rename\" as default for Copy/Move dialogs"),
3577 options->with_rename, &c_options->with_rename);
3578 gtk_widget_set_tooltip_text(with_rename,"Change the default button for Copy/Move dialogs");
3580 collections_on_top = pref_checkbox_new_int(group, _("Open collections on top"),
3581 options->collections_on_top, &c_options->collections_on_top);
3582 gtk_widget_set_tooltip_text(collections_on_top,"Open collections window on top");
3584 hide_window_in_fullscreen = pref_checkbox_new_int(group, _("Hide window in fullscreen"),
3585 options->hide_window_in_fullscreen, &c_options->hide_window_in_fullscreen);
3586 gtk_widget_set_tooltip_text(hide_window_in_fullscreen,"When alt-tabbing, prevent Geeqie window showing twice");
3588 pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
3589 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
3591 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);
3592 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."));
3594 pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
3595 16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
3597 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3598 add_dnd_default_action_selection_menu(table, 0, 0, _("Drag`n drop default action:"), options->dnd_default_action, &c_options->dnd_default_action);
3600 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3601 add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
3603 pref_spacer(group, PREF_PAD_GROUP);
3605 group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
3607 pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
3608 options->progressive_key_scrolling, &c_options->progressive_key_scrolling);
3609 pref_spin_new_int(group, _("Keyboard scrolling step multiplier:"), NULL,
3610 1, 32, 1, options->keyboard_scroll_step, (int *)&c_options->keyboard_scroll_step);
3611 pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
3612 options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
3613 pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
3614 options->image_lm_click_nav, &c_options->image_lm_click_nav);
3615 pref_checkbox_new_int(group, _("Open archive by left click on image"),
3616 options->image_l_click_archive, &c_options->image_l_click_archive);
3617 pref_checkbox_new_int(group, _("Play video by left click on image"),
3618 options->image_l_click_video, &c_options->image_l_click_video);
3619 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3620 add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
3622 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3623 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3624 add_mouse_selection_menu(table, 0, 0, _("Mouse button Back:"), options->mouse_button_8, &c_options->mouse_button_8);
3625 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3626 add_mouse_selection_menu(table, 0, 0, _("Mouse button Forward:"), options->mouse_button_9, &c_options->mouse_button_9);
3628 pref_spacer(group, PREF_PAD_GROUP);
3630 group = pref_group_new(vbox, FALSE, _("GPU"), GTK_ORIENTATION_VERTICAL);
3632 checkbox = pref_checkbox_new_int(group, _("Override disable GPU"),
3633 options->override_disable_gpu, &c_options->override_disable_gpu);
3634 gtk_widget_set_tooltip_text(checkbox, "Contact the developers for usage");
3637 pref_spacer(group, PREF_PAD_GROUP);
3639 group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
3641 pref_spin_new_int(group, _("Debug level:"), NULL,
3642 DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
3644 pref_checkbox_new_int(group, _("Timer data"),
3645 options->log_window.timer_data, &c_options->log_window.timer_data);
3647 pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
3648 1, 99999, 1, options->log_window_lines, &options->log_window_lines);
3652 /* accelerators tab */
3653 static void config_tab_accelerators(GtkWidget *notebook)
3659 GtkWidget *scrolled;
3660 GtkWidget *accel_view;
3661 GtkCellRenderer *renderer;
3662 GtkTreeSelection *selection;
3663 GtkTreeViewColumn *column;
3665 vbox = scrolled_notebook_page(notebook, _("Keyboard"));
3667 group = pref_group_new(vbox, TRUE, _("Accelerators"), GTK_ORIENTATION_VERTICAL);
3669 scrolled = gtk_scrolled_window_new(NULL, NULL);
3670 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
3671 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
3672 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3673 gtk_widget_show(scrolled);
3675 accel_store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
3677 accel_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(accel_store));
3678 g_object_unref(accel_store);
3679 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(accel_view));
3680 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
3682 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(accel_view), FALSE);
3684 renderer = gtk_cell_renderer_text_new();
3686 column = gtk_tree_view_column_new_with_attributes(_("Action"),
3691 gtk_tree_view_column_set_sort_column_id(column, AE_ACTION);
3692 gtk_tree_view_column_set_resizable(column, TRUE);
3693 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3696 renderer = gtk_cell_renderer_accel_new();
3697 g_signal_connect(G_OBJECT(renderer), "accel-cleared",
3698 G_CALLBACK(accel_store_cleared_cb), accel_store);
3699 g_signal_connect(G_OBJECT(renderer), "accel-edited",
3700 G_CALLBACK(accel_store_edited_cb), accel_store);
3703 g_object_set (renderer,
3705 "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
3708 column = gtk_tree_view_column_new_with_attributes(_("KEY"),
3713 gtk_tree_view_column_set_sort_column_id(column, AE_KEY);
3714 gtk_tree_view_column_set_resizable(column, TRUE);
3715 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3717 renderer = gtk_cell_renderer_text_new();
3719 column = gtk_tree_view_column_new_with_attributes(_("Tooltip"),
3724 gtk_tree_view_column_set_sort_column_id(column, AE_TOOLTIP);
3725 gtk_tree_view_column_set_resizable(column, TRUE);
3726 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3728 renderer = gtk_cell_renderer_text_new();
3730 column = gtk_tree_view_column_new_with_attributes("Accel",
3735 gtk_tree_view_column_set_sort_column_id(column, AE_ACCEL);
3736 gtk_tree_view_column_set_resizable(column, TRUE);
3737 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3739 accel_store_populate();
3740 gtk_container_add(GTK_CONTAINER(scrolled), accel_view);
3741 gtk_widget_show(accel_view);
3743 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3745 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
3746 G_CALLBACK(accel_default_cb), accel_view);
3747 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3748 gtk_widget_show(button);
3750 button = pref_button_new(NULL, NULL, _("Reset selected"), FALSE,
3751 G_CALLBACK(accel_reset_cb), accel_view);
3752 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3753 gtk_widget_show(button);
3756 /* toolbar main tab */
3757 static void config_tab_toolbar_main(GtkWidget *notebook)
3760 GtkWidget *toolbardata;
3763 lw = layout_window_list->data;
3765 vbox = scrolled_notebook_page(notebook, _("Toolbar Main"));
3767 toolbardata = toolbar_select_new(lw, TOOLBAR_MAIN);
3768 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3769 gtk_widget_show(vbox);
3772 /* toolbar status tab */
3773 static void config_tab_toolbar_status(GtkWidget *notebook)
3776 GtkWidget *toolbardata;
3779 lw = layout_window_list->data;
3781 vbox = scrolled_notebook_page(notebook, _("Toolbar Status"));
3783 toolbardata = toolbar_select_new(lw, TOOLBAR_STATUS);
3784 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3785 gtk_widget_show(vbox);
3789 static gint extension_sort_cb(gconstpointer a, gconstpointer b)
3791 return g_strcmp0((gchar *)a, (gchar *)b);
3794 static void config_tab_advanced(GtkWidget *notebook)
3798 GSList *formats_list;
3799 GList *extensions_list = NULL;
3802 GdkPixbufFormat *fm;
3804 GString *types_string = g_string_new(NULL);
3805 GtkWidget *types_string_label;
3806 GtkWidget *threads_string_label;
3807 GtkWidget *dupes_threads_spin;
3809 vbox = scrolled_notebook_page(notebook, _("Advanced"));
3810 group = pref_group_new(vbox, FALSE, _("External preview extraction"), GTK_ORIENTATION_VERTICAL);
3812 pref_checkbox_new_int(group, _("Use external preview extraction - Requires restart"), options->external_preview.enable, &c_options->external_preview.enable);
3814 pref_spacer(group, PREF_PAD_GROUP);
3816 formats_list = gdk_pixbuf_get_formats();
3818 while (formats_list)
3820 fm = formats_list->data;
3821 extensions = gdk_pixbuf_format_get_extensions(fm);
3824 while (extensions[i])
3826 extensions_list = g_list_insert_sorted(extensions_list, g_strdup(extensions[i]), extension_sort_cb);
3830 g_strfreev(extensions);
3831 formats_list = formats_list->next;
3834 while (extensions_list)
3836 if (types_string->len == 0)
3838 types_string = g_string_append(types_string, extensions_list->data);
3842 types_string = g_string_append(types_string, ", ");
3843 types_string = g_string_append(types_string, extensions_list->data);
3846 extensions_list = extensions_list->next;
3849 types_string = g_string_prepend(types_string, _("Usable file types:\n"));
3850 types_string_label = pref_label_new(group, types_string->str);
3851 gtk_label_set_line_wrap(GTK_LABEL(types_string_label), TRUE);
3853 pref_spacer(group, PREF_PAD_GROUP);
3855 group = pref_group_new(vbox, FALSE, _("File identification tool"), GTK_ORIENTATION_VERTICAL);
3856 external_preview_select_entry = gtk_entry_new();
3857 tabcomp = tab_completion_new(&external_preview_select_entry, options->external_preview.select, NULL, NULL, NULL, NULL);
3858 tab_completion_add_select_button(external_preview_select_entry, _("Select file identification tool"), FALSE);
3859 gtk_box_pack_start(GTK_BOX(group), tabcomp, TRUE, TRUE, 0);
3860 gtk_widget_show(tabcomp);
3862 group = pref_group_new(vbox, FALSE, _("Preview extraction tool"), GTK_ORIENTATION_VERTICAL);
3863 external_preview_extract_entry = gtk_entry_new();
3864 tabcomp = tab_completion_new(&external_preview_extract_entry, options->external_preview.extract, NULL, NULL, NULL, NULL);
3865 tab_completion_add_select_button(external_preview_extract_entry, _("Select preview extraction tool"), FALSE);
3866 gtk_box_pack_start(GTK_BOX(group), tabcomp, TRUE, TRUE, 0);
3867 gtk_widget_show(tabcomp);
3869 gtk_widget_show(vbox);
3871 g_slist_free(formats_list);
3872 string_list_free(extensions_list);
3873 g_string_free(types_string, TRUE);
3875 pref_spacer(group, PREF_PAD_GROUP);
3877 pref_line(vbox, PREF_PAD_SPACE);
3878 group = pref_group_new(vbox, FALSE, _("Thread pool limits"), GTK_ORIENTATION_VERTICAL);
3880 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.");
3881 gtk_label_set_line_wrap(GTK_LABEL(threads_string_label), TRUE);
3883 pref_spacer(vbox, PREF_PAD_GROUP);
3885 dupes_threads_spin = pref_spin_new_int(vbox, _("Duplicate check:"), _("max. threads"), 0, get_cpu_cores(), 1, options->threads.duplicates, &c_options->threads.duplicates);
3886 gtk_widget_set_tooltip_markup(dupes_threads_spin, _("Set to 0 for unlimited"));
3890 static void config_tab_stereo(GtkWidget *notebook)
3898 GtkWidget *fs_button;
3899 vbox = scrolled_notebook_page(notebook, _("Stereo"));
3901 group = pref_group_new(vbox, FALSE, _("Windowed stereo mode"), GTK_ORIENTATION_VERTICAL);
3903 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3904 add_stereo_mode_menu(table, 0, 0, _("Windowed stereo mode"), options->stereo.mode, &c_options->stereo.mode, FALSE);
3906 table = pref_table_new(group, 2, 2, TRUE, FALSE);
3907 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3908 pref_checkbox_new_int(box, _("Mirror left image"),
3909 options->stereo.mode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.mirror_left);
3910 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3911 pref_checkbox_new_int(box, _("Flip left image"),
3912 options->stereo.mode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.flip_left);
3913 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3914 pref_checkbox_new_int(box, _("Mirror right image"),
3915 options->stereo.mode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.mirror_right);
3916 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3917 pref_checkbox_new_int(box, _("Flip right image"),
3918 options->stereo.mode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.flip_right);
3919 pref_checkbox_new_int(group, _("Swap left and right images"),
3920 options->stereo.mode & PR_STEREO_SWAP, &c_options->stereo.tmp.swap);
3921 pref_checkbox_new_int(group, _("Disable stereo mode on single image source"),
3922 options->stereo.mode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.temp_disable);
3924 group = pref_group_new(vbox, FALSE, _("Fullscreen stereo mode"), GTK_ORIENTATION_VERTICAL);
3925 fs_button = pref_checkbox_new_int(group, _("Use different settings for fullscreen"),
3926 options->stereo.enable_fsmode, &c_options->stereo.enable_fsmode);
3927 box2 = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
3928 pref_checkbox_link_sensitivity(fs_button, box2);
3929 table = pref_table_new(box2, 2, 1, FALSE, FALSE);
3930 add_stereo_mode_menu(table, 0, 0, _("Fullscreen stereo mode"), options->stereo.fsmode, &c_options->stereo.fsmode, TRUE);
3931 table = pref_table_new(box2, 2, 2, TRUE, FALSE);
3932 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3933 pref_checkbox_new_int(box, _("Mirror left image"),
3934 options->stereo.fsmode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.fs_mirror_left);
3935 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3936 pref_checkbox_new_int(box, _("Flip left image"),
3937 options->stereo.fsmode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.fs_flip_left);
3938 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3939 pref_checkbox_new_int(box, _("Mirror right image"),
3940 options->stereo.fsmode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.fs_mirror_right);
3941 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3942 pref_checkbox_new_int(box, _("Flip right image"),
3943 options->stereo.fsmode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.fs_flip_right);
3944 pref_checkbox_new_int(box2, _("Swap left and right images"),
3945 options->stereo.fsmode & PR_STEREO_SWAP, &c_options->stereo.tmp.fs_swap);
3946 pref_checkbox_new_int(box2, _("Disable stereo mode on single image source"),
3947 options->stereo.fsmode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.fs_temp_disable);
3949 group2 = pref_group_new(box2, FALSE, _("Fixed position"), GTK_ORIENTATION_VERTICAL);
3950 table = pref_table_new(group2, 5, 3, FALSE, FALSE);
3951 pref_table_spin_new_int(table, 0, 0, _("Width"), NULL,
3952 1, 5000, 1, options->stereo.fixed_w, &c_options->stereo.fixed_w);
3953 pref_table_spin_new_int(table, 3, 0, _("Height"), NULL,
3954 1, 5000, 1, options->stereo.fixed_h, &c_options->stereo.fixed_h);
3955 pref_table_spin_new_int(table, 0, 1, _("Left X"), NULL,
3956 0, 5000, 1, options->stereo.fixed_x1, &c_options->stereo.fixed_x1);
3957 pref_table_spin_new_int(table, 3, 1, _("Left Y"), NULL,
3958 0, 5000, 1, options->stereo.fixed_y1, &c_options->stereo.fixed_y1);
3959 pref_table_spin_new_int(table, 0, 2, _("Right X"), NULL,
3960 0, 5000, 1, options->stereo.fixed_x2, &c_options->stereo.fixed_x2);
3961 pref_table_spin_new_int(table, 3, 2, _("Right Y"), NULL,
3962 0, 5000, 1, options->stereo.fixed_y2, &c_options->stereo.fixed_y2);
3966 /* Main preferences window */
3967 static void config_window_create(LayoutWindow *lw)
3969 GtkWidget *win_vbox;
3971 GtkWidget *notebook;
3973 GtkWidget *ct_button;
3975 if (!c_options) c_options = init_options(NULL);
3977 configwindow = window_new(GTK_WINDOW_TOPLEVEL, "preferences", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Preferences"));
3978 DEBUG_NAME(configwindow);
3979 gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
3980 g_signal_connect(G_OBJECT(configwindow), "delete_event",
3981 G_CALLBACK(config_window_delete), NULL);
3982 if (options->save_dialog_window_positions)
3984 gtk_window_resize(GTK_WINDOW(configwindow), lw->options.preferences_window.w, lw->options.preferences_window.h);
3985 gtk_window_move(GTK_WINDOW(configwindow), lw->options.preferences_window.x, lw->options.preferences_window.y);
3989 gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
3991 gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
3992 gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
3994 win_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
3995 gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
3996 gtk_widget_show(win_vbox);
3998 notebook = gtk_notebook_new();
3999 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_LEFT);
4000 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE);
4001 gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
4003 config_tab_general(notebook);
4004 config_tab_image(notebook);
4005 config_tab_osd(notebook);
4006 config_tab_windows(notebook);
4007 config_tab_accelerators(notebook);
4008 config_tab_files(notebook);
4009 config_tab_metadata(notebook);
4010 config_tab_keywords(notebook);
4011 config_tab_color(notebook);
4012 config_tab_stereo(notebook);
4013 config_tab_behavior(notebook);
4014 config_tab_toolbar_main(notebook);
4015 config_tab_toolbar_status(notebook);
4016 config_tab_advanced(notebook);
4018 gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), lw->options.preferences_window.page_number);
4020 hbox = gtk_hbutton_box_new();
4021 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
4022 gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
4023 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
4024 gtk_widget_show(hbox);
4026 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
4027 G_CALLBACK(config_window_help_cb), notebook);
4028 gtk_container_add(GTK_CONTAINER(hbox), button);
4029 gtk_widget_set_can_default(button, TRUE);
4030 gtk_widget_show(button);
4032 button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
4033 G_CALLBACK(config_window_ok_cb), notebook);
4034 gtk_container_add(GTK_CONTAINER(hbox), button);
4035 gtk_widget_set_can_default(button, TRUE);
4036 gtk_widget_grab_default(button);
4037 gtk_widget_show(button);
4041 button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
4042 G_CALLBACK(config_window_close_cb), NULL);
4043 gtk_container_add(GTK_CONTAINER(hbox), button);
4044 gtk_widget_set_can_default(button, TRUE);
4045 gtk_widget_show(button);
4047 if (!generic_dialog_get_alternative_button_order(configwindow))
4049 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
4052 gtk_widget_show(notebook);
4054 gtk_widget_show(configwindow);
4058 *-----------------------------------------------------------------------------
4059 * config window show (public)
4060 *-----------------------------------------------------------------------------
4063 void show_config_window(LayoutWindow *lw)
4067 gtk_window_present(GTK_WINDOW(configwindow));
4071 config_window_create(lw);
4080 void show_about_window(LayoutWindow *lw)
4082 GdkPixbuf *pixbuf_logo;
4083 GdkPixbuf *pixbuf_icon;
4084 gchar *authors[1000];
4089 gchar *timezone_path;
4092 #define LINE_LENGTH 1000
4093 gchar line[LINE_LENGTH];
4095 copyright = g_string_new(NULL);
4096 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");
4098 timezone_path = g_build_filename(get_rc_dir(), TIMEZONE_DATABASE_FILE, NULL);
4099 if (g_file_test(timezone_path, G_FILE_TEST_EXISTS))
4101 cd = ZDOpenDatabase(timezone_path);
4104 copyright = g_string_append(copyright, ZDGetNotice(cd));
4108 log_printf("Error: Init of timezone database %s failed\n", timezone_path);
4110 ZDCloseDatabase(cd);
4112 g_free(timezone_path);
4115 path = g_build_filename(gq_helpdir, "AUTHORS", NULL);
4116 fp = fopen(path, "r");
4119 while(fgets(line, LINE_LENGTH, fp))
4121 /* get rid of ending \n from fgets */
4122 line[strlen(line) - 1] = '\0';
4123 authors[i_authors] = g_strdup(line);
4126 authors[i_authors] = NULL;
4131 comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
4132 "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
4134 pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
4135 pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
4136 gtk_show_about_dialog(GTK_WINDOW(lw->window),
4137 "title", _("About Geeqie"),
4139 "program-name", GQ_APPNAME,
4141 "logo", pixbuf_logo,
4142 "icon", pixbuf_icon,
4143 "website", GQ_WEBSITE,
4144 "website-label", "Website",
4145 "comments", comment,
4147 "translator-credits", _("translator-credits"),
4148 "wrap-license", TRUE,
4149 "license", copyright->str,
4152 g_string_free(copyright, TRUE);
4155 while(n < i_authors)
4165 static void image_overlay_set_text_colours()
4167 c_options->image_overlay.text_red = options->image_overlay.text_red;
4168 c_options->image_overlay.text_green = options->image_overlay.text_green;
4169 c_options->image_overlay.text_blue = options->image_overlay.text_blue;
4170 c_options->image_overlay.text_alpha = options->image_overlay.text_alpha;
4171 c_options->image_overlay.background_red = options->image_overlay.background_red;
4172 c_options->image_overlay.background_green = options->image_overlay.background_green;
4173 c_options->image_overlay.background_blue = options->image_overlay.background_blue;
4174 c_options->image_overlay.background_alpha = options->image_overlay.background_alpha;
4178 *-----------------------------------------------------------------------------
4179 * timezone database routines
4180 *-----------------------------------------------------------------------------
4183 static void timezone_async_ready_cb(GObject *source_object, GAsyncResult *res, gpointer data)
4185 GError *error = NULL;
4187 gchar *tmp_filename;
4188 gchar *timezone_bin;
4189 gchar *tmp_dir = NULL;
4192 if (!g_cancellable_is_cancelled(tz->cancellable))
4194 generic_dialog_close(tz->gd);
4198 if (g_file_copy_finish(G_FILE(source_object), res, &error))
4200 tmp_filename = g_file_get_path(tz->tmp_g_file);
4201 fd = file_data_new_simple(tmp_filename);
4202 tmp_dir = open_archive(fd);
4206 timezone_bin = g_build_filename(tmp_dir, TIMEZONE_DATABASE_VERSION, TIMEZONE_DATABASE_FILE, NULL);
4207 if (isfile(timezone_bin))
4209 move_file(timezone_bin, tz->timezone_database_user);
4213 warning_dialog(_("Warning: Cannot open timezone database file"), _("See the Log Window"), GTK_STOCK_DIALOG_WARNING, NULL);
4216 g_free(timezone_bin);
4217 g_free(tmp_dir); // The folder in /tmp is deleted in exit_program_final()
4221 warning_dialog(_("Warning: Cannot open timezone database file"), _("See the Log Window"), GTK_STOCK_DIALOG_WARNING, NULL);
4223 g_free(tmp_filename);
4224 file_data_unref(fd);
4228 file_util_warning_dialog(_("Error: Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
4231 g_file_delete(tz->tmp_g_file, NULL, &error);
4232 g_object_unref(tz->tmp_g_file);
4233 tz->tmp_g_file = NULL;
4234 g_object_unref(tz->cancellable);
4235 g_object_unref(tz->timezone_database_gq);
4238 static void timezone_progress_cb(goffset current_num_bytes, goffset total_num_bytes, gpointer data)
4242 if (!g_cancellable_is_cancelled(tz->cancellable))
4244 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(tz->progress), (gdouble)current_num_bytes / total_num_bytes);
4248 static void timezone_cancel_button_cb(GenericDialog *UNUSED(gd), gpointer data)
4252 g_cancellable_cancel(tz->cancellable);
4255 static void timezone_database_install_cb(GtkWidget *widget, gpointer data)
4258 GError *error = NULL;
4259 GFileIOStream *io_stream;
4266 tz->tmp_g_file = g_file_new_tmp("geeqie_timezone_XXXXXX", &io_stream, &error);
4270 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
4271 log_printf("Error: Download timezone database failed:\n%s", error->message);
4272 g_error_free(error);
4273 g_object_unref(tz->tmp_g_file);
4277 tz->timezone_database_gq = g_file_new_for_uri(TIMEZONE_DATABASE_WEB);
4279 tz->gd = generic_dialog_new(_("Timezone database"), "download_timezone_database", NULL, TRUE, timezone_cancel_button_cb, tz);
4281 generic_dialog_add_message(tz->gd, GTK_STOCK_DIALOG_INFO, _("Downloading timezone database"), NULL, FALSE);
4283 tz->progress = gtk_progress_bar_new();
4284 gtk_box_pack_start(GTK_BOX(tz->gd->vbox), tz->progress, FALSE, FALSE, 0);
4285 gtk_widget_show(tz->progress);
4287 gtk_widget_show(tz->gd->dialog);
4288 tz->cancellable = g_cancellable_new();
4289 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);
4291 gtk_button_set_label(GTK_BUTTON(widget), _("Update"));
4294 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */