2 * Copyright (C) 2006 John Ellis
3 * Copyright (C) 2008 - 2016 The Geeqie Team
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include "preferences.h"
26 #include "bar_keywords.h"
28 #include "cache_maint.h"
33 #include "filefilter.h"
34 #include "fullscreen.h"
36 #include "image-overlay.h"
37 #include "color-man.h"
39 #include "layout_config.h"
40 #include "layout_util.h"
44 #include "pixbuf_util.h"
46 #include "slideshow.h"
50 #include "ui_fileops.h"
52 #include "ui_spinner.h"
53 #include "ui_tabcomp.h"
54 #include "ui_utildlg.h"
56 #include "zonedetect.h"
67 #include <gspell/gspell.h>
70 #define EDITOR_NAME_MAX_LENGTH 32
71 #define EDITOR_COMMAND_MAX_LENGTH 1024
73 static void image_overlay_set_text_colours();
75 GtkWidget *keyword_text;
76 static void config_tab_keywords_save();
78 typedef struct _ThumbSize ThumbSize;
85 static ThumbSize thumb_size_list[] =
120 FILETYPES_COLUMN_ENABLED = 0,
121 FILETYPES_COLUMN_FILTER,
122 FILETYPES_COLUMN_DESCRIPTION,
123 FILETYPES_COLUMN_CLASS,
124 FILETYPES_COLUMN_WRITABLE,
125 FILETYPES_COLUMN_SIDECAR,
126 FILETYPES_COLUMN_COUNT
129 gchar *format_class_list[] = {
140 /* config memory values */
141 static ConfOptions *c_options = NULL;
148 static GtkWidget *configwindow = NULL;
149 static GtkListStore *filter_store = NULL;
150 static GtkTreeStore *accel_store = NULL;
152 static GtkWidget *safe_delete_path_entry;
154 static GtkWidget *color_profile_input_file_entry[COLOR_PROFILE_INPUTS];
155 static GtkWidget *color_profile_input_name_entry[COLOR_PROFILE_INPUTS];
156 static GtkWidget *color_profile_screen_file_entry;
157 static GtkWidget *external_preview_select_entry;
158 static GtkWidget *external_preview_extract_entry;
160 static GtkWidget *sidecar_ext_entry;
161 static GtkWidget *help_search_engine_entry;
164 #define CONFIG_WINDOW_DEF_WIDTH 700
165 #define CONFIG_WINDOW_DEF_HEIGHT 600
168 *-----------------------------------------------------------------------------
169 * option widget callbacks (private)
170 *-----------------------------------------------------------------------------
173 static void zoom_increment_cb(GtkWidget *spin, gpointer UNUSED(data))
175 c_options->image.zoom_increment = (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) * 100.0 + 0.01);
178 static void slideshow_delay_hours_cb(GtkWidget *spin, gpointer UNUSED(data))
180 gint mins_secs_tenths, delay;
182 mins_secs_tenths = c_options->slideshow.delay %
183 (3600 * SLIDESHOW_SUBSECOND_PRECISION);
185 delay = (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
186 (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
189 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
190 SLIDESHOW_SUBSECOND_PRECISION;
193 static void slideshow_delay_minutes_cb(GtkWidget *spin, gpointer UNUSED(data))
195 gint hours, secs_tenths, delay;
197 hours = c_options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
198 secs_tenths = c_options->slideshow.delay % (60 * SLIDESHOW_SUBSECOND_PRECISION);
200 delay = hours * (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
201 (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
202 (60 * SLIDESHOW_SUBSECOND_PRECISION) + secs_tenths);
204 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
205 SLIDESHOW_SUBSECOND_PRECISION;
208 static void slideshow_delay_seconds_cb(GtkWidget *spin, gpointer UNUSED(data))
210 gint hours_mins, delay;
212 hours_mins = c_options->slideshow.delay / (60 * SLIDESHOW_SUBSECOND_PRECISION);
214 delay = (hours_mins * (60 * SLIDESHOW_SUBSECOND_PRECISION)) +
215 (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
216 (gdouble)(SLIDESHOW_SUBSECOND_PRECISION) + 0.01);
218 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
219 SLIDESHOW_SUBSECOND_PRECISION;
223 *-----------------------------------------------------------------------------
224 * sync program to config window routine (private)
225 *-----------------------------------------------------------------------------
228 void config_entry_to_option(GtkWidget *entry, gchar **option, gchar *(*func)(const gchar *))
234 buf = gtk_entry_get_text(GTK_ENTRY(entry));
235 if (buf && strlen(buf) > 0)
240 *option = g_strdup(buf);
245 static gboolean accel_apply_cb(GtkTreeModel *model, GtkTreePath *UNUSED(path), GtkTreeIter *iter, gpointer UNUSED(data))
247 gchar *accel_path, *accel;
249 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, AE_KEY, &accel, -1);
251 if (accel_path && accel_path[0])
254 gtk_accelerator_parse(accel, &key.accel_key, &key.accel_mods);
255 gtk_accel_map_change_entry(accel_path, key.accel_key, key.accel_mods, TRUE);
265 static void config_window_apply(void)
267 gboolean refresh = FALSE;
272 config_entry_to_option(safe_delete_path_entry, &options->file_ops.safe_delete_path, remove_trailing_slash);
274 if (options->file_filter.show_hidden_files != c_options->file_filter.show_hidden_files) refresh = TRUE;
275 if (options->file_filter.show_parent_directory != c_options->file_filter.show_parent_directory) refresh = TRUE;
276 if (options->file_filter.show_dot_directory != c_options->file_filter.show_dot_directory) refresh = TRUE;
277 if (options->file_sort.case_sensitive != c_options->file_sort.case_sensitive) refresh = TRUE;
278 if (options->file_sort.natural != c_options->file_sort.natural) refresh = TRUE;
279 if (options->file_filter.disable_file_extension_checks != c_options->file_filter.disable_file_extension_checks) refresh = TRUE;
280 if (options->file_filter.disable != c_options->file_filter.disable) refresh = TRUE;
282 options->file_ops.confirm_delete = c_options->file_ops.confirm_delete;
283 options->file_ops.enable_delete_key = c_options->file_ops.enable_delete_key;
284 options->file_ops.confirm_move_to_trash = c_options->file_ops.confirm_move_to_trash;
285 options->file_ops.use_system_trash = c_options->file_ops.use_system_trash;
286 options->file_ops.no_trash = c_options->file_ops.no_trash;
287 options->file_ops.safe_delete_folder_maxsize = c_options->file_ops.safe_delete_folder_maxsize;
288 options->tools_restore_state = c_options->tools_restore_state;
289 options->save_window_positions = c_options->save_window_positions;
290 options->use_saved_window_positions_for_new_windows = c_options->use_saved_window_positions_for_new_windows;
291 options->save_window_workspace = c_options->save_window_workspace;
292 options->save_dialog_window_positions = c_options->save_dialog_window_positions;
293 options->show_window_ids = c_options->show_window_ids;
294 options->image.scroll_reset_method = c_options->image.scroll_reset_method;
295 options->image.zoom_2pass = c_options->image.zoom_2pass;
296 options->image.fit_window_to_image = c_options->image.fit_window_to_image;
297 options->image.limit_window_size = c_options->image.limit_window_size;
298 options->image.zoom_to_fit_allow_expand = c_options->image.zoom_to_fit_allow_expand;
299 options->image.max_window_size = c_options->image.max_window_size;
300 options->image.limit_autofit_size = c_options->image.limit_autofit_size;
301 options->image.max_autofit_size = c_options->image.max_autofit_size;
302 options->image.max_enlargement_size = c_options->image.max_enlargement_size;
303 //~ options->image.use_clutter_renderer = c_options->image.use_clutter_renderer;
304 options->image.tile_size = c_options->image.tile_size;
305 options->progressive_key_scrolling = c_options->progressive_key_scrolling;
306 options->keyboard_scroll_step = c_options->keyboard_scroll_step;
308 if (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 thumb_format_changed = TRUE;
314 options->thumbnails.max_width = c_options->thumbnails.max_width;
315 options->thumbnails.max_height = c_options->thumbnails.max_height;
316 options->thumbnails.quality = c_options->thumbnails.quality;
318 options->thumbnails.enable_caching = c_options->thumbnails.enable_caching;
319 options->thumbnails.cache_into_dirs = c_options->thumbnails.cache_into_dirs;
320 options->thumbnails.use_exif = c_options->thumbnails.use_exif;
321 options->thumbnails.use_color_management = c_options->thumbnails.use_color_management;
322 options->thumbnails.collection_preview = c_options->thumbnails.collection_preview;
323 options->thumbnails.use_ft_metadata = c_options->thumbnails.use_ft_metadata;
324 // options->thumbnails.use_ft_metadata_small = c_options->thumbnails.use_ft_metadata_small;
325 options->thumbnails.spec_standard = c_options->thumbnails.spec_standard;
326 options->metadata.enable_metadata_dirs = c_options->metadata.enable_metadata_dirs;
327 options->file_filter.show_hidden_files = c_options->file_filter.show_hidden_files;
328 options->file_filter.show_parent_directory = c_options->file_filter.show_parent_directory;
329 options->file_filter.show_dot_directory = c_options->file_filter.show_dot_directory;
330 options->file_filter.disable_file_extension_checks = c_options->file_filter.disable_file_extension_checks;
332 options->file_sort.case_sensitive = c_options->file_sort.case_sensitive;
333 options->file_sort.natural = c_options->file_sort.natural;
334 options->file_filter.disable = c_options->file_filter.disable;
336 config_entry_to_option(sidecar_ext_entry, &options->sidecar.ext, NULL);
337 sidecar_ext_parse(options->sidecar.ext);
339 options->slideshow.random = c_options->slideshow.random;
340 options->slideshow.repeat = c_options->slideshow.repeat;
341 options->slideshow.delay = c_options->slideshow.delay;
343 options->mousewheel_scrolls = c_options->mousewheel_scrolls;
344 options->image_lm_click_nav = c_options->image_lm_click_nav;
345 options->image_l_click_archive = c_options->image_l_click_archive;
346 options->image_l_click_video = c_options->image_l_click_video;
347 options->image_l_click_video_editor = c_options->image_l_click_video_editor;
349 options->file_ops.enable_in_place_rename = c_options->file_ops.enable_in_place_rename;
351 options->image.tile_cache_max = c_options->image.tile_cache_max;
352 options->image.image_cache_max = c_options->image.image_cache_max;
354 options->image.zoom_quality = c_options->image.zoom_quality;
356 options->image.zoom_increment = c_options->image.zoom_increment;
358 options->image.zoom_style = c_options->image.zoom_style;
360 options->image.enable_read_ahead = c_options->image.enable_read_ahead;
363 if (options->image.use_custom_border_color != c_options->image.use_custom_border_color
364 || options->image.use_custom_border_color_in_fullscreen != c_options->image.use_custom_border_color_in_fullscreen
365 || !gdk_color_equal(&options->image.border_color, &c_options->image.border_color))
367 options->image.use_custom_border_color_in_fullscreen = c_options->image.use_custom_border_color_in_fullscreen;
368 options->image.use_custom_border_color = c_options->image.use_custom_border_color;
369 options->image.border_color = c_options->image.border_color;
370 layout_colors_update();
371 view_window_colors_update();
374 options->image.alpha_color_1 = c_options->image.alpha_color_1;
375 options->image.alpha_color_2 = c_options->image.alpha_color_2;
377 options->fullscreen.screen = c_options->fullscreen.screen;
378 options->fullscreen.clean_flip = c_options->fullscreen.clean_flip;
379 options->fullscreen.disable_saver = c_options->fullscreen.disable_saver;
380 options->fullscreen.above = c_options->fullscreen.above;
381 if (c_options->image_overlay.template_string)
382 set_image_overlay_template_string(&options->image_overlay.template_string,
383 c_options->image_overlay.template_string);
384 if (c_options->image_overlay.font)
385 set_image_overlay_font_string(&options->image_overlay.font,
386 c_options->image_overlay.font);
387 options->image_overlay.text_red = c_options->image_overlay.text_red;
388 options->image_overlay.text_green = c_options->image_overlay.text_green;
389 options->image_overlay.text_blue = c_options->image_overlay.text_blue;
390 options->image_overlay.text_alpha = c_options->image_overlay.text_alpha;
391 options->image_overlay.background_red = c_options->image_overlay.background_red;
392 options->image_overlay.background_green = c_options->image_overlay.background_green;
393 options->image_overlay.background_blue = c_options->image_overlay.background_blue;
394 options->image_overlay.background_alpha = c_options->image_overlay.background_alpha;
395 options->update_on_time_change = c_options->update_on_time_change;
397 options->duplicates_similarity_threshold = c_options->duplicates_similarity_threshold;
398 options->rot_invariant_sim = c_options->rot_invariant_sim;
400 options->tree_descend_subdirs = c_options->tree_descend_subdirs;
402 options->view_dir_list_single_click_enter = c_options->view_dir_list_single_click_enter;
403 options->circular_selection_lists = c_options->circular_selection_lists;
405 options->open_recent_list_maxsize = c_options->open_recent_list_maxsize;
406 options->recent_folder_image_list_maxsize = c_options->recent_folder_image_list_maxsize;
407 options->dnd_icon_size = c_options->dnd_icon_size;
408 options->clipboard_selection = c_options->clipboard_selection;
409 options->dnd_default_action = c_options->dnd_default_action;
411 options->metadata.save_in_image_file = c_options->metadata.save_in_image_file;
412 options->metadata.save_legacy_IPTC = c_options->metadata.save_legacy_IPTC;
413 options->metadata.warn_on_write_problems = c_options->metadata.warn_on_write_problems;
414 options->metadata.save_legacy_format = c_options->metadata.save_legacy_format;
415 options->metadata.sync_grouped_files = c_options->metadata.sync_grouped_files;
416 options->metadata.confirm_write = c_options->metadata.confirm_write;
417 options->metadata.sidecar_extended_name = c_options->metadata.sidecar_extended_name;
418 options->metadata.confirm_timeout = c_options->metadata.confirm_timeout;
419 options->metadata.confirm_after_timeout = c_options->metadata.confirm_after_timeout;
420 options->metadata.confirm_on_image_change = c_options->metadata.confirm_on_image_change;
421 options->metadata.confirm_on_dir_change = c_options->metadata.confirm_on_dir_change;
422 options->metadata.keywords_case_sensitive = c_options->metadata.keywords_case_sensitive;
423 options->metadata.write_orientation = c_options->metadata.write_orientation;
424 options->metadata.check_spelling = c_options->metadata.check_spelling;
425 options->stereo.mode = (c_options->stereo.mode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
426 (c_options->stereo.tmp.mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
427 (c_options->stereo.tmp.flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
428 (c_options->stereo.tmp.mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
429 (c_options->stereo.tmp.flip_left ? PR_STEREO_FLIP_LEFT : 0) |
430 (c_options->stereo.tmp.swap ? PR_STEREO_SWAP : 0) |
431 (c_options->stereo.tmp.temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
432 options->stereo.fsmode = (c_options->stereo.fsmode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
433 (c_options->stereo.tmp.fs_mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
434 (c_options->stereo.tmp.fs_flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
435 (c_options->stereo.tmp.fs_mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
436 (c_options->stereo.tmp.fs_flip_left ? PR_STEREO_FLIP_LEFT : 0) |
437 (c_options->stereo.tmp.fs_swap ? PR_STEREO_SWAP : 0) |
438 (c_options->stereo.tmp.fs_temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
439 options->stereo.enable_fsmode = c_options->stereo.enable_fsmode;
440 options->stereo.fixed_w = c_options->stereo.fixed_w;
441 options->stereo.fixed_h = c_options->stereo.fixed_h;
442 options->stereo.fixed_x1 = c_options->stereo.fixed_x1;
443 options->stereo.fixed_y1 = c_options->stereo.fixed_y1;
444 options->stereo.fixed_x2 = c_options->stereo.fixed_x2;
445 options->stereo.fixed_y2 = c_options->stereo.fixed_y2;
447 options->info_keywords.height = c_options->info_keywords.height;
448 options->info_title.height = c_options->info_title.height;
449 options->info_comment.height = c_options->info_comment.height;
450 options->info_rating.height = c_options->info_rating.height;
452 options->show_predefined_keyword_tree = c_options->show_predefined_keyword_tree;
453 options->expand_menu_toolbar = c_options->expand_menu_toolbar;
455 options->marks_save = c_options->marks_save;
456 options->with_rename = c_options->with_rename;
457 options->collections_on_top = c_options->collections_on_top;
458 options->hide_window_in_fullscreen = c_options->hide_window_in_fullscreen;
459 config_entry_to_option(help_search_engine_entry, &options->help_search_engine, NULL);
461 options->external_preview.enable = c_options->external_preview.enable;
462 config_entry_to_option(external_preview_select_entry, &options->external_preview.select, NULL);
463 config_entry_to_option(external_preview_extract_entry, &options->external_preview.extract, NULL);
465 options->read_metadata_in_idle = c_options->read_metadata_in_idle;
467 options->star_rating.star = c_options->star_rating.star;
468 options->star_rating.rejected = c_options->star_rating.rejected;
470 options->threads.duplicates = c_options->threads.duplicates > 0 ? c_options->threads.duplicates : -1;
473 set_debug_level(debug_c);
477 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
479 config_entry_to_option(color_profile_input_name_entry[i], &options->color_profile.input_name[i], NULL);
480 config_entry_to_option(color_profile_input_file_entry[i], &options->color_profile.input_file[i], NULL);
482 config_entry_to_option(color_profile_screen_file_entry, &options->color_profile.screen_file, NULL);
483 options->color_profile.use_x11_screen_profile = c_options->color_profile.use_x11_screen_profile;
484 if (options->color_profile.render_intent != c_options->color_profile.render_intent)
486 options->color_profile.render_intent = c_options->color_profile.render_intent;
491 options->mouse_button_8 = c_options->mouse_button_8;
492 options->mouse_button_9 = c_options->mouse_button_9;
494 options->override_disable_gpu = c_options->override_disable_gpu;
496 config_tab_keywords_save();
498 image_options_sync();
503 layout_refresh(NULL);
506 if (accel_store) gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_apply_cb, NULL);
508 toolbar_apply(TOOLBAR_MAIN);
509 toolbar_apply(TOOLBAR_STATUS);
513 *-----------------------------------------------------------------------------
514 * config window main button callbacks (private)
515 *-----------------------------------------------------------------------------
518 static void config_window_close_cb(GtkWidget *UNUSED(widget), gpointer UNUSED(data))
520 gtk_widget_destroy(configwindow);
525 static void config_window_help_cb(GtkWidget *UNUSED(widget), gpointer data)
527 GtkWidget *notebook = data;
530 static gchar *html_section[] =
532 "GuideOptionsGeneral.html",
533 "GuideOptionsImage.html",
534 "GuideOptionsOSD.html",
535 "GuideOptionsWindow.html",
536 "GuideOptionsKeyboard.html",
537 "GuideOptionsFiltering.html",
538 "GuideOptionsMetadata.html",
539 "GuideOptionsKeywords.html",
540 "GuideOptionsColor.html",
541 "GuideOptionsStereo.html",
542 "GuideOptionsBehavior.html",
543 "GuideOptionsToolbar.html",
544 "GuideOptionsToolbar.html",
545 "GuideOptionsAdvanced.html"
548 i = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
549 help_window_show(html_section[i]);
552 static gboolean config_window_delete(GtkWidget *UNUSED(widget), GdkEventAny *UNUSED(event), gpointer UNUSED(data))
554 config_window_close_cb(NULL, NULL);
558 static void config_window_ok_cb(GtkWidget *widget, gpointer data)
561 GtkNotebook *notebook = data;
569 lw = layout_window_list->data;
571 window = gtk_widget_get_window(widget);
572 gdk_window_get_root_origin(window, &x, &y);
573 w = gdk_window_get_width(window);
574 h = gdk_window_get_height(window);
575 page_number = gtk_notebook_get_current_page(notebook);
577 lw->options.preferences_window.x = x;
578 lw->options.preferences_window.y = y;
579 lw->options.preferences_window.w = w;
580 lw->options.preferences_window.h = h;
581 lw->options.preferences_window.page_number = page_number;
583 config_window_apply();
584 layout_util_sync(lw);
585 save_options(options);
586 config_window_close_cb(NULL, NULL);
590 *-----------------------------------------------------------------------------
591 * config window setup (private)
592 *-----------------------------------------------------------------------------
595 static void quality_menu_cb(GtkWidget *combo, gpointer data)
599 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
603 *option = GDK_INTERP_NEAREST;
606 *option = GDK_INTERP_TILES;
609 *option = GDK_INTERP_BILINEAR;
614 static void dnd_default_action_selection_menu_cb(GtkWidget *combo, gpointer data)
618 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
622 *option = DND_ACTION_ASK;
625 *option = DND_ACTION_COPY;
628 *option = DND_ACTION_MOVE;
632 static void clipboard_selection_menu_cb(GtkWidget *combo, gpointer data)
636 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
639 *option = CLIPBOARD_PRIMARY;
642 *option = CLIPBOARD_CLIPBOARD;
645 *option = CLIPBOARD_BOTH;
648 *option = CLIPBOARD_BOTH;
652 static void add_quality_menu(GtkWidget *table, gint column, gint row, const gchar *text,
653 guint option, guint *option_c)
660 pref_table_label(table, column, row, text, 0.0);
662 combo = gtk_combo_box_text_new();
664 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Nearest (worst, but fastest)"));
665 if (option == GDK_INTERP_NEAREST) current = 0;
666 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Tiles"));
667 if (option == GDK_INTERP_TILES) current = 1;
668 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Bilinear (best, but slowest)"));
669 if (option == GDK_INTERP_BILINEAR) current = 2;
671 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
673 g_signal_connect(G_OBJECT(combo), "changed",
674 G_CALLBACK(quality_menu_cb), option_c);
676 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
677 gtk_widget_show(combo);
680 static void add_dnd_default_action_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text, DnDAction option, DnDAction *option_c)
687 pref_table_label(table, column, row, text, 0.0);
689 combo = gtk_combo_box_text_new();
691 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Ask"));
692 if (option == DND_ACTION_ASK) current = 0;
693 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Copy"));
694 if (option == DND_ACTION_COPY) current = 1;
695 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Move"));
696 if (option == DND_ACTION_MOVE) current = 2;
698 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
700 g_signal_connect(G_OBJECT(combo), "changed",
701 G_CALLBACK(dnd_default_action_selection_menu_cb), option_c);
703 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
704 gtk_widget_show(combo);
707 static void add_clipboard_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
708 gint option, gint *option_c)
715 pref_table_label(table, column, row, text, 0.0);
717 combo = gtk_combo_box_text_new();
719 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Primary"));
720 if (option == CLIPBOARD_PRIMARY) current = 0;
721 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Clipboard"));
722 if (option == CLIPBOARD_CLIPBOARD) current = 1;
723 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Both"));
724 if (option == CLIPBOARD_BOTH) current = 2;
726 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
728 g_signal_connect(G_OBJECT(combo), "changed",
729 G_CALLBACK(clipboard_selection_menu_cb), option_c);
731 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
732 gtk_widget_show(combo);
735 static void zoom_style_selection_menu_cb(GtkWidget *combo, gpointer data)
739 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
742 *option = ZOOM_GEOMETRIC;
745 *option = ZOOM_ARITHMETIC;
748 *option = ZOOM_GEOMETRIC;
752 static void add_zoom_style_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text, ZoomStyle option, ZoomStyle *option_c)
759 pref_table_label(table, column, row, text, 0.0);
761 combo = gtk_combo_box_text_new();
763 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Geometric"));
764 if (option == ZOOM_GEOMETRIC) current = 0;
765 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Arithmetic"));
766 if (option == ZOOM_ARITHMETIC) current = 1;
768 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
770 g_signal_connect(G_OBJECT(combo), "changed", G_CALLBACK(zoom_style_selection_menu_cb), option_c);
772 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
773 gtk_widget_show(combo);
776 typedef struct _UseableMouseItems UseableMouseItems;
777 struct _UseableMouseItems
779 gchar *name; /* GtkActionEntry terminology */
784 static const UseableMouseItems useable_mouse_items[] = {
786 {"FirstImage", N_("First Image"), GTK_STOCK_GOTO_TOP},
787 {"PrevImage", N_("Previous Image"), GTK_STOCK_GO_UP},
788 {"NextImage", N_("Next Image"), GTK_STOCK_GO_DOWN},
789 {"LastImage", N_("Last Image"), GTK_STOCK_GOTO_BOTTOM},
790 {"Back", N_("Back"), GTK_STOCK_GO_BACK},
791 {"Forward", N_("Forward"), GTK_STOCK_GO_FORWARD},
792 {"Home", N_("Home"), GTK_STOCK_HOME},
793 {"Up", N_("Up"), GTK_STOCK_GO_UP},
794 {"FirstPage", N_("First page"), GTK_STOCK_MEDIA_PREVIOUS},
795 {"LastPage", N_("Last Page"), GTK_STOCK_MEDIA_NEXT},
796 {"NextPage", N_("Next page"), GTK_STOCK_MEDIA_FORWARD},
797 {"PrevPage", N_("Previous Page"), GTK_STOCK_MEDIA_REWIND},
798 {"NewWindow", N_("New _window"), GTK_STOCK_NEW},
799 {"NewCollection", N_("New collection"), GTK_STOCK_INDEX},
800 {"OpenCollection", N_("Open collection"), GTK_STOCK_OPEN},
801 {"Search", N_("Search"), GTK_STOCK_FIND},
802 {"FindDupes", N_("Find duplicates"), GTK_STOCK_FIND},
803 {"NewFolder", N_("New folder"),GTK_STOCK_DIRECTORY},
804 {"Copy", N_("Copy"), GTK_STOCK_COPY},
805 {"Move", N_("Move"), PIXBUF_INLINE_ICON_MOVE},
806 {"Rename", N_("Rename"), PIXBUF_INLINE_ICON_RENAME},
807 {"Delete", N_("Delete"), GTK_STOCK_DELETE},
808 {"CloseWindow", N_("Close Window"), GTK_STOCK_CLOSE},
809 {"PanView", N_("Pan view"), PIXBUF_INLINE_ICON_PANORAMA},
810 {"SelectAll", N_("Select all"), PIXBUF_INLINE_ICON_SELECT_ALL},
811 {"SelectNone", N_("Select none"), PIXBUF_INLINE_ICON_SELECT_NONE},
812 {"SelectInvert", N_("Select invert"), PIXBUF_INLINE_ICON_SELECT_INVERT},
813 {"ShowFileFilter", N_("Show file filter"), PIXBUF_INLINE_ICON_FILE_FILTER},
814 {"RectangularSelection", N_("Select rectangle"), PIXBUF_INLINE_ICON_SELECT_RECTANGLE},
815 {"Print", N_("Print"), GTK_STOCK_PRINT},
816 {"Preferences", N_("Preferences"), GTK_STOCK_PREFERENCES},
817 {"LayoutConfig", N_("Configure this window"), GTK_STOCK_PREFERENCES},
818 {"Maintenance", N_("Cache maintenance"), PIXBUF_INLINE_ICON_MAINTENANCE},
819 {"RotateCW", N_("Rotate clockwise 90°"), PIXBUF_INLINE_ICON_CW},
820 {"RotateCCW", N_("Rotate counterclockwise 90°"), PIXBUF_INLINE_ICON_CCW},
821 {"Rotate180", N_("Rotate 180°"), PIXBUF_INLINE_ICON_180},
822 {"Mirror", N_("Mirror"), PIXBUF_INLINE_ICON_MIRROR},
823 {"Flip", N_("Flip"), PIXBUF_INLINE_ICON_FLIP},
824 {"AlterNone", N_("Original state"), PIXBUF_INLINE_ICON_ORIGINAL},
825 {"ZoomIn", N_("Zoom in"), GTK_STOCK_ZOOM_IN},
826 {"ZoomOut", N_("Zoom out"), GTK_STOCK_ZOOM_OUT},
827 {"Zoom100", N_("Zoom 1:1"), GTK_STOCK_ZOOM_100},
828 {"ZoomFit", N_("Zoom to fit"), GTK_STOCK_ZOOM_FIT},
829 {"ZoomFillHor", N_("Fit Horizontaly"), PIXBUF_INLINE_ICON_ZOOMFILLHOR},
830 {"ZoomFillVert", N_("Fit vertically"), PIXBUF_INLINE_ICON_ZOOMFILLVERT},
831 {"Zoom200", N_("Zoom 2:1"), GTK_STOCK_FILE},
832 {"Zoom300", N_("Zoom 3:1"), GTK_STOCK_FILE},
833 {"Zoom400", N_("Zoom 4:1"), GTK_STOCK_FILE},
834 {"Zoom50", N_("Zoom 1:2"), GTK_STOCK_FILE},
835 {"Zoom33", N_("Zoom1:3"), GTK_STOCK_FILE},
836 {"Zoom25", N_("Zoom 1:4"), GTK_STOCK_FILE},
837 {"ConnectZoomIn", N_("Connected Zoom in"), GTK_STOCK_ZOOM_IN},
838 {"SplitPaneSync", N_("Split Pane Sync"), PIXBUF_INLINE_SPLIT_PANE_SYNC},
839 {"Grayscale", N_("Grayscale"), PIXBUF_INLINE_ICON_GRAYSCALE},
840 {"OverUnderExposed", N_("Over Under Exposed"), PIXBUF_INLINE_ICON_EXPOSURE},
841 {"HideTools", N_("Hide file list"), PIXBUF_INLINE_ICON_HIDETOOLS},
842 {"SlideShowPause", N_("Pause slideshow"), GTK_STOCK_MEDIA_PAUSE},
843 {"SlideShowFaster", N_("Slideshow Faster"), GTK_STOCK_FILE},
844 {"SlideShowSlower", N_("Slideshow Slower"), GTK_STOCK_FILE},
845 {"Refresh", N_("Refresh"), GTK_STOCK_REFRESH},
846 {"HelpContents", N_("Help"), GTK_STOCK_HELP},
847 {"ExifWin", N_("Exif window"), PIXBUF_INLINE_ICON_EXIF},
848 {"Thumbnails", N_("Show thumbnails"), PIXBUF_INLINE_ICON_THUMB},
849 {"ShowMarks", N_("Show marks"), PIXBUF_INLINE_ICON_MARKS},
850 {"DrawRectangle", N_("Draw Rectangle"), PIXBUF_INLINE_ICON_DRAW_RECTANGLE},
851 {"FloatTools", N_("Float file list"), PIXBUF_INLINE_ICON_FLOAT},
852 {"SBar", N_("Info sidebar"), PIXBUF_INLINE_ICON_INFO},
853 {"SBarSort", N_("Sort manager"), PIXBUF_INLINE_ICON_SORT},
854 {"Quit", N_("Quit"), GTK_STOCK_QUIT},
858 static void mouse_buttons_selection_menu_cb(GtkWidget *combo, gpointer data)
860 gchar **option = data;
863 label = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(combo));
865 const UseableMouseItems *list = useable_mouse_items;
869 if (g_strcmp0(list->label, label) == 0)
877 *option = g_strdup(list->name);
881 static void add_mouse_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
882 gchar *option, gchar **option_c)
890 pref_table_label(table, column, row, text, 0.0);
892 combo = gtk_combo_box_text_new();
894 const UseableMouseItems *list = useable_mouse_items;
898 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), list->label);
899 if (g_strcmp0(list->name, option) == 0)
907 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
909 g_signal_connect(G_OBJECT(combo), "changed",
910 G_CALLBACK(mouse_buttons_selection_menu_cb), option_c);
912 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
913 gtk_widget_show(combo);
916 static void thumb_size_menu_cb(GtkWidget *combo, gpointer UNUSED(data))
920 n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
923 if ((guint) n < sizeof(thumb_size_list) / sizeof(ThumbSize))
925 c_options->thumbnails.max_width = thumb_size_list[n].w;
926 c_options->thumbnails.max_height = thumb_size_list[n].h;
930 c_options->thumbnails.max_width = options->thumbnails.max_width;
931 c_options->thumbnails.max_height = options->thumbnails.max_height;
935 static void add_thumb_size_menu(GtkWidget *table, gint column, gint row, gchar *text)
941 c_options->thumbnails.max_width = options->thumbnails.max_width;
942 c_options->thumbnails.max_height = options->thumbnails.max_height;
944 pref_table_label(table, column, row, text, 0.0);
946 combo = gtk_combo_box_text_new();
949 for (i = 0; (guint) i < sizeof(thumb_size_list) / sizeof(ThumbSize); i++)
954 w = thumb_size_list[i].w;
955 h = thumb_size_list[i].h;
957 buf = g_strdup_printf("%d x %d", w, h);
958 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
961 if (w == options->thumbnails.max_width && h == options->thumbnails.max_height) current = i;
968 buf = g_strdup_printf("%s %d x %d", _("Custom"), options->thumbnails.max_width, options->thumbnails.max_height);
969 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
975 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
976 g_signal_connect(G_OBJECT(combo), "changed",
977 G_CALLBACK(thumb_size_menu_cb), NULL);
979 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
980 gtk_widget_show(combo);
983 static void stereo_mode_menu_cb(GtkWidget *combo, gpointer data)
987 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
991 *option = PR_STEREO_NONE;
994 *option = PR_STEREO_ANAGLYPH_RC;
997 *option = PR_STEREO_ANAGLYPH_GM;
1000 *option = PR_STEREO_ANAGLYPH_YB;
1003 *option = PR_STEREO_ANAGLYPH_GRAY_RC;
1006 *option = PR_STEREO_ANAGLYPH_GRAY_GM;
1009 *option = PR_STEREO_ANAGLYPH_GRAY_YB;
1012 *option = PR_STEREO_ANAGLYPH_DB_RC;
1015 *option = PR_STEREO_ANAGLYPH_DB_GM;
1018 *option = PR_STEREO_ANAGLYPH_DB_YB;
1021 *option = PR_STEREO_HORIZ;
1024 *option = PR_STEREO_HORIZ | PR_STEREO_HALF;
1027 *option = PR_STEREO_VERT;
1030 *option = PR_STEREO_VERT | PR_STEREO_HALF;
1033 *option = PR_STEREO_FIXED;
1038 static void add_stereo_mode_menu(GtkWidget *table, gint column, gint row, const gchar *text,
1039 gint option, gint *option_c, gboolean add_fixed)
1046 pref_table_label(table, column, row, text, 0.0);
1048 combo = gtk_combo_box_text_new();
1050 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Single image"));
1052 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Red-Cyan"));
1053 if (option & PR_STEREO_ANAGLYPH_RC) current = 1;
1054 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Green-Magenta"));
1055 if (option & PR_STEREO_ANAGLYPH_GM) current = 2;
1056 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Yellow-Blue"));
1057 if (option & PR_STEREO_ANAGLYPH_YB) current = 3;
1058 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Red-Cyan"));
1059 if (option & PR_STEREO_ANAGLYPH_GRAY_RC) current = 4;
1060 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Green-Magenta"));
1061 if (option & PR_STEREO_ANAGLYPH_GRAY_GM) current = 5;
1062 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Yellow-Blue"));
1063 if (option & PR_STEREO_ANAGLYPH_GRAY_YB) current = 6;
1064 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Red-Cyan"));
1065 if (option & PR_STEREO_ANAGLYPH_DB_RC) current = 7;
1066 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Green-Magenta"));
1067 if (option & PR_STEREO_ANAGLYPH_DB_GM) current = 8;
1068 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Yellow-Blue"));
1069 if (option & PR_STEREO_ANAGLYPH_DB_YB) current = 9;
1071 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side"));
1072 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side Half size"));
1073 if (option & PR_STEREO_HORIZ)
1076 if (option & PR_STEREO_HALF) current = 11;
1079 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom"));
1080 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom Half size"));
1081 if (option & PR_STEREO_VERT)
1084 if (option & PR_STEREO_HALF) current = 13;
1089 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Fixed position"));
1090 if (option & PR_STEREO_FIXED) current = 14;
1093 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
1095 g_signal_connect(G_OBJECT(combo), "changed",
1096 G_CALLBACK(stereo_mode_menu_cb), option_c);
1098 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
1099 gtk_widget_show(combo);
1102 static void video_menu_cb(GtkWidget *combo, gpointer data)
1104 gchar **option = data;
1106 EditorDescription *ed = g_list_nth_data(editor_list_get(), gtk_combo_box_get_active(GTK_COMBO_BOX(combo)));
1110 static void video_menu_populate(gpointer data, gpointer user_data)
1112 GtkWidget *combo = user_data;
1113 EditorDescription *ed = data;
1115 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), ed->name);
1118 static void add_video_menu(GtkWidget *table, gint column, gint row, const gchar *text,
1119 gchar *option, gchar **option_c)
1123 /* use lists since they are sorted */
1124 GList *eds = editor_list_get();
1128 pref_table_label(table, column, row, text, 0.0);
1130 combo = gtk_combo_box_text_new();
1131 g_list_foreach(eds,video_menu_populate,(gpointer)combo);
1132 current = option ? g_list_index(eds,g_hash_table_lookup(editors,option)): -1;
1134 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
1136 g_signal_connect(G_OBJECT(combo), "changed",
1137 G_CALLBACK(video_menu_cb), option_c);
1139 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
1140 gtk_widget_show(combo);
1143 static void filter_store_populate(void)
1147 if (!filter_store) return;
1149 gtk_list_store_clear(filter_store);
1151 work = filter_get_list();
1160 gtk_list_store_append(filter_store, &iter);
1161 gtk_list_store_set(filter_store, &iter, 0, fe, -1);
1165 static void filter_store_ext_edit_cb(GtkCellRendererText *UNUSED(cell), gchar *path_str,
1166 gchar *new_text, gpointer data)
1168 GtkWidget *model = data;
1169 FilterEntry *fe = data;
1173 if (!new_text || strlen(new_text) < 1) return;
1175 tpath = gtk_tree_path_new_from_string(path_str);
1176 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1177 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1179 g_free(fe->extensions);
1180 fe->extensions = g_strdup(new_text);
1182 gtk_tree_path_free(tpath);
1186 static void filter_store_class_edit_cb(GtkCellRendererText *UNUSED(cell), gchar *path_str,
1187 gchar *new_text, gpointer data)
1189 GtkWidget *model = data;
1190 FilterEntry *fe = data;
1195 if (!new_text || !new_text[0]) return;
1197 tpath = gtk_tree_path_new_from_string(path_str);
1198 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1199 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1201 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
1203 if (strcmp(new_text, _(format_class_list[i])) == 0)
1210 gtk_tree_path_free(tpath);
1214 static void filter_store_desc_edit_cb(GtkCellRendererText *UNUSED(cell), gchar *path_str,
1215 gchar *new_text, gpointer data)
1217 GtkWidget *model = data;
1222 if (!new_text || !new_text[0]) return;
1224 tpath = gtk_tree_path_new_from_string(path_str);
1225 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1226 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1228 g_free(fe->description);
1229 fe->description = g_strdup(new_text);
1231 gtk_tree_path_free(tpath);
1234 static void filter_store_enable_cb(GtkCellRendererToggle *UNUSED(renderer),
1235 gchar *path_str, gpointer data)
1237 GtkWidget *model = data;
1242 tpath = gtk_tree_path_new_from_string(path_str);
1243 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1244 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1246 fe->enabled = !fe->enabled;
1248 gtk_tree_path_free(tpath);
1252 static void filter_store_writable_cb(GtkCellRendererToggle *UNUSED(renderer),
1253 gchar *path_str, gpointer data)
1255 GtkWidget *model = data;
1260 tpath = gtk_tree_path_new_from_string(path_str);
1261 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1262 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1264 fe->writable = !fe->writable;
1265 if (fe->writable) fe->allow_sidecar = FALSE;
1267 gtk_tree_path_free(tpath);
1271 static void filter_store_sidecar_cb(GtkCellRendererToggle *UNUSED(renderer),
1272 gchar *path_str, gpointer data)
1274 GtkWidget *model = data;
1279 tpath = gtk_tree_path_new_from_string(path_str);
1280 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1281 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1283 fe->allow_sidecar = !fe->allow_sidecar;
1284 if (fe->allow_sidecar) fe->writable = FALSE;
1286 gtk_tree_path_free(tpath);
1290 static void filter_set_func(GtkTreeViewColumn *UNUSED(tree_column), GtkCellRenderer *cell,
1291 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
1295 gtk_tree_model_get(tree_model, iter, 0, &fe, -1);
1297 switch (GPOINTER_TO_INT(data))
1300 g_object_set(GTK_CELL_RENDERER(cell),
1301 "active", fe->enabled, NULL);
1304 g_object_set(GTK_CELL_RENDERER(cell),
1305 "text", fe->extensions, NULL);
1307 case FE_DESCRIPTION:
1308 g_object_set(GTK_CELL_RENDERER(cell),
1309 "text", fe->description, NULL);
1312 g_object_set(GTK_CELL_RENDERER(cell),
1313 "text", _(format_class_list[fe->file_class]), NULL);
1316 g_object_set(GTK_CELL_RENDERER(cell),
1317 "active", fe->writable, NULL);
1319 case FE_ALLOW_SIDECAR:
1320 g_object_set(GTK_CELL_RENDERER(cell),
1321 "active", fe->allow_sidecar, NULL);
1326 static gboolean filter_add_scroll(gpointer data)
1330 GtkCellRenderer *cell;
1331 GtkTreeViewColumn *column;
1334 GtkTreeModel *store;
1336 FilterEntry *filter;
1338 rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(filter_store), NULL);
1339 path = gtk_tree_path_new_from_indices(rows-1, -1);
1341 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data), 0);
1343 list_cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column));
1344 cell = g_list_last(list_cells)->data;
1346 store = gtk_tree_view_get_model(GTK_TREE_VIEW(data));
1347 valid = gtk_tree_model_get_iter_first(store, &iter);
1351 gtk_tree_model_get(store, &iter, 0, &filter, -1);
1353 if (g_strcmp0(filter->extensions, ".new") == 0)
1355 path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iter);
1359 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter);
1362 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1363 path, column, FALSE, 0.0, 0.0 );
1364 gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(data),
1365 path, column, cell, TRUE);
1367 gtk_tree_path_free(path);
1368 g_list_free(list_cells);
1373 static void filter_add_cb(GtkWidget *UNUSED(widget), gpointer data)
1375 filter_add_unique("description", ".new", FORMAT_CLASS_IMAGE, TRUE, FALSE, TRUE);
1376 filter_store_populate();
1378 g_idle_add((GSourceFunc)filter_add_scroll, data);
1381 static void filter_remove_cb(GtkWidget *UNUSED(widget), gpointer data)
1383 GtkWidget *filter_view = data;
1384 GtkTreeSelection *selection;
1388 if (!filter_store) return;
1389 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1390 if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) return;
1391 gtk_tree_model_get(GTK_TREE_MODEL(filter_store), &iter, 0, &fe, -1);
1394 filter_remove_entry(fe);
1396 filter_store_populate();
1399 static gboolean filter_default_ok_scroll(GtkTreeView *data)
1403 GtkTreeViewColumn *column;
1405 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(filter_store), &iter);
1406 path = gtk_tree_model_get_path(GTK_TREE_MODEL(filter_store), &iter);
1407 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1409 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1413 gtk_tree_path_free(path);
1418 static void filter_default_ok_cb(GenericDialog *gd, gpointer UNUSED(data))
1421 filter_add_defaults();
1423 filter_store_populate();
1425 g_idle_add((GSourceFunc)filter_default_ok_scroll, gd->data);
1428 static void dummy_cancel_cb(GenericDialog *UNUSED(gd), gpointer UNUSED(data))
1430 /* no op, only so cancel button appears */
1433 static void filter_default_cb(GtkWidget *widget, gpointer data)
1437 gd = generic_dialog_new(_("Reset filters"),
1438 "reset_filter", widget, TRUE,
1439 dummy_cancel_cb, data);
1440 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset filters"),
1441 _("This will reset the file filters to the defaults.\nContinue?"), TRUE);
1442 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, filter_default_ok_cb, TRUE);
1443 gtk_widget_show(gd->dialog);
1446 static void filter_disable_cb(GtkWidget *widget, gpointer data)
1448 GtkWidget *frame = data;
1450 gtk_widget_set_sensitive(frame,
1451 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
1454 static void safe_delete_view_cb(GtkWidget *UNUSED(widget), gpointer UNUSED(data))
1456 layout_set_path(NULL, gtk_entry_get_text(GTK_ENTRY(safe_delete_path_entry)));
1459 static void safe_delete_clear_ok_cb(GenericDialog *UNUSED(gd), gpointer UNUSED(data))
1461 file_util_trash_clear();
1464 static void safe_delete_clear_cb(GtkWidget *widget, gpointer UNUSED(data))
1468 gd = generic_dialog_new(_("Clear trash"),
1469 "clear_trash", widget, TRUE,
1470 dummy_cancel_cb, NULL);
1471 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear trash"),
1472 _("This will remove the trash contents."), FALSE);
1473 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, safe_delete_clear_ok_cb, TRUE);
1474 entry = gtk_entry_new();
1475 gtk_widget_set_can_focus(entry, FALSE);
1476 gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE);
1477 if (options->file_ops.safe_delete_path) gtk_entry_set_text(GTK_ENTRY(entry), options->file_ops.safe_delete_path);
1478 gtk_box_pack_start(GTK_BOX(gd->vbox), entry, FALSE, FALSE, 0);
1479 gtk_widget_show(entry);
1480 gtk_widget_show(gd->dialog);
1483 static void image_overlay_template_view_changed_cb(GtkWidget *UNUSED(widget), gpointer data)
1485 GtkWidget *pTextView;
1486 GtkTextBuffer *pTextBuffer;
1490 pTextView = GTK_WIDGET(data);
1492 pTextBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pTextView));
1493 gtk_text_buffer_get_start_iter(pTextBuffer, &iStart);
1494 gtk_text_buffer_get_end_iter(pTextBuffer, &iEnd);
1496 set_image_overlay_template_string(&c_options->image_overlay.template_string,
1497 gtk_text_buffer_get_text(pTextBuffer, &iStart, &iEnd, TRUE));
1500 static void image_overlay_default_template_ok_cb(GenericDialog *UNUSED(gd), gpointer data)
1502 GtkTextView *text_view = data;
1503 GtkTextBuffer *buffer;
1505 set_default_image_overlay_template_string(&options->image_overlay.template_string);
1506 if (!configwindow) return;
1508 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
1509 gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1512 static void image_overlay_default_template_cb(GtkWidget *widget, gpointer data)
1516 gd = generic_dialog_new(_("Reset image overlay template string"),
1517 "reset_image_overlay_template_string", widget, TRUE,
1518 dummy_cancel_cb, data);
1519 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset image overlay template string"),
1520 _("This will reset the image overlay template string to the default.\nContinue?"), TRUE);
1521 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, image_overlay_default_template_ok_cb, TRUE);
1522 gtk_widget_show(gd->dialog);
1525 static void image_overlay_help_cb(GtkWidget *UNUSED(widget), gpointer UNUSED(data))
1527 help_window_show("GuideOptionsOSD.html");
1530 static void image_overlay_set_font_cb(GtkWidget *widget, gpointer UNUSED(data))
1534 PangoFontDescription *font_desc;
1536 dialog = gtk_font_chooser_dialog_new("Image Overlay Font", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1537 gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), options->image_overlay.font);
1539 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1541 font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
1542 font = pango_font_description_to_string(font_desc);
1543 g_free(c_options->image_overlay.font);
1544 c_options->image_overlay.font = g_strdup(font);
1548 gtk_widget_destroy(dialog);
1551 static void image_overlay_set_text_colour_cb(GtkWidget *widget, gpointer UNUSED(data))
1556 dialog = gtk_color_chooser_dialog_new("Image Overlay Text Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1557 colour.red = options->image_overlay.text_red;
1558 colour.green = options->image_overlay.text_green;
1559 colour.blue = options->image_overlay.text_blue;
1560 colour.alpha = options->image_overlay.text_alpha;
1561 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1562 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1564 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1566 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1567 c_options->image_overlay.text_red = colour.red*255;
1568 c_options->image_overlay.text_green = colour.green*255;
1569 c_options->image_overlay.text_blue = colour.blue*255;
1570 c_options->image_overlay.text_alpha = colour.alpha*255;
1572 gtk_widget_destroy(dialog);
1576 static void image_overlay_set_background_colour_cb(GtkWidget *widget, gpointer UNUSED(data))
1581 dialog = gtk_color_chooser_dialog_new("Image Overlay Background Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1582 colour.red = options->image_overlay.background_red;
1583 colour.green = options->image_overlay.background_green;
1584 colour.blue = options->image_overlay.background_blue;
1585 colour.alpha = options->image_overlay.background_alpha;
1586 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1587 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1589 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1591 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1592 c_options->image_overlay.background_red = colour.red*255;
1593 c_options->image_overlay.background_green = colour.green*255;
1594 c_options->image_overlay.background_blue = colour.blue*255;
1595 c_options->image_overlay.background_alpha = colour.alpha*255;
1597 gtk_widget_destroy(dialog);
1600 static void accel_store_populate(void)
1603 GList *groups, *actions;
1605 const gchar *accel_path;
1609 if (!accel_store || !layout_window_list || !layout_window_list->data) return;
1611 gtk_tree_store_clear(accel_store);
1612 lw = layout_window_list->data; /* get the actions from the first window, it should not matter, they should be the same in all windows */
1614 g_assert(lw && lw->ui_manager);
1615 groups = gtk_ui_manager_get_action_groups(lw->ui_manager);
1618 actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
1621 action = GTK_ACTION(actions->data);
1622 accel_path = gtk_action_get_accel_path(action);
1623 if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
1625 gchar *label, *label2, *tooltip, *accel;
1626 g_object_get(action,
1627 "tooltip", &tooltip,
1631 if (pango_parse_markup(label, -1, '_', NULL, &label2, NULL, NULL) && label2)
1637 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1641 gtk_tree_store_append(accel_store, &iter, NULL);
1642 gtk_tree_store_set(accel_store, &iter,
1645 AE_TOOLTIP, tooltip ? tooltip : "",
1646 AE_ACCEL, accel_path,
1654 actions = actions->next;
1657 groups = groups->next;
1661 static void accel_store_cleared_cb(GtkCellRendererAccel *UNUSED(accel), gchar *UNUSED(path_string), gpointer UNUSED(user_data))
1666 static gboolean accel_remove_key_cb(GtkTreeModel *model, GtkTreePath *UNUSED(path), GtkTreeIter *iter, gpointer data)
1668 gchar *accel1 = data;
1673 gtk_tree_model_get(model, iter, AE_KEY, &accel2, -1);
1675 gtk_accelerator_parse(accel1, &key1.accel_key, &key1.accel_mods);
1676 gtk_accelerator_parse(accel2, &key2.accel_key, &key2.accel_mods);
1678 if (key1.accel_key == key2.accel_key && key1.accel_mods == key2.accel_mods)
1680 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1681 DEBUG_1("accelerator key '%s' is already used, removing.", accel1);
1690 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))
1692 GtkTreeModel *model = (GtkTreeModel *)accel_store;
1696 GtkAccelKey old_key, key;
1697 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
1699 gtk_tree_model_get_iter(model, &iter, path);
1700 gtk_tree_model_get(model, &iter, AE_ACCEL, &accel_path, -1);
1702 /* test if the accelerator can be stored without conflicts*/
1703 gtk_accel_map_lookup_entry(accel_path, &old_key);
1705 /* change the key and read it back (change may fail on keys hardcoded in gtk)*/
1706 gtk_accel_map_change_entry(accel_path, accel_key, accel_mods, TRUE);
1707 gtk_accel_map_lookup_entry(accel_path, &key);
1709 /* restore the original for now, the key will be really changed when the changes are confirmed */
1710 gtk_accel_map_change_entry(accel_path, old_key.accel_key, old_key.accel_mods, TRUE);
1712 acc = gtk_accelerator_name(key.accel_key, key.accel_mods);
1713 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, acc);
1715 gtk_tree_store_set(accel_store, &iter, AE_KEY, acc, -1);
1716 gtk_tree_path_free(path);
1720 static gboolean accel_default_scroll(GtkTreeView *data)
1724 GtkTreeViewColumn *column;
1726 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(accel_store), &iter);
1727 path = gtk_tree_model_get_path(GTK_TREE_MODEL(accel_store), &iter);
1728 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1730 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1734 gtk_tree_path_free(path);
1739 static void accel_default_cb(GtkWidget *UNUSED(widget), gpointer data)
1741 accel_store_populate();
1743 g_idle_add((GSourceFunc)accel_default_scroll, data);
1746 void accel_remove_selection(GtkTreeModel *UNUSED(model), GtkTreePath *UNUSED(path), GtkTreeIter *iter, gpointer UNUSED(data))
1748 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1751 void accel_reset_selection(GtkTreeModel *model, GtkTreePath *UNUSED(path), GtkTreeIter *iter, gpointer UNUSED(data))
1754 gchar *accel_path, *accel;
1756 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, -1);
1757 gtk_accel_map_lookup_entry(accel_path, &key);
1758 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1760 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, accel);
1762 gtk_tree_store_set(accel_store, iter, AE_KEY, accel, -1);
1767 static void accel_reset_cb(GtkWidget *UNUSED(widget), gpointer data)
1769 GtkTreeSelection *selection;
1771 if (!accel_store) return;
1772 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data));
1773 gtk_tree_selection_selected_foreach(selection, &accel_reset_selection, NULL);
1778 static GtkWidget *scrolled_notebook_page(GtkWidget *notebook, const gchar *title)
1782 GtkWidget *scrolled;
1783 GtkWidget *viewport;
1785 scrolled = gtk_scrolled_window_new(NULL, NULL);
1786 gtk_container_set_border_width(GTK_CONTAINER(scrolled), PREF_PAD_BORDER);
1787 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1788 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1789 label = gtk_label_new(title);
1790 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, label);
1791 gtk_widget_show(scrolled);
1793 viewport = gtk_viewport_new(NULL, NULL);
1794 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1795 gtk_container_add(GTK_CONTAINER(scrolled), viewport);
1796 gtk_widget_show(viewport);
1798 vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
1799 gtk_container_add(GTK_CONTAINER(viewport), vbox);
1800 gtk_widget_show(vbox);
1805 static void cache_standard_cb(GtkWidget *widget, gpointer UNUSED(data))
1807 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1809 c_options->thumbnails.spec_standard =TRUE;
1810 c_options->thumbnails.cache_into_dirs = FALSE;
1814 static void cache_geeqie_cb(GtkWidget *widget, gpointer UNUSED(data))
1816 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1818 c_options->thumbnails.spec_standard =FALSE;
1819 c_options->thumbnails.cache_into_dirs = FALSE;
1823 static void cache_local_cb(GtkWidget *widget, gpointer UNUSED(data))
1825 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1827 c_options->thumbnails.cache_into_dirs = TRUE;
1828 c_options->thumbnails.spec_standard =FALSE;
1832 static void help_search_engine_entry_icon_cb(GtkEntry *UNUSED(entry), GtkEntryIconPosition pos,
1833 GdkEvent *UNUSED(event), gpointer userdata)
1835 if (pos == GTK_ENTRY_ICON_PRIMARY)
1837 gtk_entry_set_text(GTK_ENTRY(userdata), HELP_SEARCH_ENGINE);
1841 gtk_entry_set_text(GTK_ENTRY(userdata), "");
1845 static void star_rating_star_icon_cb(GtkEntry *UNUSED(entry), GtkEntryIconPosition pos,
1846 GdkEvent *UNUSED(event), gpointer userdata)
1848 gchar *rating_symbol;
1850 if (pos == GTK_ENTRY_ICON_PRIMARY)
1852 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_STAR);
1853 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1854 g_free(rating_symbol);
1858 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1859 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1860 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1864 static void star_rating_rejected_icon_cb(GtkEntry *UNUSED(entry), GtkEntryIconPosition pos,
1865 GdkEvent *UNUSED(event), gpointer userdata)
1867 gchar *rating_symbol;
1869 if (pos == GTK_ENTRY_ICON_PRIMARY)
1871 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_REJECTED);
1872 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1873 g_free(rating_symbol);
1877 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1878 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1879 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1883 static guint star_rating_symbol_test(GtkWidget *UNUSED(widget), gpointer data)
1885 GtkContainer *hbox = data;
1886 GString *str = g_string_new(NULL);
1887 GtkEntry *hex_code_entry;
1888 gchar *hex_code_full;
1891 guint64 hex_value = 0;
1893 list = gtk_container_get_children(hbox);
1895 hex_code_entry = g_list_nth_data(list, 2);
1896 hex_code_full = g_strdup(gtk_entry_get_text(hex_code_entry));
1898 hex_code = g_strsplit(hex_code_full, "+", 2);
1899 if (hex_code[0] && hex_code[1])
1901 hex_value = strtoull(hex_code[1], NULL, 16);
1903 if (!hex_value || hex_value > 0x10FFFF)
1905 hex_value = 0x003F; // Unicode 'Question Mark'
1907 str = g_string_append_unichar(str, (gunichar)hex_value);
1908 gtk_label_set_text(g_list_nth_data(list, 1), str->str);
1910 g_strfreev(hex_code);
1911 g_string_free(str, TRUE);
1912 g_free(hex_code_full);
1917 static void star_rating_star_test_cb(GtkWidget *widget, gpointer data)
1919 guint64 star_symbol;
1921 star_symbol = star_rating_symbol_test(widget, data);
1922 c_options->star_rating.star = star_symbol;
1925 static void star_rating_rejected_test_cb(GtkWidget *widget, gpointer data)
1927 guint64 rejected_symbol;
1929 rejected_symbol = star_rating_symbol_test(widget, data);
1930 c_options->star_rating.rejected = rejected_symbol;
1933 /* general options tab */
1934 static void timezone_database_install_cb(GtkWidget *widget, gpointer data);
1935 typedef struct _TZData TZData;
1939 GCancellable *cancellable;
1941 GtkWidget *progress;
1943 GFile *timezone_database_gq;
1944 gchar *timezone_database_user;
1947 static void config_tab_general(GtkWidget *notebook)
1952 GtkWidget *group_frame;
1953 GtkWidget *subgroup;
1955 GtkWidget *ct_button;
1958 gint hours, minutes, remainder;
1960 GtkWidget *star_rating_entry;
1962 gchar *rating_symbol;
1965 gchar *download_locn;
1966 GNetworkMonitor *net_mon;
1967 GSocketConnectable *tz_org;
1968 gboolean internet_available = FALSE;
1971 vbox = scrolled_notebook_page(notebook, _("General"));
1973 group = pref_group_new(vbox, FALSE, _("Thumbnails"), GTK_ORIENTATION_VERTICAL);
1975 table = pref_table_new(group, 2, 2, FALSE, FALSE);
1976 add_thumb_size_menu(table, 0, 0, _("Size:"));
1977 add_quality_menu(table, 0, 1, _("Quality:"), options->thumbnails.quality, &c_options->thumbnails.quality);
1979 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1980 pref_label_new(hbox, _("Custom size: "));
1981 pref_spin_new_int(hbox, _("Width:"), NULL, 1, 512, 1, options->thumbnails.max_width, &c_options->thumbnails.max_width);
1982 pref_spin_new_int(hbox, _("Height:"), NULL, 1, 512, 1, options->thumbnails.max_height, &c_options->thumbnails.max_height);
1984 ct_button = pref_checkbox_new_int(group, _("Cache thumbnails and sim. files"),
1985 options->thumbnails.enable_caching, &c_options->thumbnails.enable_caching);
1987 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1988 pref_checkbox_link_sensitivity(ct_button, subgroup);
1990 c_options->thumbnails.spec_standard = options->thumbnails.spec_standard;
1991 c_options->thumbnails.cache_into_dirs = options->thumbnails.cache_into_dirs;
1992 group_frame = pref_frame_new(subgroup, TRUE, _("Use Geeqie thumbnail style and cache"),
1993 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1994 button = pref_radiobutton_new(group_frame, NULL, get_thumbnails_cache_dir(),
1995 !options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1996 G_CALLBACK(cache_geeqie_cb), NULL);
1998 group_frame = pref_frame_new(subgroup, TRUE,
1999 _("Store thumbnails local to image folder (non-standard)"),
2000 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2001 pref_radiobutton_new(group_frame, button, "*/.thumbnails",
2002 !options->thumbnails.spec_standard && options->thumbnails.cache_into_dirs,
2003 G_CALLBACK(cache_local_cb), NULL);
2005 group_frame = pref_frame_new(subgroup, TRUE,
2006 _("Use standard thumbnail style and cache, shared with other applications"),
2007 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2008 pref_radiobutton_new(group_frame, button, get_thumbnails_standard_cache_dir(),
2009 options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
2010 G_CALLBACK(cache_standard_cb), NULL);
2012 pref_checkbox_new_int(group, _("Use EXIF thumbnails when available (EXIF thumbnails may be outdated)"),
2013 options->thumbnails.use_exif, &c_options->thumbnails.use_exif);
2015 pref_checkbox_new_int(group, _("Thumbnail color management"),
2016 options->thumbnails.use_color_management, &c_options->thumbnails.use_color_management);
2018 spin = pref_spin_new_int(group, _("Collection preview:"), NULL,
2020 options->thumbnails.collection_preview, &c_options->thumbnails.collection_preview);
2021 gtk_widget_set_tooltip_text(spin, _("The maximum number of thumbnails shown in a Collection preview montage"));
2023 #ifdef HAVE_FFMPEGTHUMBNAILER_METADATA
2024 pref_checkbox_new_int(group, _("Use embedded metadata in video files as thumbnails when available"),
2025 options->thumbnails.use_ft_metadata, &c_options->thumbnails.use_ft_metadata);
2027 // pref_checkbox_new_int(group, _("Ignore embedded metadata if size is too small"),
2028 // options->thumbnails.use_ft_metadata_small, &c_options->thumbnails.use_ft_metadata_small);
2031 pref_spacer(group, PREF_PAD_GROUP);
2033 group = pref_group_new(vbox, FALSE, _("Star Rating"), GTK_ORIENTATION_VERTICAL);
2035 c_options->star_rating.star = options->star_rating.star;
2036 c_options->star_rating.rejected = options->star_rating.rejected;
2038 str = g_string_new(NULL);
2039 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2040 pref_label_new(hbox, _("Star character: "));
2041 str = g_string_append_unichar(str, options->star_rating.star);
2042 pref_label_new(hbox, g_strdup(str->str));
2043 rating_symbol = g_strdup_printf("U+%X", options->star_rating.star);
2044 star_rating_entry = gtk_entry_new();
2045 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
2046 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
2047 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
2048 gtk_widget_show(star_rating_entry);
2049 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
2050 G_CALLBACK(star_rating_star_test_cb), hbox);
2051 gtk_widget_set_tooltip_text(button, _("Display selected character"));
2052 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2053 gtk_widget_show(button);
2054 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."));
2055 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2056 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2057 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2058 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2059 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2060 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2061 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2062 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2063 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
2064 G_CALLBACK(star_rating_star_icon_cb),
2067 g_string_free(str, TRUE);
2068 g_free(rating_symbol);
2070 str = g_string_new(NULL);
2071 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2072 pref_label_new(hbox, _("Rejected character: "));
2073 str = g_string_append_unichar(str, options->star_rating.rejected);
2074 pref_label_new(hbox, g_strdup(str->str));
2075 rating_symbol = g_strdup_printf("U+%X", options->star_rating.rejected);
2076 star_rating_entry = gtk_entry_new();
2077 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
2078 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
2079 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
2080 gtk_widget_show(star_rating_entry);
2081 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
2082 G_CALLBACK(star_rating_rejected_test_cb), hbox);
2083 gtk_widget_set_tooltip_text(button, _("Display selected character"));
2084 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2085 gtk_widget_show(button);
2086 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."));
2087 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2088 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2089 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2090 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2091 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2092 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2093 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2094 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2095 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
2096 G_CALLBACK(star_rating_rejected_icon_cb),
2099 g_string_free(str, TRUE);
2100 g_free(rating_symbol);
2102 pref_spacer(group, PREF_PAD_GROUP);
2104 group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
2106 c_options->slideshow.delay = options->slideshow.delay;
2107 hours = options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2108 remainder = options->slideshow.delay % (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2109 minutes = remainder / (60 * SLIDESHOW_SUBSECOND_PRECISION);
2110 seconds = (gdouble)(remainder % (60 * SLIDESHOW_SUBSECOND_PRECISION)) /
2111 SLIDESHOW_SUBSECOND_PRECISION;
2113 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2115 spin = pref_spin_new(hbox, _("Delay between image change hrs:mins:secs.dec"), NULL,
2117 options->slideshow.delay ? hours : 0.0,
2118 G_CALLBACK(slideshow_delay_hours_cb), NULL);
2119 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2120 spin = pref_spin_new(hbox, ":" , NULL,
2122 options->slideshow.delay ? minutes: 0.0,
2123 G_CALLBACK(slideshow_delay_minutes_cb), NULL);
2124 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2125 spin = pref_spin_new(hbox, ":", NULL,
2126 SLIDESHOW_MIN_SECONDS, 59, 1.0, 1,
2127 options->slideshow.delay ? seconds : 10.0,
2128 G_CALLBACK(slideshow_delay_seconds_cb), NULL);
2129 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2131 pref_checkbox_new_int(group, _("Random"), options->slideshow.random, &c_options->slideshow.random);
2132 pref_checkbox_new_int(group, _("Repeat"), options->slideshow.repeat, &c_options->slideshow.repeat);
2134 pref_spacer(group, PREF_PAD_GROUP);
2136 group = pref_group_new(vbox, FALSE, _("Image loading and caching"), GTK_ORIENTATION_VERTICAL);
2138 pref_spin_new_int(group, _("Decoded image cache size (MiB):"), NULL,
2139 0, 99999, 1, options->image.image_cache_max, &c_options->image.image_cache_max);
2140 pref_checkbox_new_int(group, _("Preload next image"),
2141 options->image.enable_read_ahead, &c_options->image.enable_read_ahead);
2143 pref_checkbox_new_int(group, _("Refresh on file change"),
2144 options->update_on_time_change, &c_options->update_on_time_change);
2147 pref_spacer(group, PREF_PAD_GROUP);
2149 group = pref_group_new(vbox, FALSE, _("Expand menu and toolbar"), GTK_ORIENTATION_VERTICAL);
2151 pref_checkbox_new_int(group, _("Expand menu and toolbar (NOTE! Geeqie must be restarted for change to take effect)"),
2152 options->expand_menu_toolbar, &c_options->expand_menu_toolbar);
2153 gtk_widget_set_tooltip_text(group, _("Expand the menu and toolbar to the full width of the window"));
2155 pref_spacer(group, PREF_PAD_GROUP);
2157 net_mon = g_network_monitor_get_default();
2158 tz_org = g_network_address_parse_uri(TIMEZONE_DATABASE_WEB, 80, NULL);
2161 internet_available = g_network_monitor_can_reach(net_mon, tz_org, NULL, NULL);
2162 g_object_unref(tz_org);
2165 group = pref_group_new(vbox, FALSE, _("Timezone database"), GTK_ORIENTATION_VERTICAL);
2166 hbox = pref_box_new(group, TRUE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2168 if (!internet_available)
2170 gtk_widget_set_sensitive(group, FALSE);
2173 tz = g_new0(TZData, 1);
2175 path = path_from_utf8(TIMEZONE_DATABASE_WEB);
2176 basename = g_path_get_basename(path);
2177 tz->timezone_database_user = g_build_filename(get_rc_dir(), TIMEZONE_DATABASE_FILE, NULL);
2181 if (isfile(tz->timezone_database_user))
2183 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Update"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2187 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Install"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2190 download_locn = g_strconcat(_("Download database from: "), TIMEZONE_DATABASE_WEB, NULL);
2191 pref_label_new(GTK_WIDGET(hbox), download_locn);
2192 g_free(download_locn);
2194 if (!internet_available)
2196 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"));
2200 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"));
2202 gtk_widget_show(button);
2204 pref_spacer(group, PREF_PAD_GROUP);
2206 group = pref_group_new(vbox, FALSE, _("On-line help search engine"), GTK_ORIENTATION_VERTICAL);
2208 help_search_engine_entry = gtk_entry_new();
2209 gtk_entry_set_text(GTK_ENTRY(help_search_engine_entry), options->help_search_engine);
2210 gtk_box_pack_start(GTK_BOX(group), help_search_engine_entry, FALSE, FALSE, 0);
2211 gtk_widget_show(help_search_engine_entry);
2213 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"));
2215 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2216 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2217 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2218 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2219 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2220 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2221 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2222 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2223 g_signal_connect(GTK_ENTRY(help_search_engine_entry), "icon-press",
2224 G_CALLBACK(help_search_engine_entry_icon_cb),
2225 help_search_engine_entry);
2229 static void config_tab_image(GtkWidget *notebook)
2234 GtkWidget *ct_button;
2235 GtkWidget *enlargement_button;
2238 //~ #ifdef HAVE_CLUTTER
2239 //~ GtkWidget *gpu_accel;
2242 vbox = scrolled_notebook_page(notebook, _("Image"));
2244 group = pref_group_new(vbox, FALSE, _("Zoom"), GTK_ORIENTATION_VERTICAL);
2246 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2247 add_quality_menu(table, 0, 0, _("Quality:"), options->image.zoom_quality, &c_options->image.zoom_quality);
2248 //~ if (options->image.use_clutter_renderer && !options->disable_gpu)
2250 //~ gtk_widget_set_sensitive(table, FALSE);
2253 //~ #ifdef HAVE_CLUTTER
2254 //~ gpu_accel = pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library (Requires restart)"),
2255 //~ options->image.use_clutter_renderer, &c_options->image.use_clutter_renderer);
2256 //~ if (options->disable_gpu && !options->override_disable_gpu)
2258 //~ gtk_widget_set_sensitive(gpu_accel, FALSE);
2262 pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"),
2263 options->image.zoom_2pass, &c_options->image.zoom_2pass);
2264 //~ if (options->image.use_clutter_renderer && !options->disable_gpu)
2266 //~ gtk_widget_set_sensitive(two_pass, FALSE);
2269 c_options->image.zoom_increment = options->image.zoom_increment;
2270 spin = pref_spin_new(group, _("Zoom increment:"), NULL,
2271 0.01, 4.0, 0.01, 2, (gdouble)options->image.zoom_increment / 100.0,
2272 G_CALLBACK(zoom_increment_cb), NULL);
2273 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2275 c_options->image.zoom_style = options->image.zoom_style;
2276 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2277 add_zoom_style_selection_menu(table, 0, 0, _("Zoom style:"), options->image.zoom_style, &c_options->image.zoom_style);
2279 group = pref_group_new(vbox, FALSE, _("Fit image to window"), GTK_ORIENTATION_VERTICAL);
2281 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2282 enlargement_button = pref_checkbox_new_int(hbox, _("Allow enlargement of image (max. size in %)"),
2283 options->image.zoom_to_fit_allow_expand, &c_options->image.zoom_to_fit_allow_expand);
2284 spin = pref_spin_new_int(hbox, NULL, NULL,
2286 options->image.max_enlargement_size, &c_options->image.max_enlargement_size);
2287 pref_checkbox_link_sensitivity(enlargement_button, spin);
2288 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."));
2290 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2291 ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (% of actual window):"),
2292 options->image.limit_autofit_size, &c_options->image.limit_autofit_size);
2293 spin = pref_spin_new_int(hbox, NULL, NULL,
2295 options->image.max_autofit_size, &c_options->image.max_autofit_size);
2296 pref_checkbox_link_sensitivity(ct_button, spin);
2297 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."));
2299 group = pref_group_new(vbox, FALSE, _("Tile size"), GTK_ORIENTATION_VERTICAL);
2300 //~ gtk_widget_set_sensitive(group, !options->image.use_clutter_renderer);
2302 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2303 spin = pref_spin_new_int(hbox, _("Pixels"), _("(Requires restart)"),
2305 options->image.tile_size, &c_options->image.tile_size);
2306 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."));
2308 group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
2310 pref_checkbox_new_int(group, _("Use custom border color in window mode"),
2311 options->image.use_custom_border_color, &c_options->image.use_custom_border_color);
2313 pref_checkbox_new_int(group, _("Use custom border color in fullscreen mode"),
2314 options->image.use_custom_border_color_in_fullscreen, &c_options->image.use_custom_border_color_in_fullscreen);
2316 pref_color_button_new(group, _("Border color"), &options->image.border_color,
2317 G_CALLBACK(pref_color_button_set_cb), &c_options->image.border_color);
2319 c_options->image.border_color = options->image.border_color;
2321 pref_color_button_new(group, _("Alpha channel color 1"), &options->image.alpha_color_1,
2322 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_1);
2324 pref_color_button_new(group, _("Alpha channel color 2"), &options->image.alpha_color_2,
2325 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_2);
2327 c_options->image.alpha_color_1 = options->image.alpha_color_1;
2328 c_options->image.alpha_color_2 = options->image.alpha_color_2;
2333 static void save_default_window_layout_cb(GtkWidget *UNUSED(widget), gpointer UNUSED(data))
2335 LayoutWindow *lw = NULL;
2336 gchar *default_path;
2339 /* Get current lw */
2342 tmp_id = lw->options.id;
2343 lw->options.id = g_strdup("lw_default");
2345 default_path = g_build_filename(get_rc_dir(), DEFAULT_WINDOW_LAYOUT, NULL);
2346 save_default_layout_options_to_file(default_path, options, lw);
2347 g_free(lw->options.id);
2348 lw->options.id = tmp_id;
2349 g_free(default_path);
2352 static gboolean popover_cb(gpointer data)
2354 GtkPopover *popover = data;
2356 gtk_popover_popdown(popover);
2361 static void default_layout_changed_cb(GtkWidget *UNUSED(button), GtkPopover *popover)
2363 gtk_popover_popup(popover);
2365 g_timeout_add(2000, popover_cb, popover);
2368 static GtkWidget *create_popover(GtkWidget *parent, GtkWidget *child, GtkPositionType pos)
2372 popover = gtk_popover_new(parent);
2373 gtk_popover_set_position(GTK_POPOVER (popover), pos);
2374 gtk_container_add (GTK_CONTAINER(popover), child);
2375 gtk_container_set_border_width(GTK_CONTAINER (popover), 6);
2376 gtk_widget_show (child);
2381 static void config_tab_windows(GtkWidget *notebook)
2386 GtkWidget *subgroup;
2388 GtkWidget *ct_button;
2391 vbox = scrolled_notebook_page(notebook, _("Windows"));
2393 group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
2395 ct_button = pref_checkbox_new_int(group, _("Remember session"),
2396 options->save_window_positions, &c_options->save_window_positions);
2398 button = pref_checkbox_new_int(group, _("Use saved window positions also for new windows"),
2399 options->use_saved_window_positions_for_new_windows, &c_options->use_saved_window_positions_for_new_windows);
2400 pref_checkbox_link_sensitivity(ct_button, button);
2402 button = pref_checkbox_new_int(group, _("Remember window workspace"),
2403 options->save_window_workspace, &c_options->save_window_workspace);
2404 pref_checkbox_link_sensitivity(ct_button, button);
2406 pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
2407 options->tools_restore_state, &c_options->tools_restore_state);
2409 pref_checkbox_new_int(group, _("Remember dialog window positions"),
2410 options->save_dialog_window_positions, &c_options->save_dialog_window_positions);
2412 pref_checkbox_new_int(group, _("Show window IDs"),
2413 options->show_window_ids, &c_options->show_window_ids);
2415 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2416 pref_label_new(subgroup, _("Use current layout for default: "));
2417 button = pref_button_new(subgroup, NULL, _("Set"), FALSE, G_CALLBACK(save_default_window_layout_cb), NULL);
2421 popover = create_popover(button, gtk_label_new(_("Current window layout\nhas been set as default")), GTK_POS_TOP);
2422 gtk_popover_set_modal(GTK_POPOVER (popover), FALSE);
2423 g_signal_connect(button, "clicked", G_CALLBACK(default_layout_changed_cb), popover);
2425 group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
2427 pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
2428 options->image.fit_window_to_image, &c_options->image.fit_window_to_image);
2430 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2431 ct_button = pref_checkbox_new_int(hbox, _("Limit size when auto-sizing window (%):"),
2432 options->image.limit_window_size, &c_options->image.limit_window_size);
2433 spin = pref_spin_new_int(hbox, NULL, NULL,
2435 options->image.max_window_size, &c_options->image.max_window_size);
2436 pref_checkbox_link_sensitivity(ct_button, spin);
2438 group = pref_group_new(vbox, FALSE, _("Full screen"), GTK_ORIENTATION_VERTICAL);
2440 c_options->fullscreen.screen = options->fullscreen.screen;
2441 c_options->fullscreen.above = options->fullscreen.above;
2442 hbox = fullscreen_prefs_selection_new(_("Location:"), &c_options->fullscreen.screen, &c_options->fullscreen.above);
2443 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2444 gtk_widget_show(hbox);
2446 pref_checkbox_new_int(group, _("Smooth image flip"),
2447 options->fullscreen.clean_flip, &c_options->fullscreen.clean_flip);
2448 pref_checkbox_new_int(group, _("Disable screen saver"),
2449 options->fullscreen.disable_saver, &c_options->fullscreen.disable_saver);
2452 #define PRE_FORMATTED_COLUMNS 5
2453 static void config_tab_osd(GtkWidget *notebook)
2459 GtkWidget *image_overlay_template_view;
2460 GtkWidget *scrolled;
2461 GtkWidget *scrolled_pre_formatted;
2462 GtkTextBuffer *buffer;
2464 GtkWidget *subgroup;
2466 vbox = scrolled_notebook_page(notebook, _("OSD"));
2468 image_overlay_template_view = gtk_text_view_new();
2470 group = pref_group_new(vbox, FALSE, _("Overlay Screen Display"), GTK_ORIENTATION_VERTICAL);
2472 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2474 scrolled_pre_formatted = osd_new(PRE_FORMATTED_COLUMNS, image_overlay_template_view);
2475 gtk_widget_set_size_request(scrolled_pre_formatted, 200, 150);
2476 gtk_box_pack_start(GTK_BOX(subgroup), scrolled_pre_formatted, FALSE, FALSE, 0);
2477 gtk_widget_show(scrolled_pre_formatted);
2478 gtk_widget_show(subgroup);
2480 pref_line(group, PREF_PAD_GAP);
2482 pref_label_new(group, _("Image overlay template"));
2484 scrolled = gtk_scrolled_window_new(NULL, NULL);
2485 gtk_widget_set_size_request(scrolled, 200, 150);
2486 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2487 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
2488 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2489 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 5);
2490 gtk_widget_show(scrolled);
2492 gtk_widget_set_tooltip_markup(image_overlay_template_view,
2493 _("Extensive formatting options are shown in the Help file"));
2495 gtk_container_add(GTK_CONTAINER(scrolled), image_overlay_template_view);
2496 gtk_widget_show(image_overlay_template_view);
2498 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2500 button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
2501 G_CALLBACK(image_overlay_set_font_cb), notebook);
2503 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2504 gtk_widget_show(button);
2506 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Text"), FALSE,
2507 G_CALLBACK(image_overlay_set_text_colour_cb), NULL);
2508 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2509 gtk_widget_show(button);
2511 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Background"), FALSE,
2512 G_CALLBACK(image_overlay_set_background_colour_cb), NULL);
2513 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2514 gtk_widget_show(button);
2515 image_overlay_set_text_colours();
2517 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2518 G_CALLBACK(image_overlay_default_template_cb), image_overlay_template_view);
2519 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2520 gtk_widget_show(button);
2522 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
2523 G_CALLBACK(image_overlay_help_cb), NULL);
2524 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2525 gtk_widget_show(button);
2527 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_overlay_template_view));
2528 if (options->image_overlay.template_string) gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
2529 g_signal_connect(G_OBJECT(buffer), "changed",
2530 G_CALLBACK(image_overlay_template_view_changed_cb), image_overlay_template_view);
2532 pref_line(group, PREF_PAD_GAP);
2534 group = pref_group_new(vbox, FALSE, _("Exif, XMP or IPTC tags"), GTK_ORIENTATION_VERTICAL);
2535 hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
2536 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2537 gtk_widget_show(hbox);
2538 label = gtk_label_new(_("%Exif.Image.Orientation%"));
2539 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2540 gtk_widget_show(label);
2541 pref_spacer(group,TRUE);
2543 group = pref_group_new(vbox, FALSE, _("Field separators"), GTK_ORIENTATION_VERTICAL);
2544 hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
2545 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2546 gtk_widget_show(hbox);
2547 label = gtk_label_new(_("Separator shown only if both fields are non-null:\n%formatted.ShutterSpeed%|%formatted.ISOSpeedRating%"));
2548 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2549 gtk_widget_show(label);
2550 pref_spacer(group,TRUE);
2552 group = pref_group_new(vbox, FALSE, _("Field maximum length"), GTK_ORIENTATION_VERTICAL);
2553 hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
2554 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2555 gtk_widget_show(hbox);
2556 label = gtk_label_new(_("%path:39%"));
2557 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2558 gtk_widget_show(label);
2559 pref_spacer(group,TRUE);
2561 group = pref_group_new(vbox, FALSE, _("Pre- and post- text"), GTK_ORIENTATION_VERTICAL);
2562 hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
2563 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2564 gtk_widget_show(hbox);
2565 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%"));
2566 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2567 gtk_widget_show(label);
2568 pref_spacer(group,TRUE);
2570 group = pref_group_new(vbox, FALSE, _("Pango markup"), GTK_ORIENTATION_VERTICAL);
2571 hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
2572 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2573 gtk_widget_show(hbox);
2574 label = gtk_label_new(_("<b>bold</b>\n<u>underline</u>\n<i>italic</i>\n<s>strikethrough</s>"));
2575 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2576 gtk_widget_show(label);
2579 static GtkTreeModel *create_class_model(void)
2581 GtkListStore *model;
2585 /* create list store */
2586 model = gtk_list_store_new(1, G_TYPE_STRING);
2587 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
2589 gtk_list_store_append(model, &iter);
2590 gtk_list_store_set(model, &iter, 0, _(format_class_list[i]), -1);
2592 return GTK_TREE_MODEL (model);
2597 static gint filter_table_sort_cb(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer data)
2599 gint n = GPOINTER_TO_INT(data);
2601 FilterEntry *filter_a;
2602 FilterEntry *filter_b;
2604 gtk_tree_model_get(model, a, 0, &filter_a, -1);
2605 gtk_tree_model_get(model, b, 0, &filter_b, -1);
2609 case FILETYPES_COLUMN_ENABLED:
2611 ret = filter_a->enabled - filter_b->enabled;
2614 case FILETYPES_COLUMN_FILTER:
2616 ret = g_utf8_collate(filter_a->extensions, filter_b->extensions);
2619 case FILETYPES_COLUMN_DESCRIPTION:
2621 ret = g_utf8_collate(filter_a->description, filter_b->description);
2624 case FILETYPES_COLUMN_CLASS:
2626 ret = g_strcmp0(format_class_list[filter_a->file_class], format_class_list[filter_b->file_class]);
2629 case FILETYPES_COLUMN_WRITABLE:
2631 ret = filter_a->writable - filter_b->writable;
2634 case FILETYPES_COLUMN_SIDECAR:
2636 ret = filter_a->allow_sidecar - filter_b->allow_sidecar;
2640 g_return_val_if_reached(0);
2646 static gboolean search_function_cb(GtkTreeModel *model, gint UNUSED(column), const gchar *key, GtkTreeIter *iter, gpointer UNUSED(search_data))
2649 gboolean ret = TRUE;
2651 gtk_tree_model_get(model, iter, 0, &fe, -1);
2653 if (g_strstr_len(fe->extensions, -1, key))
2661 static void config_tab_files(GtkWidget *notebook)
2668 GtkWidget *ct_button;
2669 GtkWidget *scrolled;
2670 GtkWidget *filter_view;
2671 GtkCellRenderer *renderer;
2672 GtkTreeSelection *selection;
2673 GtkTreeViewColumn *column;
2675 vbox = scrolled_notebook_page(notebook, _("File Filters"));
2677 group = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2679 pref_checkbox_new_int(group, _("Show hidden files or folders"),
2680 options->file_filter.show_hidden_files, &c_options->file_filter.show_hidden_files);
2681 pref_checkbox_new_int(group, _("Show parent folder (..)"),
2682 options->file_filter.show_parent_directory, &c_options->file_filter.show_parent_directory);
2683 pref_checkbox_new_int(group, _("Case sensitive sort"),
2684 options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
2685 pref_checkbox_new_int(group, _("Natural sort order"),
2686 options->file_sort.natural, &c_options->file_sort.natural);
2687 pref_checkbox_new_int(group, _("Disable file extension checks"),
2688 options->file_filter.disable_file_extension_checks, &c_options->file_filter.disable_file_extension_checks);
2690 ct_button = pref_checkbox_new_int(group, _("Disable File Filtering"),
2691 options->file_filter.disable, &c_options->file_filter.disable);
2694 group = pref_group_new(vbox, FALSE, _("Grouping sidecar extensions"), GTK_ORIENTATION_VERTICAL);
2696 sidecar_ext_entry = gtk_entry_new();
2697 gtk_entry_set_text(GTK_ENTRY(sidecar_ext_entry), options->sidecar.ext);
2698 gtk_box_pack_start(GTK_BOX(group), sidecar_ext_entry, FALSE, FALSE, 0);
2699 gtk_widget_show(sidecar_ext_entry);
2701 group = pref_group_new(vbox, TRUE, _("File types"), GTK_ORIENTATION_VERTICAL);
2703 frame = pref_group_parent(group);
2704 g_signal_connect(G_OBJECT(ct_button), "toggled",
2705 G_CALLBACK(filter_disable_cb), frame);
2706 gtk_widget_set_sensitive(frame, !options->file_filter.disable);
2708 scrolled = gtk_scrolled_window_new(NULL, NULL);
2709 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2710 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2711 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2712 gtk_widget_show(scrolled);
2714 filter_store = gtk_list_store_new(1, G_TYPE_POINTER);
2715 filter_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(filter_store));
2716 g_object_unref(filter_store);
2717 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
2718 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
2720 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), FALSE);
2722 column = gtk_tree_view_column_new();
2723 gtk_tree_view_column_set_title(column, _("Enabled"));
2724 gtk_tree_view_column_set_resizable(column, TRUE);
2726 renderer = gtk_cell_renderer_toggle_new();
2727 g_signal_connect(G_OBJECT(renderer), "toggled",
2728 G_CALLBACK(filter_store_enable_cb), filter_store);
2729 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2730 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2731 GINT_TO_POINTER(FE_ENABLE), NULL);
2732 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);
2733 gtk_tree_view_column_set_sort_column_id(column, FILETYPES_COLUMN_ENABLED);
2734 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2736 column = gtk_tree_view_column_new();
2737 gtk_tree_view_column_set_title(column, _("Filter"));
2738 gtk_tree_view_column_set_resizable(column, TRUE);
2739 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);
2740 gtk_tree_view_column_set_sort_column_id(column, FILETYPES_COLUMN_FILTER);
2742 renderer = gtk_cell_renderer_text_new();
2743 g_signal_connect(G_OBJECT(renderer), "edited",
2744 G_CALLBACK(filter_store_ext_edit_cb), filter_store);
2745 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2746 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2747 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2748 GINT_TO_POINTER(FE_EXTENSION), NULL);
2749 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2751 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), TRUE);
2752 gtk_tree_view_set_search_column(GTK_TREE_VIEW(filter_view), FILETYPES_COLUMN_FILTER);
2753 gtk_tree_view_set_search_equal_func(GTK_TREE_VIEW(filter_view), search_function_cb, NULL, NULL);
2755 column = gtk_tree_view_column_new();
2756 gtk_tree_view_column_set_title(column, _("Description"));
2757 gtk_tree_view_column_set_resizable(column, TRUE);
2758 gtk_tree_view_column_set_fixed_width(column, 200);
2759 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
2761 renderer = gtk_cell_renderer_text_new();
2762 g_signal_connect(G_OBJECT(renderer), "edited",
2763 G_CALLBACK(filter_store_desc_edit_cb), filter_store);
2764 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2765 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2766 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2767 GINT_TO_POINTER(FE_DESCRIPTION), NULL);
2768 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2769 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);
2770 gtk_tree_view_column_set_sort_column_id(column, FILETYPES_COLUMN_DESCRIPTION);
2772 column = gtk_tree_view_column_new();
2773 gtk_tree_view_column_set_title(column, _("Class"));
2774 gtk_tree_view_column_set_resizable(column, TRUE);
2775 renderer = gtk_cell_renderer_combo_new();
2776 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE,
2777 "model", create_class_model(),
2782 g_signal_connect(G_OBJECT(renderer), "edited",
2783 G_CALLBACK(filter_store_class_edit_cb), filter_store);
2784 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2785 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2786 GINT_TO_POINTER(FE_CLASS), NULL);
2787 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2788 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);
2789 gtk_tree_view_column_set_sort_column_id(column, FILETYPES_COLUMN_CLASS);
2791 column = gtk_tree_view_column_new();
2792 gtk_tree_view_column_set_title(column, _("Writable"));
2793 gtk_tree_view_column_set_resizable(column, FALSE);
2794 renderer = gtk_cell_renderer_toggle_new();
2795 g_signal_connect(G_OBJECT(renderer), "toggled",
2796 G_CALLBACK(filter_store_writable_cb), filter_store);
2797 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2798 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2799 GINT_TO_POINTER(FE_WRITABLE), NULL);
2800 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2801 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);
2802 gtk_tree_view_column_set_sort_column_id(column, FILETYPES_COLUMN_WRITABLE);
2804 column = gtk_tree_view_column_new();
2805 gtk_tree_view_column_set_title(column, _("Sidecar is allowed"));
2806 gtk_tree_view_column_set_resizable(column, FALSE);
2807 renderer = gtk_cell_renderer_toggle_new();
2808 g_signal_connect(G_OBJECT(renderer), "toggled",
2809 G_CALLBACK(filter_store_sidecar_cb), filter_store);
2810 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2811 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2812 GINT_TO_POINTER(FE_ALLOW_SIDECAR), NULL);
2813 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2814 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);
2815 gtk_tree_view_column_set_sort_column_id(column, FILETYPES_COLUMN_SIDECAR);
2817 filter_store_populate();
2818 gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
2819 gtk_widget_show(filter_view);
2821 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2823 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2824 G_CALLBACK(filter_default_cb), filter_view);
2825 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2826 gtk_widget_show(button);
2828 button = pref_button_new(NULL, GTK_STOCK_REMOVE, NULL, FALSE,
2829 G_CALLBACK(filter_remove_cb), filter_view);
2830 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2831 gtk_widget_show(button);
2833 button = pref_button_new(NULL, GTK_STOCK_ADD, NULL, FALSE,
2834 G_CALLBACK(filter_add_cb), filter_view);
2835 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2836 gtk_widget_show(button);
2840 static void config_tab_metadata(GtkWidget *notebook)
2845 GtkWidget *ct_button;
2847 GtkWidget *tmp_widget;
2849 GtkWidget *text_label;
2851 vbox = scrolled_notebook_page(notebook, _("Metadata"));
2854 group = pref_group_new(vbox, FALSE, _("Metadata writing sequence"), GTK_ORIENTATION_VERTICAL);
2856 label = pref_label_new(group, _("Warning: Geeqie is built without Exiv2. Some options are disabled."));
2858 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."));
2859 gtk_label_set_xalign(GTK_LABEL(label), 0.0);
2860 gtk_label_set_yalign(GTK_LABEL(label), 0.5);
2862 gtk_widget_set_tooltip_text(label, _("A flowchart of the sequence is shown in the Help file"));
2864 ct_button = pref_checkbox_new_int(group, "", options->metadata.save_in_image_file, &c_options->metadata.save_in_image_file);
2865 text_label = gtk_bin_get_child(GTK_BIN(ct_button));
2866 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"));
2867 gtk_label_set_markup (GTK_LABEL(text_label), markup);
2869 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)"));
2870 gtk_widget_set_tooltip_markup(ct_button, markup);
2874 gtk_widget_set_sensitive(ct_button, FALSE);
2877 tmp_widget = pref_checkbox_new_int(group, "", options->metadata.enable_metadata_dirs, &c_options->metadata.enable_metadata_dirs);
2878 text_label = gtk_bin_get_child(GTK_BIN(tmp_widget));
2879 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)"));
2880 gtk_label_set_markup (GTK_LABEL(text_label), markup);
2883 label = pref_label_new(group, "");
2884 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(), "/");
2885 gtk_label_set_markup (GTK_LABEL(label), markup);
2888 gtk_label_set_xalign(GTK_LABEL(label), 0.0);
2889 gtk_label_set_yalign(GTK_LABEL(label), 0.5);
2890 gtk_misc_set_padding(GTK_MISC(label), 22, 0);
2891 pref_spacer(group, PREF_PAD_GROUP);
2893 group = pref_group_new(vbox, FALSE, _("Step 1 Options:"), GTK_ORIENTATION_VERTICAL);
2895 gtk_widget_set_sensitive(group, FALSE);
2898 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2899 pref_checkbox_link_sensitivity(ct_button, hbox);
2901 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);
2902 gtk_widget_set_tooltip_text(tmp_widget, _("A simplified conversion list is in the Help file"));
2904 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);
2906 pref_checkbox_new_int(hbox, _("Ask before writing to image files"), options->metadata.confirm_write, &c_options->metadata.confirm_write);
2908 tmp_widget= pref_checkbox_new_int(hbox, "", options->metadata.sidecar_extended_name, &c_options->metadata.sidecar_extended_name);
2909 gtk_widget_set_tooltip_text(tmp_widget, _("This file naming convention is used by Darktable"));
2910 text_label = gtk_bin_get_child(GTK_BIN(tmp_widget));
2911 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", ")");
2912 gtk_label_set_markup (GTK_LABEL(text_label), markup);
2915 pref_spacer(group, PREF_PAD_GROUP);
2917 group = pref_group_new(vbox, FALSE, _("Steps 2 and 3 Option:"), GTK_ORIENTATION_VERTICAL);
2919 gtk_widget_set_sensitive(group, FALSE);
2922 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);
2924 pref_spacer(group, PREF_PAD_GROUP);
2926 group = pref_group_new(vbox, FALSE, _("Miscellaneous"), GTK_ORIENTATION_VERTICAL);
2927 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);
2928 gtk_widget_set_tooltip_text(tmp_widget, _("See the Help file for a list of the tags used"));
2930 tmp_widget = pref_checkbox_new_int(group, _("Permit Keywords to be case-sensitive"), options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
2931 gtk_widget_set_tooltip_text(tmp_widget, _("When selected, \"Place\" and \"place\" are two different keywords"));
2933 ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"), options->metadata.write_orientation, &c_options->metadata.write_orientation);
2934 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"));
2937 gtk_widget_set_sensitive(ct_button, FALSE);
2940 pref_spacer(group, PREF_PAD_GROUP);
2942 group = pref_group_new(vbox, FALSE, _("Auto-save options"), GTK_ORIENTATION_VERTICAL);
2944 ct_button = pref_checkbox_new_int(group, _("Write metadata after timeout"), options->metadata.confirm_after_timeout, &c_options->metadata.confirm_after_timeout);
2946 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2947 pref_checkbox_link_sensitivity(ct_button, hbox);
2949 pref_spin_new_int(hbox, _("Timeout (seconds):"), NULL, 0, 900, 1, options->metadata.confirm_timeout, &c_options->metadata.confirm_timeout);
2951 pref_checkbox_new_int(group, _("Write metadata on image change"), options->metadata.confirm_on_image_change, &c_options->metadata.confirm_on_image_change);
2953 pref_checkbox_new_int(group, _("Write metadata on directory change"), options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
2955 pref_spacer(group, PREF_PAD_GROUP);
2958 group = pref_group_new(vbox, FALSE, _("Spelling checks"), GTK_ORIENTATION_VERTICAL);
2960 ct_button = pref_checkbox_new_int(group, _("Check spelling - Requires restart"), options->metadata.check_spelling, &c_options->metadata.check_spelling);
2961 gtk_widget_set_tooltip_text(ct_button, _("Spelling checks are performed on info sidebar panes Comment, Headline and Title"));
2964 pref_spacer(group, PREF_PAD_GROUP);
2966 group = pref_group_new(vbox, FALSE, _("Pre-load metadata"), GTK_ORIENTATION_VERTICAL);
2968 ct_button = pref_checkbox_new_int(group, _("Read metadata in background"), options->read_metadata_in_idle, &c_options->read_metadata_in_idle);
2969 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");
2974 typedef struct _KeywordFindData KeywordFindData;
2975 struct _KeywordFindData
2982 GtkWidget *button_close;
2983 GtkWidget *button_stop;
2984 GtkWidget *button_start;
2985 GtkWidget *progress;
2993 guint idle_id; /* event source id */
2996 #define KEYWORD_DIALOG_WIDTH 400
2998 static void keywords_find_folder(KeywordFindData *kfd, FileData *dir_fd)
3000 GList *list_d = NULL;
3001 GList *list_f = NULL;
3005 filelist_read(dir_fd, &list_f, &list_d);
3009 filelist_read(dir_fd, &list_f, NULL);
3012 list_f = filelist_filter(list_f, FALSE);
3013 list_d = filelist_filter(list_d, TRUE);
3015 kfd->list = g_list_concat(list_f, kfd->list);
3016 kfd->list_dir = g_list_concat(list_d, kfd->list_dir);
3019 static void keywords_find_reset(KeywordFindData *kfd)
3021 filelist_free(kfd->list);
3024 filelist_free(kfd->list_dir);
3025 kfd->list_dir = NULL;
3028 static void keywords_find_close_cb(GenericDialog *UNUSED(fd), gpointer data)
3030 KeywordFindData *kfd = data;
3032 if (!gtk_widget_get_sensitive(kfd->button_close)) return;
3034 keywords_find_reset(kfd);
3035 generic_dialog_close(kfd->gd);
3039 static void keywords_find_finish(KeywordFindData *kfd)
3041 keywords_find_reset(kfd);
3043 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("done"));
3044 spinner_set_interval(kfd->spinner, -1);
3046 gtk_widget_set_sensitive(kfd->group, TRUE);
3047 gtk_widget_set_sensitive(kfd->button_start, TRUE);
3048 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
3049 gtk_widget_set_sensitive(kfd->button_close, TRUE);
3052 static void keywords_find_stop_cb(GenericDialog *UNUSED(fd), gpointer data)
3054 KeywordFindData *kfd = data;
3056 g_idle_remove_by_data(kfd);
3058 keywords_find_finish(kfd);
3061 static gboolean keywords_find_file(gpointer data)
3063 KeywordFindData *kfd = data;
3065 GtkTextBuffer *buffer;
3073 fd = kfd->list->data;
3074 kfd->list = g_list_remove(kfd->list, fd);
3076 keywords = metadata_read_list(fd, KEYWORD_KEY, METADATA_PLAIN);
3077 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3081 gtk_text_buffer_get_end_iter(buffer, &iter);
3082 tmp = g_strconcat(keywords->data, "\n", NULL);
3083 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
3085 keywords = keywords->next;
3088 gtk_entry_set_text(GTK_ENTRY(kfd->progress), fd->path);
3089 file_data_unref(fd);
3090 string_list_free(keywords);
3094 else if (kfd->list_dir)
3098 fd = kfd->list_dir->data;
3099 kfd->list_dir = g_list_remove(kfd->list_dir, fd);
3101 keywords_find_folder(kfd, fd);
3103 file_data_unref(fd);
3108 keywords_find_finish(kfd);
3113 static void keywords_find_start_cb(GenericDialog *UNUSED(fd), gpointer data)
3115 KeywordFindData *kfd = data;
3118 if (kfd->list || !gtk_widget_get_sensitive(kfd->button_start)) return;
3120 path = remove_trailing_slash((gtk_entry_get_text(GTK_ENTRY(kfd->entry))));
3121 parse_out_relatives(path);
3125 warning_dialog(_("Invalid folder"),
3126 _("The specified folder can not be found."),
3127 GTK_STOCK_DIALOG_WARNING, kfd->gd->dialog);
3133 gtk_widget_set_sensitive(kfd->group, FALSE);
3134 gtk_widget_set_sensitive(kfd->button_start, FALSE);
3135 gtk_widget_set_sensitive(kfd->button_stop, TRUE);
3136 gtk_widget_set_sensitive(kfd->button_close, FALSE);
3137 spinner_set_interval(kfd->spinner, SPINNER_SPEED);
3139 dir_fd = file_data_new_dir(path);
3140 keywords_find_folder(kfd, dir_fd);
3141 file_data_unref(dir_fd);
3142 kfd->idle_id = g_idle_add(keywords_find_file, kfd);
3148 static void keywords_find_dialog(GtkWidget *widget, const gchar *path)
3150 KeywordFindData *kfd;
3154 kfd = g_new0(KeywordFindData, 1);
3156 kfd->gd = generic_dialog_new(_("Search for keywords"),
3157 "search_for_keywords",
3160 gtk_window_set_default_size(GTK_WINDOW(kfd->gd->dialog), KEYWORD_DIALOG_WIDTH, -1);
3161 kfd->gd->cancel_cb = keywords_find_close_cb;
3162 kfd->button_close = generic_dialog_add_button(kfd->gd, GTK_STOCK_CLOSE, NULL,
3163 keywords_find_close_cb, FALSE);
3164 kfd->button_start = generic_dialog_add_button(kfd->gd, GTK_STOCK_OK, _("S_tart"),
3165 keywords_find_start_cb, FALSE);
3166 kfd->button_stop = generic_dialog_add_button(kfd->gd, GTK_STOCK_STOP, NULL,
3167 keywords_find_stop_cb, FALSE);
3168 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
3170 generic_dialog_add_message(kfd->gd, NULL, _("Search for keywords"), NULL, FALSE);
3172 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0);
3173 pref_spacer(hbox, PREF_PAD_INDENT);
3174 kfd->group = pref_box_new(hbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
3176 hbox = pref_box_new(kfd->group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3177 pref_label_new(hbox, _("Folder:"));
3179 label = tab_completion_new(&kfd->entry, path, NULL, NULL, NULL, NULL);
3180 tab_completion_add_select_button(kfd->entry,_("Select folder") , TRUE);
3181 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
3182 gtk_widget_show(label);
3184 pref_checkbox_new_int(kfd->group, _("Include subfolders"), FALSE, &kfd->recurse);
3186 pref_line(kfd->gd->vbox, PREF_PAD_SPACE);
3187 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3189 kfd->progress = gtk_entry_new();
3190 gtk_widget_set_can_focus(kfd->progress, FALSE);
3191 gtk_editable_set_editable(GTK_EDITABLE(kfd->progress), FALSE);
3192 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("click start to begin"));
3193 gtk_box_pack_start(GTK_BOX(hbox), kfd->progress, TRUE, TRUE, 0);
3194 gtk_widget_show(kfd->progress);
3196 kfd->spinner = spinner_new(NULL, -1);
3197 gtk_box_pack_start(GTK_BOX(hbox), kfd->spinner, FALSE, FALSE, 0);
3198 gtk_widget_show(kfd->spinner);
3202 gtk_widget_show(kfd->gd->dialog);
3205 static void keywords_find_cb(GtkWidget *widget, gpointer UNUSED(data))
3207 const gchar *path = layout_get_path(NULL);
3209 if (!path || !*path) path = homedir();
3210 keywords_find_dialog(widget, path);
3213 static void config_tab_keywords_save()
3215 GtkTextIter start, end;
3216 GtkTextBuffer *buffer;
3217 GList *kw_list = NULL;
3223 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3224 gtk_text_buffer_get_bounds(buffer, &start, &end);
3226 buffer_text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
3228 kw_split = strtok(buffer_text, "\n");
3229 while (kw_split != NULL)
3235 if (g_strcmp0(work->data, kw_split) == 0)
3244 kw_list = g_list_append(kw_list, g_strdup(kw_split));
3246 kw_split = strtok(NULL, "\n");
3249 keyword_list_set(kw_list);
3251 string_list_free(kw_list);
3252 g_free(buffer_text);
3255 static void config_tab_keywords(GtkWidget *notebook)
3261 GtkWidget *scrolled;
3263 GtkTextBuffer *buffer;
3266 GspellTextView *gspell_view;
3269 vbox = scrolled_notebook_page(notebook, _("Keywords"));
3271 group = pref_group_new(vbox, TRUE, _("Edit keywords autocompletion list"), GTK_ORIENTATION_VERTICAL);
3273 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3275 button = pref_button_new(hbox, GTK_STOCK_EXECUTE, _("Search"), FALSE,
3276 G_CALLBACK(keywords_find_cb), keyword_text);
3277 gtk_widget_set_tooltip_text(button, "Search for existing keywords");
3280 keyword_text = gtk_text_view_new();
3281 gtk_widget_set_size_request(keyword_text, 20, 20);
3282 scrolled = gtk_scrolled_window_new(NULL, NULL);
3283 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3284 gtk_widget_show(scrolled);
3287 if (options->metadata.check_spelling)
3289 gspell_view = gspell_text_view_get_from_gtk_text_view(GTK_TEXT_VIEW(keyword_text));
3290 gspell_text_view_basic_setup(gspell_view);
3294 gtk_container_add(GTK_CONTAINER(scrolled), keyword_text);
3295 gtk_widget_show(keyword_text);
3297 gtk_text_view_set_editable(GTK_TEXT_VIEW(keyword_text), TRUE);
3299 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3300 gtk_text_buffer_create_tag(buffer, "monospace",
3301 "family", "monospace", NULL);
3303 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(keyword_text), GTK_WRAP_WORD);
3304 gtk_text_buffer_get_start_iter(buffer, &iter);
3305 gtk_text_buffer_create_mark(buffer, "end", &iter, FALSE);
3308 path = g_build_filename(get_rc_dir(), "keywords", NULL);
3310 GList *kwl = keyword_list_get();
3311 kwl = g_list_first(kwl);
3314 gtk_text_buffer_get_end_iter (buffer, &iter);
3315 tmp = g_strconcat(kwl->data, "\n", NULL);
3316 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
3321 gtk_text_buffer_set_modified(buffer, FALSE);
3328 static void intent_menu_cb(GtkWidget *combo, gpointer data)
3330 gint *option = data;
3332 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
3336 *option = INTENT_PERCEPTUAL;
3339 *option = INTENT_RELATIVE_COLORIMETRIC;
3342 *option = INTENT_SATURATION;
3345 *option = INTENT_ABSOLUTE_COLORIMETRIC;
3350 static void add_intent_menu(GtkWidget *table, gint column, gint row, const gchar *text,
3351 gint option, gint *option_c)
3358 pref_table_label(table, column, row, text, 0.0);
3360 combo = gtk_combo_box_text_new();
3362 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Perceptual"));
3363 if (option == INTENT_PERCEPTUAL) current = 0;
3364 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Relative Colorimetric"));
3365 if (option == INTENT_RELATIVE_COLORIMETRIC) current = 1;
3366 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Saturation"));
3367 if (option == INTENT_SATURATION) current = 2;
3368 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Absolute Colorimetric"));
3369 if (option == INTENT_ABSOLUTE_COLORIMETRIC) current = 3;
3371 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
3373 gtk_widget_set_tooltip_text(combo,"Refer to the lcms documentation for the defaults used when the selected Intent is not available");
3375 g_signal_connect(G_OBJECT(combo), "changed",
3376 G_CALLBACK(intent_menu_cb), option_c);
3378 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
3379 gtk_widget_show(combo);
3383 static void config_tab_color(GtkWidget *notebook)
3392 vbox = scrolled_notebook_page(notebook, _("Color management"));
3394 group = pref_group_new(vbox, FALSE, _("Input profiles"), GTK_ORIENTATION_VERTICAL);
3396 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3399 table = pref_table_new(group, 3, COLOR_PROFILE_INPUTS + 1, FALSE, FALSE);
3400 gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
3402 label = pref_table_label(table, 0, 0, _("Type"), 0.0);
3403 pref_label_bold(label, TRUE, FALSE);
3405 label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
3406 pref_label_bold(label, TRUE, FALSE);
3408 label = pref_table_label(table, 2, 0, _("File"), 0.0);
3409 pref_label_bold(label, TRUE, FALSE);
3411 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
3416 buf = g_strdup_printf(_("Input %d:"), i + COLOR_PROFILE_FILE);
3417 pref_table_label(table, 0, i + 1, buf, 1.0);
3420 entry = gtk_entry_new();
3421 gtk_entry_set_max_length(GTK_ENTRY(entry), EDITOR_NAME_MAX_LENGTH);
3422 if (options->color_profile.input_name[i])
3424 gtk_entry_set_text(GTK_ENTRY(entry), options->color_profile.input_name[i]);
3426 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, i + 1, i + 2,
3427 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3428 gtk_widget_show(entry);
3429 color_profile_input_name_entry[i] = entry;
3431 tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, ".icc", "ICC Files", NULL);
3432 tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
3433 gtk_widget_set_size_request(entry, 160, -1);
3434 gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
3435 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3436 gtk_widget_show(tabcomp);
3437 color_profile_input_file_entry[i] = entry;
3440 group = pref_group_new(vbox, FALSE, _("Screen profile"), GTK_ORIENTATION_VERTICAL);
3442 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3444 pref_checkbox_new_int(group, _("Use system screen profile if available"),
3445 options->color_profile.use_x11_screen_profile, &c_options->color_profile.use_x11_screen_profile);
3447 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3449 pref_table_label(table, 0, 0, _("Screen:"), 1.0);
3450 tabcomp = tab_completion_new(&color_profile_screen_file_entry,
3451 options->color_profile.screen_file, NULL, ".icc", "ICC Files", NULL);
3452 tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
3453 gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
3455 add_intent_menu(table, 0, 1, _("Render Intent:"), options->color_profile.render_intent, &c_options->color_profile.render_intent);
3457 gtk_table_attach(GTK_TABLE(table), tabcomp, 1, 2,
3459 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3461 gtk_widget_show(tabcomp);
3464 /* advanced entry tab */
3465 static void use_geeqie_trash_cb(GtkWidget *widget, gpointer UNUSED(data))
3467 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3469 c_options->file_ops.use_system_trash = FALSE;
3470 c_options->file_ops.no_trash = FALSE;
3474 static void use_system_trash_cb(GtkWidget *widget, gpointer UNUSED(data))
3476 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3478 c_options->file_ops.use_system_trash = TRUE;
3479 c_options->file_ops.no_trash = FALSE;
3483 static void use_no_cache_cb(GtkWidget *widget, gpointer UNUSED(data))
3485 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3487 c_options->file_ops.no_trash = TRUE;
3491 static void config_tab_behavior(GtkWidget *notebook)
3498 GtkWidget *ct_button;
3502 GtkWidget *with_rename;
3503 GtkWidget *collections_on_top;
3504 GtkWidget *hide_window_in_fullscreen;
3505 GtkWidget *checkbox;
3508 vbox = scrolled_notebook_page(notebook, _("Behavior"));
3510 group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
3512 pref_checkbox_new_int(group, _("Confirm permanent file delete"),
3513 options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
3514 pref_checkbox_new_int(group, _("Confirm move file to Trash"),
3515 options->file_ops.confirm_move_to_trash, &c_options->file_ops.confirm_move_to_trash);
3516 pref_checkbox_new_int(group, _("Enable Delete key"),
3517 options->file_ops.enable_delete_key, &c_options->file_ops.enable_delete_key);
3519 ct_button = pref_radiobutton_new(group, NULL, _("Use Geeqie trash location"),
3520 !options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_geeqie_trash_cb),NULL);
3522 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3523 pref_checkbox_link_sensitivity(ct_button, hbox);
3525 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
3526 pref_label_new(hbox, _("Folder:"));
3528 tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL, NULL, NULL);
3529 tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
3530 gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
3531 gtk_widget_show(tabcomp);
3533 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3534 pref_checkbox_link_sensitivity(ct_button, hbox);
3536 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
3537 spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MiB"),
3538 0, 2048, 1, options->file_ops.safe_delete_folder_maxsize, &c_options->file_ops.safe_delete_folder_maxsize);
3539 gtk_widget_set_tooltip_markup(spin, _("Set to 0 for unlimited size"));
3540 button = pref_button_new(NULL, NULL, _("View"), FALSE,
3541 G_CALLBACK(safe_delete_view_cb), NULL);
3542 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3543 gtk_widget_show(button);
3545 button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
3546 G_CALLBACK(safe_delete_clear_cb), NULL);
3547 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3549 c_options->file_ops.no_trash = options->file_ops.no_trash;
3550 c_options->file_ops.use_system_trash = options->file_ops.use_system_trash;
3552 pref_radiobutton_new(group, ct_button, _("Use system Trash bin"),
3553 options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_system_trash_cb), NULL);
3555 pref_radiobutton_new(group, ct_button, _("Use no trash at all"),
3556 options->file_ops.no_trash, G_CALLBACK(use_no_cache_cb), NULL);
3558 gtk_widget_show(button);
3560 pref_spacer(group, PREF_PAD_GROUP);
3563 group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
3565 pref_checkbox_new_int(group, _("Descend folders in tree view"),
3566 options->tree_descend_subdirs, &c_options->tree_descend_subdirs);
3568 pref_checkbox_new_int(group, _("In place renaming"),
3569 options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
3571 pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
3572 options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
3574 tmp = pref_checkbox_new_int(group, _("Circular selection lists"),
3575 options->circular_selection_lists, &c_options->circular_selection_lists);
3576 gtk_widget_set_tooltip_text(tmp, _("Traverse selection lists in a circular manner"));
3578 marks = pref_checkbox_new_int(group, _("Save marks on exit"),
3579 options->marks_save, &c_options->marks_save);
3580 gtk_widget_set_tooltip_text(marks,"Note that marks linked to a keyword will be saved irrespective of this setting");
3582 with_rename = pref_checkbox_new_int(group, _("Use \"With Rename\" as default for Copy/Move dialogs"),
3583 options->with_rename, &c_options->with_rename);
3584 gtk_widget_set_tooltip_text(with_rename,"Change the default button for Copy/Move dialogs");
3586 collections_on_top = pref_checkbox_new_int(group, _("Open collections on top"),
3587 options->collections_on_top, &c_options->collections_on_top);
3588 gtk_widget_set_tooltip_text(collections_on_top,"Open collections window on top");
3590 hide_window_in_fullscreen = pref_checkbox_new_int(group, _("Hide window in fullscreen"),
3591 options->hide_window_in_fullscreen, &c_options->hide_window_in_fullscreen);
3592 gtk_widget_set_tooltip_text(hide_window_in_fullscreen,"When alt-tabbing, prevent Geeqie window showing twice");
3594 pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
3595 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
3597 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);
3598 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."));
3600 pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
3601 16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
3603 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3604 add_dnd_default_action_selection_menu(table, 0, 0, _("Drag`n drop default action:"), options->dnd_default_action, &c_options->dnd_default_action);
3606 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3607 add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
3609 pref_spacer(group, PREF_PAD_GROUP);
3611 group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
3613 pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
3614 options->progressive_key_scrolling, &c_options->progressive_key_scrolling);
3615 pref_spin_new_int(group, _("Keyboard scrolling step multiplier:"), NULL,
3616 1, 32, 1, options->keyboard_scroll_step, (int *)&c_options->keyboard_scroll_step);
3617 pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
3618 options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
3619 pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
3620 options->image_lm_click_nav, &c_options->image_lm_click_nav);
3621 pref_checkbox_new_int(group, _("Open archive by left click on image"),
3622 options->image_l_click_archive, &c_options->image_l_click_archive);
3623 pref_checkbox_new_int(group, _("Play video by left click on image"),
3624 options->image_l_click_video, &c_options->image_l_click_video);
3625 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3626 add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
3628 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3629 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3630 add_mouse_selection_menu(table, 0, 0, _("Mouse button Back:"), options->mouse_button_8, &c_options->mouse_button_8);
3631 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3632 add_mouse_selection_menu(table, 0, 0, _("Mouse button Forward:"), options->mouse_button_9, &c_options->mouse_button_9);
3634 pref_spacer(group, PREF_PAD_GROUP);
3636 group = pref_group_new(vbox, FALSE, _("GPU"), GTK_ORIENTATION_VERTICAL);
3638 checkbox = pref_checkbox_new_int(group, _("Override disable GPU"),
3639 options->override_disable_gpu, &c_options->override_disable_gpu);
3640 gtk_widget_set_tooltip_text(checkbox, "Contact the developers for usage");
3643 pref_spacer(group, PREF_PAD_GROUP);
3645 group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
3647 pref_spin_new_int(group, _("Debug level:"), NULL,
3648 DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
3650 pref_checkbox_new_int(group, _("Timer data"),
3651 options->log_window.timer_data, &c_options->log_window.timer_data);
3653 pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
3654 1, 99999, 1, options->log_window_lines, &options->log_window_lines);
3658 /* accelerators tab */
3659 static void config_tab_accelerators(GtkWidget *notebook)
3665 GtkWidget *scrolled;
3666 GtkWidget *accel_view;
3667 GtkCellRenderer *renderer;
3668 GtkTreeSelection *selection;
3669 GtkTreeViewColumn *column;
3671 vbox = scrolled_notebook_page(notebook, _("Keyboard"));
3673 group = pref_group_new(vbox, TRUE, _("Accelerators"), GTK_ORIENTATION_VERTICAL);
3675 scrolled = gtk_scrolled_window_new(NULL, NULL);
3676 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
3677 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
3678 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3679 gtk_widget_show(scrolled);
3681 accel_store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
3683 accel_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(accel_store));
3684 g_object_unref(accel_store);
3685 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(accel_view));
3686 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
3688 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(accel_view), FALSE);
3690 renderer = gtk_cell_renderer_text_new();
3692 column = gtk_tree_view_column_new_with_attributes(_("Action"),
3697 gtk_tree_view_column_set_sort_column_id(column, AE_ACTION);
3698 gtk_tree_view_column_set_resizable(column, TRUE);
3699 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3702 renderer = gtk_cell_renderer_accel_new();
3703 g_signal_connect(G_OBJECT(renderer), "accel-cleared",
3704 G_CALLBACK(accel_store_cleared_cb), accel_store);
3705 g_signal_connect(G_OBJECT(renderer), "accel-edited",
3706 G_CALLBACK(accel_store_edited_cb), accel_store);
3709 g_object_set (renderer,
3711 "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
3714 column = gtk_tree_view_column_new_with_attributes(_("KEY"),
3719 gtk_tree_view_column_set_sort_column_id(column, AE_KEY);
3720 gtk_tree_view_column_set_resizable(column, TRUE);
3721 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3723 renderer = gtk_cell_renderer_text_new();
3725 column = gtk_tree_view_column_new_with_attributes(_("Tooltip"),
3730 gtk_tree_view_column_set_sort_column_id(column, AE_TOOLTIP);
3731 gtk_tree_view_column_set_resizable(column, TRUE);
3732 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3734 renderer = gtk_cell_renderer_text_new();
3736 column = gtk_tree_view_column_new_with_attributes("Accel",
3741 gtk_tree_view_column_set_sort_column_id(column, AE_ACCEL);
3742 gtk_tree_view_column_set_resizable(column, TRUE);
3743 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3745 accel_store_populate();
3746 gtk_container_add(GTK_CONTAINER(scrolled), accel_view);
3747 gtk_widget_show(accel_view);
3749 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3751 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
3752 G_CALLBACK(accel_default_cb), accel_view);
3753 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3754 gtk_widget_show(button);
3756 button = pref_button_new(NULL, NULL, _("Reset selected"), FALSE,
3757 G_CALLBACK(accel_reset_cb), accel_view);
3758 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3759 gtk_widget_show(button);
3762 /* toolbar main tab */
3763 static void config_tab_toolbar_main(GtkWidget *notebook)
3766 GtkWidget *toolbardata;
3769 lw = layout_window_list->data;
3771 vbox = scrolled_notebook_page(notebook, _("Toolbar Main"));
3773 toolbardata = toolbar_select_new(lw, TOOLBAR_MAIN);
3774 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3775 gtk_widget_show(vbox);
3778 /* toolbar status tab */
3779 static void config_tab_toolbar_status(GtkWidget *notebook)
3782 GtkWidget *toolbardata;
3785 lw = layout_window_list->data;
3787 vbox = scrolled_notebook_page(notebook, _("Toolbar Status"));
3789 toolbardata = toolbar_select_new(lw, TOOLBAR_STATUS);
3790 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3791 gtk_widget_show(vbox);
3795 static gint extension_sort_cb(gconstpointer a, gconstpointer b)
3797 return g_strcmp0((gchar *)a, (gchar *)b);
3800 static void config_tab_advanced(GtkWidget *notebook)
3804 GSList *formats_list;
3805 GList *extensions_list = NULL;
3808 GdkPixbufFormat *fm;
3810 GString *types_string = g_string_new(NULL);
3811 GtkWidget *types_string_label;
3812 GtkWidget *threads_string_label;
3813 GtkWidget *dupes_threads_spin;
3815 vbox = scrolled_notebook_page(notebook, _("Advanced"));
3816 group = pref_group_new(vbox, FALSE, _("External preview extraction"), GTK_ORIENTATION_VERTICAL);
3818 pref_checkbox_new_int(group, _("Use external preview extraction - Requires restart"), options->external_preview.enable, &c_options->external_preview.enable);
3820 pref_spacer(group, PREF_PAD_GROUP);
3822 formats_list = gdk_pixbuf_get_formats();
3824 while (formats_list)
3826 fm = formats_list->data;
3827 extensions = gdk_pixbuf_format_get_extensions(fm);
3830 while (extensions[i])
3832 extensions_list = g_list_insert_sorted(extensions_list, g_strdup(extensions[i]), extension_sort_cb);
3836 g_strfreev(extensions);
3837 formats_list = formats_list->next;
3840 while (extensions_list)
3842 if (types_string->len == 0)
3844 types_string = g_string_append(types_string, extensions_list->data);
3848 types_string = g_string_append(types_string, ", ");
3849 types_string = g_string_append(types_string, extensions_list->data);
3852 extensions_list = extensions_list->next;
3855 types_string = g_string_prepend(types_string, _("Usable file types:\n"));
3856 types_string_label = pref_label_new(group, types_string->str);
3857 gtk_label_set_line_wrap(GTK_LABEL(types_string_label), TRUE);
3859 pref_spacer(group, PREF_PAD_GROUP);
3861 group = pref_group_new(vbox, FALSE, _("File identification tool"), GTK_ORIENTATION_VERTICAL);
3862 external_preview_select_entry = gtk_entry_new();
3863 tabcomp = tab_completion_new(&external_preview_select_entry, options->external_preview.select, NULL, NULL, NULL, NULL);
3864 tab_completion_add_select_button(external_preview_select_entry, _("Select file identification tool"), FALSE);
3865 gtk_box_pack_start(GTK_BOX(group), tabcomp, TRUE, TRUE, 0);
3866 gtk_widget_show(tabcomp);
3868 group = pref_group_new(vbox, FALSE, _("Preview extraction tool"), GTK_ORIENTATION_VERTICAL);
3869 external_preview_extract_entry = gtk_entry_new();
3870 tabcomp = tab_completion_new(&external_preview_extract_entry, options->external_preview.extract, NULL, NULL, NULL, NULL);
3871 tab_completion_add_select_button(external_preview_extract_entry, _("Select preview extraction tool"), FALSE);
3872 gtk_box_pack_start(GTK_BOX(group), tabcomp, TRUE, TRUE, 0);
3873 gtk_widget_show(tabcomp);
3875 gtk_widget_show(vbox);
3877 g_slist_free(formats_list);
3878 string_list_free(extensions_list);
3879 g_string_free(types_string, TRUE);
3881 pref_spacer(group, PREF_PAD_GROUP);
3883 pref_line(vbox, PREF_PAD_SPACE);
3884 group = pref_group_new(vbox, FALSE, _("Thread pool limits"), GTK_ORIENTATION_VERTICAL);
3886 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.");
3887 gtk_label_set_line_wrap(GTK_LABEL(threads_string_label), TRUE);
3889 pref_spacer(vbox, PREF_PAD_GROUP);
3891 dupes_threads_spin = pref_spin_new_int(vbox, _("Duplicate check:"), _("max. threads"), 0, get_cpu_cores(), 1, options->threads.duplicates, &c_options->threads.duplicates);
3892 gtk_widget_set_tooltip_markup(dupes_threads_spin, _("Set to 0 for unlimited"));
3896 static void config_tab_stereo(GtkWidget *notebook)
3904 GtkWidget *fs_button;
3905 vbox = scrolled_notebook_page(notebook, _("Stereo"));
3907 group = pref_group_new(vbox, FALSE, _("Windowed stereo mode"), GTK_ORIENTATION_VERTICAL);
3909 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3910 add_stereo_mode_menu(table, 0, 0, _("Windowed stereo mode"), options->stereo.mode, &c_options->stereo.mode, FALSE);
3912 table = pref_table_new(group, 2, 2, TRUE, FALSE);
3913 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3914 pref_checkbox_new_int(box, _("Mirror left image"),
3915 options->stereo.mode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.mirror_left);
3916 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3917 pref_checkbox_new_int(box, _("Flip left image"),
3918 options->stereo.mode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.flip_left);
3919 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3920 pref_checkbox_new_int(box, _("Mirror right image"),
3921 options->stereo.mode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.mirror_right);
3922 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3923 pref_checkbox_new_int(box, _("Flip right image"),
3924 options->stereo.mode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.flip_right);
3925 pref_checkbox_new_int(group, _("Swap left and right images"),
3926 options->stereo.mode & PR_STEREO_SWAP, &c_options->stereo.tmp.swap);
3927 pref_checkbox_new_int(group, _("Disable stereo mode on single image source"),
3928 options->stereo.mode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.temp_disable);
3930 group = pref_group_new(vbox, FALSE, _("Fullscreen stereo mode"), GTK_ORIENTATION_VERTICAL);
3931 fs_button = pref_checkbox_new_int(group, _("Use different settings for fullscreen"),
3932 options->stereo.enable_fsmode, &c_options->stereo.enable_fsmode);
3933 box2 = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
3934 pref_checkbox_link_sensitivity(fs_button, box2);
3935 table = pref_table_new(box2, 2, 1, FALSE, FALSE);
3936 add_stereo_mode_menu(table, 0, 0, _("Fullscreen stereo mode"), options->stereo.fsmode, &c_options->stereo.fsmode, TRUE);
3937 table = pref_table_new(box2, 2, 2, TRUE, FALSE);
3938 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3939 pref_checkbox_new_int(box, _("Mirror left image"),
3940 options->stereo.fsmode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.fs_mirror_left);
3941 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3942 pref_checkbox_new_int(box, _("Flip left image"),
3943 options->stereo.fsmode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.fs_flip_left);
3944 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3945 pref_checkbox_new_int(box, _("Mirror right image"),
3946 options->stereo.fsmode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.fs_mirror_right);
3947 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3948 pref_checkbox_new_int(box, _("Flip right image"),
3949 options->stereo.fsmode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.fs_flip_right);
3950 pref_checkbox_new_int(box2, _("Swap left and right images"),
3951 options->stereo.fsmode & PR_STEREO_SWAP, &c_options->stereo.tmp.fs_swap);
3952 pref_checkbox_new_int(box2, _("Disable stereo mode on single image source"),
3953 options->stereo.fsmode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.fs_temp_disable);
3955 group2 = pref_group_new(box2, FALSE, _("Fixed position"), GTK_ORIENTATION_VERTICAL);
3956 table = pref_table_new(group2, 5, 3, FALSE, FALSE);
3957 pref_table_spin_new_int(table, 0, 0, _("Width"), NULL,
3958 1, 5000, 1, options->stereo.fixed_w, &c_options->stereo.fixed_w);
3959 pref_table_spin_new_int(table, 3, 0, _("Height"), NULL,
3960 1, 5000, 1, options->stereo.fixed_h, &c_options->stereo.fixed_h);
3961 pref_table_spin_new_int(table, 0, 1, _("Left X"), NULL,
3962 0, 5000, 1, options->stereo.fixed_x1, &c_options->stereo.fixed_x1);
3963 pref_table_spin_new_int(table, 3, 1, _("Left Y"), NULL,
3964 0, 5000, 1, options->stereo.fixed_y1, &c_options->stereo.fixed_y1);
3965 pref_table_spin_new_int(table, 0, 2, _("Right X"), NULL,
3966 0, 5000, 1, options->stereo.fixed_x2, &c_options->stereo.fixed_x2);
3967 pref_table_spin_new_int(table, 3, 2, _("Right Y"), NULL,
3968 0, 5000, 1, options->stereo.fixed_y2, &c_options->stereo.fixed_y2);
3972 /* Main preferences window */
3973 static void config_window_create(LayoutWindow *lw)
3975 GtkWidget *win_vbox;
3977 GtkWidget *notebook;
3979 GtkWidget *ct_button;
3981 if (!c_options) c_options = init_options(NULL);
3983 configwindow = window_new(GTK_WINDOW_TOPLEVEL, "preferences", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Preferences"));
3984 DEBUG_NAME(configwindow);
3985 gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
3986 g_signal_connect(G_OBJECT(configwindow), "delete_event",
3987 G_CALLBACK(config_window_delete), NULL);
3988 if (options->save_dialog_window_positions)
3990 gtk_window_resize(GTK_WINDOW(configwindow), lw->options.preferences_window.w, lw->options.preferences_window.h);
3991 gtk_window_move(GTK_WINDOW(configwindow), lw->options.preferences_window.x, lw->options.preferences_window.y);
3995 gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
3997 gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
3998 gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
4000 win_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
4001 gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
4002 gtk_widget_show(win_vbox);
4004 notebook = gtk_notebook_new();
4005 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_LEFT);
4006 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE);
4007 gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
4009 config_tab_general(notebook);
4010 config_tab_image(notebook);
4011 config_tab_osd(notebook);
4012 config_tab_windows(notebook);
4013 config_tab_accelerators(notebook);
4014 config_tab_files(notebook);
4015 config_tab_metadata(notebook);
4016 config_tab_keywords(notebook);
4017 config_tab_color(notebook);
4018 config_tab_stereo(notebook);
4019 config_tab_behavior(notebook);
4020 config_tab_toolbar_main(notebook);
4021 config_tab_toolbar_status(notebook);
4022 config_tab_advanced(notebook);
4024 gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), lw->options.preferences_window.page_number);
4026 hbox = gtk_hbutton_box_new();
4027 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
4028 gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
4029 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
4030 gtk_widget_show(hbox);
4032 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
4033 G_CALLBACK(config_window_help_cb), notebook);
4034 gtk_container_add(GTK_CONTAINER(hbox), button);
4035 gtk_widget_set_can_default(button, TRUE);
4036 gtk_widget_show(button);
4038 button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
4039 G_CALLBACK(config_window_ok_cb), notebook);
4040 gtk_container_add(GTK_CONTAINER(hbox), button);
4041 gtk_widget_set_can_default(button, TRUE);
4042 gtk_widget_grab_default(button);
4043 gtk_widget_show(button);
4047 button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
4048 G_CALLBACK(config_window_close_cb), NULL);
4049 gtk_container_add(GTK_CONTAINER(hbox), button);
4050 gtk_widget_set_can_default(button, TRUE);
4051 gtk_widget_show(button);
4053 if (!generic_dialog_get_alternative_button_order(configwindow))
4055 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
4058 gtk_widget_show(notebook);
4060 gtk_widget_show(configwindow);
4064 *-----------------------------------------------------------------------------
4065 * config window show (public)
4066 *-----------------------------------------------------------------------------
4069 void show_config_window(LayoutWindow *lw)
4073 gtk_window_present(GTK_WINDOW(configwindow));
4077 config_window_create(lw);
4086 void show_about_window(LayoutWindow *lw)
4088 GdkPixbuf *pixbuf_logo;
4089 GdkPixbuf *pixbuf_icon;
4090 gchar *authors[1000];
4095 gchar *timezone_path;
4098 #define LINE_LENGTH 1000
4099 gchar line[LINE_LENGTH];
4101 copyright = g_string_new(NULL);
4102 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");
4104 timezone_path = g_build_filename(get_rc_dir(), TIMEZONE_DATABASE_FILE, NULL);
4105 if (g_file_test(timezone_path, G_FILE_TEST_EXISTS))
4107 cd = ZDOpenDatabase(timezone_path);
4110 copyright = g_string_append(copyright, ZDGetNotice(cd));
4114 log_printf("Error: Init of timezone database %s failed\n", timezone_path);
4116 ZDCloseDatabase(cd);
4118 g_free(timezone_path);
4121 path = g_build_filename(gq_helpdir, "AUTHORS", NULL);
4122 fp = fopen(path, "r");
4125 while(fgets(line, LINE_LENGTH, fp))
4127 /* get rid of ending \n from fgets */
4128 line[strlen(line) - 1] = '\0';
4129 authors[i_authors] = g_strdup(line);
4132 authors[i_authors] = NULL;
4137 comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
4138 "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
4140 pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
4141 pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
4142 gtk_show_about_dialog(GTK_WINDOW(lw->window),
4143 "title", _("About Geeqie"),
4145 "program-name", GQ_APPNAME,
4147 "logo", pixbuf_logo,
4148 "icon", pixbuf_icon,
4149 "website", GQ_WEBSITE,
4150 "website-label", "Website",
4151 "comments", comment,
4153 "translator-credits", _("translator-credits"),
4154 "wrap-license", TRUE,
4155 "license", copyright->str,
4158 g_string_free(copyright, TRUE);
4161 while(n < i_authors)
4171 static void image_overlay_set_text_colours()
4173 c_options->image_overlay.text_red = options->image_overlay.text_red;
4174 c_options->image_overlay.text_green = options->image_overlay.text_green;
4175 c_options->image_overlay.text_blue = options->image_overlay.text_blue;
4176 c_options->image_overlay.text_alpha = options->image_overlay.text_alpha;
4177 c_options->image_overlay.background_red = options->image_overlay.background_red;
4178 c_options->image_overlay.background_green = options->image_overlay.background_green;
4179 c_options->image_overlay.background_blue = options->image_overlay.background_blue;
4180 c_options->image_overlay.background_alpha = options->image_overlay.background_alpha;
4184 *-----------------------------------------------------------------------------
4185 * timezone database routines
4186 *-----------------------------------------------------------------------------
4189 static void timezone_async_ready_cb(GObject *source_object, GAsyncResult *res, gpointer data)
4191 GError *error = NULL;
4193 gchar *tmp_filename;
4194 gchar *timezone_bin;
4195 gchar *tmp_dir = NULL;
4198 if (!g_cancellable_is_cancelled(tz->cancellable))
4200 generic_dialog_close(tz->gd);
4204 if (g_file_copy_finish(G_FILE(source_object), res, &error))
4206 tmp_filename = g_file_get_path(tz->tmp_g_file);
4207 fd = file_data_new_simple(tmp_filename);
4208 tmp_dir = open_archive(fd);
4212 timezone_bin = g_build_filename(tmp_dir, TIMEZONE_DATABASE_VERSION, TIMEZONE_DATABASE_FILE, NULL);
4213 if (isfile(timezone_bin))
4215 move_file(timezone_bin, tz->timezone_database_user);
4219 warning_dialog(_("Warning: Cannot open timezone database file"), _("See the Log Window"), GTK_STOCK_DIALOG_WARNING, NULL);
4222 g_free(timezone_bin);
4223 g_free(tmp_dir); // The folder in /tmp is deleted in exit_program_final()
4227 warning_dialog(_("Warning: Cannot open timezone database file"), _("See the Log Window"), GTK_STOCK_DIALOG_WARNING, NULL);
4229 g_free(tmp_filename);
4230 file_data_unref(fd);
4234 file_util_warning_dialog(_("Error: Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
4237 g_file_delete(tz->tmp_g_file, NULL, &error);
4238 g_object_unref(tz->tmp_g_file);
4239 tz->tmp_g_file = NULL;
4240 g_object_unref(tz->cancellable);
4241 g_object_unref(tz->timezone_database_gq);
4244 static void timezone_progress_cb(goffset current_num_bytes, goffset total_num_bytes, gpointer data)
4248 if (!g_cancellable_is_cancelled(tz->cancellable))
4250 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(tz->progress), (gdouble)current_num_bytes / total_num_bytes);
4254 static void timezone_cancel_button_cb(GenericDialog *UNUSED(gd), gpointer data)
4258 g_cancellable_cancel(tz->cancellable);
4261 static void timezone_database_install_cb(GtkWidget *widget, gpointer data)
4264 GError *error = NULL;
4265 GFileIOStream *io_stream;
4272 tz->tmp_g_file = g_file_new_tmp("geeqie_timezone_XXXXXX", &io_stream, &error);
4276 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
4277 log_printf("Error: Download timezone database failed:\n%s", error->message);
4278 g_error_free(error);
4279 g_object_unref(tz->tmp_g_file);
4283 tz->timezone_database_gq = g_file_new_for_uri(TIMEZONE_DATABASE_WEB);
4285 tz->gd = generic_dialog_new(_("Timezone database"), "download_timezone_database", NULL, TRUE, timezone_cancel_button_cb, tz);
4287 generic_dialog_add_message(tz->gd, GTK_STOCK_DIALOG_INFO, _("Downloading timezone database"), NULL, FALSE);
4289 tz->progress = gtk_progress_bar_new();
4290 gtk_box_pack_start(GTK_BOX(tz->gd->vbox), tz->progress, FALSE, FALSE, 0);
4291 gtk_widget_show(tz->progress);
4293 gtk_widget_show(tz->gd->dialog);
4294 tz->cancellable = g_cancellable_new();
4295 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);
4297 gtk_button_set_label(GTK_BUTTON(widget), _("Update"));
4300 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */