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"
66 #define EDITOR_NAME_MAX_LENGTH 32
67 #define EDITOR_COMMAND_MAX_LENGTH 1024
69 static void image_overlay_set_text_colours();
71 GtkWidget *keyword_text;
72 static void config_tab_keywords_save();
74 typedef struct _ThumbSize ThumbSize;
81 static ThumbSize thumb_size_list[] =
116 FILETYPES_COLUMN_FILTER = 0,
117 FILETYPES_COLUMN_DESCRIPTION,
118 FILETYPES_COLUMN_CLASS,
119 FILETYPES_COLUMN_WRITABLE,
120 FILETYPES_COLUMN_SIDECAR,
121 FILETYPES_COLUMN_COUNT
124 gchar *format_class_list[] = {
135 /* config memory values */
136 static ConfOptions *c_options = NULL;
143 static GtkWidget *configwindow = NULL;
144 static GtkListStore *filter_store = NULL;
145 static GtkTreeStore *accel_store = NULL;
147 static GtkWidget *safe_delete_path_entry;
149 static GtkWidget *color_profile_input_file_entry[COLOR_PROFILE_INPUTS];
150 static GtkWidget *color_profile_input_name_entry[COLOR_PROFILE_INPUTS];
151 static GtkWidget *color_profile_screen_file_entry;
152 static GtkWidget *external_preview_select_entry;
153 static GtkWidget *external_preview_extract_entry;
155 static GtkWidget *sidecar_ext_entry;
156 static GtkWidget *help_search_engine_entry;
159 #define CONFIG_WINDOW_DEF_WIDTH 700
160 #define CONFIG_WINDOW_DEF_HEIGHT 600
163 *-----------------------------------------------------------------------------
164 * option widget callbacks (private)
165 *-----------------------------------------------------------------------------
168 static void zoom_increment_cb(GtkWidget *spin, gpointer data)
170 c_options->image.zoom_increment = (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) * 100.0 + 0.01);
173 static void slideshow_delay_hours_cb(GtkWidget *spin, gpointer data)
175 gint mins_secs_tenths, delay;
177 mins_secs_tenths = c_options->slideshow.delay %
178 (3600 * SLIDESHOW_SUBSECOND_PRECISION);
180 delay = (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
181 (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
184 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
185 SLIDESHOW_SUBSECOND_PRECISION;
188 static void slideshow_delay_minutes_cb(GtkWidget *spin, gpointer data)
190 gint hours, secs_tenths, delay;
192 hours = c_options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
193 secs_tenths = c_options->slideshow.delay % (60 * SLIDESHOW_SUBSECOND_PRECISION);
195 delay = hours * (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
196 (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
197 (60 * SLIDESHOW_SUBSECOND_PRECISION) + secs_tenths);
199 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
200 SLIDESHOW_SUBSECOND_PRECISION;
203 static void slideshow_delay_seconds_cb(GtkWidget *spin, gpointer data)
205 gint hours_mins, delay;
207 hours_mins = c_options->slideshow.delay / (60 * SLIDESHOW_SUBSECOND_PRECISION);
209 delay = (hours_mins * (60 * SLIDESHOW_SUBSECOND_PRECISION)) +
210 (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
211 (gdouble)(SLIDESHOW_SUBSECOND_PRECISION) + 0.01);
213 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
214 SLIDESHOW_SUBSECOND_PRECISION;
218 *-----------------------------------------------------------------------------
219 * sync program to config window routine (private)
220 *-----------------------------------------------------------------------------
223 void config_entry_to_option(GtkWidget *entry, gchar **option, gchar *(*func)(const gchar *))
229 buf = gtk_entry_get_text(GTK_ENTRY(entry));
230 if (buf && strlen(buf) > 0)
235 *option = g_strdup(buf);
240 static gboolean accel_apply_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
242 gchar *accel_path, *accel;
244 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, AE_KEY, &accel, -1);
246 if (accel_path && accel_path[0])
249 gtk_accelerator_parse(accel, &key.accel_key, &key.accel_mods);
250 gtk_accel_map_change_entry(accel_path, key.accel_key, key.accel_mods, TRUE);
260 static void config_window_apply(void)
262 gboolean refresh = FALSE;
267 config_entry_to_option(safe_delete_path_entry, &options->file_ops.safe_delete_path, remove_trailing_slash);
269 if (options->file_filter.show_hidden_files != c_options->file_filter.show_hidden_files) refresh = TRUE;
270 if (options->file_filter.show_parent_directory != c_options->file_filter.show_parent_directory) refresh = TRUE;
271 if (options->file_filter.show_dot_directory != c_options->file_filter.show_dot_directory) refresh = TRUE;
272 if (options->file_sort.case_sensitive != c_options->file_sort.case_sensitive) refresh = TRUE;
273 if (options->file_sort.natural != c_options->file_sort.natural) refresh = TRUE;
274 if (options->file_filter.disable_file_extension_checks != c_options->file_filter.disable_file_extension_checks) refresh = TRUE;
275 if (options->file_filter.disable != c_options->file_filter.disable) refresh = TRUE;
277 options->file_ops.confirm_delete = c_options->file_ops.confirm_delete;
278 options->file_ops.enable_delete_key = c_options->file_ops.enable_delete_key;
279 options->file_ops.confirm_move_to_trash = c_options->file_ops.confirm_move_to_trash;
280 options->file_ops.use_system_trash = c_options->file_ops.use_system_trash;
281 options->file_ops.no_trash = c_options->file_ops.no_trash;
282 options->file_ops.safe_delete_folder_maxsize = c_options->file_ops.safe_delete_folder_maxsize;
283 options->tools_restore_state = c_options->tools_restore_state;
284 options->save_window_positions = c_options->save_window_positions;
285 options->use_saved_window_positions_for_new_windows = c_options->use_saved_window_positions_for_new_windows;
286 options->save_window_workspace = c_options->save_window_workspace;
287 options->save_dialog_window_positions = c_options->save_dialog_window_positions;
288 options->show_window_ids = c_options->show_window_ids;
289 options->image.scroll_reset_method = c_options->image.scroll_reset_method;
290 options->image.zoom_2pass = c_options->image.zoom_2pass;
291 options->image.fit_window_to_image = c_options->image.fit_window_to_image;
292 options->image.limit_window_size = c_options->image.limit_window_size;
293 options->image.zoom_to_fit_allow_expand = c_options->image.zoom_to_fit_allow_expand;
294 options->image.max_window_size = c_options->image.max_window_size;
295 options->image.limit_autofit_size = c_options->image.limit_autofit_size;
296 options->image.max_autofit_size = c_options->image.max_autofit_size;
297 options->image.max_enlargement_size = c_options->image.max_enlargement_size;
298 options->image.use_clutter_renderer = c_options->image.use_clutter_renderer;
299 options->image.tile_size = c_options->image.tile_size;
300 options->progressive_key_scrolling = c_options->progressive_key_scrolling;
301 options->keyboard_scroll_step = c_options->keyboard_scroll_step;
303 if (options->thumbnails.max_width != c_options->thumbnails.max_width
304 || options->thumbnails.max_height != c_options->thumbnails.max_height
305 || options->thumbnails.quality != c_options->thumbnails.quality)
307 thumb_format_changed = TRUE;
309 options->thumbnails.max_width = c_options->thumbnails.max_width;
310 options->thumbnails.max_height = c_options->thumbnails.max_height;
311 options->thumbnails.quality = c_options->thumbnails.quality;
313 options->thumbnails.enable_caching = c_options->thumbnails.enable_caching;
314 options->thumbnails.cache_into_dirs = c_options->thumbnails.cache_into_dirs;
315 options->thumbnails.use_exif = c_options->thumbnails.use_exif;
316 options->thumbnails.use_color_management = c_options->thumbnails.use_color_management;
317 options->thumbnails.collection_preview = c_options->thumbnails.collection_preview;
318 options->thumbnails.use_ft_metadata = c_options->thumbnails.use_ft_metadata;
319 // options->thumbnails.use_ft_metadata_small = c_options->thumbnails.use_ft_metadata_small;
320 options->thumbnails.spec_standard = c_options->thumbnails.spec_standard;
321 options->metadata.enable_metadata_dirs = c_options->metadata.enable_metadata_dirs;
322 options->file_filter.show_hidden_files = c_options->file_filter.show_hidden_files;
323 options->file_filter.show_parent_directory = c_options->file_filter.show_parent_directory;
324 options->file_filter.show_dot_directory = c_options->file_filter.show_dot_directory;
325 options->file_filter.disable_file_extension_checks = c_options->file_filter.disable_file_extension_checks;
327 options->file_sort.case_sensitive = c_options->file_sort.case_sensitive;
328 options->file_sort.natural = c_options->file_sort.natural;
329 options->file_filter.disable = c_options->file_filter.disable;
331 config_entry_to_option(sidecar_ext_entry, &options->sidecar.ext, NULL);
332 sidecar_ext_parse(options->sidecar.ext);
334 options->slideshow.random = c_options->slideshow.random;
335 options->slideshow.repeat = c_options->slideshow.repeat;
336 options->slideshow.delay = c_options->slideshow.delay;
338 options->mousewheel_scrolls = c_options->mousewheel_scrolls;
339 options->image_lm_click_nav = c_options->image_lm_click_nav;
340 options->image_l_click_archive = c_options->image_l_click_archive;
341 options->image_l_click_video = c_options->image_l_click_video;
342 options->image_l_click_video_editor = c_options->image_l_click_video_editor;
344 options->file_ops.enable_in_place_rename = c_options->file_ops.enable_in_place_rename;
346 options->image.tile_cache_max = c_options->image.tile_cache_max;
347 options->image.image_cache_max = c_options->image.image_cache_max;
349 options->image.zoom_quality = c_options->image.zoom_quality;
351 options->image.zoom_increment = c_options->image.zoom_increment;
353 options->image.zoom_style = c_options->image.zoom_style;
355 options->image.enable_read_ahead = c_options->image.enable_read_ahead;
358 if (options->image.use_custom_border_color != c_options->image.use_custom_border_color
359 || options->image.use_custom_border_color_in_fullscreen != c_options->image.use_custom_border_color_in_fullscreen
360 || !gdk_color_equal(&options->image.border_color, &c_options->image.border_color))
362 options->image.use_custom_border_color_in_fullscreen = c_options->image.use_custom_border_color_in_fullscreen;
363 options->image.use_custom_border_color = c_options->image.use_custom_border_color;
364 options->image.border_color = c_options->image.border_color;
365 layout_colors_update();
366 view_window_colors_update();
369 options->image.alpha_color_1 = c_options->image.alpha_color_1;
370 options->image.alpha_color_2 = c_options->image.alpha_color_2;
372 options->fullscreen.screen = c_options->fullscreen.screen;
373 options->fullscreen.clean_flip = c_options->fullscreen.clean_flip;
374 options->fullscreen.disable_saver = c_options->fullscreen.disable_saver;
375 options->fullscreen.above = c_options->fullscreen.above;
376 if (c_options->image_overlay.template_string)
377 set_image_overlay_template_string(&options->image_overlay.template_string,
378 c_options->image_overlay.template_string);
379 if (c_options->image_overlay.font)
380 set_image_overlay_font_string(&options->image_overlay.font,
381 c_options->image_overlay.font);
382 options->image_overlay.text_red = c_options->image_overlay.text_red;
383 options->image_overlay.text_green = c_options->image_overlay.text_green;
384 options->image_overlay.text_blue = c_options->image_overlay.text_blue;
385 options->image_overlay.text_alpha = c_options->image_overlay.text_alpha;
386 options->image_overlay.background_red = c_options->image_overlay.background_red;
387 options->image_overlay.background_green = c_options->image_overlay.background_green;
388 options->image_overlay.background_blue = c_options->image_overlay.background_blue;
389 options->image_overlay.background_alpha = c_options->image_overlay.background_alpha;
390 options->update_on_time_change = c_options->update_on_time_change;
392 options->duplicates_similarity_threshold = c_options->duplicates_similarity_threshold;
393 options->rot_invariant_sim = c_options->rot_invariant_sim;
395 options->tree_descend_subdirs = c_options->tree_descend_subdirs;
397 options->view_dir_list_single_click_enter = c_options->view_dir_list_single_click_enter;
398 options->circular_selection_lists = c_options->circular_selection_lists;
400 options->open_recent_list_maxsize = c_options->open_recent_list_maxsize;
401 options->dnd_icon_size = c_options->dnd_icon_size;
402 options->clipboard_selection = c_options->clipboard_selection;
403 options->dnd_default_action = c_options->dnd_default_action;
405 options->metadata.save_in_image_file = c_options->metadata.save_in_image_file;
406 options->metadata.save_legacy_IPTC = c_options->metadata.save_legacy_IPTC;
407 options->metadata.warn_on_write_problems = c_options->metadata.warn_on_write_problems;
408 options->metadata.save_legacy_format = c_options->metadata.save_legacy_format;
409 options->metadata.sync_grouped_files = c_options->metadata.sync_grouped_files;
410 options->metadata.confirm_write = c_options->metadata.confirm_write;
411 options->metadata.sidecar_extended_name = c_options->metadata.sidecar_extended_name;
412 options->metadata.confirm_timeout = c_options->metadata.confirm_timeout;
413 options->metadata.confirm_after_timeout = c_options->metadata.confirm_after_timeout;
414 options->metadata.confirm_on_image_change = c_options->metadata.confirm_on_image_change;
415 options->metadata.confirm_on_dir_change = c_options->metadata.confirm_on_dir_change;
416 options->metadata.keywords_case_sensitive = c_options->metadata.keywords_case_sensitive;
417 options->metadata.write_orientation = c_options->metadata.write_orientation;
418 options->stereo.mode = (c_options->stereo.mode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
419 (c_options->stereo.tmp.mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
420 (c_options->stereo.tmp.flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
421 (c_options->stereo.tmp.mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
422 (c_options->stereo.tmp.flip_left ? PR_STEREO_FLIP_LEFT : 0) |
423 (c_options->stereo.tmp.swap ? PR_STEREO_SWAP : 0) |
424 (c_options->stereo.tmp.temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
425 options->stereo.fsmode = (c_options->stereo.fsmode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
426 (c_options->stereo.tmp.fs_mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
427 (c_options->stereo.tmp.fs_flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
428 (c_options->stereo.tmp.fs_mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
429 (c_options->stereo.tmp.fs_flip_left ? PR_STEREO_FLIP_LEFT : 0) |
430 (c_options->stereo.tmp.fs_swap ? PR_STEREO_SWAP : 0) |
431 (c_options->stereo.tmp.fs_temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
432 options->stereo.enable_fsmode = c_options->stereo.enable_fsmode;
433 options->stereo.fixed_w = c_options->stereo.fixed_w;
434 options->stereo.fixed_h = c_options->stereo.fixed_h;
435 options->stereo.fixed_x1 = c_options->stereo.fixed_x1;
436 options->stereo.fixed_y1 = c_options->stereo.fixed_y1;
437 options->stereo.fixed_x2 = c_options->stereo.fixed_x2;
438 options->stereo.fixed_y2 = c_options->stereo.fixed_y2;
440 options->info_keywords.height = c_options->info_keywords.height;
441 options->info_title.height = c_options->info_title.height;
442 options->info_comment.height = c_options->info_comment.height;
443 options->info_rating.height = c_options->info_rating.height;
445 options->show_predefined_keyword_tree = c_options->show_predefined_keyword_tree;
446 options->expand_menu_toolbar = c_options->expand_menu_toolbar;
448 options->marks_save = c_options->marks_save;
449 options->with_rename = c_options->with_rename;
450 options->collections_on_top = c_options->collections_on_top;
451 options->hide_window_in_fullscreen = c_options->hide_window_in_fullscreen;
452 config_entry_to_option(help_search_engine_entry, &options->help_search_engine, NULL);
454 options->external_preview.enable = c_options->external_preview.enable;
455 config_entry_to_option(external_preview_select_entry, &options->external_preview.select, NULL);
456 config_entry_to_option(external_preview_extract_entry, &options->external_preview.extract, NULL);
458 options->read_metadata_in_idle = c_options->read_metadata_in_idle;
460 options->star_rating.star = c_options->star_rating.star;
461 options->star_rating.rejected = c_options->star_rating.rejected;
463 options->threads.duplicates = c_options->threads.duplicates > 0 ? c_options->threads.duplicates : -1;
466 set_debug_level(debug_c);
470 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
472 config_entry_to_option(color_profile_input_name_entry[i], &options->color_profile.input_name[i], NULL);
473 config_entry_to_option(color_profile_input_file_entry[i], &options->color_profile.input_file[i], NULL);
475 config_entry_to_option(color_profile_screen_file_entry, &options->color_profile.screen_file, NULL);
476 options->color_profile.use_x11_screen_profile = c_options->color_profile.use_x11_screen_profile;
477 if (options->color_profile.render_intent != c_options->color_profile.render_intent)
479 options->color_profile.render_intent = c_options->color_profile.render_intent;
484 options->mouse_button_8 = c_options->mouse_button_8;
485 options->mouse_button_9 = c_options->mouse_button_9;
487 options->override_disable_gpu = c_options->override_disable_gpu;
489 config_tab_keywords_save();
491 image_options_sync();
496 layout_refresh(NULL);
499 if (accel_store) gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_apply_cb, NULL);
501 toolbar_apply(TOOLBAR_MAIN);
502 toolbar_apply(TOOLBAR_STATUS);
506 *-----------------------------------------------------------------------------
507 * config window main button callbacks (private)
508 *-----------------------------------------------------------------------------
511 static void config_window_close_cb(GtkWidget *widget, gpointer data)
513 gtk_widget_destroy(configwindow);
518 static void config_window_help_cb(GtkWidget *widget, gpointer data)
520 GtkWidget *notebook = data;
523 static gchar *html_section[] =
525 "GuideOptionsGeneral.html",
526 "GuideOptionsImage.html",
527 "GuideOptionsOSD.html",
528 "GuideOptionsWindow.html",
529 "GuideOptionsKeyboard.html",
530 "GuideOptionsFiltering.html",
531 "GuideOptionsMetadata.html",
532 "GuideOptionsKeywords.html",
533 "GuideOptionsColor.html",
534 "GuideOptionsStereo.html",
535 "GuideOptionsBehavior.html",
536 "GuideOptionsToolbar.html",
537 "GuideOptionsToolbar.html",
538 "GuideOptionsAdvanced.html"
541 i = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
542 help_window_show(html_section[i]);
545 static gboolean config_window_delete(GtkWidget *widget, GdkEventAny *event, gpointer data)
547 config_window_close_cb(NULL, NULL);
551 static void config_window_ok_cb(GtkWidget *widget, gpointer data)
554 GtkNotebook *notebook = data;
562 lw = layout_window_list->data;
564 window = gtk_widget_get_window(widget);
565 gdk_window_get_root_origin(window, &x, &y);
566 w = gdk_window_get_width(window);
567 h = gdk_window_get_height(window);
568 page_number = gtk_notebook_get_current_page(notebook);
570 lw->options.preferences_window.x = x;
571 lw->options.preferences_window.y = y;
572 lw->options.preferences_window.w = w;
573 lw->options.preferences_window.h = h;
574 lw->options.preferences_window.page_number = page_number;
576 config_window_apply();
577 layout_util_sync(lw);
578 save_options(options);
579 config_window_close_cb(NULL, NULL);
583 *-----------------------------------------------------------------------------
584 * config window setup (private)
585 *-----------------------------------------------------------------------------
588 static void quality_menu_cb(GtkWidget *combo, gpointer data)
592 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
596 *option = GDK_INTERP_NEAREST;
599 *option = GDK_INTERP_TILES;
602 *option = GDK_INTERP_BILINEAR;
607 static void dnd_default_action_selection_menu_cb(GtkWidget *combo, gpointer data)
611 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
615 *option = DND_ACTION_ASK;
618 *option = DND_ACTION_COPY;
621 *option = DND_ACTION_MOVE;
625 static void clipboard_selection_menu_cb(GtkWidget *combo, gpointer data)
629 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
632 *option = CLIPBOARD_PRIMARY;
635 *option = CLIPBOARD_CLIPBOARD;
638 *option = CLIPBOARD_BOTH;
641 *option = CLIPBOARD_BOTH;
645 static void add_quality_menu(GtkWidget *table, gint column, gint row, const gchar *text,
646 guint option, guint *option_c)
653 pref_table_label(table, column, row, text, 0.0);
655 combo = gtk_combo_box_text_new();
657 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Nearest (worst, but fastest)"));
658 if (option == GDK_INTERP_NEAREST) current = 0;
659 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Tiles"));
660 if (option == GDK_INTERP_TILES) current = 1;
661 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Bilinear (best, but slowest)"));
662 if (option == GDK_INTERP_BILINEAR) current = 2;
664 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
666 g_signal_connect(G_OBJECT(combo), "changed",
667 G_CALLBACK(quality_menu_cb), option_c);
669 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
670 gtk_widget_show(combo);
673 static void add_dnd_default_action_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text, DnDAction option, DnDAction *option_c)
680 pref_table_label(table, column, row, text, 0.0);
682 combo = gtk_combo_box_text_new();
684 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Ask"));
685 if (option == DND_ACTION_ASK) current = 0;
686 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Copy"));
687 if (option == DND_ACTION_COPY) current = 1;
688 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Move"));
689 if (option == DND_ACTION_MOVE) current = 2;
691 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
693 g_signal_connect(G_OBJECT(combo), "changed",
694 G_CALLBACK(dnd_default_action_selection_menu_cb), option_c);
696 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
697 gtk_widget_show(combo);
700 static void add_clipboard_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
701 gint option, gint *option_c)
708 pref_table_label(table, column, row, text, 0.0);
710 combo = gtk_combo_box_text_new();
712 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Primary"));
713 if (option == CLIPBOARD_PRIMARY) current = 0;
714 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Clipboard"));
715 if (option == CLIPBOARD_CLIPBOARD) current = 1;
716 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Both"));
717 if (option == CLIPBOARD_BOTH) current = 2;
719 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
721 g_signal_connect(G_OBJECT(combo), "changed",
722 G_CALLBACK(clipboard_selection_menu_cb), option_c);
724 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
725 gtk_widget_show(combo);
728 static void zoom_style_selection_menu_cb(GtkWidget *combo, gpointer data)
732 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
735 *option = ZOOM_GEOMETRIC;
738 *option = ZOOM_ARITHMETIC;
741 *option = ZOOM_GEOMETRIC;
745 static void add_zoom_style_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text, ZoomStyle option, ZoomStyle *option_c)
752 pref_table_label(table, column, row, text, 0.0);
754 combo = gtk_combo_box_text_new();
756 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Geometric"));
757 if (option == ZOOM_GEOMETRIC) current = 0;
758 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Arithmetic"));
759 if (option == ZOOM_ARITHMETIC) current = 1;
761 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
763 g_signal_connect(G_OBJECT(combo), "changed", G_CALLBACK(zoom_style_selection_menu_cb), option_c);
765 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
766 gtk_widget_show(combo);
769 typedef struct _UseableMouseItems UseableMouseItems;
770 struct _UseableMouseItems
772 gchar *name; /* GtkActionEntry terminology */
777 static const UseableMouseItems useable_mouse_items[] = {
779 {"FirstImage", N_("First Image"), GTK_STOCK_GOTO_TOP},
780 {"PrevImage", N_("Previous Image"), GTK_STOCK_GO_UP},
781 {"NextImage", N_("Next Image"), GTK_STOCK_GO_DOWN},
782 {"LastImage", N_("Last Image"), GTK_STOCK_GOTO_BOTTOM},
783 {"Back", N_("Back"), GTK_STOCK_GO_BACK},
784 {"Forward", N_("Forward"), GTK_STOCK_GO_FORWARD},
785 {"Home", N_("Home"), GTK_STOCK_HOME},
786 {"Up", N_("Up"), GTK_STOCK_GO_UP},
787 {"FirstPage", N_("First page"), GTK_STOCK_MEDIA_PREVIOUS},
788 {"LastPage", N_("Last Page"), GTK_STOCK_MEDIA_NEXT},
789 {"NextPage", N_("Next page"), GTK_STOCK_MEDIA_FORWARD},
790 {"PrevPage", N_("Previous Page"), GTK_STOCK_MEDIA_REWIND},
791 {"NewWindow", N_("New _window"), GTK_STOCK_NEW},
792 {"NewCollection", N_("New collection"), GTK_STOCK_INDEX},
793 {"OpenCollection", N_("Open collection"), GTK_STOCK_OPEN},
794 {"Search", N_("Search"), GTK_STOCK_FIND},
795 {"FindDupes", N_("Find duplicates"), GTK_STOCK_FIND},
796 {"NewFolder", N_("New folder"),GTK_STOCK_DIRECTORY},
797 {"Copy", N_("Copy"), GTK_STOCK_COPY},
798 {"Move", N_("Move"), PIXBUF_INLINE_ICON_MOVE},
799 {"Rename", N_("Rename"), PIXBUF_INLINE_ICON_RENAME},
800 {"Delete", N_("Delete"), GTK_STOCK_DELETE},
801 {"CloseWindow", N_("Close Window"), GTK_STOCK_CLOSE},
802 {"PanView", N_("Pan view"), PIXBUF_INLINE_ICON_PANORAMA},
803 {"SelectAll", N_("Select all"), PIXBUF_INLINE_ICON_SELECT_ALL},
804 {"SelectNone", N_("Select none"), PIXBUF_INLINE_ICON_SELECT_NONE},
805 {"SelectInvert", N_("Select invert"), PIXBUF_INLINE_ICON_SELECT_INVERT},
806 {"ShowFileFilter", N_("Show file filter"), PIXBUF_INLINE_ICON_FILE_FILTER},
807 {"RectangularSelection", N_("Select rectangle"), PIXBUF_INLINE_ICON_SELECT_RECTANGLE},
808 {"Print", N_("Print"), GTK_STOCK_PRINT},
809 {"Preferences", N_("Preferences"), GTK_STOCK_PREFERENCES},
810 {"LayoutConfig", N_("Configure this window"), GTK_STOCK_PREFERENCES},
811 {"Maintenance", N_("Cache maintenance"), PIXBUF_INLINE_ICON_MAINTENANCE},
812 {"RotateCW", N_("Rotate clockwise 90°"), PIXBUF_INLINE_ICON_CW},
813 {"RotateCCW", N_("Rotate counterclockwise 90°"), PIXBUF_INLINE_ICON_CCW},
814 {"Rotate180", N_("Rotate 180°"), PIXBUF_INLINE_ICON_180},
815 {"Mirror", N_("Mirror"), PIXBUF_INLINE_ICON_MIRROR},
816 {"Flip", N_("Flip"), PIXBUF_INLINE_ICON_FLIP},
817 {"AlterNone", N_("Original state"), PIXBUF_INLINE_ICON_ORIGINAL},
818 {"ZoomIn", N_("Zoom in"), GTK_STOCK_ZOOM_IN},
819 {"ZoomOut", N_("Zoom out"), GTK_STOCK_ZOOM_OUT},
820 {"Zoom100", N_("Zoom 1:1"), GTK_STOCK_ZOOM_100},
821 {"ZoomFit", N_("Zoom to fit"), GTK_STOCK_ZOOM_FIT},
822 {"ZoomFillHor", N_("Fit Horizontaly"), PIXBUF_INLINE_ICON_ZOOMFILLHOR},
823 {"ZoomFillVert", N_("Fit vertically"), PIXBUF_INLINE_ICON_ZOOMFILLVERT},
824 {"Zoom200", N_("Zoom 2:1"), GTK_STOCK_FILE},
825 {"Zoom300", N_("Zoom 3:1"), GTK_STOCK_FILE},
826 {"Zoom400", N_("Zoom 4:1"), GTK_STOCK_FILE},
827 {"Zoom50", N_("Zoom 1:2"), GTK_STOCK_FILE},
828 {"Zoom33", N_("Zoom1:3"), GTK_STOCK_FILE},
829 {"Zoom25", N_("Zoom 1:4"), GTK_STOCK_FILE},
830 {"ConnectZoomIn", N_("Connected Zoom in"), GTK_STOCK_ZOOM_IN},
831 {"SplitPaneSync", N_("Split Pane Sync"), PIXBUF_INLINE_SPLIT_PANE_SYNC},
832 {"Grayscale", N_("Grayscale"), PIXBUF_INLINE_ICON_GRAYSCALE},
833 {"OverUnderExposed", N_("Over Under Exposed"), PIXBUF_INLINE_ICON_EXPOSURE},
834 {"HideTools", N_("Hide file list"), PIXBUF_INLINE_ICON_HIDETOOLS},
835 {"SlideShowPause", N_("Pause slideshow"), GTK_STOCK_MEDIA_PAUSE},
836 {"SlideShowFaster", N_("Slideshow Faster"), GTK_STOCK_FILE},
837 {"SlideShowSlower", N_("Slideshow Slower"), GTK_STOCK_FILE},
838 {"Refresh", N_("Refresh"), GTK_STOCK_REFRESH},
839 {"HelpContents", N_("Help"), GTK_STOCK_HELP},
840 {"ExifWin", N_("Exif window"), PIXBUF_INLINE_ICON_EXIF},
841 {"Thumbnails", N_("Show thumbnails"), PIXBUF_INLINE_ICON_THUMB},
842 {"ShowMarks", N_("Show marks"), PIXBUF_INLINE_ICON_MARKS},
843 {"DrawRectangle", N_("Draw Rectangle"), PIXBUF_INLINE_ICON_DRAW_RECTANGLE},
844 {"FloatTools", N_("Float file list"), PIXBUF_INLINE_ICON_FLOAT},
845 {"SBar", N_("Info sidebar"), PIXBUF_INLINE_ICON_INFO},
846 {"SBarSort", N_("Sort manager"), PIXBUF_INLINE_ICON_SORT},
847 {"Quit", N_("Quit"), GTK_STOCK_QUIT},
851 static void mouse_buttons_selection_menu_cb(GtkWidget *combo, gpointer data)
853 gchar **option = data;
856 label = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(combo));
858 const UseableMouseItems *list = useable_mouse_items;
862 if (g_strcmp0(list->label, label) == 0)
870 *option = g_strdup(list->name);
874 static void add_mouse_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
875 gchar *option, gchar **option_c)
883 pref_table_label(table, column, row, text, 0.0);
885 combo = gtk_combo_box_text_new();
887 const UseableMouseItems *list = useable_mouse_items;
891 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), list->label);
892 if (g_strcmp0(list->name, option) == 0)
900 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
902 g_signal_connect(G_OBJECT(combo), "changed",
903 G_CALLBACK(mouse_buttons_selection_menu_cb), option_c);
905 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
906 gtk_widget_show(combo);
909 static void thumb_size_menu_cb(GtkWidget *combo, gpointer data)
913 n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
916 if ((guint) n < sizeof(thumb_size_list) / sizeof(ThumbSize))
918 c_options->thumbnails.max_width = thumb_size_list[n].w;
919 c_options->thumbnails.max_height = thumb_size_list[n].h;
923 c_options->thumbnails.max_width = options->thumbnails.max_width;
924 c_options->thumbnails.max_height = options->thumbnails.max_height;
928 static void add_thumb_size_menu(GtkWidget *table, gint column, gint row, gchar *text)
934 c_options->thumbnails.max_width = options->thumbnails.max_width;
935 c_options->thumbnails.max_height = options->thumbnails.max_height;
937 pref_table_label(table, column, row, text, 0.0);
939 combo = gtk_combo_box_text_new();
942 for (i = 0; (guint) i < sizeof(thumb_size_list) / sizeof(ThumbSize); i++)
947 w = thumb_size_list[i].w;
948 h = thumb_size_list[i].h;
950 buf = g_strdup_printf("%d x %d", w, h);
951 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
954 if (w == options->thumbnails.max_width && h == options->thumbnails.max_height) current = i;
961 buf = g_strdup_printf("%s %d x %d", _("Custom"), options->thumbnails.max_width, options->thumbnails.max_height);
962 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
968 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
969 g_signal_connect(G_OBJECT(combo), "changed",
970 G_CALLBACK(thumb_size_menu_cb), NULL);
972 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
973 gtk_widget_show(combo);
976 static void stereo_mode_menu_cb(GtkWidget *combo, gpointer data)
980 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
984 *option = PR_STEREO_NONE;
987 *option = PR_STEREO_ANAGLYPH_RC;
990 *option = PR_STEREO_ANAGLYPH_GM;
993 *option = PR_STEREO_ANAGLYPH_YB;
996 *option = PR_STEREO_ANAGLYPH_GRAY_RC;
999 *option = PR_STEREO_ANAGLYPH_GRAY_GM;
1002 *option = PR_STEREO_ANAGLYPH_GRAY_YB;
1005 *option = PR_STEREO_ANAGLYPH_DB_RC;
1008 *option = PR_STEREO_ANAGLYPH_DB_GM;
1011 *option = PR_STEREO_ANAGLYPH_DB_YB;
1014 *option = PR_STEREO_HORIZ;
1017 *option = PR_STEREO_HORIZ | PR_STEREO_HALF;
1020 *option = PR_STEREO_VERT;
1023 *option = PR_STEREO_VERT | PR_STEREO_HALF;
1026 *option = PR_STEREO_FIXED;
1031 static void add_stereo_mode_menu(GtkWidget *table, gint column, gint row, const gchar *text,
1032 gint option, gint *option_c, gboolean add_fixed)
1039 pref_table_label(table, column, row, text, 0.0);
1041 combo = gtk_combo_box_text_new();
1043 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Single image"));
1045 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Red-Cyan"));
1046 if (option & PR_STEREO_ANAGLYPH_RC) current = 1;
1047 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Green-Magenta"));
1048 if (option & PR_STEREO_ANAGLYPH_GM) current = 2;
1049 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Yellow-Blue"));
1050 if (option & PR_STEREO_ANAGLYPH_YB) current = 3;
1051 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Red-Cyan"));
1052 if (option & PR_STEREO_ANAGLYPH_GRAY_RC) current = 4;
1053 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Green-Magenta"));
1054 if (option & PR_STEREO_ANAGLYPH_GRAY_GM) current = 5;
1055 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Yellow-Blue"));
1056 if (option & PR_STEREO_ANAGLYPH_GRAY_YB) current = 6;
1057 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Red-Cyan"));
1058 if (option & PR_STEREO_ANAGLYPH_DB_RC) current = 7;
1059 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Green-Magenta"));
1060 if (option & PR_STEREO_ANAGLYPH_DB_GM) current = 8;
1061 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Yellow-Blue"));
1062 if (option & PR_STEREO_ANAGLYPH_DB_YB) current = 9;
1064 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side"));
1065 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side Half size"));
1066 if (option & PR_STEREO_HORIZ)
1069 if (option & PR_STEREO_HALF) current = 11;
1072 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom"));
1073 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom Half size"));
1074 if (option & PR_STEREO_VERT)
1077 if (option & PR_STEREO_HALF) current = 13;
1082 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Fixed position"));
1083 if (option & PR_STEREO_FIXED) current = 14;
1086 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
1088 g_signal_connect(G_OBJECT(combo), "changed",
1089 G_CALLBACK(stereo_mode_menu_cb), option_c);
1091 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
1092 gtk_widget_show(combo);
1095 static void video_menu_cb(GtkWidget *combo, gpointer data)
1097 gchar **option = data;
1099 EditorDescription *ed = g_list_nth_data(editor_list_get(), gtk_combo_box_get_active(GTK_COMBO_BOX(combo)));
1103 static void video_menu_populate(gpointer data, gpointer user_data)
1105 GtkWidget *combo = user_data;
1106 EditorDescription *ed = data;
1108 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), ed->name);
1111 static void add_video_menu(GtkWidget *table, gint column, gint row, const gchar *text,
1112 gchar *option, gchar **option_c)
1116 /* use lists since they are sorted */
1117 GList *eds = editor_list_get();
1121 pref_table_label(table, column, row, text, 0.0);
1123 combo = gtk_combo_box_text_new();
1124 g_list_foreach(eds,video_menu_populate,(gpointer)combo);
1125 current = option ? g_list_index(eds,g_hash_table_lookup(editors,option)): -1;
1127 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
1129 g_signal_connect(G_OBJECT(combo), "changed",
1130 G_CALLBACK(video_menu_cb), option_c);
1132 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
1133 gtk_widget_show(combo);
1136 static void filter_store_populate(void)
1140 if (!filter_store) return;
1142 gtk_list_store_clear(filter_store);
1144 work = filter_get_list();
1153 gtk_list_store_append(filter_store, &iter);
1154 gtk_list_store_set(filter_store, &iter, 0, fe, -1);
1158 static void filter_store_ext_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1159 gchar *new_text, gpointer data)
1161 GtkWidget *model = data;
1162 FilterEntry *fe = data;
1166 if (!new_text || strlen(new_text) < 1) return;
1168 tpath = gtk_tree_path_new_from_string(path_str);
1169 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1170 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1172 g_free(fe->extensions);
1173 fe->extensions = g_strdup(new_text);
1175 gtk_tree_path_free(tpath);
1179 static void filter_store_class_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1180 gchar *new_text, gpointer data)
1182 GtkWidget *model = data;
1183 FilterEntry *fe = data;
1188 if (!new_text || !new_text[0]) return;
1190 tpath = gtk_tree_path_new_from_string(path_str);
1191 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1192 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1194 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
1196 if (strcmp(new_text, _(format_class_list[i])) == 0)
1203 gtk_tree_path_free(tpath);
1207 static void filter_store_desc_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1208 gchar *new_text, gpointer data)
1210 GtkWidget *model = data;
1215 if (!new_text || !new_text[0]) return;
1217 tpath = gtk_tree_path_new_from_string(path_str);
1218 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1219 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1221 g_free(fe->description);
1222 fe->description = g_strdup(new_text);
1224 gtk_tree_path_free(tpath);
1227 static void filter_store_enable_cb(GtkCellRendererToggle *renderer,
1228 gchar *path_str, gpointer data)
1230 GtkWidget *model = data;
1235 tpath = gtk_tree_path_new_from_string(path_str);
1236 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1237 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1239 fe->enabled = !fe->enabled;
1241 gtk_tree_path_free(tpath);
1245 static void filter_store_writable_cb(GtkCellRendererToggle *renderer,
1246 gchar *path_str, gpointer data)
1248 GtkWidget *model = data;
1253 tpath = gtk_tree_path_new_from_string(path_str);
1254 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1255 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1257 fe->writable = !fe->writable;
1258 if (fe->writable) fe->allow_sidecar = FALSE;
1260 gtk_tree_path_free(tpath);
1264 static void filter_store_sidecar_cb(GtkCellRendererToggle *renderer,
1265 gchar *path_str, gpointer data)
1267 GtkWidget *model = data;
1272 tpath = gtk_tree_path_new_from_string(path_str);
1273 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1274 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1276 fe->allow_sidecar = !fe->allow_sidecar;
1277 if (fe->allow_sidecar) fe->writable = FALSE;
1279 gtk_tree_path_free(tpath);
1283 static void filter_set_func(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
1284 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
1288 gtk_tree_model_get(tree_model, iter, 0, &fe, -1);
1290 switch (GPOINTER_TO_INT(data))
1293 g_object_set(GTK_CELL_RENDERER(cell),
1294 "active", fe->enabled, NULL);
1297 g_object_set(GTK_CELL_RENDERER(cell),
1298 "text", fe->extensions, NULL);
1300 case FE_DESCRIPTION:
1301 g_object_set(GTK_CELL_RENDERER(cell),
1302 "text", fe->description, NULL);
1305 g_object_set(GTK_CELL_RENDERER(cell),
1306 "text", _(format_class_list[fe->file_class]), NULL);
1309 g_object_set(GTK_CELL_RENDERER(cell),
1310 "active", fe->writable, NULL);
1312 case FE_ALLOW_SIDECAR:
1313 g_object_set(GTK_CELL_RENDERER(cell),
1314 "active", fe->allow_sidecar, NULL);
1319 static gboolean filter_add_scroll(gpointer data)
1323 GtkCellRenderer *cell;
1324 GtkTreeViewColumn *column;
1327 rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(filter_store), NULL);
1328 path = gtk_tree_path_new_from_indices(rows-1, -1);
1330 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data), 0);
1332 list_cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column));
1333 cell = g_list_last(list_cells)->data;
1335 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1336 path, column, FALSE, 0.0, 0.0 );
1337 gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(data),
1338 path, column, cell, TRUE);
1340 gtk_tree_path_free(path);
1341 g_list_free(list_cells);
1346 static void filter_add_cb(GtkWidget *widget, gpointer data)
1348 filter_add_unique("description", ".new", FORMAT_CLASS_IMAGE, TRUE, FALSE, TRUE);
1349 filter_store_populate();
1351 g_idle_add((GSourceFunc)filter_add_scroll, data);
1354 static void filter_remove_cb(GtkWidget *widget, gpointer data)
1356 GtkWidget *filter_view = data;
1357 GtkTreeSelection *selection;
1361 if (!filter_store) return;
1362 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1363 if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) return;
1364 gtk_tree_model_get(GTK_TREE_MODEL(filter_store), &iter, 0, &fe, -1);
1367 filter_remove_entry(fe);
1369 filter_store_populate();
1372 static gboolean filter_default_ok_scroll(GtkTreeView *data)
1376 GtkTreeViewColumn *column;
1378 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(filter_store), &iter);
1379 path = gtk_tree_model_get_path(GTK_TREE_MODEL(filter_store), &iter);
1380 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1382 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1386 gtk_tree_path_free(path);
1391 static void filter_default_ok_cb(GenericDialog *gd, gpointer data)
1394 filter_add_defaults();
1396 filter_store_populate();
1398 g_idle_add((GSourceFunc)filter_default_ok_scroll, gd->data);
1401 static void dummy_cancel_cb(GenericDialog *gd, gpointer data)
1403 /* no op, only so cancel button appears */
1406 static void filter_default_cb(GtkWidget *widget, gpointer data)
1410 gd = generic_dialog_new(_("Reset filters"),
1411 "reset_filter", widget, TRUE,
1412 dummy_cancel_cb, data);
1413 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset filters"),
1414 _("This will reset the file filters to the defaults.\nContinue?"), TRUE);
1415 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, filter_default_ok_cb, TRUE);
1416 gtk_widget_show(gd->dialog);
1419 static void filter_disable_cb(GtkWidget *widget, gpointer data)
1421 GtkWidget *frame = data;
1423 gtk_widget_set_sensitive(frame,
1424 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
1427 static void safe_delete_view_cb(GtkWidget *widget, gpointer data)
1429 layout_set_path(NULL, gtk_entry_get_text(GTK_ENTRY(safe_delete_path_entry)));
1432 static void safe_delete_clear_ok_cb(GenericDialog *gd, gpointer data)
1434 file_util_trash_clear();
1437 static void safe_delete_clear_cb(GtkWidget *widget, gpointer data)
1441 gd = generic_dialog_new(_("Clear trash"),
1442 "clear_trash", widget, TRUE,
1443 dummy_cancel_cb, NULL);
1444 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear trash"),
1445 _("This will remove the trash contents."), FALSE);
1446 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, safe_delete_clear_ok_cb, TRUE);
1447 entry = gtk_entry_new();
1448 gtk_widget_set_can_focus(entry, FALSE);
1449 gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE);
1450 if (options->file_ops.safe_delete_path) gtk_entry_set_text(GTK_ENTRY(entry), options->file_ops.safe_delete_path);
1451 gtk_box_pack_start(GTK_BOX(gd->vbox), entry, FALSE, FALSE, 0);
1452 gtk_widget_show(entry);
1453 gtk_widget_show(gd->dialog);
1456 static void image_overlay_template_view_changed_cb(GtkWidget *widget, gpointer data)
1458 GtkWidget *pTextView;
1459 GtkTextBuffer *pTextBuffer;
1463 pTextView = GTK_WIDGET(data);
1465 pTextBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pTextView));
1466 gtk_text_buffer_get_start_iter(pTextBuffer, &iStart);
1467 gtk_text_buffer_get_end_iter(pTextBuffer, &iEnd);
1469 set_image_overlay_template_string(&c_options->image_overlay.template_string,
1470 gtk_text_buffer_get_text(pTextBuffer, &iStart, &iEnd, TRUE));
1473 static void image_overlay_default_template_ok_cb(GenericDialog *gd, gpointer data)
1475 GtkTextView *text_view = data;
1476 GtkTextBuffer *buffer;
1478 set_default_image_overlay_template_string(&options->image_overlay.template_string);
1479 if (!configwindow) return;
1481 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
1482 gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1485 static void image_overlay_default_template_cb(GtkWidget *widget, gpointer data)
1489 gd = generic_dialog_new(_("Reset image overlay template string"),
1490 "reset_image_overlay_template_string", widget, TRUE,
1491 dummy_cancel_cb, data);
1492 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset image overlay template string"),
1493 _("This will reset the image overlay template string to the default.\nContinue?"), TRUE);
1494 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, image_overlay_default_template_ok_cb, TRUE);
1495 gtk_widget_show(gd->dialog);
1498 static void image_overlay_help_cb(GtkWidget *widget, gpointer data)
1500 help_window_show("GuideOptionsOSD.html");
1503 static void image_overlay_set_font_cb(GtkWidget *widget, gpointer data)
1505 #if GTK_CHECK_VERSION(3,4,0)
1508 PangoFontDescription *font_desc;
1510 dialog = gtk_font_chooser_dialog_new("Image Overlay Font", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1511 gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), options->image_overlay.font);
1513 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1515 font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
1516 font = pango_font_description_to_string(font_desc);
1517 g_free(c_options->image_overlay.font);
1518 c_options->image_overlay.font = g_strdup(font);
1522 gtk_widget_destroy(dialog);
1526 font = gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget));
1527 c_options->image_overlay.font = g_strdup(font);
1531 static void image_overlay_set_text_colour_cb(GtkWidget *widget, gpointer data)
1534 #if GTK_CHECK_VERSION(3,4,0)
1537 dialog = gtk_color_chooser_dialog_new("Image Overlay Text Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1538 colour.red = options->image_overlay.text_red;
1539 colour.green = options->image_overlay.text_green;
1540 colour.blue = options->image_overlay.text_blue;
1541 colour.alpha = options->image_overlay.text_alpha;
1542 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1543 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1545 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1547 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1548 c_options->image_overlay.text_red = colour.red*255;
1549 c_options->image_overlay.text_green = colour.green*255;
1550 c_options->image_overlay.text_blue = colour.blue*255;
1551 c_options->image_overlay.text_alpha = colour.alpha*255;
1553 gtk_widget_destroy(dialog);
1556 GtkColorSelection *colorsel;
1558 dialog = gtk_color_selection_dialog_new("Image Overlay Text Colour");
1559 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1560 colour.red = options->image_overlay.text_red*257;
1561 colour.green = options->image_overlay.text_green*257;
1562 colour.blue = options->image_overlay.text_blue*257;
1563 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1564 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1565 gtk_color_selection_set_current_color(colorsel, &colour);
1566 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.text_alpha*257);
1568 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1570 gtk_color_selection_get_current_color(colorsel, &colour);
1571 c_options->image_overlay.text_red = colour.red/257;
1572 c_options->image_overlay.text_green = colour.green/257;
1573 c_options->image_overlay.text_blue = colour.blue/257;
1574 c_options->image_overlay.text_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1576 gtk_widget_destroy (dialog);
1581 static void image_overlay_set_background_colour_cb(GtkWidget *widget, gpointer data)
1584 #if GTK_CHECK_VERSION(3,4,0)
1587 dialog = gtk_color_chooser_dialog_new("Image Overlay Background Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1588 colour.red = options->image_overlay.background_red;
1589 colour.green = options->image_overlay.background_green;
1590 colour.blue = options->image_overlay.background_blue;
1591 colour.alpha = options->image_overlay.background_alpha;
1592 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1593 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1595 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1597 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1598 c_options->image_overlay.background_red = colour.red*255;
1599 c_options->image_overlay.background_green = colour.green*255;
1600 c_options->image_overlay.background_blue = colour.blue*255;
1601 c_options->image_overlay.background_alpha = colour.alpha*255;
1603 gtk_widget_destroy(dialog);
1606 GtkColorSelection *colorsel;
1608 dialog = gtk_color_selection_dialog_new("Image Overlay Background Colour");
1609 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1610 colour.red = options->image_overlay.background_red*257;
1611 colour.green = options->image_overlay.background_green*257;
1612 colour.blue = options->image_overlay.background_blue*257;
1613 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1614 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1615 gtk_color_selection_set_current_color(colorsel, &colour);
1616 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.background_alpha*257);
1618 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1620 gtk_color_selection_get_current_color(colorsel, &colour);
1621 c_options->image_overlay.background_red = colour.red/257;
1622 c_options->image_overlay.background_green = colour.green/257;
1623 c_options->image_overlay.background_blue = colour.blue/257;
1624 c_options->image_overlay.background_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1626 gtk_widget_destroy(dialog);
1630 static void accel_store_populate(void)
1633 GList *groups, *actions;
1635 const gchar *accel_path;
1639 if (!accel_store || !layout_window_list || !layout_window_list->data) return;
1641 gtk_tree_store_clear(accel_store);
1642 lw = layout_window_list->data; /* get the actions from the first window, it should not matter, they should be the same in all windows */
1644 g_assert(lw && lw->ui_manager);
1645 groups = gtk_ui_manager_get_action_groups(lw->ui_manager);
1648 actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
1651 action = GTK_ACTION(actions->data);
1652 accel_path = gtk_action_get_accel_path(action);
1653 if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
1655 gchar *label, *label2, *tooltip, *accel;
1656 g_object_get(action,
1657 "tooltip", &tooltip,
1661 if (pango_parse_markup(label, -1, '_', NULL, &label2, NULL, NULL) && label2)
1667 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1671 gtk_tree_store_append(accel_store, &iter, NULL);
1672 gtk_tree_store_set(accel_store, &iter,
1675 AE_TOOLTIP, tooltip ? tooltip : "",
1676 AE_ACCEL, accel_path,
1684 actions = actions->next;
1687 groups = groups->next;
1691 static void accel_store_cleared_cb(GtkCellRendererAccel *accel, gchar *path_string, gpointer user_data)
1696 static gboolean accel_remove_key_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1698 gchar *accel1 = data;
1703 gtk_tree_model_get(model, iter, AE_KEY, &accel2, -1);
1705 gtk_accelerator_parse(accel1, &key1.accel_key, &key1.accel_mods);
1706 gtk_accelerator_parse(accel2, &key2.accel_key, &key2.accel_mods);
1708 if (key1.accel_key == key2.accel_key && key1.accel_mods == key2.accel_mods)
1710 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1711 DEBUG_1("accelerator key '%s' is already used, removing.", accel1);
1720 static void accel_store_edited_cb(GtkCellRendererAccel *accel, gchar *path_string, guint accel_key, GdkModifierType accel_mods, guint hardware_keycode, gpointer user_data)
1722 GtkTreeModel *model = (GtkTreeModel *)accel_store;
1726 GtkAccelKey old_key, key;
1727 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
1729 gtk_tree_model_get_iter(model, &iter, path);
1730 gtk_tree_model_get(model, &iter, AE_ACCEL, &accel_path, -1);
1732 /* test if the accelerator can be stored without conflicts*/
1733 gtk_accel_map_lookup_entry(accel_path, &old_key);
1735 /* change the key and read it back (change may fail on keys hardcoded in gtk)*/
1736 gtk_accel_map_change_entry(accel_path, accel_key, accel_mods, TRUE);
1737 gtk_accel_map_lookup_entry(accel_path, &key);
1739 /* restore the original for now, the key will be really changed when the changes are confirmed */
1740 gtk_accel_map_change_entry(accel_path, old_key.accel_key, old_key.accel_mods, TRUE);
1742 acc = gtk_accelerator_name(key.accel_key, key.accel_mods);
1743 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, acc);
1745 gtk_tree_store_set(accel_store, &iter, AE_KEY, acc, -1);
1746 gtk_tree_path_free(path);
1750 static gboolean accel_default_scroll(GtkTreeView *data)
1754 GtkTreeViewColumn *column;
1756 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(accel_store), &iter);
1757 path = gtk_tree_model_get_path(GTK_TREE_MODEL(accel_store), &iter);
1758 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1760 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1764 gtk_tree_path_free(path);
1769 static void accel_default_cb(GtkWidget *widget, gpointer data)
1771 accel_store_populate();
1773 g_idle_add((GSourceFunc)accel_default_scroll, data);
1776 void accel_remove_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1778 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1781 void accel_reset_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1784 gchar *accel_path, *accel;
1786 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, -1);
1787 gtk_accel_map_lookup_entry(accel_path, &key);
1788 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1790 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, accel);
1792 gtk_tree_store_set(accel_store, iter, AE_KEY, accel, -1);
1797 static void accel_reset_cb(GtkWidget *widget, gpointer data)
1799 GtkTreeSelection *selection;
1801 if (!accel_store) return;
1802 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data));
1803 gtk_tree_selection_selected_foreach(selection, &accel_reset_selection, NULL);
1808 static GtkWidget *scrolled_notebook_page(GtkWidget *notebook, const gchar *title)
1812 GtkWidget *scrolled;
1813 GtkWidget *viewport;
1815 scrolled = gtk_scrolled_window_new(NULL, NULL);
1816 gtk_container_set_border_width(GTK_CONTAINER(scrolled), PREF_PAD_BORDER);
1817 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1818 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1819 label = gtk_label_new(title);
1820 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, label);
1821 gtk_widget_show(scrolled);
1823 viewport = gtk_viewport_new(NULL, NULL);
1824 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1825 gtk_container_add(GTK_CONTAINER(scrolled), viewport);
1826 gtk_widget_show(viewport);
1828 vbox = gtk_vbox_new(FALSE, 0);
1829 gtk_container_add(GTK_CONTAINER(viewport), vbox);
1830 gtk_widget_show(vbox);
1835 static void cache_standard_cb(GtkWidget *widget, gpointer data)
1837 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1839 c_options->thumbnails.spec_standard =TRUE;
1840 c_options->thumbnails.cache_into_dirs = FALSE;
1844 static void cache_geeqie_cb(GtkWidget *widget, gpointer data)
1846 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1848 c_options->thumbnails.spec_standard =FALSE;
1849 c_options->thumbnails.cache_into_dirs = FALSE;
1853 static void cache_local_cb(GtkWidget *widget, gpointer data)
1855 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1857 c_options->thumbnails.cache_into_dirs = TRUE;
1858 c_options->thumbnails.spec_standard =FALSE;
1862 static void help_search_engine_entry_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1863 GdkEvent *event, gpointer userdata)
1865 if (pos == GTK_ENTRY_ICON_PRIMARY)
1867 gtk_entry_set_text(GTK_ENTRY(userdata), HELP_SEARCH_ENGINE);
1871 gtk_entry_set_text(GTK_ENTRY(userdata), "");
1875 static void star_rating_star_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1876 GdkEvent *event, gpointer userdata)
1878 gchar *rating_symbol;
1880 if (pos == GTK_ENTRY_ICON_PRIMARY)
1882 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_STAR);
1883 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1884 g_free(rating_symbol);
1888 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1889 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1890 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1894 static void star_rating_rejected_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1895 GdkEvent *event, gpointer userdata)
1897 gchar *rating_symbol;
1899 if (pos == GTK_ENTRY_ICON_PRIMARY)
1901 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_REJECTED);
1902 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1903 g_free(rating_symbol);
1907 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1908 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1909 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1913 static guint star_rating_symbol_test(GtkWidget *widget, gpointer data)
1915 GtkContainer *hbox = data;
1916 GString *str = g_string_new(NULL);
1917 GtkEntry *hex_code_entry;
1918 gchar *hex_code_full;
1921 guint64 hex_value = 0;
1923 list = gtk_container_get_children(hbox);
1925 hex_code_entry = g_list_nth_data(list, 2);
1926 hex_code_full = g_strdup(gtk_entry_get_text(hex_code_entry));
1928 hex_code = g_strsplit(hex_code_full, "+", 2);
1929 if (hex_code[0] && hex_code[1])
1931 hex_value = strtoull(hex_code[1], NULL, 16);
1933 if (!hex_value || hex_value > 0x10FFFF)
1935 hex_value = 0x003F; // Unicode 'Question Mark'
1937 str = g_string_append_unichar(str, (gunichar)hex_value);
1938 gtk_label_set_text(g_list_nth_data(list, 1), str->str);
1940 g_strfreev(hex_code);
1941 g_string_free(str, TRUE);
1942 g_free(hex_code_full);
1947 static void star_rating_star_test_cb(GtkWidget *widget, gpointer data)
1949 guint64 star_symbol;
1951 star_symbol = star_rating_symbol_test(widget, data);
1952 c_options->star_rating.star = star_symbol;
1955 static void star_rating_rejected_test_cb(GtkWidget *widget, gpointer data)
1957 guint64 rejected_symbol;
1959 rejected_symbol = star_rating_symbol_test(widget, data);
1960 c_options->star_rating.rejected = rejected_symbol;
1963 /* general options tab */
1964 static void timezone_database_install_cb(GtkWidget *widget, gpointer data);
1965 typedef struct _TZData TZData;
1969 GCancellable *cancellable;
1971 GtkWidget *progress;
1973 GFile *timezone_database_gq;
1974 gchar *timezone_database_user;
1977 static void config_tab_general(GtkWidget *notebook)
1982 GtkWidget *group_frame;
1983 GtkWidget *subgroup;
1985 GtkWidget *ct_button;
1988 gint hours, minutes, remainder;
1990 GtkWidget *star_rating_entry;
1992 gchar *rating_symbol;
1995 gchar *download_locn;
1996 GNetworkMonitor *net_mon;
1997 GSocketConnectable *tz_org;
1998 gboolean internet_available = FALSE;
2001 vbox = scrolled_notebook_page(notebook, _("General"));
2003 group = pref_group_new(vbox, FALSE, _("Thumbnails"), GTK_ORIENTATION_VERTICAL);
2005 table = pref_table_new(group, 2, 2, FALSE, FALSE);
2006 add_thumb_size_menu(table, 0, 0, _("Size:"));
2007 add_quality_menu(table, 0, 1, _("Quality:"), options->thumbnails.quality, &c_options->thumbnails.quality);
2009 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2010 pref_label_new(hbox, _("Custom size: "));
2011 pref_spin_new_int(hbox, _("Width:"), NULL, 1, 512, 1, options->thumbnails.max_width, &c_options->thumbnails.max_width);
2012 pref_spin_new_int(hbox, _("Height:"), NULL, 1, 512, 1, options->thumbnails.max_height, &c_options->thumbnails.max_height);
2014 ct_button = pref_checkbox_new_int(group, _("Cache thumbnails and sim. files"),
2015 options->thumbnails.enable_caching, &c_options->thumbnails.enable_caching);
2017 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2018 pref_checkbox_link_sensitivity(ct_button, subgroup);
2020 c_options->thumbnails.spec_standard = options->thumbnails.spec_standard;
2021 c_options->thumbnails.cache_into_dirs = options->thumbnails.cache_into_dirs;
2022 group_frame = pref_frame_new(subgroup, TRUE, _("Use Geeqie thumbnail style and cache"),
2023 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2024 button = pref_radiobutton_new(group_frame, NULL, get_thumbnails_cache_dir(),
2025 !options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
2026 G_CALLBACK(cache_geeqie_cb), NULL);
2028 group_frame = pref_frame_new(subgroup, TRUE,
2029 _("Store thumbnails local to image folder (non-standard)"),
2030 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2031 pref_radiobutton_new(group_frame, button, "*/.thumbnails",
2032 !options->thumbnails.spec_standard && options->thumbnails.cache_into_dirs,
2033 G_CALLBACK(cache_local_cb), NULL);
2035 group_frame = pref_frame_new(subgroup, TRUE,
2036 _("Use standard thumbnail style and cache, shared with other applications"),
2037 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2038 pref_radiobutton_new(group_frame, button, get_thumbnails_standard_cache_dir(),
2039 options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
2040 G_CALLBACK(cache_standard_cb), NULL);
2042 pref_checkbox_new_int(group, _("Use EXIF thumbnails when available (EXIF thumbnails may be outdated)"),
2043 options->thumbnails.use_exif, &c_options->thumbnails.use_exif);
2045 pref_checkbox_new_int(group, _("Thumbnail color management"),
2046 options->thumbnails.use_color_management, &c_options->thumbnails.use_color_management);
2048 spin = pref_spin_new_int(group, _("Collection preview:"), NULL,
2050 options->thumbnails.collection_preview, &c_options->thumbnails.collection_preview);
2051 gtk_widget_set_tooltip_text(spin, _("The maximum number of thumbnails shown in a Collection preview montage"));
2053 #ifdef HAVE_FFMPEGTHUMBNAILER_METADATA
2054 pref_checkbox_new_int(group, _("Use embedded metadata in video files as thumbnails when available"),
2055 options->thumbnails.use_ft_metadata, &c_options->thumbnails.use_ft_metadata);
2057 // pref_checkbox_new_int(group, _("Ignore embedded metadata if size is too small"),
2058 // options->thumbnails.use_ft_metadata_small, &c_options->thumbnails.use_ft_metadata_small);
2061 pref_spacer(group, PREF_PAD_GROUP);
2063 group = pref_group_new(vbox, FALSE, _("Star Rating"), GTK_ORIENTATION_VERTICAL);
2065 c_options->star_rating.star = options->star_rating.star;
2066 c_options->star_rating.rejected = options->star_rating.rejected;
2068 str = g_string_new(NULL);
2069 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2070 pref_label_new(hbox, _("Star character: "));
2071 str = g_string_append_unichar(str, options->star_rating.star);
2072 pref_label_new(hbox, g_strdup(str->str));
2073 rating_symbol = g_strdup_printf("U+%X", options->star_rating.star);
2074 star_rating_entry = gtk_entry_new();
2075 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
2076 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
2077 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
2078 gtk_widget_show(star_rating_entry);
2079 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
2080 G_CALLBACK(star_rating_star_test_cb), hbox);
2081 gtk_widget_set_tooltip_text(button, _("Display selected character"));
2082 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2083 gtk_widget_show(button);
2084 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."));
2085 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2086 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2087 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2088 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2089 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2090 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2091 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2092 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2093 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
2094 G_CALLBACK(star_rating_star_icon_cb),
2097 g_string_free(str, TRUE);
2098 g_free(rating_symbol);
2100 str = g_string_new(NULL);
2101 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2102 pref_label_new(hbox, _("Rejected character: "));
2103 str = g_string_append_unichar(str, options->star_rating.rejected);
2104 pref_label_new(hbox, g_strdup(str->str));
2105 rating_symbol = g_strdup_printf("U+%X", options->star_rating.rejected);
2106 star_rating_entry = gtk_entry_new();
2107 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
2108 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
2109 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
2110 gtk_widget_show(star_rating_entry);
2111 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
2112 G_CALLBACK(star_rating_rejected_test_cb), hbox);
2113 gtk_widget_set_tooltip_text(button, _("Display selected character"));
2114 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2115 gtk_widget_show(button);
2116 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."));
2117 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2118 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2119 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2120 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2121 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2122 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2123 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2124 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2125 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
2126 G_CALLBACK(star_rating_rejected_icon_cb),
2129 g_string_free(str, TRUE);
2130 g_free(rating_symbol);
2132 pref_spacer(group, PREF_PAD_GROUP);
2134 group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
2136 c_options->slideshow.delay = options->slideshow.delay;
2137 hours = options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2138 remainder = options->slideshow.delay % (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2139 minutes = remainder / (60 * SLIDESHOW_SUBSECOND_PRECISION);
2140 seconds = (gdouble)(remainder % (60 * SLIDESHOW_SUBSECOND_PRECISION)) /
2141 SLIDESHOW_SUBSECOND_PRECISION;
2143 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2145 spin = pref_spin_new(hbox, _("Delay between image change hrs:mins:secs.dec"), NULL,
2147 options->slideshow.delay ? hours : 0.0,
2148 G_CALLBACK(slideshow_delay_hours_cb), NULL);
2149 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2150 spin = pref_spin_new(hbox, ":" , NULL,
2152 options->slideshow.delay ? minutes: 0.0,
2153 G_CALLBACK(slideshow_delay_minutes_cb), NULL);
2154 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2155 spin = pref_spin_new(hbox, ":", NULL,
2156 SLIDESHOW_MIN_SECONDS, 59, 1.0, 1,
2157 options->slideshow.delay ? seconds : 10.0,
2158 G_CALLBACK(slideshow_delay_seconds_cb), NULL);
2159 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2161 pref_checkbox_new_int(group, _("Random"), options->slideshow.random, &c_options->slideshow.random);
2162 pref_checkbox_new_int(group, _("Repeat"), options->slideshow.repeat, &c_options->slideshow.repeat);
2164 pref_spacer(group, PREF_PAD_GROUP);
2166 group = pref_group_new(vbox, FALSE, _("Image loading and caching"), GTK_ORIENTATION_VERTICAL);
2168 pref_spin_new_int(group, _("Decoded image cache size (MiB):"), NULL,
2169 0, 99999, 1, options->image.image_cache_max, &c_options->image.image_cache_max);
2170 pref_checkbox_new_int(group, _("Preload next image"),
2171 options->image.enable_read_ahead, &c_options->image.enable_read_ahead);
2173 pref_checkbox_new_int(group, _("Refresh on file change"),
2174 options->update_on_time_change, &c_options->update_on_time_change);
2177 pref_spacer(group, PREF_PAD_GROUP);
2179 group = pref_group_new(vbox, FALSE, _("Expand menu and toolbar"), GTK_ORIENTATION_VERTICAL);
2181 pref_checkbox_new_int(group, _("Expand menu and toolbar (NOTE! Geeqie must be restarted for change to take effect)"),
2182 options->expand_menu_toolbar, &c_options->expand_menu_toolbar);
2183 gtk_widget_set_tooltip_text(group, _("Expand the menu and toolbar to the full width of the window"));
2185 pref_spacer(group, PREF_PAD_GROUP);
2187 net_mon = g_network_monitor_get_default();
2188 tz_org = g_network_address_parse_uri(TIMEZONE_DATABASE_WEB, 80, NULL);
2191 internet_available = g_network_monitor_can_reach(net_mon, tz_org, NULL, NULL);
2192 g_object_unref(tz_org);
2195 group = pref_group_new(vbox, FALSE, _("Timezone database"), GTK_ORIENTATION_VERTICAL);
2196 hbox = pref_box_new(group, TRUE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2198 if (!internet_available)
2200 gtk_widget_set_sensitive(group, FALSE);
2203 tz = g_new0(TZData, 1);
2205 path = path_from_utf8(TIMEZONE_DATABASE_WEB);
2206 basename = g_path_get_basename(path);
2207 tz->timezone_database_user = g_build_filename(get_rc_dir(), TIMEZONE_DATABASE_FILE, NULL);
2211 if (isfile(tz->timezone_database_user))
2213 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Update"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2217 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Install"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2220 download_locn = g_strconcat(_("Download database from: "), TIMEZONE_DATABASE_WEB, NULL);
2221 pref_label_new(GTK_WIDGET(hbox), download_locn);
2222 g_free(download_locn);
2224 if (!internet_available)
2226 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"));
2230 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"));
2232 gtk_widget_show(button);
2234 pref_spacer(group, PREF_PAD_GROUP);
2236 group = pref_group_new(vbox, FALSE, _("On-line help search engine"), GTK_ORIENTATION_VERTICAL);
2238 help_search_engine_entry = gtk_entry_new();
2239 gtk_entry_set_text(GTK_ENTRY(help_search_engine_entry), options->help_search_engine);
2240 gtk_box_pack_start(GTK_BOX(group), help_search_engine_entry, FALSE, FALSE, 0);
2241 gtk_widget_show(help_search_engine_entry);
2243 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"));
2245 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2246 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2247 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2248 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2249 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2250 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2251 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2252 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2253 g_signal_connect(GTK_ENTRY(help_search_engine_entry), "icon-press",
2254 G_CALLBACK(help_search_engine_entry_icon_cb),
2255 help_search_engine_entry);
2259 static void config_tab_image(GtkWidget *notebook)
2264 GtkWidget *ct_button;
2265 GtkWidget *enlargement_button;
2268 GtkWidget *two_pass;
2270 GtkWidget *gpu_accel;
2273 vbox = scrolled_notebook_page(notebook, _("Image"));
2275 group = pref_group_new(vbox, FALSE, _("Zoom"), GTK_ORIENTATION_VERTICAL);
2277 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2278 add_quality_menu(table, 0, 0, _("Quality:"), options->image.zoom_quality, &c_options->image.zoom_quality);
2279 if (options->image.use_clutter_renderer && !options->disable_gpu)
2281 gtk_widget_set_sensitive(table, FALSE);
2285 gpu_accel = pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library (Requires restart)"),
2286 options->image.use_clutter_renderer, &c_options->image.use_clutter_renderer);
2287 if (options->disable_gpu && !options->override_disable_gpu)
2289 gtk_widget_set_sensitive(gpu_accel, FALSE);
2293 two_pass = pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"),
2294 options->image.zoom_2pass, &c_options->image.zoom_2pass);
2295 if (options->image.use_clutter_renderer && !options->disable_gpu)
2297 gtk_widget_set_sensitive(two_pass, FALSE);
2300 c_options->image.zoom_increment = options->image.zoom_increment;
2301 spin = pref_spin_new(group, _("Zoom increment:"), NULL,
2302 0.01, 4.0, 0.01, 2, (gdouble)options->image.zoom_increment / 100.0,
2303 G_CALLBACK(zoom_increment_cb), NULL);
2304 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2306 c_options->image.zoom_style = options->image.zoom_style;
2307 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2308 add_zoom_style_selection_menu(table, 0, 0, _("Zoom style:"), options->image.zoom_style, &c_options->image.zoom_style);
2310 group = pref_group_new(vbox, FALSE, _("Fit image to window"), GTK_ORIENTATION_VERTICAL);
2312 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2313 enlargement_button = pref_checkbox_new_int(hbox, _("Allow enlargement of image (max. size in %)"),
2314 options->image.zoom_to_fit_allow_expand, &c_options->image.zoom_to_fit_allow_expand);
2315 spin = pref_spin_new_int(hbox, NULL, NULL,
2317 options->image.max_enlargement_size, &c_options->image.max_enlargement_size);
2318 pref_checkbox_link_sensitivity(enlargement_button, spin);
2319 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."));
2321 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2322 ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (% of actual window):"),
2323 options->image.limit_autofit_size, &c_options->image.limit_autofit_size);
2324 spin = pref_spin_new_int(hbox, NULL, NULL,
2326 options->image.max_autofit_size, &c_options->image.max_autofit_size);
2327 pref_checkbox_link_sensitivity(ct_button, spin);
2328 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."));
2330 group = pref_group_new(vbox, FALSE, _("Tile size"), GTK_ORIENTATION_VERTICAL);
2331 gtk_widget_set_sensitive(group, !options->image.use_clutter_renderer);
2333 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2334 spin = pref_spin_new_int(hbox, _("Pixels"), _("(Requires restart)"),
2336 options->image.tile_size, &c_options->image.tile_size);
2337 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."));
2339 group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
2341 pref_checkbox_new_int(group, _("Use custom border color in window mode"),
2342 options->image.use_custom_border_color, &c_options->image.use_custom_border_color);
2344 pref_checkbox_new_int(group, _("Use custom border color in fullscreen mode"),
2345 options->image.use_custom_border_color_in_fullscreen, &c_options->image.use_custom_border_color_in_fullscreen);
2347 pref_color_button_new(group, _("Border color"), &options->image.border_color,
2348 G_CALLBACK(pref_color_button_set_cb), &c_options->image.border_color);
2350 c_options->image.border_color = options->image.border_color;
2352 pref_color_button_new(group, _("Alpha channel color 1"), &options->image.alpha_color_1,
2353 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_1);
2355 pref_color_button_new(group, _("Alpha channel color 2"), &options->image.alpha_color_2,
2356 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_2);
2358 c_options->image.alpha_color_1 = options->image.alpha_color_1;
2359 c_options->image.alpha_color_2 = options->image.alpha_color_2;
2364 static void save_default_window_layout_cb(GtkWidget *widget, gpointer data)
2366 LayoutWindow *lw = NULL;
2367 gchar *default_path;
2370 /* Get current lw */
2373 tmp_id = lw->options.id;
2374 lw->options.id = g_strdup("lw_default");
2376 default_path = g_build_filename(get_rc_dir(), DEFAULT_WINDOW_LAYOUT, NULL);
2377 save_default_layout_options_to_file(default_path, options, lw);
2378 g_free(lw->options.id);
2379 lw->options.id = tmp_id;
2380 g_free(default_path);
2383 #if GTK_CHECK_VERSION(3,22,0)
2384 static gboolean popover_cb(gpointer data)
2386 GtkPopover *popover = data;
2388 gtk_popover_popdown(popover);
2393 static void default_layout_changed_cb(GtkWidget *button, GtkPopover *popover)
2395 gtk_popover_popup(popover);
2397 g_timeout_add(2000, popover_cb, popover);
2400 static GtkWidget *create_popover(GtkWidget *parent, GtkWidget *child, GtkPositionType pos)
2404 popover = gtk_popover_new(parent);
2405 gtk_popover_set_position(GTK_POPOVER (popover), pos);
2406 gtk_container_add (GTK_CONTAINER(popover), child);
2407 gtk_container_set_border_width(GTK_CONTAINER (popover), 6);
2408 gtk_widget_show (child);
2414 static void config_tab_windows(GtkWidget *notebook)
2419 GtkWidget *subgroup;
2421 GtkWidget *ct_button;
2424 vbox = scrolled_notebook_page(notebook, _("Windows"));
2426 group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
2428 ct_button = pref_checkbox_new_int(group, _("Remember session"),
2429 options->save_window_positions, &c_options->save_window_positions);
2431 button = pref_checkbox_new_int(group, _("Use saved window positions also for new windows"),
2432 options->use_saved_window_positions_for_new_windows, &c_options->use_saved_window_positions_for_new_windows);
2433 pref_checkbox_link_sensitivity(ct_button, button);
2435 button = pref_checkbox_new_int(group, _("Remember window workspace"),
2436 options->save_window_workspace, &c_options->save_window_workspace);
2437 pref_checkbox_link_sensitivity(ct_button, button);
2439 pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
2440 options->tools_restore_state, &c_options->tools_restore_state);
2442 pref_checkbox_new_int(group, _("Remember dialog window positions"),
2443 options->save_dialog_window_positions, &c_options->save_dialog_window_positions);
2445 pref_checkbox_new_int(group, _("Show window IDs"),
2446 options->show_window_ids, &c_options->show_window_ids);
2448 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2449 pref_label_new(subgroup, _("Use current layout for default: "));
2450 button = pref_button_new(subgroup, NULL, _("Set"), FALSE, G_CALLBACK(save_default_window_layout_cb), NULL);
2452 #if GTK_CHECK_VERSION(3,22,0)
2455 popover = create_popover(button, gtk_label_new(_("Current window layout\nhas been set as default")), GTK_POS_TOP);
2456 gtk_popover_set_modal(GTK_POPOVER (popover), FALSE);
2457 g_signal_connect(button, "clicked", G_CALLBACK(default_layout_changed_cb), popover);
2460 group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
2462 pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
2463 options->image.fit_window_to_image, &c_options->image.fit_window_to_image);
2465 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2466 ct_button = pref_checkbox_new_int(hbox, _("Limit size when auto-sizing window (%):"),
2467 options->image.limit_window_size, &c_options->image.limit_window_size);
2468 spin = pref_spin_new_int(hbox, NULL, NULL,
2470 options->image.max_window_size, &c_options->image.max_window_size);
2471 pref_checkbox_link_sensitivity(ct_button, spin);
2473 group = pref_group_new(vbox, FALSE, _("Full screen"), GTK_ORIENTATION_VERTICAL);
2475 c_options->fullscreen.screen = options->fullscreen.screen;
2476 c_options->fullscreen.above = options->fullscreen.above;
2477 hbox = fullscreen_prefs_selection_new(_("Location:"), &c_options->fullscreen.screen, &c_options->fullscreen.above);
2478 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2479 gtk_widget_show(hbox);
2481 pref_checkbox_new_int(group, _("Smooth image flip"),
2482 options->fullscreen.clean_flip, &c_options->fullscreen.clean_flip);
2483 pref_checkbox_new_int(group, _("Disable screen saver"),
2484 options->fullscreen.disable_saver, &c_options->fullscreen.disable_saver);
2487 #define PRE_FORMATTED_COLUMNS 5
2488 static void config_tab_osd(GtkWidget *notebook)
2494 GtkWidget *image_overlay_template_view;
2495 GtkWidget *scrolled;
2496 GtkWidget *scrolled_pre_formatted;
2497 GtkTextBuffer *buffer;
2499 GtkWidget *subgroup;
2501 vbox = scrolled_notebook_page(notebook, _("OSD"));
2503 image_overlay_template_view = gtk_text_view_new();
2505 group = pref_group_new(vbox, FALSE, _("Overlay Screen Display"), GTK_ORIENTATION_VERTICAL);
2507 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2509 scrolled_pre_formatted = osd_new(PRE_FORMATTED_COLUMNS, image_overlay_template_view);
2510 gtk_widget_set_size_request(scrolled_pre_formatted, 200, 150);
2511 gtk_box_pack_start(GTK_BOX(subgroup), scrolled_pre_formatted, FALSE, FALSE, 0);
2512 gtk_widget_show(scrolled_pre_formatted);
2513 gtk_widget_show(subgroup);
2515 pref_line(group, PREF_PAD_GAP);
2517 pref_label_new(group, _("Image overlay template"));
2519 scrolled = gtk_scrolled_window_new(NULL, NULL);
2520 gtk_widget_set_size_request(scrolled, 200, 150);
2521 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2522 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
2523 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2524 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 5);
2525 gtk_widget_show(scrolled);
2527 gtk_widget_set_tooltip_markup(image_overlay_template_view,
2528 _("Extensive formatting options are shown in the Help file"));
2530 gtk_container_add(GTK_CONTAINER(scrolled), image_overlay_template_view);
2531 gtk_widget_show(image_overlay_template_view);
2533 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2535 #if GTK_CHECK_VERSION(3,4,0)
2536 button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
2537 G_CALLBACK(image_overlay_set_font_cb), notebook);
2539 button = gtk_font_button_new();
2540 gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Image Overlay Font");
2541 gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->image_overlay.font);
2542 g_signal_connect(G_OBJECT(button), "font-set",
2543 G_CALLBACK(image_overlay_set_font_cb),NULL);
2545 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2546 gtk_widget_show(button);
2548 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Text"), FALSE,
2549 G_CALLBACK(image_overlay_set_text_colour_cb), NULL);
2550 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2551 gtk_widget_show(button);
2553 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Background"), FALSE,
2554 G_CALLBACK(image_overlay_set_background_colour_cb), NULL);
2555 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2556 gtk_widget_show(button);
2557 image_overlay_set_text_colours();
2559 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2560 G_CALLBACK(image_overlay_default_template_cb), image_overlay_template_view);
2561 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2562 gtk_widget_show(button);
2564 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
2565 G_CALLBACK(image_overlay_help_cb), NULL);
2566 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2567 gtk_widget_show(button);
2569 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_overlay_template_view));
2570 if (options->image_overlay.template_string) gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
2571 g_signal_connect(G_OBJECT(buffer), "changed",
2572 G_CALLBACK(image_overlay_template_view_changed_cb), image_overlay_template_view);
2574 pref_line(group, PREF_PAD_GAP);
2576 group = pref_group_new(vbox, FALSE, _("Exif, XMP or IPTC tags"), GTK_ORIENTATION_VERTICAL);
2577 hbox = gtk_hbox_new(FALSE, 0);
2578 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2579 gtk_widget_show(hbox);
2580 label = gtk_label_new(_("%Exif.Image.Orientation%"));
2581 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2582 gtk_widget_show(label);
2583 pref_spacer(group,TRUE);
2585 group = pref_group_new(vbox, FALSE, _("Field separators"), GTK_ORIENTATION_VERTICAL);
2586 hbox = gtk_hbox_new(FALSE, 0);
2587 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2588 gtk_widget_show(hbox);
2589 label = gtk_label_new(_("Separator shown only if both fields are non-null:\n%formatted.ShutterSpeed%|%formatted.ISOSpeedRating%"));
2590 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2591 gtk_widget_show(label);
2592 pref_spacer(group,TRUE);
2594 group = pref_group_new(vbox, FALSE, _("Field maximum length"), GTK_ORIENTATION_VERTICAL);
2595 hbox = gtk_hbox_new(FALSE, 0);
2596 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2597 gtk_widget_show(hbox);
2598 label = gtk_label_new(_("%path:39%"));
2599 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2600 gtk_widget_show(label);
2601 pref_spacer(group,TRUE);
2603 group = pref_group_new(vbox, FALSE, _("Pre- and post- text"), 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(_("Text shown only if the field is non-null:\n%formatted.Aperture:F no. * setting%\n %formatted.Aperture:10:F no. * setting%"));
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, _("Pango markup"), 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(_("<b>bold</b>\n<u>underline</u>\n<i>italic</i>\n<s>strikethrough</s>"));
2617 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2618 gtk_widget_show(label);
2621 static GtkTreeModel *create_class_model(void)
2623 GtkListStore *model;
2627 /* create list store */
2628 model = gtk_list_store_new(1, G_TYPE_STRING);
2629 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
2631 gtk_list_store_append(model, &iter);
2632 gtk_list_store_set(model, &iter, 0, _(format_class_list[i]), -1);
2634 return GTK_TREE_MODEL (model);
2639 static gint filter_table_sort_cb(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer data)
2641 gint n = GPOINTER_TO_INT(data);
2643 FilterEntry *filter_a;
2644 FilterEntry *filter_b;
2646 gtk_tree_model_get(model, a, 0, &filter_a, -1);
2647 gtk_tree_model_get(model, b, 0, &filter_b, -1);
2651 case FILETYPES_COLUMN_DESCRIPTION:
2653 ret = g_utf8_collate(filter_a->description, filter_b->description);
2656 case FILETYPES_COLUMN_CLASS:
2658 ret = g_strcmp0(format_class_list[filter_a->file_class], format_class_list[filter_b->file_class]);
2661 case FILETYPES_COLUMN_WRITABLE:
2663 ret = filter_a->writable - filter_b->writable;
2666 case FILETYPES_COLUMN_SIDECAR:
2668 ret = filter_a->allow_sidecar - filter_b->allow_sidecar;
2672 g_return_val_if_reached(0);
2678 static gboolean search_function_cb(GtkTreeModel *model, gint column, const gchar *key, GtkTreeIter *iter, gpointer search_data)
2681 gboolean ret = TRUE;
2683 gtk_tree_model_get(model, iter, 0, &fe, -1);
2685 if (g_strstr_len(fe->extensions, -1, key))
2693 static void config_tab_files(GtkWidget *notebook)
2700 GtkWidget *ct_button;
2701 GtkWidget *scrolled;
2702 GtkWidget *filter_view;
2703 GtkCellRenderer *renderer;
2704 GtkTreeSelection *selection;
2705 GtkTreeViewColumn *column;
2707 vbox = scrolled_notebook_page(notebook, _("Files"));
2709 group = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2711 pref_checkbox_new_int(group, _("Show hidden files or folders"),
2712 options->file_filter.show_hidden_files, &c_options->file_filter.show_hidden_files);
2713 pref_checkbox_new_int(group, _("Show parent folder (..)"),
2714 options->file_filter.show_parent_directory, &c_options->file_filter.show_parent_directory);
2715 pref_checkbox_new_int(group, _("Case sensitive sort"),
2716 options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
2717 pref_checkbox_new_int(group, _("Natural sort order"),
2718 options->file_sort.natural, &c_options->file_sort.natural);
2719 pref_checkbox_new_int(group, _("Disable file extension checks"),
2720 options->file_filter.disable_file_extension_checks, &c_options->file_filter.disable_file_extension_checks);
2722 ct_button = pref_checkbox_new_int(group, _("Disable File Filtering"),
2723 options->file_filter.disable, &c_options->file_filter.disable);
2726 group = pref_group_new(vbox, FALSE, _("Grouping sidecar extensions"), GTK_ORIENTATION_VERTICAL);
2728 sidecar_ext_entry = gtk_entry_new();
2729 gtk_entry_set_text(GTK_ENTRY(sidecar_ext_entry), options->sidecar.ext);
2730 gtk_box_pack_start(GTK_BOX(group), sidecar_ext_entry, FALSE, FALSE, 0);
2731 gtk_widget_show(sidecar_ext_entry);
2733 group = pref_group_new(vbox, TRUE, _("File types"), GTK_ORIENTATION_VERTICAL);
2735 frame = pref_group_parent(group);
2736 g_signal_connect(G_OBJECT(ct_button), "toggled",
2737 G_CALLBACK(filter_disable_cb), frame);
2738 gtk_widget_set_sensitive(frame, !options->file_filter.disable);
2740 scrolled = gtk_scrolled_window_new(NULL, NULL);
2741 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2742 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2743 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2744 gtk_widget_show(scrolled);
2746 filter_store = gtk_list_store_new(1, G_TYPE_POINTER);
2747 filter_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(filter_store));
2748 g_object_unref(filter_store);
2749 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
2750 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
2752 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), FALSE);
2754 column = gtk_tree_view_column_new();
2755 gtk_tree_view_column_set_title(column, _("Filter"));
2756 gtk_tree_view_column_set_resizable(column, TRUE);
2758 renderer = gtk_cell_renderer_toggle_new();
2759 g_signal_connect(G_OBJECT(renderer), "toggled",
2760 G_CALLBACK(filter_store_enable_cb), filter_store);
2761 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2762 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2763 GINT_TO_POINTER(FE_ENABLE), NULL);
2765 renderer = gtk_cell_renderer_text_new();
2766 g_signal_connect(G_OBJECT(renderer), "edited",
2767 G_CALLBACK(filter_store_ext_edit_cb), filter_store);
2768 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2769 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2770 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2771 GINT_TO_POINTER(FE_EXTENSION), NULL);
2772 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2774 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), TRUE);
2775 gtk_tree_view_set_search_column(GTK_TREE_VIEW(filter_view), FILETYPES_COLUMN_FILTER);
2776 gtk_tree_view_set_search_equal_func(GTK_TREE_VIEW(filter_view), search_function_cb, NULL, NULL);
2778 column = gtk_tree_view_column_new();
2779 gtk_tree_view_column_set_title(column, _("Description"));
2780 gtk_tree_view_column_set_resizable(column, TRUE);
2781 gtk_tree_view_column_set_fixed_width(column, 200);
2782 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
2784 renderer = gtk_cell_renderer_text_new();
2785 g_signal_connect(G_OBJECT(renderer), "edited",
2786 G_CALLBACK(filter_store_desc_edit_cb), filter_store);
2787 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2788 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2789 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2790 GINT_TO_POINTER(FE_DESCRIPTION), NULL);
2791 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2792 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);
2793 gtk_tree_view_column_set_sort_column_id(column, FILETYPES_COLUMN_DESCRIPTION);
2795 column = gtk_tree_view_column_new();
2796 gtk_tree_view_column_set_title(column, _("Class"));
2797 gtk_tree_view_column_set_resizable(column, TRUE);
2798 renderer = gtk_cell_renderer_combo_new();
2799 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE,
2800 "model", create_class_model(),
2805 g_signal_connect(G_OBJECT(renderer), "edited",
2806 G_CALLBACK(filter_store_class_edit_cb), filter_store);
2807 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2808 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2809 GINT_TO_POINTER(FE_CLASS), NULL);
2810 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2811 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);
2812 gtk_tree_view_column_set_sort_column_id(column, FILETYPES_COLUMN_CLASS);
2814 column = gtk_tree_view_column_new();
2815 gtk_tree_view_column_set_title(column, _("Writable"));
2816 gtk_tree_view_column_set_resizable(column, FALSE);
2817 renderer = gtk_cell_renderer_toggle_new();
2818 g_signal_connect(G_OBJECT(renderer), "toggled",
2819 G_CALLBACK(filter_store_writable_cb), filter_store);
2820 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2821 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2822 GINT_TO_POINTER(FE_WRITABLE), NULL);
2823 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2824 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);
2825 gtk_tree_view_column_set_sort_column_id(column, FILETYPES_COLUMN_WRITABLE);
2827 column = gtk_tree_view_column_new();
2828 gtk_tree_view_column_set_title(column, _("Sidecar is allowed"));
2829 gtk_tree_view_column_set_resizable(column, FALSE);
2830 renderer = gtk_cell_renderer_toggle_new();
2831 g_signal_connect(G_OBJECT(renderer), "toggled",
2832 G_CALLBACK(filter_store_sidecar_cb), filter_store);
2833 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2834 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2835 GINT_TO_POINTER(FE_ALLOW_SIDECAR), NULL);
2836 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2837 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);
2838 gtk_tree_view_column_set_sort_column_id(column, FILETYPES_COLUMN_SIDECAR);
2840 filter_store_populate();
2841 gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
2842 gtk_widget_show(filter_view);
2844 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2846 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2847 G_CALLBACK(filter_default_cb), filter_view);
2848 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2849 gtk_widget_show(button);
2851 button = pref_button_new(NULL, GTK_STOCK_REMOVE, NULL, FALSE,
2852 G_CALLBACK(filter_remove_cb), filter_view);
2853 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2854 gtk_widget_show(button);
2856 button = pref_button_new(NULL, GTK_STOCK_ADD, NULL, FALSE,
2857 G_CALLBACK(filter_add_cb), filter_view);
2858 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2859 gtk_widget_show(button);
2863 static void config_tab_metadata(GtkWidget *notebook)
2868 GtkWidget *ct_button;
2872 vbox = scrolled_notebook_page(notebook, _("Metadata"));
2875 group = pref_group_new(vbox, FALSE, _("Metadata writing process"), GTK_ORIENTATION_VERTICAL);
2877 label = pref_label_new(group, _("Warning: Geeqie is built without Exiv2. Some options are disabled."));
2879 label = pref_label_new(group, _("Metadata are written in the following order. The process ends after first success."));
2880 #if GTK_CHECK_VERSION(3,16,0)
2881 gtk_label_set_xalign(GTK_LABEL(label), 0.0);
2882 gtk_label_set_yalign(GTK_LABEL(label), 0.5);
2884 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2887 ct_button = pref_checkbox_new_int(group, _("1) Save metadata in image files, or sidecar files, according to the XMP standard"),
2888 options->metadata.save_in_image_file, &c_options->metadata.save_in_image_file);
2890 gtk_widget_set_sensitive(ct_button, FALSE);
2893 pref_checkbox_new_int(group, _("2) Save metadata in '.metadata' folder, local to image folder (non-standard)"),
2894 options->metadata.enable_metadata_dirs, &c_options->metadata.enable_metadata_dirs);
2896 text = g_strdup_printf(_("3) Save metadata in Geeqie private directory '%s'"), get_metadata_cache_dir());
2897 label = pref_label_new(group, text);
2898 #if GTK_CHECK_VERSION(3,16,0)
2899 gtk_label_set_xalign(GTK_LABEL(label), 0.0);
2900 gtk_label_set_yalign(GTK_LABEL(label), 0.5);
2902 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2904 gtk_misc_set_padding(GTK_MISC(label), 22, 0);
2907 group = pref_group_new(vbox, FALSE, _("Step 1: Write to image files"), GTK_ORIENTATION_VERTICAL);
2909 gtk_widget_set_sensitive(group, FALSE);
2912 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2913 pref_checkbox_link_sensitivity(ct_button, hbox);
2915 pref_checkbox_new_int(hbox, _("Store metadata also in legacy IPTC tags (converted according to IPTC4XMP standard)"),
2916 options->metadata.save_legacy_IPTC, &c_options->metadata.save_legacy_IPTC);
2918 pref_checkbox_new_int(hbox, _("Warn if the image files are unwritable"),
2919 options->metadata.warn_on_write_problems, &c_options->metadata.warn_on_write_problems);
2921 pref_checkbox_new_int(hbox, _("Ask before writing to image files"),
2922 options->metadata.confirm_write, &c_options->metadata.confirm_write);
2924 pref_checkbox_new_int(hbox, _("Create sidecar files named image.ext.xmp (as opposed to image.xmp)"),
2925 options->metadata.sidecar_extended_name, &c_options->metadata.sidecar_extended_name);
2927 group = pref_group_new(vbox, FALSE, _("Step 2 and 3: write to Geeqie private files"), GTK_ORIENTATION_VERTICAL);
2929 gtk_widget_set_sensitive(group, FALSE);
2932 pref_checkbox_new_int(group, _("Use GQview legacy metadata format (supports only keywords and comments) instead of XMP"),
2933 options->metadata.save_legacy_format, &c_options->metadata.save_legacy_format);
2936 group = pref_group_new(vbox, FALSE, _("Miscellaneous"), GTK_ORIENTATION_VERTICAL);
2937 pref_checkbox_new_int(group, _("Write the same description tags (keywords, comment, etc.) to all grouped sidecars"),
2938 options->metadata.sync_grouped_files, &c_options->metadata.sync_grouped_files);
2940 pref_checkbox_new_int(group, _("Allow keywords to differ only in case"),
2941 options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
2943 ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"),
2944 options->metadata.write_orientation, &c_options->metadata.write_orientation);
2946 gtk_widget_set_sensitive(ct_button, FALSE);
2949 group = pref_group_new(vbox, FALSE, _("Auto-save options"), GTK_ORIENTATION_VERTICAL);
2951 ct_button = pref_checkbox_new_int(group, _("Write metadata after timeout"),
2952 options->metadata.confirm_after_timeout, &c_options->metadata.confirm_after_timeout);
2954 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2955 pref_checkbox_link_sensitivity(ct_button, hbox);
2957 pref_spin_new_int(hbox, _("Timeout (seconds):"), NULL, 0, 900, 1,
2958 options->metadata.confirm_timeout, &c_options->metadata.confirm_timeout);
2960 pref_checkbox_new_int(group, _("Write metadata on image change"),
2961 options->metadata.confirm_on_image_change, &c_options->metadata.confirm_on_image_change);
2963 pref_checkbox_new_int(group, _("Write metadata on directory change"),
2964 options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
2966 group = pref_group_new(vbox, FALSE, _("Pre-load metadata"), GTK_ORIENTATION_VERTICAL);
2968 ct_button = pref_checkbox_new_int(group, _("Read metadata in background"),
2969 options->read_metadata_in_idle, &c_options->read_metadata_in_idle);
2970 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");
2975 typedef struct _KeywordFindData KeywordFindData;
2976 struct _KeywordFindData
2983 GtkWidget *button_close;
2984 GtkWidget *button_stop;
2985 GtkWidget *button_start;
2986 GtkWidget *progress;
2994 guint idle_id; /* event source id */
2997 #define KEYWORD_DIALOG_WIDTH 400
2999 static void keywords_find_folder(KeywordFindData *kfd, FileData *dir_fd)
3001 GList *list_d = NULL;
3002 GList *list_f = NULL;
3006 filelist_read(dir_fd, &list_f, &list_d);
3010 filelist_read(dir_fd, &list_f, NULL);
3013 list_f = filelist_filter(list_f, FALSE);
3014 list_d = filelist_filter(list_d, TRUE);
3016 kfd->list = g_list_concat(list_f, kfd->list);
3017 kfd->list_dir = g_list_concat(list_d, kfd->list_dir);
3020 static void keywords_find_reset(KeywordFindData *kfd)
3022 filelist_free(kfd->list);
3025 filelist_free(kfd->list_dir);
3026 kfd->list_dir = NULL;
3029 static void keywords_find_close_cb(GenericDialog *fd, gpointer data)
3031 KeywordFindData *kfd = data;
3033 if (!gtk_widget_get_sensitive(kfd->button_close)) return;
3035 keywords_find_reset(kfd);
3036 generic_dialog_close(kfd->gd);
3040 static void keywords_find_finish(KeywordFindData *kfd)
3042 keywords_find_reset(kfd);
3044 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("done"));
3045 spinner_set_interval(kfd->spinner, -1);
3047 gtk_widget_set_sensitive(kfd->group, TRUE);
3048 gtk_widget_set_sensitive(kfd->button_start, TRUE);
3049 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
3050 gtk_widget_set_sensitive(kfd->button_close, TRUE);
3053 static void keywords_find_stop_cb(GenericDialog *fd, gpointer data)
3055 KeywordFindData *kfd = data;
3057 g_idle_remove_by_data(kfd);
3059 keywords_find_finish(kfd);
3062 static gboolean keywords_find_file(gpointer data)
3064 KeywordFindData *kfd = data;
3066 GtkTextBuffer *buffer;
3074 fd = kfd->list->data;
3075 kfd->list = g_list_remove(kfd->list, fd);
3077 keywords = metadata_read_list(fd, KEYWORD_KEY, METADATA_PLAIN);
3078 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3082 gtk_text_buffer_get_end_iter(buffer, &iter);
3083 tmp = g_strconcat(keywords->data, "\n", NULL);
3084 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
3086 keywords = keywords->next;
3089 gtk_entry_set_text(GTK_ENTRY(kfd->progress), fd->path);
3090 file_data_unref(fd);
3091 string_list_free(keywords);
3095 else if (kfd->list_dir)
3099 fd = kfd->list_dir->data;
3100 kfd->list_dir = g_list_remove(kfd->list_dir, fd);
3102 keywords_find_folder(kfd, fd);
3104 file_data_unref(fd);
3109 keywords_find_finish(kfd);
3114 static void keywords_find_start_cb(GenericDialog *fd, gpointer data)
3116 KeywordFindData *kfd = data;
3119 if (kfd->list || !gtk_widget_get_sensitive(kfd->button_start)) return;
3121 path = remove_trailing_slash((gtk_entry_get_text(GTK_ENTRY(kfd->entry))));
3122 parse_out_relatives(path);
3126 warning_dialog(_("Invalid folder"),
3127 _("The specified folder can not be found."),
3128 GTK_STOCK_DIALOG_WARNING, kfd->gd->dialog);
3134 gtk_widget_set_sensitive(kfd->group, FALSE);
3135 gtk_widget_set_sensitive(kfd->button_start, FALSE);
3136 gtk_widget_set_sensitive(kfd->button_stop, TRUE);
3137 gtk_widget_set_sensitive(kfd->button_close, FALSE);
3138 spinner_set_interval(kfd->spinner, SPINNER_SPEED);
3140 dir_fd = file_data_new_dir(path);
3141 keywords_find_folder(kfd, dir_fd);
3142 file_data_unref(dir_fd);
3143 kfd->idle_id = g_idle_add(keywords_find_file, kfd);
3149 static void keywords_find_dialog(GtkWidget *widget, const gchar *path)
3151 KeywordFindData *kfd;
3155 kfd = g_new0(KeywordFindData, 1);
3157 kfd->gd = generic_dialog_new(_("Search for keywords"),
3158 "search_for_keywords",
3161 gtk_window_set_default_size(GTK_WINDOW(kfd->gd->dialog), KEYWORD_DIALOG_WIDTH, -1);
3162 kfd->gd->cancel_cb = keywords_find_close_cb;
3163 kfd->button_close = generic_dialog_add_button(kfd->gd, GTK_STOCK_CLOSE, NULL,
3164 keywords_find_close_cb, FALSE);
3165 kfd->button_start = generic_dialog_add_button(kfd->gd, GTK_STOCK_OK, _("S_tart"),
3166 keywords_find_start_cb, FALSE);
3167 kfd->button_stop = generic_dialog_add_button(kfd->gd, GTK_STOCK_STOP, NULL,
3168 keywords_find_stop_cb, FALSE);
3169 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
3171 generic_dialog_add_message(kfd->gd, NULL, _("Search for keywords"), NULL, FALSE);
3173 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0);
3174 pref_spacer(hbox, PREF_PAD_INDENT);
3175 kfd->group = pref_box_new(hbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
3177 hbox = pref_box_new(kfd->group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3178 pref_label_new(hbox, _("Folder:"));
3180 label = tab_completion_new(&kfd->entry, path, NULL, NULL, NULL, NULL);
3181 tab_completion_add_select_button(kfd->entry,_("Select folder") , TRUE);
3182 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
3183 gtk_widget_show(label);
3185 pref_checkbox_new_int(kfd->group, _("Include subfolders"), FALSE, &kfd->recurse);
3187 pref_line(kfd->gd->vbox, PREF_PAD_SPACE);
3188 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3190 kfd->progress = gtk_entry_new();
3191 gtk_widget_set_can_focus(kfd->progress, FALSE);
3192 gtk_editable_set_editable(GTK_EDITABLE(kfd->progress), FALSE);
3193 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("click start to begin"));
3194 gtk_box_pack_start(GTK_BOX(hbox), kfd->progress, TRUE, TRUE, 0);
3195 gtk_widget_show(kfd->progress);
3197 kfd->spinner = spinner_new(NULL, -1);
3198 gtk_box_pack_start(GTK_BOX(hbox), kfd->spinner, FALSE, FALSE, 0);
3199 gtk_widget_show(kfd->spinner);
3203 gtk_widget_show(kfd->gd->dialog);
3206 static void keywords_find_cb(GtkWidget *widget, gpointer data)
3208 const gchar *path = layout_get_path(NULL);
3210 if (!path || !*path) path = homedir();
3211 keywords_find_dialog(widget, path);
3214 static void config_tab_keywords_save()
3216 GtkTextIter start, end;
3217 GtkTextBuffer *buffer;
3218 GList *kw_list = NULL;
3224 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3225 gtk_text_buffer_get_bounds(buffer, &start, &end);
3227 buffer_text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
3229 kw_split = strtok(buffer_text, "\n");
3230 while (kw_split != NULL)
3236 if (g_strcmp0(work->data, kw_split) == 0)
3245 kw_list = g_list_append(kw_list, g_strdup(kw_split));
3247 kw_split = strtok(NULL, "\n");
3250 keyword_list_set(kw_list);
3252 string_list_free(kw_list);
3253 g_free(buffer_text);
3256 static void config_tab_keywords(GtkWidget *notebook)
3262 GtkWidget *scrolled;
3264 GtkTextBuffer *buffer;
3267 vbox = scrolled_notebook_page(notebook, _("Keywords"));
3269 group = pref_group_new(vbox, TRUE, _("Edit keywords autocompletion list"), GTK_ORIENTATION_VERTICAL);
3271 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3273 button = pref_button_new(hbox, GTK_STOCK_EXECUTE, _("Search"), FALSE,
3274 G_CALLBACK(keywords_find_cb), keyword_text);
3275 gtk_widget_set_tooltip_text(button, "Search for existing keywords");
3278 keyword_text = gtk_text_view_new();
3279 gtk_widget_set_size_request(keyword_text, 20, 20);
3280 scrolled = gtk_scrolled_window_new(NULL, NULL);
3281 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3282 gtk_widget_show(scrolled);
3284 gtk_container_add(GTK_CONTAINER(scrolled), keyword_text);
3285 gtk_widget_show(keyword_text);
3287 gtk_text_view_set_editable(GTK_TEXT_VIEW(keyword_text), TRUE);
3289 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3290 gtk_text_buffer_create_tag(buffer, "monospace",
3291 "family", "monospace", NULL);
3293 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(keyword_text), GTK_WRAP_WORD);
3294 gtk_text_buffer_get_start_iter(buffer, &iter);
3295 gtk_text_buffer_create_mark(buffer, "end", &iter, FALSE);
3298 path = g_build_filename(get_rc_dir(), "keywords", NULL);
3300 GList *kwl = keyword_list_get();
3301 kwl = g_list_first(kwl);
3304 gtk_text_buffer_get_end_iter (buffer, &iter);
3305 tmp = g_strconcat(kwl->data, "\n", NULL);
3306 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
3311 gtk_text_buffer_set_modified(buffer, FALSE);
3318 static void intent_menu_cb(GtkWidget *combo, gpointer data)
3320 gint *option = data;
3322 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
3326 *option = INTENT_PERCEPTUAL;
3329 *option = INTENT_RELATIVE_COLORIMETRIC;
3332 *option = INTENT_SATURATION;
3335 *option = INTENT_ABSOLUTE_COLORIMETRIC;
3340 static void add_intent_menu(GtkWidget *table, gint column, gint row, const gchar *text,
3341 gint option, gint *option_c)
3348 pref_table_label(table, column, row, text, 0.0);
3350 combo = gtk_combo_box_text_new();
3352 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Perceptual"));
3353 if (option == INTENT_PERCEPTUAL) current = 0;
3354 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Relative Colorimetric"));
3355 if (option == INTENT_RELATIVE_COLORIMETRIC) current = 1;
3356 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Saturation"));
3357 if (option == INTENT_SATURATION) current = 2;
3358 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Absolute Colorimetric"));
3359 if (option == INTENT_ABSOLUTE_COLORIMETRIC) current = 3;
3361 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
3363 gtk_widget_set_tooltip_text(combo,"Refer to the lcms documentation for the defaults used when the selected Intent is not available");
3365 g_signal_connect(G_OBJECT(combo), "changed",
3366 G_CALLBACK(intent_menu_cb), option_c);
3368 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
3369 gtk_widget_show(combo);
3373 static void config_tab_color(GtkWidget *notebook)
3382 vbox = scrolled_notebook_page(notebook, _("Color management"));
3384 group = pref_group_new(vbox, FALSE, _("Input profiles"), GTK_ORIENTATION_VERTICAL);
3386 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3389 table = pref_table_new(group, 3, COLOR_PROFILE_INPUTS + 1, FALSE, FALSE);
3390 gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
3392 label = pref_table_label(table, 0, 0, _("Type"), 0.0);
3393 pref_label_bold(label, TRUE, FALSE);
3395 label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
3396 pref_label_bold(label, TRUE, FALSE);
3398 label = pref_table_label(table, 2, 0, _("File"), 0.0);
3399 pref_label_bold(label, TRUE, FALSE);
3401 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
3406 buf = g_strdup_printf(_("Input %d:"), i + COLOR_PROFILE_FILE);
3407 pref_table_label(table, 0, i + 1, buf, 1.0);
3410 entry = gtk_entry_new();
3411 gtk_entry_set_max_length(GTK_ENTRY(entry), EDITOR_NAME_MAX_LENGTH);
3412 if (options->color_profile.input_name[i])
3414 gtk_entry_set_text(GTK_ENTRY(entry), options->color_profile.input_name[i]);
3416 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, i + 1, i + 2,
3417 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3418 gtk_widget_show(entry);
3419 color_profile_input_name_entry[i] = entry;
3421 tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, ".icc", "ICC Files", NULL);
3422 tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
3423 gtk_widget_set_size_request(entry, 160, -1);
3424 gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
3425 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3426 gtk_widget_show(tabcomp);
3427 color_profile_input_file_entry[i] = entry;
3430 group = pref_group_new(vbox, FALSE, _("Screen profile"), GTK_ORIENTATION_VERTICAL);
3432 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3434 pref_checkbox_new_int(group, _("Use system screen profile if available"),
3435 options->color_profile.use_x11_screen_profile, &c_options->color_profile.use_x11_screen_profile);
3437 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3439 pref_table_label(table, 0, 0, _("Screen:"), 1.0);
3440 tabcomp = tab_completion_new(&color_profile_screen_file_entry,
3441 options->color_profile.screen_file, NULL, ".icc", "ICC Files", NULL);
3442 tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
3443 gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
3445 add_intent_menu(table, 0, 1, _("Render Intent:"), options->color_profile.render_intent, &c_options->color_profile.render_intent);
3447 gtk_table_attach(GTK_TABLE(table), tabcomp, 1, 2,
3449 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3451 gtk_widget_show(tabcomp);
3454 /* advanced entry tab */
3455 static void use_geeqie_trash_cb(GtkWidget *widget, gpointer data)
3457 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3459 c_options->file_ops.use_system_trash = FALSE;
3460 c_options->file_ops.no_trash = FALSE;
3464 static void use_system_trash_cb(GtkWidget *widget, gpointer data)
3466 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3468 c_options->file_ops.use_system_trash = TRUE;
3469 c_options->file_ops.no_trash = FALSE;
3473 static void use_no_cache_cb(GtkWidget *widget, gpointer data)
3475 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3477 c_options->file_ops.no_trash = TRUE;
3481 static void config_tab_behavior(GtkWidget *notebook)
3488 GtkWidget *ct_button;
3492 GtkWidget *with_rename;
3493 GtkWidget *collections_on_top;
3494 GtkWidget *hide_window_in_fullscreen;
3495 GtkWidget *checkbox;
3498 vbox = scrolled_notebook_page(notebook, _("Behavior"));
3500 group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
3502 pref_checkbox_new_int(group, _("Confirm permanent file delete"),
3503 options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
3504 pref_checkbox_new_int(group, _("Confirm move file to Trash"),
3505 options->file_ops.confirm_move_to_trash, &c_options->file_ops.confirm_move_to_trash);
3506 pref_checkbox_new_int(group, _("Enable Delete key"),
3507 options->file_ops.enable_delete_key, &c_options->file_ops.enable_delete_key);
3509 ct_button = pref_radiobutton_new(group, NULL, _("Use Geeqie trash location"),
3510 !options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_geeqie_trash_cb),NULL);
3512 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3513 pref_checkbox_link_sensitivity(ct_button, hbox);
3515 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
3516 pref_label_new(hbox, _("Folder:"));
3518 tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL, NULL, NULL);
3519 tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
3520 gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
3521 gtk_widget_show(tabcomp);
3523 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3524 pref_checkbox_link_sensitivity(ct_button, hbox);
3526 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
3527 spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MiB"),
3528 0, 2048, 1, options->file_ops.safe_delete_folder_maxsize, &c_options->file_ops.safe_delete_folder_maxsize);
3529 gtk_widget_set_tooltip_markup(spin, _("Set to 0 for unlimited size"));
3530 button = pref_button_new(NULL, NULL, _("View"), FALSE,
3531 G_CALLBACK(safe_delete_view_cb), NULL);
3532 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3533 gtk_widget_show(button);
3535 button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
3536 G_CALLBACK(safe_delete_clear_cb), NULL);
3537 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3538 pref_radiobutton_new(group, ct_button, _("Use system Trash bin"),
3539 options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_system_trash_cb), NULL);
3541 pref_radiobutton_new(group, ct_button, _("Use no trash at all"),
3542 options->file_ops.no_trash, G_CALLBACK(use_no_cache_cb), NULL);
3544 gtk_widget_show(button);
3546 pref_spacer(group, PREF_PAD_GROUP);
3549 group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
3551 pref_checkbox_new_int(group, _("Descend folders in tree view"),
3552 options->tree_descend_subdirs, &c_options->tree_descend_subdirs);
3554 pref_checkbox_new_int(group, _("In place renaming"),
3555 options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
3557 pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
3558 options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
3560 tmp = pref_checkbox_new_int(group, _("Circular selection lists"),
3561 options->circular_selection_lists, &c_options->circular_selection_lists);
3562 gtk_widget_set_tooltip_text(tmp, _("Traverse selection lists in a circular manner"));
3564 marks = pref_checkbox_new_int(group, _("Save marks on exit"),
3565 options->marks_save, &c_options->marks_save);
3566 gtk_widget_set_tooltip_text(marks,"Note that marks linked to a keyword will be saved irrespective of this setting");
3568 with_rename = pref_checkbox_new_int(group, _("Use \"With Rename\" as default for Copy/Move dialogs"),
3569 options->with_rename, &c_options->with_rename);
3570 gtk_widget_set_tooltip_text(with_rename,"Change the default button for Copy/Move dialogs");
3572 collections_on_top = pref_checkbox_new_int(group, _("Open collections on top"),
3573 options->collections_on_top, &c_options->collections_on_top);
3574 gtk_widget_set_tooltip_text(collections_on_top,"Open collections window on top");
3576 hide_window_in_fullscreen = pref_checkbox_new_int(group, _("Hide window in fullscreen"),
3577 options->hide_window_in_fullscreen, &c_options->hide_window_in_fullscreen);
3578 gtk_widget_set_tooltip_text(hide_window_in_fullscreen,"When alt-tabbing, prevent Geeqie window showing twice");
3580 pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
3581 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
3583 pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
3584 16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
3586 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3587 add_dnd_default_action_selection_menu(table, 0, 0, _("Drag`n drop default action:"), options->dnd_default_action, &c_options->dnd_default_action);
3589 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3590 add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
3592 pref_spacer(group, PREF_PAD_GROUP);
3594 group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
3596 pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
3597 options->progressive_key_scrolling, &c_options->progressive_key_scrolling);
3598 pref_spin_new_int(group, _("Keyboard scrolling step multiplier:"), NULL,
3599 1, 32, 1, options->keyboard_scroll_step, (int *)&c_options->keyboard_scroll_step);
3600 pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
3601 options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
3602 pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
3603 options->image_lm_click_nav, &c_options->image_lm_click_nav);
3604 pref_checkbox_new_int(group, _("Open archive by left click on image"),
3605 options->image_l_click_archive, &c_options->image_l_click_archive);
3606 pref_checkbox_new_int(group, _("Play video by left click on image"),
3607 options->image_l_click_video, &c_options->image_l_click_video);
3608 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3609 add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
3611 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3612 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3613 add_mouse_selection_menu(table, 0, 0, _("Mouse button Back:"), options->mouse_button_8, &c_options->mouse_button_8);
3614 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3615 add_mouse_selection_menu(table, 0, 0, _("Mouse button Forward:"), options->mouse_button_9, &c_options->mouse_button_9);
3617 pref_spacer(group, PREF_PAD_GROUP);
3619 group = pref_group_new(vbox, FALSE, _("GPU"), GTK_ORIENTATION_VERTICAL);
3621 checkbox = pref_checkbox_new_int(group, _("Override disable GPU"),
3622 options->override_disable_gpu, &c_options->override_disable_gpu);
3623 gtk_widget_set_tooltip_text(checkbox, "Contact the developers for usage");
3626 pref_spacer(group, PREF_PAD_GROUP);
3628 group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
3630 pref_spin_new_int(group, _("Debug level:"), NULL,
3631 DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
3633 pref_checkbox_new_int(group, _("Timer data"),
3634 options->log_window.timer_data, &c_options->log_window.timer_data);
3636 pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
3637 1, 99999, 1, options->log_window_lines, &options->log_window_lines);
3641 /* accelerators tab */
3642 static void config_tab_accelerators(GtkWidget *notebook)
3648 GtkWidget *scrolled;
3649 GtkWidget *accel_view;
3650 GtkCellRenderer *renderer;
3651 GtkTreeSelection *selection;
3652 GtkTreeViewColumn *column;
3654 vbox = scrolled_notebook_page(notebook, _("Keyboard"));
3656 group = pref_group_new(vbox, TRUE, _("Accelerators"), GTK_ORIENTATION_VERTICAL);
3658 scrolled = gtk_scrolled_window_new(NULL, NULL);
3659 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
3660 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
3661 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3662 gtk_widget_show(scrolled);
3664 accel_store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
3666 accel_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(accel_store));
3667 g_object_unref(accel_store);
3668 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(accel_view));
3669 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
3671 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(accel_view), FALSE);
3673 renderer = gtk_cell_renderer_text_new();
3675 column = gtk_tree_view_column_new_with_attributes(_("Action"),
3680 gtk_tree_view_column_set_sort_column_id(column, AE_ACTION);
3681 gtk_tree_view_column_set_resizable(column, TRUE);
3682 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3685 renderer = gtk_cell_renderer_accel_new();
3686 g_signal_connect(G_OBJECT(renderer), "accel-cleared",
3687 G_CALLBACK(accel_store_cleared_cb), accel_store);
3688 g_signal_connect(G_OBJECT(renderer), "accel-edited",
3689 G_CALLBACK(accel_store_edited_cb), accel_store);
3692 g_object_set (renderer,
3694 "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
3697 column = gtk_tree_view_column_new_with_attributes(_("KEY"),
3702 gtk_tree_view_column_set_sort_column_id(column, AE_KEY);
3703 gtk_tree_view_column_set_resizable(column, TRUE);
3704 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3706 renderer = gtk_cell_renderer_text_new();
3708 column = gtk_tree_view_column_new_with_attributes(_("Tooltip"),
3713 gtk_tree_view_column_set_sort_column_id(column, AE_TOOLTIP);
3714 gtk_tree_view_column_set_resizable(column, TRUE);
3715 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3717 renderer = gtk_cell_renderer_text_new();
3719 column = gtk_tree_view_column_new_with_attributes("Accel",
3724 gtk_tree_view_column_set_sort_column_id(column, AE_ACCEL);
3725 gtk_tree_view_column_set_resizable(column, TRUE);
3726 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3728 accel_store_populate();
3729 gtk_container_add(GTK_CONTAINER(scrolled), accel_view);
3730 gtk_widget_show(accel_view);
3732 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3734 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
3735 G_CALLBACK(accel_default_cb), accel_view);
3736 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3737 gtk_widget_show(button);
3739 button = pref_button_new(NULL, NULL, _("Reset selected"), FALSE,
3740 G_CALLBACK(accel_reset_cb), accel_view);
3741 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3742 gtk_widget_show(button);
3745 /* toolbar main tab */
3746 static void config_tab_toolbar_main(GtkWidget *notebook)
3749 GtkWidget *toolbardata;
3752 lw = layout_window_list->data;
3754 vbox = scrolled_notebook_page(notebook, _("Toolbar Main"));
3756 toolbardata = toolbar_select_new(lw, TOOLBAR_MAIN);
3757 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3758 gtk_widget_show(vbox);
3761 /* toolbar status tab */
3762 static void config_tab_toolbar_status(GtkWidget *notebook)
3765 GtkWidget *toolbardata;
3768 lw = layout_window_list->data;
3770 vbox = scrolled_notebook_page(notebook, _("Toolbar Status"));
3772 toolbardata = toolbar_select_new(lw, TOOLBAR_STATUS);
3773 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3774 gtk_widget_show(vbox);
3778 static gint extension_sort_cb(gconstpointer a, gconstpointer b)
3780 return g_strcmp0((gchar *)a, (gchar *)b);
3783 static void config_tab_advanced(GtkWidget *notebook)
3787 GSList *formats_list;
3788 GList *extensions_list = NULL;
3791 GdkPixbufFormat *fm;
3793 GString *types_string = g_string_new(NULL);
3794 GtkWidget *types_string_label;
3795 GtkWidget *threads_string_label;
3796 GtkWidget *dupes_threads_spin;
3798 vbox = scrolled_notebook_page(notebook, _("Advanced"));
3799 group = pref_group_new(vbox, FALSE, _("External preview extraction"), GTK_ORIENTATION_VERTICAL);
3801 pref_checkbox_new_int(group, _("Use external preview extraction - Requires restart"), options->external_preview.enable, &c_options->external_preview.enable);
3803 pref_spacer(group, PREF_PAD_GROUP);
3805 formats_list = gdk_pixbuf_get_formats();
3807 while (formats_list)
3809 fm = formats_list->data;
3810 extensions = gdk_pixbuf_format_get_extensions(fm);
3813 while (extensions[i])
3815 extensions_list = g_list_insert_sorted(extensions_list, g_strdup(extensions[i]), extension_sort_cb);
3819 g_strfreev(extensions);
3820 formats_list = formats_list->next;
3823 while (extensions_list)
3825 if (types_string->len == 0)
3827 types_string = g_string_append(types_string, extensions_list->data);
3831 types_string = g_string_append(types_string, ", ");
3832 types_string = g_string_append(types_string, extensions_list->data);
3835 extensions_list = extensions_list->next;
3838 types_string = g_string_prepend(types_string, _("Usable file types:\n"));
3839 types_string_label = pref_label_new(group, types_string->str);
3840 gtk_label_set_line_wrap(GTK_LABEL(types_string_label), TRUE);
3842 pref_spacer(group, PREF_PAD_GROUP);
3844 group = pref_group_new(vbox, FALSE, _("File identification tool"), GTK_ORIENTATION_VERTICAL);
3845 external_preview_select_entry = gtk_entry_new();
3846 tabcomp = tab_completion_new(&external_preview_select_entry, options->external_preview.select, NULL, NULL, NULL, NULL);
3847 tab_completion_add_select_button(external_preview_select_entry, _("Select file identification tool"), FALSE);
3848 gtk_box_pack_start(GTK_BOX(group), tabcomp, TRUE, TRUE, 0);
3849 gtk_widget_show(tabcomp);
3851 group = pref_group_new(vbox, FALSE, _("Preview extraction tool"), GTK_ORIENTATION_VERTICAL);
3852 external_preview_extract_entry = gtk_entry_new();
3853 tabcomp = tab_completion_new(&external_preview_extract_entry, options->external_preview.extract, NULL, NULL, NULL, NULL);
3854 tab_completion_add_select_button(external_preview_extract_entry, _("Select preview extraction tool"), FALSE);
3855 gtk_box_pack_start(GTK_BOX(group), tabcomp, TRUE, TRUE, 0);
3856 gtk_widget_show(tabcomp);
3858 gtk_widget_show(vbox);
3860 g_slist_free(formats_list);
3861 string_list_free(extensions_list);
3862 g_string_free(types_string, TRUE);
3864 pref_spacer(group, PREF_PAD_GROUP);
3866 pref_line(vbox, PREF_PAD_SPACE);
3867 group = pref_group_new(vbox, FALSE, _("Thread pool limits"), GTK_ORIENTATION_VERTICAL);
3869 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.");
3870 gtk_label_set_line_wrap(GTK_LABEL(threads_string_label), TRUE);
3872 pref_spacer(vbox, PREF_PAD_GROUP);
3874 dupes_threads_spin = pref_spin_new_int(vbox, _("Duplicate check:"), _("max. threads"), 0, get_cpu_cores(), 1, options->threads.duplicates, &c_options->threads.duplicates);
3875 gtk_widget_set_tooltip_markup(dupes_threads_spin, _("Set to 0 for unlimited"));
3879 static void config_tab_stereo(GtkWidget *notebook)
3887 GtkWidget *fs_button;
3888 vbox = scrolled_notebook_page(notebook, _("Stereo"));
3890 group = pref_group_new(vbox, FALSE, _("Windowed stereo mode"), GTK_ORIENTATION_VERTICAL);
3892 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3893 add_stereo_mode_menu(table, 0, 0, _("Windowed stereo mode"), options->stereo.mode, &c_options->stereo.mode, FALSE);
3895 table = pref_table_new(group, 2, 2, TRUE, FALSE);
3896 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3897 pref_checkbox_new_int(box, _("Mirror left image"),
3898 options->stereo.mode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.mirror_left);
3899 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3900 pref_checkbox_new_int(box, _("Flip left image"),
3901 options->stereo.mode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.flip_left);
3902 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3903 pref_checkbox_new_int(box, _("Mirror right image"),
3904 options->stereo.mode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.mirror_right);
3905 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3906 pref_checkbox_new_int(box, _("Flip right image"),
3907 options->stereo.mode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.flip_right);
3908 pref_checkbox_new_int(group, _("Swap left and right images"),
3909 options->stereo.mode & PR_STEREO_SWAP, &c_options->stereo.tmp.swap);
3910 pref_checkbox_new_int(group, _("Disable stereo mode on single image source"),
3911 options->stereo.mode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.temp_disable);
3913 group = pref_group_new(vbox, FALSE, _("Fullscreen stereo mode"), GTK_ORIENTATION_VERTICAL);
3914 fs_button = pref_checkbox_new_int(group, _("Use different settings for fullscreen"),
3915 options->stereo.enable_fsmode, &c_options->stereo.enable_fsmode);
3916 box2 = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
3917 pref_checkbox_link_sensitivity(fs_button, box2);
3918 table = pref_table_new(box2, 2, 1, FALSE, FALSE);
3919 add_stereo_mode_menu(table, 0, 0, _("Fullscreen stereo mode"), options->stereo.fsmode, &c_options->stereo.fsmode, TRUE);
3920 table = pref_table_new(box2, 2, 2, TRUE, FALSE);
3921 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3922 pref_checkbox_new_int(box, _("Mirror left image"),
3923 options->stereo.fsmode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.fs_mirror_left);
3924 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3925 pref_checkbox_new_int(box, _("Flip left image"),
3926 options->stereo.fsmode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.fs_flip_left);
3927 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3928 pref_checkbox_new_int(box, _("Mirror right image"),
3929 options->stereo.fsmode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.fs_mirror_right);
3930 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3931 pref_checkbox_new_int(box, _("Flip right image"),
3932 options->stereo.fsmode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.fs_flip_right);
3933 pref_checkbox_new_int(box2, _("Swap left and right images"),
3934 options->stereo.fsmode & PR_STEREO_SWAP, &c_options->stereo.tmp.fs_swap);
3935 pref_checkbox_new_int(box2, _("Disable stereo mode on single image source"),
3936 options->stereo.fsmode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.fs_temp_disable);
3938 group2 = pref_group_new(box2, FALSE, _("Fixed position"), GTK_ORIENTATION_VERTICAL);
3939 table = pref_table_new(group2, 5, 3, FALSE, FALSE);
3940 pref_table_spin_new_int(table, 0, 0, _("Width"), NULL,
3941 1, 5000, 1, options->stereo.fixed_w, &c_options->stereo.fixed_w);
3942 pref_table_spin_new_int(table, 3, 0, _("Height"), NULL,
3943 1, 5000, 1, options->stereo.fixed_h, &c_options->stereo.fixed_h);
3944 pref_table_spin_new_int(table, 0, 1, _("Left X"), NULL,
3945 0, 5000, 1, options->stereo.fixed_x1, &c_options->stereo.fixed_x1);
3946 pref_table_spin_new_int(table, 3, 1, _("Left Y"), NULL,
3947 0, 5000, 1, options->stereo.fixed_y1, &c_options->stereo.fixed_y1);
3948 pref_table_spin_new_int(table, 0, 2, _("Right X"), NULL,
3949 0, 5000, 1, options->stereo.fixed_x2, &c_options->stereo.fixed_x2);
3950 pref_table_spin_new_int(table, 3, 2, _("Right Y"), NULL,
3951 0, 5000, 1, options->stereo.fixed_y2, &c_options->stereo.fixed_y2);
3955 /* Main preferences window */
3956 static void config_window_create(LayoutWindow *lw)
3958 GtkWidget *win_vbox;
3960 GtkWidget *notebook;
3962 GtkWidget *ct_button;
3964 if (!c_options) c_options = init_options(NULL);
3966 configwindow = window_new(GTK_WINDOW_TOPLEVEL, "preferences", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Preferences"));
3967 DEBUG_NAME(configwindow);
3968 gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
3969 g_signal_connect(G_OBJECT(configwindow), "delete_event",
3970 G_CALLBACK(config_window_delete), NULL);
3971 if (options->save_dialog_window_positions)
3973 gtk_window_resize(GTK_WINDOW(configwindow), lw->options.preferences_window.w, lw->options.preferences_window.h);
3974 gtk_window_move(GTK_WINDOW(configwindow), lw->options.preferences_window.x, lw->options.preferences_window.y);
3978 gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
3980 gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
3981 gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
3983 win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
3984 gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
3985 gtk_widget_show(win_vbox);
3987 notebook = gtk_notebook_new();
3988 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_LEFT);
3989 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE);
3990 gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
3992 config_tab_general(notebook);
3993 config_tab_image(notebook);
3994 config_tab_osd(notebook);
3995 config_tab_windows(notebook);
3996 config_tab_accelerators(notebook);
3997 config_tab_files(notebook);
3998 config_tab_metadata(notebook);
3999 config_tab_keywords(notebook);
4000 config_tab_color(notebook);
4001 config_tab_stereo(notebook);
4002 config_tab_behavior(notebook);
4003 config_tab_toolbar_main(notebook);
4004 config_tab_toolbar_status(notebook);
4005 config_tab_advanced(notebook);
4007 gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), lw->options.preferences_window.page_number);
4009 hbox = gtk_hbutton_box_new();
4010 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
4011 gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
4012 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
4013 gtk_widget_show(hbox);
4015 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
4016 G_CALLBACK(config_window_help_cb), notebook);
4017 gtk_container_add(GTK_CONTAINER(hbox), button);
4018 gtk_widget_set_can_default(button, TRUE);
4019 gtk_widget_show(button);
4021 button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
4022 G_CALLBACK(config_window_ok_cb), notebook);
4023 gtk_container_add(GTK_CONTAINER(hbox), button);
4024 gtk_widget_set_can_default(button, TRUE);
4025 gtk_widget_grab_default(button);
4026 gtk_widget_show(button);
4030 button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
4031 G_CALLBACK(config_window_close_cb), NULL);
4032 gtk_container_add(GTK_CONTAINER(hbox), button);
4033 gtk_widget_set_can_default(button, TRUE);
4034 gtk_widget_show(button);
4036 if (!generic_dialog_get_alternative_button_order(configwindow))
4038 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
4041 gtk_widget_show(notebook);
4043 gtk_widget_show(configwindow);
4047 *-----------------------------------------------------------------------------
4048 * config window show (public)
4049 *-----------------------------------------------------------------------------
4052 void show_config_window(LayoutWindow *lw)
4056 gtk_window_present(GTK_WINDOW(configwindow));
4060 config_window_create(lw);
4069 void show_about_window(LayoutWindow *lw)
4071 GdkPixbuf *pixbuf_logo;
4072 GdkPixbuf *pixbuf_icon;
4073 gchar *authors[1000];
4078 gchar *timezone_path;
4081 #define LINE_LENGTH 1000
4082 gchar line[LINE_LENGTH];
4084 copyright = g_string_new(NULL);
4085 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");
4087 timezone_path = g_build_filename(get_rc_dir(), TIMEZONE_DATABASE_FILE, NULL);
4088 if (g_file_test(timezone_path, G_FILE_TEST_EXISTS))
4090 cd = ZDOpenDatabase(timezone_path);
4093 copyright = g_string_append(copyright, ZDGetNotice(cd));
4097 log_printf("Error: Init of timezone database %s failed\n", timezone_path);
4099 ZDCloseDatabase(cd);
4101 g_free(timezone_path);
4104 path = g_build_filename(gq_helpdir, "AUTHORS", NULL);
4105 fp = fopen(path, "r");
4108 while(fgets(line, LINE_LENGTH, fp))
4110 /* get rid of ending \n from fgets */
4111 line[strlen(line) - 1] = '\0';
4112 authors[i_authors] = g_strdup(line);
4115 authors[i_authors] = NULL;
4120 comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
4121 "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
4123 pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
4124 pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
4125 gtk_show_about_dialog(GTK_WINDOW(lw->window),
4126 "title", _("About Geeqie"),
4128 "program-name", GQ_APPNAME,
4130 "logo", pixbuf_logo,
4131 "icon", pixbuf_icon,
4132 "website", GQ_WEBSITE,
4133 "website-label", "Website",
4134 "comments", comment,
4136 "translator-credits", _("translator-credits"),
4137 "wrap-license", TRUE,
4138 "license", copyright->str,
4141 g_string_free(copyright, TRUE);
4144 while(n < i_authors)
4154 static void image_overlay_set_text_colours()
4156 c_options->image_overlay.text_red = options->image_overlay.text_red;
4157 c_options->image_overlay.text_green = options->image_overlay.text_green;
4158 c_options->image_overlay.text_blue = options->image_overlay.text_blue;
4159 c_options->image_overlay.text_alpha = options->image_overlay.text_alpha;
4160 c_options->image_overlay.background_red = options->image_overlay.background_red;
4161 c_options->image_overlay.background_green = options->image_overlay.background_green;
4162 c_options->image_overlay.background_blue = options->image_overlay.background_blue;
4163 c_options->image_overlay.background_alpha = options->image_overlay.background_alpha;
4167 *-----------------------------------------------------------------------------
4168 * timezone database routines
4169 *-----------------------------------------------------------------------------
4172 static void timezone_async_ready_cb(GObject *source_object, GAsyncResult *res, gpointer data)
4174 GError *error = NULL;
4176 gchar *tmp_filename;
4177 gchar *timezone_bin;
4178 gchar *tmp_dir = NULL;
4181 if (!g_cancellable_is_cancelled(tz->cancellable))
4183 generic_dialog_close(tz->gd);
4187 if (g_file_copy_finish(G_FILE(source_object), res, &error))
4189 tmp_filename = g_file_get_path(tz->tmp_g_file);
4190 fd = file_data_new_simple(tmp_filename);
4191 tmp_dir = open_archive(fd);
4195 timezone_bin = g_build_filename(tmp_dir, TIMEZONE_DATABASE_VERSION, TIMEZONE_DATABASE_FILE, NULL);
4196 if (isfile(timezone_bin))
4198 move_file(timezone_bin, tz->timezone_database_user);
4202 warning_dialog(_("Warning: Cannot open timezone database file"), _("See the Log Window"), GTK_STOCK_DIALOG_WARNING, NULL);
4205 g_free(timezone_bin);
4206 g_free(tmp_dir); // The folder in /tmp is deleted in exit_program_final()
4210 warning_dialog(_("Warning: Cannot open timezone database file"), _("See the Log Window"), GTK_STOCK_DIALOG_WARNING, NULL);
4212 g_free(tmp_filename);
4213 file_data_unref(fd);
4217 file_util_warning_dialog(_("Error: Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
4220 g_file_delete(tz->tmp_g_file, NULL, &error);
4221 g_object_unref(tz->tmp_g_file);
4222 tz->tmp_g_file = NULL;
4223 g_object_unref(tz->cancellable);
4224 g_object_unref(tz->timezone_database_gq);
4227 static void timezone_progress_cb(goffset current_num_bytes, goffset total_num_bytes, gpointer data)
4231 if (!g_cancellable_is_cancelled(tz->cancellable))
4233 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(tz->progress), (gdouble)current_num_bytes / total_num_bytes);
4237 static void timezone_cancel_button_cb(GenericDialog *gd, gpointer data)
4241 g_cancellable_cancel(tz->cancellable);
4244 static void timezone_database_install_cb(GtkWidget *widget, gpointer data)
4247 GError *error = NULL;
4248 GFileIOStream *io_stream;
4255 tz->tmp_g_file = g_file_new_tmp("geeqie_timezone_XXXXXX", &io_stream, &error);
4259 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
4260 log_printf("Error: Download timezone database failed:\n%s", error->message);
4261 g_error_free(error);
4262 g_object_unref(tz->tmp_g_file);
4266 tz->timezone_database_gq = g_file_new_for_uri(TIMEZONE_DATABASE_WEB);
4268 tz->gd = generic_dialog_new(_("Timezone database"), "download_timezone_database", NULL, TRUE, timezone_cancel_button_cb, tz);
4270 generic_dialog_add_message(tz->gd, GTK_STOCK_DIALOG_INFO, _("Downloading timezone database"), NULL, FALSE);
4272 tz->progress = gtk_progress_bar_new();
4273 gtk_box_pack_start(GTK_BOX(tz->gd->vbox), tz->progress, FALSE, FALSE, 0);
4274 gtk_widget_show(tz->progress);
4276 gtk_widget_show(tz->gd->dialog);
4277 tz->cancellable = g_cancellable_new();
4278 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);
4280 gtk_button_set_label(GTK_BUTTON(widget), _("Update"));
4283 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */