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);
3539 c_options->file_ops.no_trash = options->file_ops.no_trash;
3540 c_options->file_ops.use_system_trash = options->file_ops.use_system_trash;
3542 pref_radiobutton_new(group, ct_button, _("Use system Trash bin"),
3543 options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_system_trash_cb), NULL);
3545 pref_radiobutton_new(group, ct_button, _("Use no trash at all"),
3546 options->file_ops.no_trash, G_CALLBACK(use_no_cache_cb), NULL);
3548 gtk_widget_show(button);
3550 pref_spacer(group, PREF_PAD_GROUP);
3553 group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
3555 pref_checkbox_new_int(group, _("Descend folders in tree view"),
3556 options->tree_descend_subdirs, &c_options->tree_descend_subdirs);
3558 pref_checkbox_new_int(group, _("In place renaming"),
3559 options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
3561 pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
3562 options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
3564 tmp = pref_checkbox_new_int(group, _("Circular selection lists"),
3565 options->circular_selection_lists, &c_options->circular_selection_lists);
3566 gtk_widget_set_tooltip_text(tmp, _("Traverse selection lists in a circular manner"));
3568 marks = pref_checkbox_new_int(group, _("Save marks on exit"),
3569 options->marks_save, &c_options->marks_save);
3570 gtk_widget_set_tooltip_text(marks,"Note that marks linked to a keyword will be saved irrespective of this setting");
3572 with_rename = pref_checkbox_new_int(group, _("Use \"With Rename\" as default for Copy/Move dialogs"),
3573 options->with_rename, &c_options->with_rename);
3574 gtk_widget_set_tooltip_text(with_rename,"Change the default button for Copy/Move dialogs");
3576 collections_on_top = pref_checkbox_new_int(group, _("Open collections on top"),
3577 options->collections_on_top, &c_options->collections_on_top);
3578 gtk_widget_set_tooltip_text(collections_on_top,"Open collections window on top");
3580 hide_window_in_fullscreen = pref_checkbox_new_int(group, _("Hide window in fullscreen"),
3581 options->hide_window_in_fullscreen, &c_options->hide_window_in_fullscreen);
3582 gtk_widget_set_tooltip_text(hide_window_in_fullscreen,"When alt-tabbing, prevent Geeqie window showing twice");
3584 pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
3585 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
3587 pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
3588 16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
3590 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3591 add_dnd_default_action_selection_menu(table, 0, 0, _("Drag`n drop default action:"), options->dnd_default_action, &c_options->dnd_default_action);
3593 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3594 add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
3596 pref_spacer(group, PREF_PAD_GROUP);
3598 group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
3600 pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
3601 options->progressive_key_scrolling, &c_options->progressive_key_scrolling);
3602 pref_spin_new_int(group, _("Keyboard scrolling step multiplier:"), NULL,
3603 1, 32, 1, options->keyboard_scroll_step, (int *)&c_options->keyboard_scroll_step);
3604 pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
3605 options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
3606 pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
3607 options->image_lm_click_nav, &c_options->image_lm_click_nav);
3608 pref_checkbox_new_int(group, _("Open archive by left click on image"),
3609 options->image_l_click_archive, &c_options->image_l_click_archive);
3610 pref_checkbox_new_int(group, _("Play video by left click on image"),
3611 options->image_l_click_video, &c_options->image_l_click_video);
3612 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3613 add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
3615 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3616 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3617 add_mouse_selection_menu(table, 0, 0, _("Mouse button Back:"), options->mouse_button_8, &c_options->mouse_button_8);
3618 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3619 add_mouse_selection_menu(table, 0, 0, _("Mouse button Forward:"), options->mouse_button_9, &c_options->mouse_button_9);
3621 pref_spacer(group, PREF_PAD_GROUP);
3623 group = pref_group_new(vbox, FALSE, _("GPU"), GTK_ORIENTATION_VERTICAL);
3625 checkbox = pref_checkbox_new_int(group, _("Override disable GPU"),
3626 options->override_disable_gpu, &c_options->override_disable_gpu);
3627 gtk_widget_set_tooltip_text(checkbox, "Contact the developers for usage");
3630 pref_spacer(group, PREF_PAD_GROUP);
3632 group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
3634 pref_spin_new_int(group, _("Debug level:"), NULL,
3635 DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
3637 pref_checkbox_new_int(group, _("Timer data"),
3638 options->log_window.timer_data, &c_options->log_window.timer_data);
3640 pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
3641 1, 99999, 1, options->log_window_lines, &options->log_window_lines);
3645 /* accelerators tab */
3646 static void config_tab_accelerators(GtkWidget *notebook)
3652 GtkWidget *scrolled;
3653 GtkWidget *accel_view;
3654 GtkCellRenderer *renderer;
3655 GtkTreeSelection *selection;
3656 GtkTreeViewColumn *column;
3658 vbox = scrolled_notebook_page(notebook, _("Keyboard"));
3660 group = pref_group_new(vbox, TRUE, _("Accelerators"), GTK_ORIENTATION_VERTICAL);
3662 scrolled = gtk_scrolled_window_new(NULL, NULL);
3663 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
3664 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
3665 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3666 gtk_widget_show(scrolled);
3668 accel_store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
3670 accel_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(accel_store));
3671 g_object_unref(accel_store);
3672 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(accel_view));
3673 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
3675 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(accel_view), FALSE);
3677 renderer = gtk_cell_renderer_text_new();
3679 column = gtk_tree_view_column_new_with_attributes(_("Action"),
3684 gtk_tree_view_column_set_sort_column_id(column, AE_ACTION);
3685 gtk_tree_view_column_set_resizable(column, TRUE);
3686 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3689 renderer = gtk_cell_renderer_accel_new();
3690 g_signal_connect(G_OBJECT(renderer), "accel-cleared",
3691 G_CALLBACK(accel_store_cleared_cb), accel_store);
3692 g_signal_connect(G_OBJECT(renderer), "accel-edited",
3693 G_CALLBACK(accel_store_edited_cb), accel_store);
3696 g_object_set (renderer,
3698 "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
3701 column = gtk_tree_view_column_new_with_attributes(_("KEY"),
3706 gtk_tree_view_column_set_sort_column_id(column, AE_KEY);
3707 gtk_tree_view_column_set_resizable(column, TRUE);
3708 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3710 renderer = gtk_cell_renderer_text_new();
3712 column = gtk_tree_view_column_new_with_attributes(_("Tooltip"),
3717 gtk_tree_view_column_set_sort_column_id(column, AE_TOOLTIP);
3718 gtk_tree_view_column_set_resizable(column, TRUE);
3719 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3721 renderer = gtk_cell_renderer_text_new();
3723 column = gtk_tree_view_column_new_with_attributes("Accel",
3728 gtk_tree_view_column_set_sort_column_id(column, AE_ACCEL);
3729 gtk_tree_view_column_set_resizable(column, TRUE);
3730 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3732 accel_store_populate();
3733 gtk_container_add(GTK_CONTAINER(scrolled), accel_view);
3734 gtk_widget_show(accel_view);
3736 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3738 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
3739 G_CALLBACK(accel_default_cb), accel_view);
3740 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3741 gtk_widget_show(button);
3743 button = pref_button_new(NULL, NULL, _("Reset selected"), FALSE,
3744 G_CALLBACK(accel_reset_cb), accel_view);
3745 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3746 gtk_widget_show(button);
3749 /* toolbar main tab */
3750 static void config_tab_toolbar_main(GtkWidget *notebook)
3753 GtkWidget *toolbardata;
3756 lw = layout_window_list->data;
3758 vbox = scrolled_notebook_page(notebook, _("Toolbar Main"));
3760 toolbardata = toolbar_select_new(lw, TOOLBAR_MAIN);
3761 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3762 gtk_widget_show(vbox);
3765 /* toolbar status tab */
3766 static void config_tab_toolbar_status(GtkWidget *notebook)
3769 GtkWidget *toolbardata;
3772 lw = layout_window_list->data;
3774 vbox = scrolled_notebook_page(notebook, _("Toolbar Status"));
3776 toolbardata = toolbar_select_new(lw, TOOLBAR_STATUS);
3777 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3778 gtk_widget_show(vbox);
3782 static gint extension_sort_cb(gconstpointer a, gconstpointer b)
3784 return g_strcmp0((gchar *)a, (gchar *)b);
3787 static void config_tab_advanced(GtkWidget *notebook)
3791 GSList *formats_list;
3792 GList *extensions_list = NULL;
3795 GdkPixbufFormat *fm;
3797 GString *types_string = g_string_new(NULL);
3798 GtkWidget *types_string_label;
3799 GtkWidget *threads_string_label;
3800 GtkWidget *dupes_threads_spin;
3802 vbox = scrolled_notebook_page(notebook, _("Advanced"));
3803 group = pref_group_new(vbox, FALSE, _("External preview extraction"), GTK_ORIENTATION_VERTICAL);
3805 pref_checkbox_new_int(group, _("Use external preview extraction - Requires restart"), options->external_preview.enable, &c_options->external_preview.enable);
3807 pref_spacer(group, PREF_PAD_GROUP);
3809 formats_list = gdk_pixbuf_get_formats();
3811 while (formats_list)
3813 fm = formats_list->data;
3814 extensions = gdk_pixbuf_format_get_extensions(fm);
3817 while (extensions[i])
3819 extensions_list = g_list_insert_sorted(extensions_list, g_strdup(extensions[i]), extension_sort_cb);
3823 g_strfreev(extensions);
3824 formats_list = formats_list->next;
3827 while (extensions_list)
3829 if (types_string->len == 0)
3831 types_string = g_string_append(types_string, extensions_list->data);
3835 types_string = g_string_append(types_string, ", ");
3836 types_string = g_string_append(types_string, extensions_list->data);
3839 extensions_list = extensions_list->next;
3842 types_string = g_string_prepend(types_string, _("Usable file types:\n"));
3843 types_string_label = pref_label_new(group, types_string->str);
3844 gtk_label_set_line_wrap(GTK_LABEL(types_string_label), TRUE);
3846 pref_spacer(group, PREF_PAD_GROUP);
3848 group = pref_group_new(vbox, FALSE, _("File identification tool"), GTK_ORIENTATION_VERTICAL);
3849 external_preview_select_entry = gtk_entry_new();
3850 tabcomp = tab_completion_new(&external_preview_select_entry, options->external_preview.select, NULL, NULL, NULL, NULL);
3851 tab_completion_add_select_button(external_preview_select_entry, _("Select file identification tool"), FALSE);
3852 gtk_box_pack_start(GTK_BOX(group), tabcomp, TRUE, TRUE, 0);
3853 gtk_widget_show(tabcomp);
3855 group = pref_group_new(vbox, FALSE, _("Preview extraction tool"), GTK_ORIENTATION_VERTICAL);
3856 external_preview_extract_entry = gtk_entry_new();
3857 tabcomp = tab_completion_new(&external_preview_extract_entry, options->external_preview.extract, NULL, NULL, NULL, NULL);
3858 tab_completion_add_select_button(external_preview_extract_entry, _("Select preview extraction tool"), FALSE);
3859 gtk_box_pack_start(GTK_BOX(group), tabcomp, TRUE, TRUE, 0);
3860 gtk_widget_show(tabcomp);
3862 gtk_widget_show(vbox);
3864 g_slist_free(formats_list);
3865 string_list_free(extensions_list);
3866 g_string_free(types_string, TRUE);
3868 pref_spacer(group, PREF_PAD_GROUP);
3870 pref_line(vbox, PREF_PAD_SPACE);
3871 group = pref_group_new(vbox, FALSE, _("Thread pool limits"), GTK_ORIENTATION_VERTICAL);
3873 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.");
3874 gtk_label_set_line_wrap(GTK_LABEL(threads_string_label), TRUE);
3876 pref_spacer(vbox, PREF_PAD_GROUP);
3878 dupes_threads_spin = pref_spin_new_int(vbox, _("Duplicate check:"), _("max. threads"), 0, get_cpu_cores(), 1, options->threads.duplicates, &c_options->threads.duplicates);
3879 gtk_widget_set_tooltip_markup(dupes_threads_spin, _("Set to 0 for unlimited"));
3883 static void config_tab_stereo(GtkWidget *notebook)
3891 GtkWidget *fs_button;
3892 vbox = scrolled_notebook_page(notebook, _("Stereo"));
3894 group = pref_group_new(vbox, FALSE, _("Windowed stereo mode"), GTK_ORIENTATION_VERTICAL);
3896 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3897 add_stereo_mode_menu(table, 0, 0, _("Windowed stereo mode"), options->stereo.mode, &c_options->stereo.mode, FALSE);
3899 table = pref_table_new(group, 2, 2, TRUE, FALSE);
3900 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3901 pref_checkbox_new_int(box, _("Mirror left image"),
3902 options->stereo.mode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.mirror_left);
3903 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3904 pref_checkbox_new_int(box, _("Flip left image"),
3905 options->stereo.mode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.flip_left);
3906 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3907 pref_checkbox_new_int(box, _("Mirror right image"),
3908 options->stereo.mode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.mirror_right);
3909 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3910 pref_checkbox_new_int(box, _("Flip right image"),
3911 options->stereo.mode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.flip_right);
3912 pref_checkbox_new_int(group, _("Swap left and right images"),
3913 options->stereo.mode & PR_STEREO_SWAP, &c_options->stereo.tmp.swap);
3914 pref_checkbox_new_int(group, _("Disable stereo mode on single image source"),
3915 options->stereo.mode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.temp_disable);
3917 group = pref_group_new(vbox, FALSE, _("Fullscreen stereo mode"), GTK_ORIENTATION_VERTICAL);
3918 fs_button = pref_checkbox_new_int(group, _("Use different settings for fullscreen"),
3919 options->stereo.enable_fsmode, &c_options->stereo.enable_fsmode);
3920 box2 = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
3921 pref_checkbox_link_sensitivity(fs_button, box2);
3922 table = pref_table_new(box2, 2, 1, FALSE, FALSE);
3923 add_stereo_mode_menu(table, 0, 0, _("Fullscreen stereo mode"), options->stereo.fsmode, &c_options->stereo.fsmode, TRUE);
3924 table = pref_table_new(box2, 2, 2, TRUE, FALSE);
3925 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3926 pref_checkbox_new_int(box, _("Mirror left image"),
3927 options->stereo.fsmode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.fs_mirror_left);
3928 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3929 pref_checkbox_new_int(box, _("Flip left image"),
3930 options->stereo.fsmode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.fs_flip_left);
3931 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3932 pref_checkbox_new_int(box, _("Mirror right image"),
3933 options->stereo.fsmode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.fs_mirror_right);
3934 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3935 pref_checkbox_new_int(box, _("Flip right image"),
3936 options->stereo.fsmode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.fs_flip_right);
3937 pref_checkbox_new_int(box2, _("Swap left and right images"),
3938 options->stereo.fsmode & PR_STEREO_SWAP, &c_options->stereo.tmp.fs_swap);
3939 pref_checkbox_new_int(box2, _("Disable stereo mode on single image source"),
3940 options->stereo.fsmode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.fs_temp_disable);
3942 group2 = pref_group_new(box2, FALSE, _("Fixed position"), GTK_ORIENTATION_VERTICAL);
3943 table = pref_table_new(group2, 5, 3, FALSE, FALSE);
3944 pref_table_spin_new_int(table, 0, 0, _("Width"), NULL,
3945 1, 5000, 1, options->stereo.fixed_w, &c_options->stereo.fixed_w);
3946 pref_table_spin_new_int(table, 3, 0, _("Height"), NULL,
3947 1, 5000, 1, options->stereo.fixed_h, &c_options->stereo.fixed_h);
3948 pref_table_spin_new_int(table, 0, 1, _("Left X"), NULL,
3949 0, 5000, 1, options->stereo.fixed_x1, &c_options->stereo.fixed_x1);
3950 pref_table_spin_new_int(table, 3, 1, _("Left Y"), NULL,
3951 0, 5000, 1, options->stereo.fixed_y1, &c_options->stereo.fixed_y1);
3952 pref_table_spin_new_int(table, 0, 2, _("Right X"), NULL,
3953 0, 5000, 1, options->stereo.fixed_x2, &c_options->stereo.fixed_x2);
3954 pref_table_spin_new_int(table, 3, 2, _("Right Y"), NULL,
3955 0, 5000, 1, options->stereo.fixed_y2, &c_options->stereo.fixed_y2);
3959 /* Main preferences window */
3960 static void config_window_create(LayoutWindow *lw)
3962 GtkWidget *win_vbox;
3964 GtkWidget *notebook;
3966 GtkWidget *ct_button;
3968 if (!c_options) c_options = init_options(NULL);
3970 configwindow = window_new(GTK_WINDOW_TOPLEVEL, "preferences", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Preferences"));
3971 DEBUG_NAME(configwindow);
3972 gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
3973 g_signal_connect(G_OBJECT(configwindow), "delete_event",
3974 G_CALLBACK(config_window_delete), NULL);
3975 if (options->save_dialog_window_positions)
3977 gtk_window_resize(GTK_WINDOW(configwindow), lw->options.preferences_window.w, lw->options.preferences_window.h);
3978 gtk_window_move(GTK_WINDOW(configwindow), lw->options.preferences_window.x, lw->options.preferences_window.y);
3982 gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
3984 gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
3985 gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
3987 win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
3988 gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
3989 gtk_widget_show(win_vbox);
3991 notebook = gtk_notebook_new();
3992 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_LEFT);
3993 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE);
3994 gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
3996 config_tab_general(notebook);
3997 config_tab_image(notebook);
3998 config_tab_osd(notebook);
3999 config_tab_windows(notebook);
4000 config_tab_accelerators(notebook);
4001 config_tab_files(notebook);
4002 config_tab_metadata(notebook);
4003 config_tab_keywords(notebook);
4004 config_tab_color(notebook);
4005 config_tab_stereo(notebook);
4006 config_tab_behavior(notebook);
4007 config_tab_toolbar_main(notebook);
4008 config_tab_toolbar_status(notebook);
4009 config_tab_advanced(notebook);
4011 gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), lw->options.preferences_window.page_number);
4013 hbox = gtk_hbutton_box_new();
4014 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
4015 gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
4016 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
4017 gtk_widget_show(hbox);
4019 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
4020 G_CALLBACK(config_window_help_cb), notebook);
4021 gtk_container_add(GTK_CONTAINER(hbox), button);
4022 gtk_widget_set_can_default(button, TRUE);
4023 gtk_widget_show(button);
4025 button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
4026 G_CALLBACK(config_window_ok_cb), notebook);
4027 gtk_container_add(GTK_CONTAINER(hbox), button);
4028 gtk_widget_set_can_default(button, TRUE);
4029 gtk_widget_grab_default(button);
4030 gtk_widget_show(button);
4034 button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
4035 G_CALLBACK(config_window_close_cb), NULL);
4036 gtk_container_add(GTK_CONTAINER(hbox), button);
4037 gtk_widget_set_can_default(button, TRUE);
4038 gtk_widget_show(button);
4040 if (!generic_dialog_get_alternative_button_order(configwindow))
4042 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
4045 gtk_widget_show(notebook);
4047 gtk_widget_show(configwindow);
4051 *-----------------------------------------------------------------------------
4052 * config window show (public)
4053 *-----------------------------------------------------------------------------
4056 void show_config_window(LayoutWindow *lw)
4060 gtk_window_present(GTK_WINDOW(configwindow));
4064 config_window_create(lw);
4073 void show_about_window(LayoutWindow *lw)
4075 GdkPixbuf *pixbuf_logo;
4076 GdkPixbuf *pixbuf_icon;
4077 gchar *authors[1000];
4082 gchar *timezone_path;
4085 #define LINE_LENGTH 1000
4086 gchar line[LINE_LENGTH];
4088 copyright = g_string_new(NULL);
4089 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");
4091 timezone_path = g_build_filename(get_rc_dir(), TIMEZONE_DATABASE_FILE, NULL);
4092 if (g_file_test(timezone_path, G_FILE_TEST_EXISTS))
4094 cd = ZDOpenDatabase(timezone_path);
4097 copyright = g_string_append(copyright, ZDGetNotice(cd));
4101 log_printf("Error: Init of timezone database %s failed\n", timezone_path);
4103 ZDCloseDatabase(cd);
4105 g_free(timezone_path);
4108 path = g_build_filename(gq_helpdir, "AUTHORS", NULL);
4109 fp = fopen(path, "r");
4112 while(fgets(line, LINE_LENGTH, fp))
4114 /* get rid of ending \n from fgets */
4115 line[strlen(line) - 1] = '\0';
4116 authors[i_authors] = g_strdup(line);
4119 authors[i_authors] = NULL;
4124 comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
4125 "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
4127 pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
4128 pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
4129 gtk_show_about_dialog(GTK_WINDOW(lw->window),
4130 "title", _("About Geeqie"),
4132 "program-name", GQ_APPNAME,
4134 "logo", pixbuf_logo,
4135 "icon", pixbuf_icon,
4136 "website", GQ_WEBSITE,
4137 "website-label", "Website",
4138 "comments", comment,
4140 "translator-credits", _("translator-credits"),
4141 "wrap-license", TRUE,
4142 "license", copyright->str,
4145 g_string_free(copyright, TRUE);
4148 while(n < i_authors)
4158 static void image_overlay_set_text_colours()
4160 c_options->image_overlay.text_red = options->image_overlay.text_red;
4161 c_options->image_overlay.text_green = options->image_overlay.text_green;
4162 c_options->image_overlay.text_blue = options->image_overlay.text_blue;
4163 c_options->image_overlay.text_alpha = options->image_overlay.text_alpha;
4164 c_options->image_overlay.background_red = options->image_overlay.background_red;
4165 c_options->image_overlay.background_green = options->image_overlay.background_green;
4166 c_options->image_overlay.background_blue = options->image_overlay.background_blue;
4167 c_options->image_overlay.background_alpha = options->image_overlay.background_alpha;
4171 *-----------------------------------------------------------------------------
4172 * timezone database routines
4173 *-----------------------------------------------------------------------------
4176 static void timezone_async_ready_cb(GObject *source_object, GAsyncResult *res, gpointer data)
4178 GError *error = NULL;
4180 gchar *tmp_filename;
4181 gchar *timezone_bin;
4182 gchar *tmp_dir = NULL;
4185 if (!g_cancellable_is_cancelled(tz->cancellable))
4187 generic_dialog_close(tz->gd);
4191 if (g_file_copy_finish(G_FILE(source_object), res, &error))
4193 tmp_filename = g_file_get_path(tz->tmp_g_file);
4194 fd = file_data_new_simple(tmp_filename);
4195 tmp_dir = open_archive(fd);
4199 timezone_bin = g_build_filename(tmp_dir, TIMEZONE_DATABASE_VERSION, TIMEZONE_DATABASE_FILE, NULL);
4200 if (isfile(timezone_bin))
4202 move_file(timezone_bin, tz->timezone_database_user);
4206 warning_dialog(_("Warning: Cannot open timezone database file"), _("See the Log Window"), GTK_STOCK_DIALOG_WARNING, NULL);
4209 g_free(timezone_bin);
4210 g_free(tmp_dir); // The folder in /tmp is deleted in exit_program_final()
4214 warning_dialog(_("Warning: Cannot open timezone database file"), _("See the Log Window"), GTK_STOCK_DIALOG_WARNING, NULL);
4216 g_free(tmp_filename);
4217 file_data_unref(fd);
4221 file_util_warning_dialog(_("Error: Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
4224 g_file_delete(tz->tmp_g_file, NULL, &error);
4225 g_object_unref(tz->tmp_g_file);
4226 tz->tmp_g_file = NULL;
4227 g_object_unref(tz->cancellable);
4228 g_object_unref(tz->timezone_database_gq);
4231 static void timezone_progress_cb(goffset current_num_bytes, goffset total_num_bytes, gpointer data)
4235 if (!g_cancellable_is_cancelled(tz->cancellable))
4237 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(tz->progress), (gdouble)current_num_bytes / total_num_bytes);
4241 static void timezone_cancel_button_cb(GenericDialog *gd, gpointer data)
4245 g_cancellable_cancel(tz->cancellable);
4248 static void timezone_database_install_cb(GtkWidget *widget, gpointer data)
4251 GError *error = NULL;
4252 GFileIOStream *io_stream;
4259 tz->tmp_g_file = g_file_new_tmp("geeqie_timezone_XXXXXX", &io_stream, &error);
4263 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
4264 log_printf("Error: Download timezone database failed:\n%s", error->message);
4265 g_error_free(error);
4266 g_object_unref(tz->tmp_g_file);
4270 tz->timezone_database_gq = g_file_new_for_uri(TIMEZONE_DATABASE_WEB);
4272 tz->gd = generic_dialog_new(_("Timezone database"), "download_timezone_database", NULL, TRUE, timezone_cancel_button_cb, tz);
4274 generic_dialog_add_message(tz->gd, GTK_STOCK_DIALOG_INFO, _("Downloading timezone database"), NULL, FALSE);
4276 tz->progress = gtk_progress_bar_new();
4277 gtk_box_pack_start(GTK_BOX(tz->gd->vbox), tz->progress, FALSE, FALSE, 0);
4278 gtk_widget_show(tz->progress);
4280 gtk_widget_show(tz->gd->dialog);
4281 tz->cancellable = g_cancellable_new();
4282 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);
4284 gtk_button_set_label(GTK_BUTTON(widget), _("Update"));
4287 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */