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 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 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 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 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 *path, GtkTreeIter *iter, gpointer 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 *widget, gpointer data)
520 gtk_widget_destroy(configwindow);
525 static void config_window_help_cb(GtkWidget *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 *widget, GdkEventAny *event, gpointer 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 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 *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 *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 *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 *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 *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 *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 *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 *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 *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 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 *gd, gpointer 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 *widget, gpointer 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 *gd, gpointer data)
1461 file_util_trash_clear();
1464 static void safe_delete_clear_cb(GtkWidget *widget, gpointer 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 *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 *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 *widget, gpointer data)
1527 help_window_show("GuideOptionsOSD.html");
1530 static void image_overlay_set_font_cb(GtkWidget *widget, gpointer data)
1532 #if GTK_CHECK_VERSION(3,4,0)
1535 PangoFontDescription *font_desc;
1537 dialog = gtk_font_chooser_dialog_new("Image Overlay Font", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1538 gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), options->image_overlay.font);
1540 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1542 font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
1543 font = pango_font_description_to_string(font_desc);
1544 g_free(c_options->image_overlay.font);
1545 c_options->image_overlay.font = g_strdup(font);
1549 gtk_widget_destroy(dialog);
1553 font = gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget));
1554 c_options->image_overlay.font = g_strdup(font);
1558 static void image_overlay_set_text_colour_cb(GtkWidget *widget, gpointer data)
1561 #if GTK_CHECK_VERSION(3,4,0)
1564 dialog = gtk_color_chooser_dialog_new("Image Overlay Text Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1565 colour.red = options->image_overlay.text_red;
1566 colour.green = options->image_overlay.text_green;
1567 colour.blue = options->image_overlay.text_blue;
1568 colour.alpha = options->image_overlay.text_alpha;
1569 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1570 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1572 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1574 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1575 c_options->image_overlay.text_red = colour.red*255;
1576 c_options->image_overlay.text_green = colour.green*255;
1577 c_options->image_overlay.text_blue = colour.blue*255;
1578 c_options->image_overlay.text_alpha = colour.alpha*255;
1580 gtk_widget_destroy(dialog);
1583 GtkColorSelection *colorsel;
1585 dialog = gtk_color_selection_dialog_new("Image Overlay Text Colour");
1586 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1587 colour.red = options->image_overlay.text_red*257;
1588 colour.green = options->image_overlay.text_green*257;
1589 colour.blue = options->image_overlay.text_blue*257;
1590 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1591 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1592 gtk_color_selection_set_current_color(colorsel, &colour);
1593 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.text_alpha*257);
1595 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1597 gtk_color_selection_get_current_color(colorsel, &colour);
1598 c_options->image_overlay.text_red = colour.red/257;
1599 c_options->image_overlay.text_green = colour.green/257;
1600 c_options->image_overlay.text_blue = colour.blue/257;
1601 c_options->image_overlay.text_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1603 gtk_widget_destroy (dialog);
1608 static void image_overlay_set_background_colour_cb(GtkWidget *widget, gpointer data)
1611 #if GTK_CHECK_VERSION(3,4,0)
1614 dialog = gtk_color_chooser_dialog_new("Image Overlay Background Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1615 colour.red = options->image_overlay.background_red;
1616 colour.green = options->image_overlay.background_green;
1617 colour.blue = options->image_overlay.background_blue;
1618 colour.alpha = options->image_overlay.background_alpha;
1619 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1620 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1622 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1624 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1625 c_options->image_overlay.background_red = colour.red*255;
1626 c_options->image_overlay.background_green = colour.green*255;
1627 c_options->image_overlay.background_blue = colour.blue*255;
1628 c_options->image_overlay.background_alpha = colour.alpha*255;
1630 gtk_widget_destroy(dialog);
1633 GtkColorSelection *colorsel;
1635 dialog = gtk_color_selection_dialog_new("Image Overlay Background Colour");
1636 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1637 colour.red = options->image_overlay.background_red*257;
1638 colour.green = options->image_overlay.background_green*257;
1639 colour.blue = options->image_overlay.background_blue*257;
1640 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1641 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1642 gtk_color_selection_set_current_color(colorsel, &colour);
1643 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.background_alpha*257);
1645 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1647 gtk_color_selection_get_current_color(colorsel, &colour);
1648 c_options->image_overlay.background_red = colour.red/257;
1649 c_options->image_overlay.background_green = colour.green/257;
1650 c_options->image_overlay.background_blue = colour.blue/257;
1651 c_options->image_overlay.background_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1653 gtk_widget_destroy(dialog);
1657 static void accel_store_populate(void)
1660 GList *groups, *actions;
1662 const gchar *accel_path;
1666 if (!accel_store || !layout_window_list || !layout_window_list->data) return;
1668 gtk_tree_store_clear(accel_store);
1669 lw = layout_window_list->data; /* get the actions from the first window, it should not matter, they should be the same in all windows */
1671 g_assert(lw && lw->ui_manager);
1672 groups = gtk_ui_manager_get_action_groups(lw->ui_manager);
1675 actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
1678 action = GTK_ACTION(actions->data);
1679 accel_path = gtk_action_get_accel_path(action);
1680 if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
1682 gchar *label, *label2, *tooltip, *accel;
1683 g_object_get(action,
1684 "tooltip", &tooltip,
1688 if (pango_parse_markup(label, -1, '_', NULL, &label2, NULL, NULL) && label2)
1694 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1698 gtk_tree_store_append(accel_store, &iter, NULL);
1699 gtk_tree_store_set(accel_store, &iter,
1702 AE_TOOLTIP, tooltip ? tooltip : "",
1703 AE_ACCEL, accel_path,
1711 actions = actions->next;
1714 groups = groups->next;
1718 static void accel_store_cleared_cb(GtkCellRendererAccel *accel, gchar *path_string, gpointer user_data)
1723 static gboolean accel_remove_key_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1725 gchar *accel1 = data;
1730 gtk_tree_model_get(model, iter, AE_KEY, &accel2, -1);
1732 gtk_accelerator_parse(accel1, &key1.accel_key, &key1.accel_mods);
1733 gtk_accelerator_parse(accel2, &key2.accel_key, &key2.accel_mods);
1735 if (key1.accel_key == key2.accel_key && key1.accel_mods == key2.accel_mods)
1737 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1738 DEBUG_1("accelerator key '%s' is already used, removing.", accel1);
1747 static void accel_store_edited_cb(GtkCellRendererAccel *accel, gchar *path_string, guint accel_key, GdkModifierType accel_mods, guint hardware_keycode, gpointer user_data)
1749 GtkTreeModel *model = (GtkTreeModel *)accel_store;
1753 GtkAccelKey old_key, key;
1754 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
1756 gtk_tree_model_get_iter(model, &iter, path);
1757 gtk_tree_model_get(model, &iter, AE_ACCEL, &accel_path, -1);
1759 /* test if the accelerator can be stored without conflicts*/
1760 gtk_accel_map_lookup_entry(accel_path, &old_key);
1762 /* change the key and read it back (change may fail on keys hardcoded in gtk)*/
1763 gtk_accel_map_change_entry(accel_path, accel_key, accel_mods, TRUE);
1764 gtk_accel_map_lookup_entry(accel_path, &key);
1766 /* restore the original for now, the key will be really changed when the changes are confirmed */
1767 gtk_accel_map_change_entry(accel_path, old_key.accel_key, old_key.accel_mods, TRUE);
1769 acc = gtk_accelerator_name(key.accel_key, key.accel_mods);
1770 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, acc);
1772 gtk_tree_store_set(accel_store, &iter, AE_KEY, acc, -1);
1773 gtk_tree_path_free(path);
1777 static gboolean accel_default_scroll(GtkTreeView *data)
1781 GtkTreeViewColumn *column;
1783 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(accel_store), &iter);
1784 path = gtk_tree_model_get_path(GTK_TREE_MODEL(accel_store), &iter);
1785 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1787 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1791 gtk_tree_path_free(path);
1796 static void accel_default_cb(GtkWidget *widget, gpointer data)
1798 accel_store_populate();
1800 g_idle_add((GSourceFunc)accel_default_scroll, data);
1803 void accel_remove_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1805 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1808 void accel_reset_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1811 gchar *accel_path, *accel;
1813 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, -1);
1814 gtk_accel_map_lookup_entry(accel_path, &key);
1815 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1817 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, accel);
1819 gtk_tree_store_set(accel_store, iter, AE_KEY, accel, -1);
1824 static void accel_reset_cb(GtkWidget *widget, gpointer data)
1826 GtkTreeSelection *selection;
1828 if (!accel_store) return;
1829 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data));
1830 gtk_tree_selection_selected_foreach(selection, &accel_reset_selection, NULL);
1835 static GtkWidget *scrolled_notebook_page(GtkWidget *notebook, const gchar *title)
1839 GtkWidget *scrolled;
1840 GtkWidget *viewport;
1842 scrolled = gtk_scrolled_window_new(NULL, NULL);
1843 gtk_container_set_border_width(GTK_CONTAINER(scrolled), PREF_PAD_BORDER);
1844 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1845 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1846 label = gtk_label_new(title);
1847 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, label);
1848 gtk_widget_show(scrolled);
1850 viewport = gtk_viewport_new(NULL, NULL);
1851 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1852 gtk_container_add(GTK_CONTAINER(scrolled), viewport);
1853 gtk_widget_show(viewport);
1855 vbox = gtk_vbox_new(FALSE, 0);
1856 gtk_container_add(GTK_CONTAINER(viewport), vbox);
1857 gtk_widget_show(vbox);
1862 static void cache_standard_cb(GtkWidget *widget, gpointer data)
1864 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1866 c_options->thumbnails.spec_standard =TRUE;
1867 c_options->thumbnails.cache_into_dirs = FALSE;
1871 static void cache_geeqie_cb(GtkWidget *widget, gpointer data)
1873 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1875 c_options->thumbnails.spec_standard =FALSE;
1876 c_options->thumbnails.cache_into_dirs = FALSE;
1880 static void cache_local_cb(GtkWidget *widget, gpointer data)
1882 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1884 c_options->thumbnails.cache_into_dirs = TRUE;
1885 c_options->thumbnails.spec_standard =FALSE;
1889 static void help_search_engine_entry_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1890 GdkEvent *event, gpointer userdata)
1892 if (pos == GTK_ENTRY_ICON_PRIMARY)
1894 gtk_entry_set_text(GTK_ENTRY(userdata), HELP_SEARCH_ENGINE);
1898 gtk_entry_set_text(GTK_ENTRY(userdata), "");
1902 static void star_rating_star_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1903 GdkEvent *event, gpointer userdata)
1905 gchar *rating_symbol;
1907 if (pos == GTK_ENTRY_ICON_PRIMARY)
1909 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_STAR);
1910 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1911 g_free(rating_symbol);
1915 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1916 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1917 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1921 static void star_rating_rejected_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1922 GdkEvent *event, gpointer userdata)
1924 gchar *rating_symbol;
1926 if (pos == GTK_ENTRY_ICON_PRIMARY)
1928 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_REJECTED);
1929 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1930 g_free(rating_symbol);
1934 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1935 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1936 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1940 static guint star_rating_symbol_test(GtkWidget *widget, gpointer data)
1942 GtkContainer *hbox = data;
1943 GString *str = g_string_new(NULL);
1944 GtkEntry *hex_code_entry;
1945 gchar *hex_code_full;
1948 guint64 hex_value = 0;
1950 list = gtk_container_get_children(hbox);
1952 hex_code_entry = g_list_nth_data(list, 2);
1953 hex_code_full = g_strdup(gtk_entry_get_text(hex_code_entry));
1955 hex_code = g_strsplit(hex_code_full, "+", 2);
1956 if (hex_code[0] && hex_code[1])
1958 hex_value = strtoull(hex_code[1], NULL, 16);
1960 if (!hex_value || hex_value > 0x10FFFF)
1962 hex_value = 0x003F; // Unicode 'Question Mark'
1964 str = g_string_append_unichar(str, (gunichar)hex_value);
1965 gtk_label_set_text(g_list_nth_data(list, 1), str->str);
1967 g_strfreev(hex_code);
1968 g_string_free(str, TRUE);
1969 g_free(hex_code_full);
1974 static void star_rating_star_test_cb(GtkWidget *widget, gpointer data)
1976 guint64 star_symbol;
1978 star_symbol = star_rating_symbol_test(widget, data);
1979 c_options->star_rating.star = star_symbol;
1982 static void star_rating_rejected_test_cb(GtkWidget *widget, gpointer data)
1984 guint64 rejected_symbol;
1986 rejected_symbol = star_rating_symbol_test(widget, data);
1987 c_options->star_rating.rejected = rejected_symbol;
1990 /* general options tab */
1991 static void timezone_database_install_cb(GtkWidget *widget, gpointer data);
1992 typedef struct _TZData TZData;
1996 GCancellable *cancellable;
1998 GtkWidget *progress;
2000 GFile *timezone_database_gq;
2001 gchar *timezone_database_user;
2004 static void config_tab_general(GtkWidget *notebook)
2009 GtkWidget *group_frame;
2010 GtkWidget *subgroup;
2012 GtkWidget *ct_button;
2015 gint hours, minutes, remainder;
2017 GtkWidget *star_rating_entry;
2019 gchar *rating_symbol;
2022 gchar *download_locn;
2023 GNetworkMonitor *net_mon;
2024 GSocketConnectable *tz_org;
2025 gboolean internet_available = FALSE;
2028 vbox = scrolled_notebook_page(notebook, _("General"));
2030 group = pref_group_new(vbox, FALSE, _("Thumbnails"), GTK_ORIENTATION_VERTICAL);
2032 table = pref_table_new(group, 2, 2, FALSE, FALSE);
2033 add_thumb_size_menu(table, 0, 0, _("Size:"));
2034 add_quality_menu(table, 0, 1, _("Quality:"), options->thumbnails.quality, &c_options->thumbnails.quality);
2036 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2037 pref_label_new(hbox, _("Custom size: "));
2038 pref_spin_new_int(hbox, _("Width:"), NULL, 1, 512, 1, options->thumbnails.max_width, &c_options->thumbnails.max_width);
2039 pref_spin_new_int(hbox, _("Height:"), NULL, 1, 512, 1, options->thumbnails.max_height, &c_options->thumbnails.max_height);
2041 ct_button = pref_checkbox_new_int(group, _("Cache thumbnails and sim. files"),
2042 options->thumbnails.enable_caching, &c_options->thumbnails.enable_caching);
2044 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2045 pref_checkbox_link_sensitivity(ct_button, subgroup);
2047 c_options->thumbnails.spec_standard = options->thumbnails.spec_standard;
2048 c_options->thumbnails.cache_into_dirs = options->thumbnails.cache_into_dirs;
2049 group_frame = pref_frame_new(subgroup, TRUE, _("Use Geeqie thumbnail style and cache"),
2050 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2051 button = pref_radiobutton_new(group_frame, NULL, get_thumbnails_cache_dir(),
2052 !options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
2053 G_CALLBACK(cache_geeqie_cb), NULL);
2055 group_frame = pref_frame_new(subgroup, TRUE,
2056 _("Store thumbnails local to image folder (non-standard)"),
2057 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2058 pref_radiobutton_new(group_frame, button, "*/.thumbnails",
2059 !options->thumbnails.spec_standard && options->thumbnails.cache_into_dirs,
2060 G_CALLBACK(cache_local_cb), NULL);
2062 group_frame = pref_frame_new(subgroup, TRUE,
2063 _("Use standard thumbnail style and cache, shared with other applications"),
2064 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2065 pref_radiobutton_new(group_frame, button, get_thumbnails_standard_cache_dir(),
2066 options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
2067 G_CALLBACK(cache_standard_cb), NULL);
2069 pref_checkbox_new_int(group, _("Use EXIF thumbnails when available (EXIF thumbnails may be outdated)"),
2070 options->thumbnails.use_exif, &c_options->thumbnails.use_exif);
2072 pref_checkbox_new_int(group, _("Thumbnail color management"),
2073 options->thumbnails.use_color_management, &c_options->thumbnails.use_color_management);
2075 spin = pref_spin_new_int(group, _("Collection preview:"), NULL,
2077 options->thumbnails.collection_preview, &c_options->thumbnails.collection_preview);
2078 gtk_widget_set_tooltip_text(spin, _("The maximum number of thumbnails shown in a Collection preview montage"));
2080 #ifdef HAVE_FFMPEGTHUMBNAILER_METADATA
2081 pref_checkbox_new_int(group, _("Use embedded metadata in video files as thumbnails when available"),
2082 options->thumbnails.use_ft_metadata, &c_options->thumbnails.use_ft_metadata);
2084 // pref_checkbox_new_int(group, _("Ignore embedded metadata if size is too small"),
2085 // options->thumbnails.use_ft_metadata_small, &c_options->thumbnails.use_ft_metadata_small);
2088 pref_spacer(group, PREF_PAD_GROUP);
2090 group = pref_group_new(vbox, FALSE, _("Star Rating"), GTK_ORIENTATION_VERTICAL);
2092 c_options->star_rating.star = options->star_rating.star;
2093 c_options->star_rating.rejected = options->star_rating.rejected;
2095 str = g_string_new(NULL);
2096 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2097 pref_label_new(hbox, _("Star character: "));
2098 str = g_string_append_unichar(str, options->star_rating.star);
2099 pref_label_new(hbox, g_strdup(str->str));
2100 rating_symbol = g_strdup_printf("U+%X", options->star_rating.star);
2101 star_rating_entry = gtk_entry_new();
2102 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
2103 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
2104 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
2105 gtk_widget_show(star_rating_entry);
2106 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
2107 G_CALLBACK(star_rating_star_test_cb), hbox);
2108 gtk_widget_set_tooltip_text(button, _("Display selected character"));
2109 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2110 gtk_widget_show(button);
2111 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."));
2112 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2113 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2114 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2115 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2116 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2117 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2118 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2119 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2120 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
2121 G_CALLBACK(star_rating_star_icon_cb),
2124 g_string_free(str, TRUE);
2125 g_free(rating_symbol);
2127 str = g_string_new(NULL);
2128 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2129 pref_label_new(hbox, _("Rejected character: "));
2130 str = g_string_append_unichar(str, options->star_rating.rejected);
2131 pref_label_new(hbox, g_strdup(str->str));
2132 rating_symbol = g_strdup_printf("U+%X", options->star_rating.rejected);
2133 star_rating_entry = gtk_entry_new();
2134 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
2135 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
2136 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
2137 gtk_widget_show(star_rating_entry);
2138 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
2139 G_CALLBACK(star_rating_rejected_test_cb), hbox);
2140 gtk_widget_set_tooltip_text(button, _("Display selected character"));
2141 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2142 gtk_widget_show(button);
2143 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."));
2144 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2145 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2146 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2147 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2148 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2149 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2150 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2151 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2152 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
2153 G_CALLBACK(star_rating_rejected_icon_cb),
2156 g_string_free(str, TRUE);
2157 g_free(rating_symbol);
2159 pref_spacer(group, PREF_PAD_GROUP);
2161 group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
2163 c_options->slideshow.delay = options->slideshow.delay;
2164 hours = options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2165 remainder = options->slideshow.delay % (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2166 minutes = remainder / (60 * SLIDESHOW_SUBSECOND_PRECISION);
2167 seconds = (gdouble)(remainder % (60 * SLIDESHOW_SUBSECOND_PRECISION)) /
2168 SLIDESHOW_SUBSECOND_PRECISION;
2170 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2172 spin = pref_spin_new(hbox, _("Delay between image change hrs:mins:secs.dec"), NULL,
2174 options->slideshow.delay ? hours : 0.0,
2175 G_CALLBACK(slideshow_delay_hours_cb), NULL);
2176 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2177 spin = pref_spin_new(hbox, ":" , NULL,
2179 options->slideshow.delay ? minutes: 0.0,
2180 G_CALLBACK(slideshow_delay_minutes_cb), NULL);
2181 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2182 spin = pref_spin_new(hbox, ":", NULL,
2183 SLIDESHOW_MIN_SECONDS, 59, 1.0, 1,
2184 options->slideshow.delay ? seconds : 10.0,
2185 G_CALLBACK(slideshow_delay_seconds_cb), NULL);
2186 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2188 pref_checkbox_new_int(group, _("Random"), options->slideshow.random, &c_options->slideshow.random);
2189 pref_checkbox_new_int(group, _("Repeat"), options->slideshow.repeat, &c_options->slideshow.repeat);
2191 pref_spacer(group, PREF_PAD_GROUP);
2193 group = pref_group_new(vbox, FALSE, _("Image loading and caching"), GTK_ORIENTATION_VERTICAL);
2195 pref_spin_new_int(group, _("Decoded image cache size (MiB):"), NULL,
2196 0, 99999, 1, options->image.image_cache_max, &c_options->image.image_cache_max);
2197 pref_checkbox_new_int(group, _("Preload next image"),
2198 options->image.enable_read_ahead, &c_options->image.enable_read_ahead);
2200 pref_checkbox_new_int(group, _("Refresh on file change"),
2201 options->update_on_time_change, &c_options->update_on_time_change);
2204 pref_spacer(group, PREF_PAD_GROUP);
2206 group = pref_group_new(vbox, FALSE, _("Expand menu and toolbar"), GTK_ORIENTATION_VERTICAL);
2208 pref_checkbox_new_int(group, _("Expand menu and toolbar (NOTE! Geeqie must be restarted for change to take effect)"),
2209 options->expand_menu_toolbar, &c_options->expand_menu_toolbar);
2210 gtk_widget_set_tooltip_text(group, _("Expand the menu and toolbar to the full width of the window"));
2212 pref_spacer(group, PREF_PAD_GROUP);
2214 net_mon = g_network_monitor_get_default();
2215 tz_org = g_network_address_parse_uri(TIMEZONE_DATABASE_WEB, 80, NULL);
2218 internet_available = g_network_monitor_can_reach(net_mon, tz_org, NULL, NULL);
2219 g_object_unref(tz_org);
2222 group = pref_group_new(vbox, FALSE, _("Timezone database"), GTK_ORIENTATION_VERTICAL);
2223 hbox = pref_box_new(group, TRUE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2225 if (!internet_available)
2227 gtk_widget_set_sensitive(group, FALSE);
2230 tz = g_new0(TZData, 1);
2232 path = path_from_utf8(TIMEZONE_DATABASE_WEB);
2233 basename = g_path_get_basename(path);
2234 tz->timezone_database_user = g_build_filename(get_rc_dir(), TIMEZONE_DATABASE_FILE, NULL);
2238 if (isfile(tz->timezone_database_user))
2240 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Update"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2244 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Install"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2247 download_locn = g_strconcat(_("Download database from: "), TIMEZONE_DATABASE_WEB, NULL);
2248 pref_label_new(GTK_WIDGET(hbox), download_locn);
2249 g_free(download_locn);
2251 if (!internet_available)
2253 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"));
2257 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"));
2259 gtk_widget_show(button);
2261 pref_spacer(group, PREF_PAD_GROUP);
2263 group = pref_group_new(vbox, FALSE, _("On-line help search engine"), GTK_ORIENTATION_VERTICAL);
2265 help_search_engine_entry = gtk_entry_new();
2266 gtk_entry_set_text(GTK_ENTRY(help_search_engine_entry), options->help_search_engine);
2267 gtk_box_pack_start(GTK_BOX(group), help_search_engine_entry, FALSE, FALSE, 0);
2268 gtk_widget_show(help_search_engine_entry);
2270 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"));
2272 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2273 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2274 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2275 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2276 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2277 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2278 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2279 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2280 g_signal_connect(GTK_ENTRY(help_search_engine_entry), "icon-press",
2281 G_CALLBACK(help_search_engine_entry_icon_cb),
2282 help_search_engine_entry);
2286 static void config_tab_image(GtkWidget *notebook)
2291 GtkWidget *ct_button;
2292 GtkWidget *enlargement_button;
2295 GtkWidget *two_pass;
2297 GtkWidget *gpu_accel;
2300 vbox = scrolled_notebook_page(notebook, _("Image"));
2302 group = pref_group_new(vbox, FALSE, _("Zoom"), GTK_ORIENTATION_VERTICAL);
2304 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2305 add_quality_menu(table, 0, 0, _("Quality:"), options->image.zoom_quality, &c_options->image.zoom_quality);
2306 if (options->image.use_clutter_renderer && !options->disable_gpu)
2308 gtk_widget_set_sensitive(table, FALSE);
2312 gpu_accel = pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library (Requires restart)"),
2313 options->image.use_clutter_renderer, &c_options->image.use_clutter_renderer);
2314 if (options->disable_gpu && !options->override_disable_gpu)
2316 gtk_widget_set_sensitive(gpu_accel, FALSE);
2320 two_pass = pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"),
2321 options->image.zoom_2pass, &c_options->image.zoom_2pass);
2322 if (options->image.use_clutter_renderer && !options->disable_gpu)
2324 gtk_widget_set_sensitive(two_pass, FALSE);
2327 c_options->image.zoom_increment = options->image.zoom_increment;
2328 spin = pref_spin_new(group, _("Zoom increment:"), NULL,
2329 0.01, 4.0, 0.01, 2, (gdouble)options->image.zoom_increment / 100.0,
2330 G_CALLBACK(zoom_increment_cb), NULL);
2331 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2333 c_options->image.zoom_style = options->image.zoom_style;
2334 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2335 add_zoom_style_selection_menu(table, 0, 0, _("Zoom style:"), options->image.zoom_style, &c_options->image.zoom_style);
2337 group = pref_group_new(vbox, FALSE, _("Fit image to window"), GTK_ORIENTATION_VERTICAL);
2339 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2340 enlargement_button = pref_checkbox_new_int(hbox, _("Allow enlargement of image (max. size in %)"),
2341 options->image.zoom_to_fit_allow_expand, &c_options->image.zoom_to_fit_allow_expand);
2342 spin = pref_spin_new_int(hbox, NULL, NULL,
2344 options->image.max_enlargement_size, &c_options->image.max_enlargement_size);
2345 pref_checkbox_link_sensitivity(enlargement_button, spin);
2346 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."));
2348 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2349 ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (% of actual window):"),
2350 options->image.limit_autofit_size, &c_options->image.limit_autofit_size);
2351 spin = pref_spin_new_int(hbox, NULL, NULL,
2353 options->image.max_autofit_size, &c_options->image.max_autofit_size);
2354 pref_checkbox_link_sensitivity(ct_button, spin);
2355 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."));
2357 group = pref_group_new(vbox, FALSE, _("Tile size"), GTK_ORIENTATION_VERTICAL);
2358 gtk_widget_set_sensitive(group, !options->image.use_clutter_renderer);
2360 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2361 spin = pref_spin_new_int(hbox, _("Pixels"), _("(Requires restart)"),
2363 options->image.tile_size, &c_options->image.tile_size);
2364 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."));
2366 group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
2368 pref_checkbox_new_int(group, _("Use custom border color in window mode"),
2369 options->image.use_custom_border_color, &c_options->image.use_custom_border_color);
2371 pref_checkbox_new_int(group, _("Use custom border color in fullscreen mode"),
2372 options->image.use_custom_border_color_in_fullscreen, &c_options->image.use_custom_border_color_in_fullscreen);
2374 pref_color_button_new(group, _("Border color"), &options->image.border_color,
2375 G_CALLBACK(pref_color_button_set_cb), &c_options->image.border_color);
2377 c_options->image.border_color = options->image.border_color;
2379 pref_color_button_new(group, _("Alpha channel color 1"), &options->image.alpha_color_1,
2380 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_1);
2382 pref_color_button_new(group, _("Alpha channel color 2"), &options->image.alpha_color_2,
2383 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_2);
2385 c_options->image.alpha_color_1 = options->image.alpha_color_1;
2386 c_options->image.alpha_color_2 = options->image.alpha_color_2;
2391 static void save_default_window_layout_cb(GtkWidget *widget, gpointer data)
2393 LayoutWindow *lw = NULL;
2394 gchar *default_path;
2397 /* Get current lw */
2400 tmp_id = lw->options.id;
2401 lw->options.id = g_strdup("lw_default");
2403 default_path = g_build_filename(get_rc_dir(), DEFAULT_WINDOW_LAYOUT, NULL);
2404 save_default_layout_options_to_file(default_path, options, lw);
2405 g_free(lw->options.id);
2406 lw->options.id = tmp_id;
2407 g_free(default_path);
2410 #if GTK_CHECK_VERSION(3,22,0)
2411 static gboolean popover_cb(gpointer data)
2413 GtkPopover *popover = data;
2415 gtk_popover_popdown(popover);
2420 static void default_layout_changed_cb(GtkWidget *button, GtkPopover *popover)
2422 gtk_popover_popup(popover);
2424 g_timeout_add(2000, popover_cb, popover);
2427 static GtkWidget *create_popover(GtkWidget *parent, GtkWidget *child, GtkPositionType pos)
2431 popover = gtk_popover_new(parent);
2432 gtk_popover_set_position(GTK_POPOVER (popover), pos);
2433 gtk_container_add (GTK_CONTAINER(popover), child);
2434 gtk_container_set_border_width(GTK_CONTAINER (popover), 6);
2435 gtk_widget_show (child);
2441 static void config_tab_windows(GtkWidget *notebook)
2446 GtkWidget *subgroup;
2448 GtkWidget *ct_button;
2451 vbox = scrolled_notebook_page(notebook, _("Windows"));
2453 group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
2455 ct_button = pref_checkbox_new_int(group, _("Remember session"),
2456 options->save_window_positions, &c_options->save_window_positions);
2458 button = pref_checkbox_new_int(group, _("Use saved window positions also for new windows"),
2459 options->use_saved_window_positions_for_new_windows, &c_options->use_saved_window_positions_for_new_windows);
2460 pref_checkbox_link_sensitivity(ct_button, button);
2462 button = pref_checkbox_new_int(group, _("Remember window workspace"),
2463 options->save_window_workspace, &c_options->save_window_workspace);
2464 pref_checkbox_link_sensitivity(ct_button, button);
2466 pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
2467 options->tools_restore_state, &c_options->tools_restore_state);
2469 pref_checkbox_new_int(group, _("Remember dialog window positions"),
2470 options->save_dialog_window_positions, &c_options->save_dialog_window_positions);
2472 pref_checkbox_new_int(group, _("Show window IDs"),
2473 options->show_window_ids, &c_options->show_window_ids);
2475 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2476 pref_label_new(subgroup, _("Use current layout for default: "));
2477 button = pref_button_new(subgroup, NULL, _("Set"), FALSE, G_CALLBACK(save_default_window_layout_cb), NULL);
2479 #if GTK_CHECK_VERSION(3,22,0)
2482 popover = create_popover(button, gtk_label_new(_("Current window layout\nhas been set as default")), GTK_POS_TOP);
2483 gtk_popover_set_modal(GTK_POPOVER (popover), FALSE);
2484 g_signal_connect(button, "clicked", G_CALLBACK(default_layout_changed_cb), popover);
2487 group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
2489 pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
2490 options->image.fit_window_to_image, &c_options->image.fit_window_to_image);
2492 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2493 ct_button = pref_checkbox_new_int(hbox, _("Limit size when auto-sizing window (%):"),
2494 options->image.limit_window_size, &c_options->image.limit_window_size);
2495 spin = pref_spin_new_int(hbox, NULL, NULL,
2497 options->image.max_window_size, &c_options->image.max_window_size);
2498 pref_checkbox_link_sensitivity(ct_button, spin);
2500 group = pref_group_new(vbox, FALSE, _("Full screen"), GTK_ORIENTATION_VERTICAL);
2502 c_options->fullscreen.screen = options->fullscreen.screen;
2503 c_options->fullscreen.above = options->fullscreen.above;
2504 hbox = fullscreen_prefs_selection_new(_("Location:"), &c_options->fullscreen.screen, &c_options->fullscreen.above);
2505 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2506 gtk_widget_show(hbox);
2508 pref_checkbox_new_int(group, _("Smooth image flip"),
2509 options->fullscreen.clean_flip, &c_options->fullscreen.clean_flip);
2510 pref_checkbox_new_int(group, _("Disable screen saver"),
2511 options->fullscreen.disable_saver, &c_options->fullscreen.disable_saver);
2514 #define PRE_FORMATTED_COLUMNS 5
2515 static void config_tab_osd(GtkWidget *notebook)
2521 GtkWidget *image_overlay_template_view;
2522 GtkWidget *scrolled;
2523 GtkWidget *scrolled_pre_formatted;
2524 GtkTextBuffer *buffer;
2526 GtkWidget *subgroup;
2528 vbox = scrolled_notebook_page(notebook, _("OSD"));
2530 image_overlay_template_view = gtk_text_view_new();
2532 group = pref_group_new(vbox, FALSE, _("Overlay Screen Display"), GTK_ORIENTATION_VERTICAL);
2534 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2536 scrolled_pre_formatted = osd_new(PRE_FORMATTED_COLUMNS, image_overlay_template_view);
2537 gtk_widget_set_size_request(scrolled_pre_formatted, 200, 150);
2538 gtk_box_pack_start(GTK_BOX(subgroup), scrolled_pre_formatted, FALSE, FALSE, 0);
2539 gtk_widget_show(scrolled_pre_formatted);
2540 gtk_widget_show(subgroup);
2542 pref_line(group, PREF_PAD_GAP);
2544 pref_label_new(group, _("Image overlay template"));
2546 scrolled = gtk_scrolled_window_new(NULL, NULL);
2547 gtk_widget_set_size_request(scrolled, 200, 150);
2548 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2549 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
2550 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2551 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 5);
2552 gtk_widget_show(scrolled);
2554 gtk_widget_set_tooltip_markup(image_overlay_template_view,
2555 _("Extensive formatting options are shown in the Help file"));
2557 gtk_container_add(GTK_CONTAINER(scrolled), image_overlay_template_view);
2558 gtk_widget_show(image_overlay_template_view);
2560 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2562 #if GTK_CHECK_VERSION(3,4,0)
2563 button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
2564 G_CALLBACK(image_overlay_set_font_cb), notebook);
2566 button = gtk_font_button_new();
2567 gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Image Overlay Font");
2568 gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->image_overlay.font);
2569 g_signal_connect(G_OBJECT(button), "font-set",
2570 G_CALLBACK(image_overlay_set_font_cb),NULL);
2572 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2573 gtk_widget_show(button);
2575 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Text"), FALSE,
2576 G_CALLBACK(image_overlay_set_text_colour_cb), NULL);
2577 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2578 gtk_widget_show(button);
2580 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Background"), FALSE,
2581 G_CALLBACK(image_overlay_set_background_colour_cb), NULL);
2582 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2583 gtk_widget_show(button);
2584 image_overlay_set_text_colours();
2586 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2587 G_CALLBACK(image_overlay_default_template_cb), image_overlay_template_view);
2588 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2589 gtk_widget_show(button);
2591 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
2592 G_CALLBACK(image_overlay_help_cb), NULL);
2593 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2594 gtk_widget_show(button);
2596 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_overlay_template_view));
2597 if (options->image_overlay.template_string) gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
2598 g_signal_connect(G_OBJECT(buffer), "changed",
2599 G_CALLBACK(image_overlay_template_view_changed_cb), image_overlay_template_view);
2601 pref_line(group, PREF_PAD_GAP);
2603 group = pref_group_new(vbox, FALSE, _("Exif, XMP or IPTC tags"), GTK_ORIENTATION_VERTICAL);
2604 hbox = gtk_hbox_new(FALSE, 0);
2605 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2606 gtk_widget_show(hbox);
2607 label = gtk_label_new(_("%Exif.Image.Orientation%"));
2608 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2609 gtk_widget_show(label);
2610 pref_spacer(group,TRUE);
2612 group = pref_group_new(vbox, FALSE, _("Field separators"), GTK_ORIENTATION_VERTICAL);
2613 hbox = gtk_hbox_new(FALSE, 0);
2614 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2615 gtk_widget_show(hbox);
2616 label = gtk_label_new(_("Separator shown only if both fields are non-null:\n%formatted.ShutterSpeed%|%formatted.ISOSpeedRating%"));
2617 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2618 gtk_widget_show(label);
2619 pref_spacer(group,TRUE);
2621 group = pref_group_new(vbox, FALSE, _("Field maximum length"), GTK_ORIENTATION_VERTICAL);
2622 hbox = gtk_hbox_new(FALSE, 0);
2623 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2624 gtk_widget_show(hbox);
2625 label = gtk_label_new(_("%path:39%"));
2626 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2627 gtk_widget_show(label);
2628 pref_spacer(group,TRUE);
2630 group = pref_group_new(vbox, FALSE, _("Pre- and post- text"), GTK_ORIENTATION_VERTICAL);
2631 hbox = gtk_hbox_new(FALSE, 0);
2632 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2633 gtk_widget_show(hbox);
2634 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%"));
2635 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2636 gtk_widget_show(label);
2637 pref_spacer(group,TRUE);
2639 group = pref_group_new(vbox, FALSE, _("Pango markup"), GTK_ORIENTATION_VERTICAL);
2640 hbox = gtk_hbox_new(FALSE, 0);
2641 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2642 gtk_widget_show(hbox);
2643 label = gtk_label_new(_("<b>bold</b>\n<u>underline</u>\n<i>italic</i>\n<s>strikethrough</s>"));
2644 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2645 gtk_widget_show(label);
2648 static GtkTreeModel *create_class_model(void)
2650 GtkListStore *model;
2654 /* create list store */
2655 model = gtk_list_store_new(1, G_TYPE_STRING);
2656 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
2658 gtk_list_store_append(model, &iter);
2659 gtk_list_store_set(model, &iter, 0, _(format_class_list[i]), -1);
2661 return GTK_TREE_MODEL (model);
2666 static gint filter_table_sort_cb(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer data)
2668 gint n = GPOINTER_TO_INT(data);
2670 FilterEntry *filter_a;
2671 FilterEntry *filter_b;
2673 gtk_tree_model_get(model, a, 0, &filter_a, -1);
2674 gtk_tree_model_get(model, b, 0, &filter_b, -1);
2678 case FILETYPES_COLUMN_ENABLED:
2680 ret = filter_a->enabled - filter_b->enabled;
2683 case FILETYPES_COLUMN_FILTER:
2685 ret = g_utf8_collate(filter_a->extensions, filter_b->extensions);
2688 case FILETYPES_COLUMN_DESCRIPTION:
2690 ret = g_utf8_collate(filter_a->description, filter_b->description);
2693 case FILETYPES_COLUMN_CLASS:
2695 ret = g_strcmp0(format_class_list[filter_a->file_class], format_class_list[filter_b->file_class]);
2698 case FILETYPES_COLUMN_WRITABLE:
2700 ret = filter_a->writable - filter_b->writable;
2703 case FILETYPES_COLUMN_SIDECAR:
2705 ret = filter_a->allow_sidecar - filter_b->allow_sidecar;
2709 g_return_val_if_reached(0);
2715 static gboolean search_function_cb(GtkTreeModel *model, gint column, const gchar *key, GtkTreeIter *iter, gpointer search_data)
2718 gboolean ret = TRUE;
2720 gtk_tree_model_get(model, iter, 0, &fe, -1);
2722 if (g_strstr_len(fe->extensions, -1, key))
2730 static void config_tab_files(GtkWidget *notebook)
2737 GtkWidget *ct_button;
2738 GtkWidget *scrolled;
2739 GtkWidget *filter_view;
2740 GtkCellRenderer *renderer;
2741 GtkTreeSelection *selection;
2742 GtkTreeViewColumn *column;
2744 vbox = scrolled_notebook_page(notebook, _("Files"));
2746 group = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2748 pref_checkbox_new_int(group, _("Show hidden files or folders"),
2749 options->file_filter.show_hidden_files, &c_options->file_filter.show_hidden_files);
2750 pref_checkbox_new_int(group, _("Show parent folder (..)"),
2751 options->file_filter.show_parent_directory, &c_options->file_filter.show_parent_directory);
2752 pref_checkbox_new_int(group, _("Case sensitive sort"),
2753 options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
2754 pref_checkbox_new_int(group, _("Natural sort order"),
2755 options->file_sort.natural, &c_options->file_sort.natural);
2756 pref_checkbox_new_int(group, _("Disable file extension checks"),
2757 options->file_filter.disable_file_extension_checks, &c_options->file_filter.disable_file_extension_checks);
2759 ct_button = pref_checkbox_new_int(group, _("Disable File Filtering"),
2760 options->file_filter.disable, &c_options->file_filter.disable);
2763 group = pref_group_new(vbox, FALSE, _("Grouping sidecar extensions"), GTK_ORIENTATION_VERTICAL);
2765 sidecar_ext_entry = gtk_entry_new();
2766 gtk_entry_set_text(GTK_ENTRY(sidecar_ext_entry), options->sidecar.ext);
2767 gtk_box_pack_start(GTK_BOX(group), sidecar_ext_entry, FALSE, FALSE, 0);
2768 gtk_widget_show(sidecar_ext_entry);
2770 group = pref_group_new(vbox, TRUE, _("File types"), GTK_ORIENTATION_VERTICAL);
2772 frame = pref_group_parent(group);
2773 g_signal_connect(G_OBJECT(ct_button), "toggled",
2774 G_CALLBACK(filter_disable_cb), frame);
2775 gtk_widget_set_sensitive(frame, !options->file_filter.disable);
2777 scrolled = gtk_scrolled_window_new(NULL, NULL);
2778 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2779 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2780 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2781 gtk_widget_show(scrolled);
2783 filter_store = gtk_list_store_new(1, G_TYPE_POINTER);
2784 filter_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(filter_store));
2785 g_object_unref(filter_store);
2786 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
2787 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
2789 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), FALSE);
2791 column = gtk_tree_view_column_new();
2792 gtk_tree_view_column_set_title(column, _("Enabled"));
2793 gtk_tree_view_column_set_resizable(column, TRUE);
2795 renderer = gtk_cell_renderer_toggle_new();
2796 g_signal_connect(G_OBJECT(renderer), "toggled",
2797 G_CALLBACK(filter_store_enable_cb), filter_store);
2798 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2799 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2800 GINT_TO_POINTER(FE_ENABLE), NULL);
2801 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);
2802 gtk_tree_view_column_set_sort_column_id(column, FILETYPES_COLUMN_ENABLED);
2803 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2805 column = gtk_tree_view_column_new();
2806 gtk_tree_view_column_set_title(column, _("Filter"));
2807 gtk_tree_view_column_set_resizable(column, TRUE);
2808 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);
2809 gtk_tree_view_column_set_sort_column_id(column, FILETYPES_COLUMN_FILTER);
2811 renderer = gtk_cell_renderer_text_new();
2812 g_signal_connect(G_OBJECT(renderer), "edited",
2813 G_CALLBACK(filter_store_ext_edit_cb), filter_store);
2814 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2815 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2816 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2817 GINT_TO_POINTER(FE_EXTENSION), NULL);
2818 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2820 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), TRUE);
2821 gtk_tree_view_set_search_column(GTK_TREE_VIEW(filter_view), FILETYPES_COLUMN_FILTER);
2822 gtk_tree_view_set_search_equal_func(GTK_TREE_VIEW(filter_view), search_function_cb, NULL, NULL);
2824 column = gtk_tree_view_column_new();
2825 gtk_tree_view_column_set_title(column, _("Description"));
2826 gtk_tree_view_column_set_resizable(column, TRUE);
2827 gtk_tree_view_column_set_fixed_width(column, 200);
2828 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
2830 renderer = gtk_cell_renderer_text_new();
2831 g_signal_connect(G_OBJECT(renderer), "edited",
2832 G_CALLBACK(filter_store_desc_edit_cb), filter_store);
2833 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2834 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2835 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2836 GINT_TO_POINTER(FE_DESCRIPTION), NULL);
2837 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2838 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);
2839 gtk_tree_view_column_set_sort_column_id(column, FILETYPES_COLUMN_DESCRIPTION);
2841 column = gtk_tree_view_column_new();
2842 gtk_tree_view_column_set_title(column, _("Class"));
2843 gtk_tree_view_column_set_resizable(column, TRUE);
2844 renderer = gtk_cell_renderer_combo_new();
2845 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE,
2846 "model", create_class_model(),
2851 g_signal_connect(G_OBJECT(renderer), "edited",
2852 G_CALLBACK(filter_store_class_edit_cb), filter_store);
2853 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2854 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2855 GINT_TO_POINTER(FE_CLASS), NULL);
2856 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2857 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);
2858 gtk_tree_view_column_set_sort_column_id(column, FILETYPES_COLUMN_CLASS);
2860 column = gtk_tree_view_column_new();
2861 gtk_tree_view_column_set_title(column, _("Writable"));
2862 gtk_tree_view_column_set_resizable(column, FALSE);
2863 renderer = gtk_cell_renderer_toggle_new();
2864 g_signal_connect(G_OBJECT(renderer), "toggled",
2865 G_CALLBACK(filter_store_writable_cb), filter_store);
2866 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2867 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2868 GINT_TO_POINTER(FE_WRITABLE), NULL);
2869 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2870 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);
2871 gtk_tree_view_column_set_sort_column_id(column, FILETYPES_COLUMN_WRITABLE);
2873 column = gtk_tree_view_column_new();
2874 gtk_tree_view_column_set_title(column, _("Sidecar is allowed"));
2875 gtk_tree_view_column_set_resizable(column, FALSE);
2876 renderer = gtk_cell_renderer_toggle_new();
2877 g_signal_connect(G_OBJECT(renderer), "toggled",
2878 G_CALLBACK(filter_store_sidecar_cb), filter_store);
2879 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2880 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2881 GINT_TO_POINTER(FE_ALLOW_SIDECAR), NULL);
2882 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2883 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);
2884 gtk_tree_view_column_set_sort_column_id(column, FILETYPES_COLUMN_SIDECAR);
2886 filter_store_populate();
2887 gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
2888 gtk_widget_show(filter_view);
2890 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2892 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2893 G_CALLBACK(filter_default_cb), filter_view);
2894 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2895 gtk_widget_show(button);
2897 button = pref_button_new(NULL, GTK_STOCK_REMOVE, NULL, FALSE,
2898 G_CALLBACK(filter_remove_cb), filter_view);
2899 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2900 gtk_widget_show(button);
2902 button = pref_button_new(NULL, GTK_STOCK_ADD, NULL, FALSE,
2903 G_CALLBACK(filter_add_cb), filter_view);
2904 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2905 gtk_widget_show(button);
2909 static void config_tab_metadata(GtkWidget *notebook)
2914 GtkWidget *ct_button;
2918 vbox = scrolled_notebook_page(notebook, _("Metadata"));
2921 group = pref_group_new(vbox, FALSE, _("Metadata writing process"), GTK_ORIENTATION_VERTICAL);
2923 label = pref_label_new(group, _("Warning: Geeqie is built without Exiv2. Some options are disabled."));
2925 label = pref_label_new(group, _("Metadata are written in the following order. The process ends after first success."));
2926 #if GTK_CHECK_VERSION(3,16,0)
2927 gtk_label_set_xalign(GTK_LABEL(label), 0.0);
2928 gtk_label_set_yalign(GTK_LABEL(label), 0.5);
2930 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2933 ct_button = pref_checkbox_new_int(group, _("1) Save metadata in image files, or sidecar files, according to the XMP standard"),
2934 options->metadata.save_in_image_file, &c_options->metadata.save_in_image_file);
2936 gtk_widget_set_sensitive(ct_button, FALSE);
2939 pref_checkbox_new_int(group, _("2) Save metadata in '.metadata' folder, local to image folder (non-standard)"),
2940 options->metadata.enable_metadata_dirs, &c_options->metadata.enable_metadata_dirs);
2942 text = g_strdup_printf(_("3) Save metadata in Geeqie private directory '%s'"), get_metadata_cache_dir());
2943 label = pref_label_new(group, text);
2944 #if GTK_CHECK_VERSION(3,16,0)
2945 gtk_label_set_xalign(GTK_LABEL(label), 0.0);
2946 gtk_label_set_yalign(GTK_LABEL(label), 0.5);
2948 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2950 gtk_misc_set_padding(GTK_MISC(label), 22, 0);
2953 group = pref_group_new(vbox, FALSE, _("Step 1: Write to image files"), GTK_ORIENTATION_VERTICAL);
2955 gtk_widget_set_sensitive(group, FALSE);
2958 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2959 pref_checkbox_link_sensitivity(ct_button, hbox);
2961 pref_checkbox_new_int(hbox, _("Store metadata also in legacy IPTC tags (converted according to IPTC4XMP standard)"),
2962 options->metadata.save_legacy_IPTC, &c_options->metadata.save_legacy_IPTC);
2964 pref_checkbox_new_int(hbox, _("Warn if the image files are unwritable"),
2965 options->metadata.warn_on_write_problems, &c_options->metadata.warn_on_write_problems);
2967 pref_checkbox_new_int(hbox, _("Ask before writing to image files"),
2968 options->metadata.confirm_write, &c_options->metadata.confirm_write);
2970 pref_checkbox_new_int(hbox, _("Create sidecar files named image.ext.xmp (as opposed to image.xmp)"),
2971 options->metadata.sidecar_extended_name, &c_options->metadata.sidecar_extended_name);
2973 group = pref_group_new(vbox, FALSE, _("Step 2 and 3: write to Geeqie private files"), GTK_ORIENTATION_VERTICAL);
2975 gtk_widget_set_sensitive(group, FALSE);
2978 pref_checkbox_new_int(group, _("Use GQview legacy metadata format (supports only keywords and comments) instead of XMP"),
2979 options->metadata.save_legacy_format, &c_options->metadata.save_legacy_format);
2982 group = pref_group_new(vbox, FALSE, _("Miscellaneous"), GTK_ORIENTATION_VERTICAL);
2983 pref_checkbox_new_int(group, _("Write the same description tags (keywords, comment, etc.) to all grouped sidecars"),
2984 options->metadata.sync_grouped_files, &c_options->metadata.sync_grouped_files);
2986 pref_checkbox_new_int(group, _("Allow keywords to differ only in case"),
2987 options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
2989 ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"),
2990 options->metadata.write_orientation, &c_options->metadata.write_orientation);
2992 gtk_widget_set_sensitive(ct_button, FALSE);
2995 group = pref_group_new(vbox, FALSE, _("Auto-save options"), GTK_ORIENTATION_VERTICAL);
2997 ct_button = pref_checkbox_new_int(group, _("Write metadata after timeout"),
2998 options->metadata.confirm_after_timeout, &c_options->metadata.confirm_after_timeout);
3000 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3001 pref_checkbox_link_sensitivity(ct_button, hbox);
3003 pref_spin_new_int(hbox, _("Timeout (seconds):"), NULL, 0, 900, 1,
3004 options->metadata.confirm_timeout, &c_options->metadata.confirm_timeout);
3006 pref_checkbox_new_int(group, _("Write metadata on image change"),
3007 options->metadata.confirm_on_image_change, &c_options->metadata.confirm_on_image_change);
3009 pref_checkbox_new_int(group, _("Write metadata on directory change"),
3010 options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
3013 #if GTK_CHECK_VERSION(3,20,0)
3014 group = pref_group_new(vbox, FALSE, _("Spelling checks"), GTK_ORIENTATION_VERTICAL);
3016 ct_button = pref_checkbox_new_int(group, _("Check spelling -Requires restart"), options->metadata.check_spelling, &c_options->metadata.check_spelling);
3020 group = pref_group_new(vbox, FALSE, _("Pre-load metadata"), GTK_ORIENTATION_VERTICAL);
3022 ct_button = pref_checkbox_new_int(group, _("Read metadata in background"),
3023 options->read_metadata_in_idle, &c_options->read_metadata_in_idle);
3024 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");
3029 typedef struct _KeywordFindData KeywordFindData;
3030 struct _KeywordFindData
3037 GtkWidget *button_close;
3038 GtkWidget *button_stop;
3039 GtkWidget *button_start;
3040 GtkWidget *progress;
3048 guint idle_id; /* event source id */
3051 #define KEYWORD_DIALOG_WIDTH 400
3053 static void keywords_find_folder(KeywordFindData *kfd, FileData *dir_fd)
3055 GList *list_d = NULL;
3056 GList *list_f = NULL;
3060 filelist_read(dir_fd, &list_f, &list_d);
3064 filelist_read(dir_fd, &list_f, NULL);
3067 list_f = filelist_filter(list_f, FALSE);
3068 list_d = filelist_filter(list_d, TRUE);
3070 kfd->list = g_list_concat(list_f, kfd->list);
3071 kfd->list_dir = g_list_concat(list_d, kfd->list_dir);
3074 static void keywords_find_reset(KeywordFindData *kfd)
3076 filelist_free(kfd->list);
3079 filelist_free(kfd->list_dir);
3080 kfd->list_dir = NULL;
3083 static void keywords_find_close_cb(GenericDialog *fd, gpointer data)
3085 KeywordFindData *kfd = data;
3087 if (!gtk_widget_get_sensitive(kfd->button_close)) return;
3089 keywords_find_reset(kfd);
3090 generic_dialog_close(kfd->gd);
3094 static void keywords_find_finish(KeywordFindData *kfd)
3096 keywords_find_reset(kfd);
3098 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("done"));
3099 spinner_set_interval(kfd->spinner, -1);
3101 gtk_widget_set_sensitive(kfd->group, TRUE);
3102 gtk_widget_set_sensitive(kfd->button_start, TRUE);
3103 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
3104 gtk_widget_set_sensitive(kfd->button_close, TRUE);
3107 static void keywords_find_stop_cb(GenericDialog *fd, gpointer data)
3109 KeywordFindData *kfd = data;
3111 g_idle_remove_by_data(kfd);
3113 keywords_find_finish(kfd);
3116 static gboolean keywords_find_file(gpointer data)
3118 KeywordFindData *kfd = data;
3120 GtkTextBuffer *buffer;
3128 fd = kfd->list->data;
3129 kfd->list = g_list_remove(kfd->list, fd);
3131 keywords = metadata_read_list(fd, KEYWORD_KEY, METADATA_PLAIN);
3132 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3136 gtk_text_buffer_get_end_iter(buffer, &iter);
3137 tmp = g_strconcat(keywords->data, "\n", NULL);
3138 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
3140 keywords = keywords->next;
3143 gtk_entry_set_text(GTK_ENTRY(kfd->progress), fd->path);
3144 file_data_unref(fd);
3145 string_list_free(keywords);
3149 else if (kfd->list_dir)
3153 fd = kfd->list_dir->data;
3154 kfd->list_dir = g_list_remove(kfd->list_dir, fd);
3156 keywords_find_folder(kfd, fd);
3158 file_data_unref(fd);
3163 keywords_find_finish(kfd);
3168 static void keywords_find_start_cb(GenericDialog *fd, gpointer data)
3170 KeywordFindData *kfd = data;
3173 if (kfd->list || !gtk_widget_get_sensitive(kfd->button_start)) return;
3175 path = remove_trailing_slash((gtk_entry_get_text(GTK_ENTRY(kfd->entry))));
3176 parse_out_relatives(path);
3180 warning_dialog(_("Invalid folder"),
3181 _("The specified folder can not be found."),
3182 GTK_STOCK_DIALOG_WARNING, kfd->gd->dialog);
3188 gtk_widget_set_sensitive(kfd->group, FALSE);
3189 gtk_widget_set_sensitive(kfd->button_start, FALSE);
3190 gtk_widget_set_sensitive(kfd->button_stop, TRUE);
3191 gtk_widget_set_sensitive(kfd->button_close, FALSE);
3192 spinner_set_interval(kfd->spinner, SPINNER_SPEED);
3194 dir_fd = file_data_new_dir(path);
3195 keywords_find_folder(kfd, dir_fd);
3196 file_data_unref(dir_fd);
3197 kfd->idle_id = g_idle_add(keywords_find_file, kfd);
3203 static void keywords_find_dialog(GtkWidget *widget, const gchar *path)
3205 KeywordFindData *kfd;
3209 kfd = g_new0(KeywordFindData, 1);
3211 kfd->gd = generic_dialog_new(_("Search for keywords"),
3212 "search_for_keywords",
3215 gtk_window_set_default_size(GTK_WINDOW(kfd->gd->dialog), KEYWORD_DIALOG_WIDTH, -1);
3216 kfd->gd->cancel_cb = keywords_find_close_cb;
3217 kfd->button_close = generic_dialog_add_button(kfd->gd, GTK_STOCK_CLOSE, NULL,
3218 keywords_find_close_cb, FALSE);
3219 kfd->button_start = generic_dialog_add_button(kfd->gd, GTK_STOCK_OK, _("S_tart"),
3220 keywords_find_start_cb, FALSE);
3221 kfd->button_stop = generic_dialog_add_button(kfd->gd, GTK_STOCK_STOP, NULL,
3222 keywords_find_stop_cb, FALSE);
3223 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
3225 generic_dialog_add_message(kfd->gd, NULL, _("Search for keywords"), NULL, FALSE);
3227 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0);
3228 pref_spacer(hbox, PREF_PAD_INDENT);
3229 kfd->group = pref_box_new(hbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
3231 hbox = pref_box_new(kfd->group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3232 pref_label_new(hbox, _("Folder:"));
3234 label = tab_completion_new(&kfd->entry, path, NULL, NULL, NULL, NULL);
3235 tab_completion_add_select_button(kfd->entry,_("Select folder") , TRUE);
3236 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
3237 gtk_widget_show(label);
3239 pref_checkbox_new_int(kfd->group, _("Include subfolders"), FALSE, &kfd->recurse);
3241 pref_line(kfd->gd->vbox, PREF_PAD_SPACE);
3242 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3244 kfd->progress = gtk_entry_new();
3245 gtk_widget_set_can_focus(kfd->progress, FALSE);
3246 gtk_editable_set_editable(GTK_EDITABLE(kfd->progress), FALSE);
3247 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("click start to begin"));
3248 gtk_box_pack_start(GTK_BOX(hbox), kfd->progress, TRUE, TRUE, 0);
3249 gtk_widget_show(kfd->progress);
3251 kfd->spinner = spinner_new(NULL, -1);
3252 gtk_box_pack_start(GTK_BOX(hbox), kfd->spinner, FALSE, FALSE, 0);
3253 gtk_widget_show(kfd->spinner);
3257 gtk_widget_show(kfd->gd->dialog);
3260 static void keywords_find_cb(GtkWidget *widget, gpointer data)
3262 const gchar *path = layout_get_path(NULL);
3264 if (!path || !*path) path = homedir();
3265 keywords_find_dialog(widget, path);
3268 static void config_tab_keywords_save()
3270 GtkTextIter start, end;
3271 GtkTextBuffer *buffer;
3272 GList *kw_list = NULL;
3278 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3279 gtk_text_buffer_get_bounds(buffer, &start, &end);
3281 buffer_text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
3283 kw_split = strtok(buffer_text, "\n");
3284 while (kw_split != NULL)
3290 if (g_strcmp0(work->data, kw_split) == 0)
3299 kw_list = g_list_append(kw_list, g_strdup(kw_split));
3301 kw_split = strtok(NULL, "\n");
3304 keyword_list_set(kw_list);
3306 string_list_free(kw_list);
3307 g_free(buffer_text);
3310 static void config_tab_keywords(GtkWidget *notebook)
3316 GtkWidget *scrolled;
3318 GtkTextBuffer *buffer;
3321 GspellTextView *gspell_view;
3324 vbox = scrolled_notebook_page(notebook, _("Keywords"));
3326 group = pref_group_new(vbox, TRUE, _("Edit keywords autocompletion list"), GTK_ORIENTATION_VERTICAL);
3328 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3330 button = pref_button_new(hbox, GTK_STOCK_EXECUTE, _("Search"), FALSE,
3331 G_CALLBACK(keywords_find_cb), keyword_text);
3332 gtk_widget_set_tooltip_text(button, "Search for existing keywords");
3335 keyword_text = gtk_text_view_new();
3336 gtk_widget_set_size_request(keyword_text, 20, 20);
3337 scrolled = gtk_scrolled_window_new(NULL, NULL);
3338 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3339 gtk_widget_show(scrolled);
3342 #if GTK_CHECK_VERSION(3,20,0)
3343 if (options->metadata.check_spelling)
3345 gspell_view = gspell_text_view_get_from_gtk_text_view(GTK_TEXT_VIEW(keyword_text));
3346 gspell_text_view_basic_setup(gspell_view);
3351 gtk_container_add(GTK_CONTAINER(scrolled), keyword_text);
3352 gtk_widget_show(keyword_text);
3354 gtk_text_view_set_editable(GTK_TEXT_VIEW(keyword_text), TRUE);
3356 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3357 gtk_text_buffer_create_tag(buffer, "monospace",
3358 "family", "monospace", NULL);
3360 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(keyword_text), GTK_WRAP_WORD);
3361 gtk_text_buffer_get_start_iter(buffer, &iter);
3362 gtk_text_buffer_create_mark(buffer, "end", &iter, FALSE);
3365 path = g_build_filename(get_rc_dir(), "keywords", NULL);
3367 GList *kwl = keyword_list_get();
3368 kwl = g_list_first(kwl);
3371 gtk_text_buffer_get_end_iter (buffer, &iter);
3372 tmp = g_strconcat(kwl->data, "\n", NULL);
3373 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
3378 gtk_text_buffer_set_modified(buffer, FALSE);
3385 static void intent_menu_cb(GtkWidget *combo, gpointer data)
3387 gint *option = data;
3389 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
3393 *option = INTENT_PERCEPTUAL;
3396 *option = INTENT_RELATIVE_COLORIMETRIC;
3399 *option = INTENT_SATURATION;
3402 *option = INTENT_ABSOLUTE_COLORIMETRIC;
3407 static void add_intent_menu(GtkWidget *table, gint column, gint row, const gchar *text,
3408 gint option, gint *option_c)
3415 pref_table_label(table, column, row, text, 0.0);
3417 combo = gtk_combo_box_text_new();
3419 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Perceptual"));
3420 if (option == INTENT_PERCEPTUAL) current = 0;
3421 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Relative Colorimetric"));
3422 if (option == INTENT_RELATIVE_COLORIMETRIC) current = 1;
3423 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Saturation"));
3424 if (option == INTENT_SATURATION) current = 2;
3425 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Absolute Colorimetric"));
3426 if (option == INTENT_ABSOLUTE_COLORIMETRIC) current = 3;
3428 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
3430 gtk_widget_set_tooltip_text(combo,"Refer to the lcms documentation for the defaults used when the selected Intent is not available");
3432 g_signal_connect(G_OBJECT(combo), "changed",
3433 G_CALLBACK(intent_menu_cb), option_c);
3435 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
3436 gtk_widget_show(combo);
3440 static void config_tab_color(GtkWidget *notebook)
3449 vbox = scrolled_notebook_page(notebook, _("Color management"));
3451 group = pref_group_new(vbox, FALSE, _("Input profiles"), GTK_ORIENTATION_VERTICAL);
3453 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3456 table = pref_table_new(group, 3, COLOR_PROFILE_INPUTS + 1, FALSE, FALSE);
3457 gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
3459 label = pref_table_label(table, 0, 0, _("Type"), 0.0);
3460 pref_label_bold(label, TRUE, FALSE);
3462 label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
3463 pref_label_bold(label, TRUE, FALSE);
3465 label = pref_table_label(table, 2, 0, _("File"), 0.0);
3466 pref_label_bold(label, TRUE, FALSE);
3468 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
3473 buf = g_strdup_printf(_("Input %d:"), i + COLOR_PROFILE_FILE);
3474 pref_table_label(table, 0, i + 1, buf, 1.0);
3477 entry = gtk_entry_new();
3478 gtk_entry_set_max_length(GTK_ENTRY(entry), EDITOR_NAME_MAX_LENGTH);
3479 if (options->color_profile.input_name[i])
3481 gtk_entry_set_text(GTK_ENTRY(entry), options->color_profile.input_name[i]);
3483 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, i + 1, i + 2,
3484 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3485 gtk_widget_show(entry);
3486 color_profile_input_name_entry[i] = entry;
3488 tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, ".icc", "ICC Files", NULL);
3489 tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
3490 gtk_widget_set_size_request(entry, 160, -1);
3491 gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
3492 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3493 gtk_widget_show(tabcomp);
3494 color_profile_input_file_entry[i] = entry;
3497 group = pref_group_new(vbox, FALSE, _("Screen profile"), GTK_ORIENTATION_VERTICAL);
3499 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3501 pref_checkbox_new_int(group, _("Use system screen profile if available"),
3502 options->color_profile.use_x11_screen_profile, &c_options->color_profile.use_x11_screen_profile);
3504 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3506 pref_table_label(table, 0, 0, _("Screen:"), 1.0);
3507 tabcomp = tab_completion_new(&color_profile_screen_file_entry,
3508 options->color_profile.screen_file, NULL, ".icc", "ICC Files", NULL);
3509 tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
3510 gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
3512 add_intent_menu(table, 0, 1, _("Render Intent:"), options->color_profile.render_intent, &c_options->color_profile.render_intent);
3514 gtk_table_attach(GTK_TABLE(table), tabcomp, 1, 2,
3516 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3518 gtk_widget_show(tabcomp);
3521 /* advanced entry tab */
3522 static void use_geeqie_trash_cb(GtkWidget *widget, gpointer data)
3524 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3526 c_options->file_ops.use_system_trash = FALSE;
3527 c_options->file_ops.no_trash = FALSE;
3531 static void use_system_trash_cb(GtkWidget *widget, gpointer data)
3533 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3535 c_options->file_ops.use_system_trash = TRUE;
3536 c_options->file_ops.no_trash = FALSE;
3540 static void use_no_cache_cb(GtkWidget *widget, gpointer data)
3542 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3544 c_options->file_ops.no_trash = TRUE;
3548 static void config_tab_behavior(GtkWidget *notebook)
3555 GtkWidget *ct_button;
3559 GtkWidget *with_rename;
3560 GtkWidget *collections_on_top;
3561 GtkWidget *hide_window_in_fullscreen;
3562 GtkWidget *checkbox;
3565 vbox = scrolled_notebook_page(notebook, _("Behavior"));
3567 group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
3569 pref_checkbox_new_int(group, _("Confirm permanent file delete"),
3570 options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
3571 pref_checkbox_new_int(group, _("Confirm move file to Trash"),
3572 options->file_ops.confirm_move_to_trash, &c_options->file_ops.confirm_move_to_trash);
3573 pref_checkbox_new_int(group, _("Enable Delete key"),
3574 options->file_ops.enable_delete_key, &c_options->file_ops.enable_delete_key);
3576 ct_button = pref_radiobutton_new(group, NULL, _("Use Geeqie trash location"),
3577 !options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_geeqie_trash_cb),NULL);
3579 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3580 pref_checkbox_link_sensitivity(ct_button, hbox);
3582 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
3583 pref_label_new(hbox, _("Folder:"));
3585 tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL, NULL, NULL);
3586 tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
3587 gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
3588 gtk_widget_show(tabcomp);
3590 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3591 pref_checkbox_link_sensitivity(ct_button, hbox);
3593 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
3594 spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MiB"),
3595 0, 2048, 1, options->file_ops.safe_delete_folder_maxsize, &c_options->file_ops.safe_delete_folder_maxsize);
3596 gtk_widget_set_tooltip_markup(spin, _("Set to 0 for unlimited size"));
3597 button = pref_button_new(NULL, NULL, _("View"), FALSE,
3598 G_CALLBACK(safe_delete_view_cb), NULL);
3599 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3600 gtk_widget_show(button);
3602 button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
3603 G_CALLBACK(safe_delete_clear_cb), NULL);
3604 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3606 c_options->file_ops.no_trash = options->file_ops.no_trash;
3607 c_options->file_ops.use_system_trash = options->file_ops.use_system_trash;
3609 pref_radiobutton_new(group, ct_button, _("Use system Trash bin"),
3610 options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_system_trash_cb), NULL);
3612 pref_radiobutton_new(group, ct_button, _("Use no trash at all"),
3613 options->file_ops.no_trash, G_CALLBACK(use_no_cache_cb), NULL);
3615 gtk_widget_show(button);
3617 pref_spacer(group, PREF_PAD_GROUP);
3620 group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
3622 pref_checkbox_new_int(group, _("Descend folders in tree view"),
3623 options->tree_descend_subdirs, &c_options->tree_descend_subdirs);
3625 pref_checkbox_new_int(group, _("In place renaming"),
3626 options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
3628 pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
3629 options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
3631 tmp = pref_checkbox_new_int(group, _("Circular selection lists"),
3632 options->circular_selection_lists, &c_options->circular_selection_lists);
3633 gtk_widget_set_tooltip_text(tmp, _("Traverse selection lists in a circular manner"));
3635 marks = pref_checkbox_new_int(group, _("Save marks on exit"),
3636 options->marks_save, &c_options->marks_save);
3637 gtk_widget_set_tooltip_text(marks,"Note that marks linked to a keyword will be saved irrespective of this setting");
3639 with_rename = pref_checkbox_new_int(group, _("Use \"With Rename\" as default for Copy/Move dialogs"),
3640 options->with_rename, &c_options->with_rename);
3641 gtk_widget_set_tooltip_text(with_rename,"Change the default button for Copy/Move dialogs");
3643 collections_on_top = pref_checkbox_new_int(group, _("Open collections on top"),
3644 options->collections_on_top, &c_options->collections_on_top);
3645 gtk_widget_set_tooltip_text(collections_on_top,"Open collections window on top");
3647 hide_window_in_fullscreen = pref_checkbox_new_int(group, _("Hide window in fullscreen"),
3648 options->hide_window_in_fullscreen, &c_options->hide_window_in_fullscreen);
3649 gtk_widget_set_tooltip_text(hide_window_in_fullscreen,"When alt-tabbing, prevent Geeqie window showing twice");
3651 pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
3652 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
3654 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);
3655 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."));
3657 pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
3658 16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
3660 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3661 add_dnd_default_action_selection_menu(table, 0, 0, _("Drag`n drop default action:"), options->dnd_default_action, &c_options->dnd_default_action);
3663 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3664 add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
3666 pref_spacer(group, PREF_PAD_GROUP);
3668 group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
3670 pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
3671 options->progressive_key_scrolling, &c_options->progressive_key_scrolling);
3672 pref_spin_new_int(group, _("Keyboard scrolling step multiplier:"), NULL,
3673 1, 32, 1, options->keyboard_scroll_step, (int *)&c_options->keyboard_scroll_step);
3674 pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
3675 options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
3676 pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
3677 options->image_lm_click_nav, &c_options->image_lm_click_nav);
3678 pref_checkbox_new_int(group, _("Open archive by left click on image"),
3679 options->image_l_click_archive, &c_options->image_l_click_archive);
3680 pref_checkbox_new_int(group, _("Play video by left click on image"),
3681 options->image_l_click_video, &c_options->image_l_click_video);
3682 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3683 add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
3685 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3686 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3687 add_mouse_selection_menu(table, 0, 0, _("Mouse button Back:"), options->mouse_button_8, &c_options->mouse_button_8);
3688 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3689 add_mouse_selection_menu(table, 0, 0, _("Mouse button Forward:"), options->mouse_button_9, &c_options->mouse_button_9);
3691 pref_spacer(group, PREF_PAD_GROUP);
3693 group = pref_group_new(vbox, FALSE, _("GPU"), GTK_ORIENTATION_VERTICAL);
3695 checkbox = pref_checkbox_new_int(group, _("Override disable GPU"),
3696 options->override_disable_gpu, &c_options->override_disable_gpu);
3697 gtk_widget_set_tooltip_text(checkbox, "Contact the developers for usage");
3700 pref_spacer(group, PREF_PAD_GROUP);
3702 group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
3704 pref_spin_new_int(group, _("Debug level:"), NULL,
3705 DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
3707 pref_checkbox_new_int(group, _("Timer data"),
3708 options->log_window.timer_data, &c_options->log_window.timer_data);
3710 pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
3711 1, 99999, 1, options->log_window_lines, &options->log_window_lines);
3715 /* accelerators tab */
3716 static void config_tab_accelerators(GtkWidget *notebook)
3722 GtkWidget *scrolled;
3723 GtkWidget *accel_view;
3724 GtkCellRenderer *renderer;
3725 GtkTreeSelection *selection;
3726 GtkTreeViewColumn *column;
3728 vbox = scrolled_notebook_page(notebook, _("Keyboard"));
3730 group = pref_group_new(vbox, TRUE, _("Accelerators"), GTK_ORIENTATION_VERTICAL);
3732 scrolled = gtk_scrolled_window_new(NULL, NULL);
3733 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
3734 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
3735 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3736 gtk_widget_show(scrolled);
3738 accel_store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
3740 accel_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(accel_store));
3741 g_object_unref(accel_store);
3742 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(accel_view));
3743 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
3745 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(accel_view), FALSE);
3747 renderer = gtk_cell_renderer_text_new();
3749 column = gtk_tree_view_column_new_with_attributes(_("Action"),
3754 gtk_tree_view_column_set_sort_column_id(column, AE_ACTION);
3755 gtk_tree_view_column_set_resizable(column, TRUE);
3756 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3759 renderer = gtk_cell_renderer_accel_new();
3760 g_signal_connect(G_OBJECT(renderer), "accel-cleared",
3761 G_CALLBACK(accel_store_cleared_cb), accel_store);
3762 g_signal_connect(G_OBJECT(renderer), "accel-edited",
3763 G_CALLBACK(accel_store_edited_cb), accel_store);
3766 g_object_set (renderer,
3768 "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
3771 column = gtk_tree_view_column_new_with_attributes(_("KEY"),
3776 gtk_tree_view_column_set_sort_column_id(column, AE_KEY);
3777 gtk_tree_view_column_set_resizable(column, TRUE);
3778 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3780 renderer = gtk_cell_renderer_text_new();
3782 column = gtk_tree_view_column_new_with_attributes(_("Tooltip"),
3787 gtk_tree_view_column_set_sort_column_id(column, AE_TOOLTIP);
3788 gtk_tree_view_column_set_resizable(column, TRUE);
3789 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3791 renderer = gtk_cell_renderer_text_new();
3793 column = gtk_tree_view_column_new_with_attributes("Accel",
3798 gtk_tree_view_column_set_sort_column_id(column, AE_ACCEL);
3799 gtk_tree_view_column_set_resizable(column, TRUE);
3800 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3802 accel_store_populate();
3803 gtk_container_add(GTK_CONTAINER(scrolled), accel_view);
3804 gtk_widget_show(accel_view);
3806 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3808 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
3809 G_CALLBACK(accel_default_cb), accel_view);
3810 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3811 gtk_widget_show(button);
3813 button = pref_button_new(NULL, NULL, _("Reset selected"), FALSE,
3814 G_CALLBACK(accel_reset_cb), accel_view);
3815 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3816 gtk_widget_show(button);
3819 /* toolbar main tab */
3820 static void config_tab_toolbar_main(GtkWidget *notebook)
3823 GtkWidget *toolbardata;
3826 lw = layout_window_list->data;
3828 vbox = scrolled_notebook_page(notebook, _("Toolbar Main"));
3830 toolbardata = toolbar_select_new(lw, TOOLBAR_MAIN);
3831 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3832 gtk_widget_show(vbox);
3835 /* toolbar status tab */
3836 static void config_tab_toolbar_status(GtkWidget *notebook)
3839 GtkWidget *toolbardata;
3842 lw = layout_window_list->data;
3844 vbox = scrolled_notebook_page(notebook, _("Toolbar Status"));
3846 toolbardata = toolbar_select_new(lw, TOOLBAR_STATUS);
3847 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3848 gtk_widget_show(vbox);
3852 static gint extension_sort_cb(gconstpointer a, gconstpointer b)
3854 return g_strcmp0((gchar *)a, (gchar *)b);
3857 static void config_tab_advanced(GtkWidget *notebook)
3861 GSList *formats_list;
3862 GList *extensions_list = NULL;
3865 GdkPixbufFormat *fm;
3867 GString *types_string = g_string_new(NULL);
3868 GtkWidget *types_string_label;
3869 GtkWidget *threads_string_label;
3870 GtkWidget *dupes_threads_spin;
3872 vbox = scrolled_notebook_page(notebook, _("Advanced"));
3873 group = pref_group_new(vbox, FALSE, _("External preview extraction"), GTK_ORIENTATION_VERTICAL);
3875 pref_checkbox_new_int(group, _("Use external preview extraction - Requires restart"), options->external_preview.enable, &c_options->external_preview.enable);
3877 pref_spacer(group, PREF_PAD_GROUP);
3879 formats_list = gdk_pixbuf_get_formats();
3881 while (formats_list)
3883 fm = formats_list->data;
3884 extensions = gdk_pixbuf_format_get_extensions(fm);
3887 while (extensions[i])
3889 extensions_list = g_list_insert_sorted(extensions_list, g_strdup(extensions[i]), extension_sort_cb);
3893 g_strfreev(extensions);
3894 formats_list = formats_list->next;
3897 while (extensions_list)
3899 if (types_string->len == 0)
3901 types_string = g_string_append(types_string, extensions_list->data);
3905 types_string = g_string_append(types_string, ", ");
3906 types_string = g_string_append(types_string, extensions_list->data);
3909 extensions_list = extensions_list->next;
3912 types_string = g_string_prepend(types_string, _("Usable file types:\n"));
3913 types_string_label = pref_label_new(group, types_string->str);
3914 gtk_label_set_line_wrap(GTK_LABEL(types_string_label), TRUE);
3916 pref_spacer(group, PREF_PAD_GROUP);
3918 group = pref_group_new(vbox, FALSE, _("File identification tool"), GTK_ORIENTATION_VERTICAL);
3919 external_preview_select_entry = gtk_entry_new();
3920 tabcomp = tab_completion_new(&external_preview_select_entry, options->external_preview.select, NULL, NULL, NULL, NULL);
3921 tab_completion_add_select_button(external_preview_select_entry, _("Select file identification tool"), FALSE);
3922 gtk_box_pack_start(GTK_BOX(group), tabcomp, TRUE, TRUE, 0);
3923 gtk_widget_show(tabcomp);
3925 group = pref_group_new(vbox, FALSE, _("Preview extraction tool"), GTK_ORIENTATION_VERTICAL);
3926 external_preview_extract_entry = gtk_entry_new();
3927 tabcomp = tab_completion_new(&external_preview_extract_entry, options->external_preview.extract, NULL, NULL, NULL, NULL);
3928 tab_completion_add_select_button(external_preview_extract_entry, _("Select preview extraction tool"), FALSE);
3929 gtk_box_pack_start(GTK_BOX(group), tabcomp, TRUE, TRUE, 0);
3930 gtk_widget_show(tabcomp);
3932 gtk_widget_show(vbox);
3934 g_slist_free(formats_list);
3935 string_list_free(extensions_list);
3936 g_string_free(types_string, TRUE);
3938 pref_spacer(group, PREF_PAD_GROUP);
3940 pref_line(vbox, PREF_PAD_SPACE);
3941 group = pref_group_new(vbox, FALSE, _("Thread pool limits"), GTK_ORIENTATION_VERTICAL);
3943 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.");
3944 gtk_label_set_line_wrap(GTK_LABEL(threads_string_label), TRUE);
3946 pref_spacer(vbox, PREF_PAD_GROUP);
3948 dupes_threads_spin = pref_spin_new_int(vbox, _("Duplicate check:"), _("max. threads"), 0, get_cpu_cores(), 1, options->threads.duplicates, &c_options->threads.duplicates);
3949 gtk_widget_set_tooltip_markup(dupes_threads_spin, _("Set to 0 for unlimited"));
3953 static void config_tab_stereo(GtkWidget *notebook)
3961 GtkWidget *fs_button;
3962 vbox = scrolled_notebook_page(notebook, _("Stereo"));
3964 group = pref_group_new(vbox, FALSE, _("Windowed stereo mode"), GTK_ORIENTATION_VERTICAL);
3966 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3967 add_stereo_mode_menu(table, 0, 0, _("Windowed stereo mode"), options->stereo.mode, &c_options->stereo.mode, FALSE);
3969 table = pref_table_new(group, 2, 2, TRUE, FALSE);
3970 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3971 pref_checkbox_new_int(box, _("Mirror left image"),
3972 options->stereo.mode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.mirror_left);
3973 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3974 pref_checkbox_new_int(box, _("Flip left image"),
3975 options->stereo.mode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.flip_left);
3976 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3977 pref_checkbox_new_int(box, _("Mirror right image"),
3978 options->stereo.mode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.mirror_right);
3979 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3980 pref_checkbox_new_int(box, _("Flip right image"),
3981 options->stereo.mode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.flip_right);
3982 pref_checkbox_new_int(group, _("Swap left and right images"),
3983 options->stereo.mode & PR_STEREO_SWAP, &c_options->stereo.tmp.swap);
3984 pref_checkbox_new_int(group, _("Disable stereo mode on single image source"),
3985 options->stereo.mode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.temp_disable);
3987 group = pref_group_new(vbox, FALSE, _("Fullscreen stereo mode"), GTK_ORIENTATION_VERTICAL);
3988 fs_button = pref_checkbox_new_int(group, _("Use different settings for fullscreen"),
3989 options->stereo.enable_fsmode, &c_options->stereo.enable_fsmode);
3990 box2 = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
3991 pref_checkbox_link_sensitivity(fs_button, box2);
3992 table = pref_table_new(box2, 2, 1, FALSE, FALSE);
3993 add_stereo_mode_menu(table, 0, 0, _("Fullscreen stereo mode"), options->stereo.fsmode, &c_options->stereo.fsmode, TRUE);
3994 table = pref_table_new(box2, 2, 2, TRUE, FALSE);
3995 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3996 pref_checkbox_new_int(box, _("Mirror left image"),
3997 options->stereo.fsmode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.fs_mirror_left);
3998 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3999 pref_checkbox_new_int(box, _("Flip left image"),
4000 options->stereo.fsmode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.fs_flip_left);
4001 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
4002 pref_checkbox_new_int(box, _("Mirror right image"),
4003 options->stereo.fsmode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.fs_mirror_right);
4004 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
4005 pref_checkbox_new_int(box, _("Flip right image"),
4006 options->stereo.fsmode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.fs_flip_right);
4007 pref_checkbox_new_int(box2, _("Swap left and right images"),
4008 options->stereo.fsmode & PR_STEREO_SWAP, &c_options->stereo.tmp.fs_swap);
4009 pref_checkbox_new_int(box2, _("Disable stereo mode on single image source"),
4010 options->stereo.fsmode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.fs_temp_disable);
4012 group2 = pref_group_new(box2, FALSE, _("Fixed position"), GTK_ORIENTATION_VERTICAL);
4013 table = pref_table_new(group2, 5, 3, FALSE, FALSE);
4014 pref_table_spin_new_int(table, 0, 0, _("Width"), NULL,
4015 1, 5000, 1, options->stereo.fixed_w, &c_options->stereo.fixed_w);
4016 pref_table_spin_new_int(table, 3, 0, _("Height"), NULL,
4017 1, 5000, 1, options->stereo.fixed_h, &c_options->stereo.fixed_h);
4018 pref_table_spin_new_int(table, 0, 1, _("Left X"), NULL,
4019 0, 5000, 1, options->stereo.fixed_x1, &c_options->stereo.fixed_x1);
4020 pref_table_spin_new_int(table, 3, 1, _("Left Y"), NULL,
4021 0, 5000, 1, options->stereo.fixed_y1, &c_options->stereo.fixed_y1);
4022 pref_table_spin_new_int(table, 0, 2, _("Right X"), NULL,
4023 0, 5000, 1, options->stereo.fixed_x2, &c_options->stereo.fixed_x2);
4024 pref_table_spin_new_int(table, 3, 2, _("Right Y"), NULL,
4025 0, 5000, 1, options->stereo.fixed_y2, &c_options->stereo.fixed_y2);
4029 /* Main preferences window */
4030 static void config_window_create(LayoutWindow *lw)
4032 GtkWidget *win_vbox;
4034 GtkWidget *notebook;
4036 GtkWidget *ct_button;
4038 if (!c_options) c_options = init_options(NULL);
4040 configwindow = window_new(GTK_WINDOW_TOPLEVEL, "preferences", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Preferences"));
4041 DEBUG_NAME(configwindow);
4042 gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
4043 g_signal_connect(G_OBJECT(configwindow), "delete_event",
4044 G_CALLBACK(config_window_delete), NULL);
4045 if (options->save_dialog_window_positions)
4047 gtk_window_resize(GTK_WINDOW(configwindow), lw->options.preferences_window.w, lw->options.preferences_window.h);
4048 gtk_window_move(GTK_WINDOW(configwindow), lw->options.preferences_window.x, lw->options.preferences_window.y);
4052 gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
4054 gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
4055 gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
4057 win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
4058 gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
4059 gtk_widget_show(win_vbox);
4061 notebook = gtk_notebook_new();
4062 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_LEFT);
4063 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE);
4064 gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
4066 config_tab_general(notebook);
4067 config_tab_image(notebook);
4068 config_tab_osd(notebook);
4069 config_tab_windows(notebook);
4070 config_tab_accelerators(notebook);
4071 config_tab_files(notebook);
4072 config_tab_metadata(notebook);
4073 config_tab_keywords(notebook);
4074 config_tab_color(notebook);
4075 config_tab_stereo(notebook);
4076 config_tab_behavior(notebook);
4077 config_tab_toolbar_main(notebook);
4078 config_tab_toolbar_status(notebook);
4079 config_tab_advanced(notebook);
4081 gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), lw->options.preferences_window.page_number);
4083 hbox = gtk_hbutton_box_new();
4084 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
4085 gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
4086 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
4087 gtk_widget_show(hbox);
4089 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
4090 G_CALLBACK(config_window_help_cb), notebook);
4091 gtk_container_add(GTK_CONTAINER(hbox), button);
4092 gtk_widget_set_can_default(button, TRUE);
4093 gtk_widget_show(button);
4095 button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
4096 G_CALLBACK(config_window_ok_cb), notebook);
4097 gtk_container_add(GTK_CONTAINER(hbox), button);
4098 gtk_widget_set_can_default(button, TRUE);
4099 gtk_widget_grab_default(button);
4100 gtk_widget_show(button);
4104 button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
4105 G_CALLBACK(config_window_close_cb), NULL);
4106 gtk_container_add(GTK_CONTAINER(hbox), button);
4107 gtk_widget_set_can_default(button, TRUE);
4108 gtk_widget_show(button);
4110 if (!generic_dialog_get_alternative_button_order(configwindow))
4112 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
4115 gtk_widget_show(notebook);
4117 gtk_widget_show(configwindow);
4121 *-----------------------------------------------------------------------------
4122 * config window show (public)
4123 *-----------------------------------------------------------------------------
4126 void show_config_window(LayoutWindow *lw)
4130 gtk_window_present(GTK_WINDOW(configwindow));
4134 config_window_create(lw);
4143 void show_about_window(LayoutWindow *lw)
4145 GdkPixbuf *pixbuf_logo;
4146 GdkPixbuf *pixbuf_icon;
4147 gchar *authors[1000];
4152 gchar *timezone_path;
4155 #define LINE_LENGTH 1000
4156 gchar line[LINE_LENGTH];
4158 copyright = g_string_new(NULL);
4159 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");
4161 timezone_path = g_build_filename(get_rc_dir(), TIMEZONE_DATABASE_FILE, NULL);
4162 if (g_file_test(timezone_path, G_FILE_TEST_EXISTS))
4164 cd = ZDOpenDatabase(timezone_path);
4167 copyright = g_string_append(copyright, ZDGetNotice(cd));
4171 log_printf("Error: Init of timezone database %s failed\n", timezone_path);
4173 ZDCloseDatabase(cd);
4175 g_free(timezone_path);
4178 path = g_build_filename(gq_helpdir, "AUTHORS", NULL);
4179 fp = fopen(path, "r");
4182 while(fgets(line, LINE_LENGTH, fp))
4184 /* get rid of ending \n from fgets */
4185 line[strlen(line) - 1] = '\0';
4186 authors[i_authors] = g_strdup(line);
4189 authors[i_authors] = NULL;
4194 comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
4195 "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
4197 pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
4198 pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
4199 gtk_show_about_dialog(GTK_WINDOW(lw->window),
4200 "title", _("About Geeqie"),
4202 "program-name", GQ_APPNAME,
4204 "logo", pixbuf_logo,
4205 "icon", pixbuf_icon,
4206 "website", GQ_WEBSITE,
4207 "website-label", "Website",
4208 "comments", comment,
4210 "translator-credits", _("translator-credits"),
4211 "wrap-license", TRUE,
4212 "license", copyright->str,
4215 g_string_free(copyright, TRUE);
4218 while(n < i_authors)
4228 static void image_overlay_set_text_colours()
4230 c_options->image_overlay.text_red = options->image_overlay.text_red;
4231 c_options->image_overlay.text_green = options->image_overlay.text_green;
4232 c_options->image_overlay.text_blue = options->image_overlay.text_blue;
4233 c_options->image_overlay.text_alpha = options->image_overlay.text_alpha;
4234 c_options->image_overlay.background_red = options->image_overlay.background_red;
4235 c_options->image_overlay.background_green = options->image_overlay.background_green;
4236 c_options->image_overlay.background_blue = options->image_overlay.background_blue;
4237 c_options->image_overlay.background_alpha = options->image_overlay.background_alpha;
4241 *-----------------------------------------------------------------------------
4242 * timezone database routines
4243 *-----------------------------------------------------------------------------
4246 static void timezone_async_ready_cb(GObject *source_object, GAsyncResult *res, gpointer data)
4248 GError *error = NULL;
4250 gchar *tmp_filename;
4251 gchar *timezone_bin;
4252 gchar *tmp_dir = NULL;
4255 if (!g_cancellable_is_cancelled(tz->cancellable))
4257 generic_dialog_close(tz->gd);
4261 if (g_file_copy_finish(G_FILE(source_object), res, &error))
4263 tmp_filename = g_file_get_path(tz->tmp_g_file);
4264 fd = file_data_new_simple(tmp_filename);
4265 tmp_dir = open_archive(fd);
4269 timezone_bin = g_build_filename(tmp_dir, TIMEZONE_DATABASE_VERSION, TIMEZONE_DATABASE_FILE, NULL);
4270 if (isfile(timezone_bin))
4272 move_file(timezone_bin, tz->timezone_database_user);
4276 warning_dialog(_("Warning: Cannot open timezone database file"), _("See the Log Window"), GTK_STOCK_DIALOG_WARNING, NULL);
4279 g_free(timezone_bin);
4280 g_free(tmp_dir); // The folder in /tmp is deleted in exit_program_final()
4284 warning_dialog(_("Warning: Cannot open timezone database file"), _("See the Log Window"), GTK_STOCK_DIALOG_WARNING, NULL);
4286 g_free(tmp_filename);
4287 file_data_unref(fd);
4291 file_util_warning_dialog(_("Error: Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
4294 g_file_delete(tz->tmp_g_file, NULL, &error);
4295 g_object_unref(tz->tmp_g_file);
4296 tz->tmp_g_file = NULL;
4297 g_object_unref(tz->cancellable);
4298 g_object_unref(tz->timezone_database_gq);
4301 static void timezone_progress_cb(goffset current_num_bytes, goffset total_num_bytes, gpointer data)
4305 if (!g_cancellable_is_cancelled(tz->cancellable))
4307 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(tz->progress), (gdouble)current_num_bytes / total_num_bytes);
4311 static void timezone_cancel_button_cb(GenericDialog *gd, gpointer data)
4315 g_cancellable_cancel(tz->cancellable);
4318 static void timezone_database_install_cb(GtkWidget *widget, gpointer data)
4321 GError *error = NULL;
4322 GFileIOStream *io_stream;
4329 tz->tmp_g_file = g_file_new_tmp("geeqie_timezone_XXXXXX", &io_stream, &error);
4333 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
4334 log_printf("Error: Download timezone database failed:\n%s", error->message);
4335 g_error_free(error);
4336 g_object_unref(tz->tmp_g_file);
4340 tz->timezone_database_gq = g_file_new_for_uri(TIMEZONE_DATABASE_WEB);
4342 tz->gd = generic_dialog_new(_("Timezone database"), "download_timezone_database", NULL, TRUE, timezone_cancel_button_cb, tz);
4344 generic_dialog_add_message(tz->gd, GTK_STOCK_DIALOG_INFO, _("Downloading timezone database"), NULL, FALSE);
4346 tz->progress = gtk_progress_bar_new();
4347 gtk_box_pack_start(GTK_BOX(tz->gd->vbox), tz->progress, FALSE, FALSE, 0);
4348 gtk_widget_show(tz->progress);
4350 gtk_widget_show(tz->gd->dialog);
4351 tz->cancellable = g_cancellable_new();
4352 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);
4354 gtk_button_set_label(GTK_BUTTON(widget), _("Update"));
4357 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */