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 *geeqie_org;
1998 gboolean internet_available;
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 geeqie_org = g_network_address_parse_uri(GQ_WEBSITE, 80, NULL);
2189 internet_available = g_network_monitor_can_reach(net_mon, geeqie_org, NULL, NULL);
2190 g_object_unref(geeqie_org);
2192 group = pref_group_new(vbox, FALSE, _("Timezone database"), GTK_ORIENTATION_VERTICAL);
2193 hbox = pref_box_new(group, TRUE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2195 if (!internet_available)
2197 gtk_widget_set_sensitive(group, FALSE);
2200 tz = g_new0(TZData, 1);
2202 path = path_from_utf8(TIMEZONE_DATABASE_WEB);
2203 basename = g_path_get_basename(path);
2204 tz->timezone_database_user = g_build_filename(get_rc_dir(), TIMEZONE_DATABASE_FILE, NULL);
2208 if (isfile(tz->timezone_database_user))
2210 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Update"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2214 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Install"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2217 download_locn = g_strconcat(_("Download database from: "), TIMEZONE_DATABASE_WEB, NULL);
2218 pref_label_new(GTK_WIDGET(hbox), download_locn);
2219 g_free(download_locn);
2221 if (!internet_available)
2223 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"));
2227 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"));
2229 gtk_widget_show(button);
2231 pref_spacer(group, PREF_PAD_GROUP);
2233 group = pref_group_new(vbox, FALSE, _("On-line help search engine"), GTK_ORIENTATION_VERTICAL);
2235 help_search_engine_entry = gtk_entry_new();
2236 gtk_entry_set_text(GTK_ENTRY(help_search_engine_entry), options->help_search_engine);
2237 gtk_box_pack_start(GTK_BOX(group), help_search_engine_entry, FALSE, FALSE, 0);
2238 gtk_widget_show(help_search_engine_entry);
2240 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"));
2242 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2243 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2244 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2245 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2246 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2247 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2248 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2249 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2250 g_signal_connect(GTK_ENTRY(help_search_engine_entry), "icon-press",
2251 G_CALLBACK(help_search_engine_entry_icon_cb),
2252 help_search_engine_entry);
2256 static void config_tab_image(GtkWidget *notebook)
2261 GtkWidget *ct_button;
2262 GtkWidget *enlargement_button;
2265 GtkWidget *two_pass;
2267 GtkWidget *gpu_accel;
2270 vbox = scrolled_notebook_page(notebook, _("Image"));
2272 group = pref_group_new(vbox, FALSE, _("Zoom"), GTK_ORIENTATION_VERTICAL);
2274 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2275 add_quality_menu(table, 0, 0, _("Quality:"), options->image.zoom_quality, &c_options->image.zoom_quality);
2276 if (options->image.use_clutter_renderer && !options->disable_gpu)
2278 gtk_widget_set_sensitive(table, FALSE);
2282 gpu_accel = pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library (Requires restart)"),
2283 options->image.use_clutter_renderer, &c_options->image.use_clutter_renderer);
2284 if (options->disable_gpu && !options->override_disable_gpu)
2286 gtk_widget_set_sensitive(gpu_accel, FALSE);
2290 two_pass = pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"),
2291 options->image.zoom_2pass, &c_options->image.zoom_2pass);
2292 if (options->image.use_clutter_renderer && !options->disable_gpu)
2294 gtk_widget_set_sensitive(two_pass, FALSE);
2297 c_options->image.zoom_increment = options->image.zoom_increment;
2298 spin = pref_spin_new(group, _("Zoom increment:"), NULL,
2299 0.01, 4.0, 0.01, 2, (gdouble)options->image.zoom_increment / 100.0,
2300 G_CALLBACK(zoom_increment_cb), NULL);
2301 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2303 c_options->image.zoom_style = options->image.zoom_style;
2304 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2305 add_zoom_style_selection_menu(table, 0, 0, _("Zoom style:"), options->image.zoom_style, &c_options->image.zoom_style);
2307 group = pref_group_new(vbox, FALSE, _("Fit image to window"), GTK_ORIENTATION_VERTICAL);
2309 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2310 enlargement_button = pref_checkbox_new_int(hbox, _("Allow enlargement of image (max. size in %)"),
2311 options->image.zoom_to_fit_allow_expand, &c_options->image.zoom_to_fit_allow_expand);
2312 spin = pref_spin_new_int(hbox, NULL, NULL,
2314 options->image.max_enlargement_size, &c_options->image.max_enlargement_size);
2315 pref_checkbox_link_sensitivity(enlargement_button, spin);
2316 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."));
2318 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2319 ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (% of actual window):"),
2320 options->image.limit_autofit_size, &c_options->image.limit_autofit_size);
2321 spin = pref_spin_new_int(hbox, NULL, NULL,
2323 options->image.max_autofit_size, &c_options->image.max_autofit_size);
2324 pref_checkbox_link_sensitivity(ct_button, spin);
2325 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."));
2327 group = pref_group_new(vbox, FALSE, _("Tile size"), GTK_ORIENTATION_VERTICAL);
2328 gtk_widget_set_sensitive(group, !options->image.use_clutter_renderer);
2330 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2331 spin = pref_spin_new_int(hbox, _("Pixels"), _("(Requires restart)"),
2333 options->image.tile_size, &c_options->image.tile_size);
2334 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."));
2336 group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
2338 pref_checkbox_new_int(group, _("Use custom border color in window mode"),
2339 options->image.use_custom_border_color, &c_options->image.use_custom_border_color);
2341 pref_checkbox_new_int(group, _("Use custom border color in fullscreen mode"),
2342 options->image.use_custom_border_color_in_fullscreen, &c_options->image.use_custom_border_color_in_fullscreen);
2344 pref_color_button_new(group, _("Border color"), &options->image.border_color,
2345 G_CALLBACK(pref_color_button_set_cb), &c_options->image.border_color);
2347 c_options->image.border_color = options->image.border_color;
2349 pref_color_button_new(group, _("Alpha channel color 1"), &options->image.alpha_color_1,
2350 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_1);
2352 pref_color_button_new(group, _("Alpha channel color 2"), &options->image.alpha_color_2,
2353 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_2);
2355 c_options->image.alpha_color_1 = options->image.alpha_color_1;
2356 c_options->image.alpha_color_2 = options->image.alpha_color_2;
2361 static void save_default_window_layout_cb(GtkWidget *widget, gpointer data)
2363 LayoutWindow *lw = NULL;
2364 gchar *default_path;
2367 /* Get current lw */
2370 tmp_id = lw->options.id;
2371 lw->options.id = g_strdup("lw_default");
2373 default_path = g_build_filename(get_rc_dir(), DEFAULT_WINDOW_LAYOUT, NULL);
2374 save_default_layout_options_to_file(default_path, options, lw);
2375 g_free(lw->options.id);
2376 lw->options.id = tmp_id;
2377 g_free(default_path);
2380 #if GTK_CHECK_VERSION(3,22,0)
2381 static gboolean popover_cb(gpointer data)
2383 GtkPopover *popover = data;
2385 gtk_popover_popdown(popover);
2390 static void default_layout_changed_cb(GtkWidget *button, GtkPopover *popover)
2392 gtk_popover_popup(popover);
2394 g_timeout_add(2000, popover_cb, popover);
2397 static GtkWidget *create_popover(GtkWidget *parent, GtkWidget *child, GtkPositionType pos)
2401 popover = gtk_popover_new(parent);
2402 gtk_popover_set_position(GTK_POPOVER (popover), pos);
2403 gtk_container_add (GTK_CONTAINER(popover), child);
2404 gtk_container_set_border_width(GTK_CONTAINER (popover), 6);
2405 gtk_widget_show (child);
2411 static void config_tab_windows(GtkWidget *notebook)
2416 GtkWidget *subgroup;
2418 GtkWidget *ct_button;
2421 vbox = scrolled_notebook_page(notebook, _("Windows"));
2423 group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
2425 ct_button = pref_checkbox_new_int(group, _("Remember session"),
2426 options->save_window_positions, &c_options->save_window_positions);
2428 button = pref_checkbox_new_int(group, _("Use saved window positions also for new windows"),
2429 options->use_saved_window_positions_for_new_windows, &c_options->use_saved_window_positions_for_new_windows);
2430 pref_checkbox_link_sensitivity(ct_button, button);
2432 button = pref_checkbox_new_int(group, _("Remember window workspace"),
2433 options->save_window_workspace, &c_options->save_window_workspace);
2434 pref_checkbox_link_sensitivity(ct_button, button);
2436 pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
2437 options->tools_restore_state, &c_options->tools_restore_state);
2439 pref_checkbox_new_int(group, _("Remember dialog window positions"),
2440 options->save_dialog_window_positions, &c_options->save_dialog_window_positions);
2442 pref_checkbox_new_int(group, _("Show window IDs"),
2443 options->show_window_ids, &c_options->show_window_ids);
2445 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2446 pref_label_new(subgroup, _("Use current layout for default: "));
2447 button = pref_button_new(subgroup, NULL, _("Set"), FALSE, G_CALLBACK(save_default_window_layout_cb), NULL);
2449 #if GTK_CHECK_VERSION(3,22,0)
2452 popover = create_popover(button, gtk_label_new(_("Current window layout\nhas been set as default")), GTK_POS_TOP);
2453 gtk_popover_set_modal(GTK_POPOVER (popover), FALSE);
2454 g_signal_connect(button, "clicked", G_CALLBACK(default_layout_changed_cb), popover);
2457 group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
2459 pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
2460 options->image.fit_window_to_image, &c_options->image.fit_window_to_image);
2462 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2463 ct_button = pref_checkbox_new_int(hbox, _("Limit size when auto-sizing window (%):"),
2464 options->image.limit_window_size, &c_options->image.limit_window_size);
2465 spin = pref_spin_new_int(hbox, NULL, NULL,
2467 options->image.max_window_size, &c_options->image.max_window_size);
2468 pref_checkbox_link_sensitivity(ct_button, spin);
2470 group = pref_group_new(vbox, FALSE, _("Full screen"), GTK_ORIENTATION_VERTICAL);
2472 c_options->fullscreen.screen = options->fullscreen.screen;
2473 c_options->fullscreen.above = options->fullscreen.above;
2474 hbox = fullscreen_prefs_selection_new(_("Location:"), &c_options->fullscreen.screen, &c_options->fullscreen.above);
2475 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2476 gtk_widget_show(hbox);
2478 pref_checkbox_new_int(group, _("Smooth image flip"),
2479 options->fullscreen.clean_flip, &c_options->fullscreen.clean_flip);
2480 pref_checkbox_new_int(group, _("Disable screen saver"),
2481 options->fullscreen.disable_saver, &c_options->fullscreen.disable_saver);
2484 #define PRE_FORMATTED_COLUMNS 5
2485 static void config_tab_osd(GtkWidget *notebook)
2491 GtkWidget *image_overlay_template_view;
2492 GtkWidget *scrolled;
2493 GtkWidget *scrolled_pre_formatted;
2494 GtkTextBuffer *buffer;
2496 GtkWidget *subgroup;
2498 vbox = scrolled_notebook_page(notebook, _("OSD"));
2500 image_overlay_template_view = gtk_text_view_new();
2502 group = pref_group_new(vbox, FALSE, _("Overlay Screen Display"), GTK_ORIENTATION_VERTICAL);
2504 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2506 scrolled_pre_formatted = osd_new(PRE_FORMATTED_COLUMNS, image_overlay_template_view);
2507 gtk_widget_set_size_request(scrolled_pre_formatted, 200, 150);
2508 gtk_box_pack_start(GTK_BOX(subgroup), scrolled_pre_formatted, FALSE, FALSE, 0);
2509 gtk_widget_show(scrolled_pre_formatted);
2510 gtk_widget_show(subgroup);
2512 pref_line(group, PREF_PAD_GAP);
2514 pref_label_new(group, _("Image overlay template"));
2516 scrolled = gtk_scrolled_window_new(NULL, NULL);
2517 gtk_widget_set_size_request(scrolled, 200, 150);
2518 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2519 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
2520 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2521 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 5);
2522 gtk_widget_show(scrolled);
2524 gtk_widget_set_tooltip_markup(image_overlay_template_view,
2525 _("Extensive formatting options are shown in the Help file"));
2527 gtk_container_add(GTK_CONTAINER(scrolled), image_overlay_template_view);
2528 gtk_widget_show(image_overlay_template_view);
2530 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2532 #if GTK_CHECK_VERSION(3,4,0)
2533 button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
2534 G_CALLBACK(image_overlay_set_font_cb), notebook);
2536 button = gtk_font_button_new();
2537 gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Image Overlay Font");
2538 gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->image_overlay.font);
2539 g_signal_connect(G_OBJECT(button), "font-set",
2540 G_CALLBACK(image_overlay_set_font_cb),NULL);
2542 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2543 gtk_widget_show(button);
2545 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Text"), FALSE,
2546 G_CALLBACK(image_overlay_set_text_colour_cb), NULL);
2547 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2548 gtk_widget_show(button);
2550 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Background"), FALSE,
2551 G_CALLBACK(image_overlay_set_background_colour_cb), NULL);
2552 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2553 gtk_widget_show(button);
2554 image_overlay_set_text_colours();
2556 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2557 G_CALLBACK(image_overlay_default_template_cb), image_overlay_template_view);
2558 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2559 gtk_widget_show(button);
2561 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
2562 G_CALLBACK(image_overlay_help_cb), NULL);
2563 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2564 gtk_widget_show(button);
2566 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_overlay_template_view));
2567 if (options->image_overlay.template_string) gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
2568 g_signal_connect(G_OBJECT(buffer), "changed",
2569 G_CALLBACK(image_overlay_template_view_changed_cb), image_overlay_template_view);
2571 pref_line(group, PREF_PAD_GAP);
2573 group = pref_group_new(vbox, FALSE, _("Exif, XMP or IPTC tags"), GTK_ORIENTATION_VERTICAL);
2574 hbox = gtk_hbox_new(FALSE, 0);
2575 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2576 gtk_widget_show(hbox);
2577 label = gtk_label_new(_("%Exif.Image.Orientation%"));
2578 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2579 gtk_widget_show(label);
2580 pref_spacer(group,TRUE);
2582 group = pref_group_new(vbox, FALSE, _("Field separators"), GTK_ORIENTATION_VERTICAL);
2583 hbox = gtk_hbox_new(FALSE, 0);
2584 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2585 gtk_widget_show(hbox);
2586 label = gtk_label_new(_("Separator shown only if both fields are non-null:\n%formatted.ShutterSpeed%|%formatted.ISOSpeedRating%"));
2587 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2588 gtk_widget_show(label);
2589 pref_spacer(group,TRUE);
2591 group = pref_group_new(vbox, FALSE, _("Field maximum length"), GTK_ORIENTATION_VERTICAL);
2592 hbox = gtk_hbox_new(FALSE, 0);
2593 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2594 gtk_widget_show(hbox);
2595 label = gtk_label_new(_("%path:39%"));
2596 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2597 gtk_widget_show(label);
2598 pref_spacer(group,TRUE);
2600 group = pref_group_new(vbox, FALSE, _("Pre- and post- text"), GTK_ORIENTATION_VERTICAL);
2601 hbox = gtk_hbox_new(FALSE, 0);
2602 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2603 gtk_widget_show(hbox);
2604 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%"));
2605 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2606 gtk_widget_show(label);
2607 pref_spacer(group,TRUE);
2609 group = pref_group_new(vbox, FALSE, _("Pango markup"), GTK_ORIENTATION_VERTICAL);
2610 hbox = gtk_hbox_new(FALSE, 0);
2611 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2612 gtk_widget_show(hbox);
2613 label = gtk_label_new(_("<b>bold</b>\n<u>underline</u>\n<i>italic</i>\n<s>strikethrough</s>"));
2614 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2615 gtk_widget_show(label);
2618 static GtkTreeModel *create_class_model(void)
2620 GtkListStore *model;
2624 /* create list store */
2625 model = gtk_list_store_new(1, G_TYPE_STRING);
2626 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
2628 gtk_list_store_append(model, &iter);
2629 gtk_list_store_set(model, &iter, 0, _(format_class_list[i]), -1);
2631 return GTK_TREE_MODEL (model);
2636 static gint filter_table_sort_cb(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer data)
2638 gint n = GPOINTER_TO_INT(data);
2640 FilterEntry *filter_a;
2641 FilterEntry *filter_b;
2643 gtk_tree_model_get(model, a, 0, &filter_a, -1);
2644 gtk_tree_model_get(model, b, 0, &filter_b, -1);
2648 case FILETYPES_COLUMN_DESCRIPTION:
2650 ret = g_utf8_collate(filter_a->description, filter_b->description);
2653 case FILETYPES_COLUMN_CLASS:
2655 ret = g_strcmp0(format_class_list[filter_a->file_class], format_class_list[filter_b->file_class]);
2658 case FILETYPES_COLUMN_WRITABLE:
2660 ret = filter_a->writable - filter_b->writable;
2663 case FILETYPES_COLUMN_SIDECAR:
2665 ret = filter_a->allow_sidecar - filter_b->allow_sidecar;
2669 g_return_val_if_reached(0);
2675 static gboolean search_function_cb(GtkTreeModel *model, gint column, const gchar *key, GtkTreeIter *iter, gpointer search_data)
2678 gboolean ret = TRUE;
2680 gtk_tree_model_get(model, iter, 0, &fe, -1);
2682 if (g_strstr_len(fe->extensions, -1, key))
2690 static void config_tab_files(GtkWidget *notebook)
2697 GtkWidget *ct_button;
2698 GtkWidget *scrolled;
2699 GtkWidget *filter_view;
2700 GtkCellRenderer *renderer;
2701 GtkTreeSelection *selection;
2702 GtkTreeViewColumn *column;
2704 vbox = scrolled_notebook_page(notebook, _("Files"));
2706 group = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2708 pref_checkbox_new_int(group, _("Show hidden files or folders"),
2709 options->file_filter.show_hidden_files, &c_options->file_filter.show_hidden_files);
2710 pref_checkbox_new_int(group, _("Show parent folder (..)"),
2711 options->file_filter.show_parent_directory, &c_options->file_filter.show_parent_directory);
2712 pref_checkbox_new_int(group, _("Case sensitive sort"),
2713 options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
2714 pref_checkbox_new_int(group, _("Natural sort order"),
2715 options->file_sort.natural, &c_options->file_sort.natural);
2716 pref_checkbox_new_int(group, _("Disable file extension checks"),
2717 options->file_filter.disable_file_extension_checks, &c_options->file_filter.disable_file_extension_checks);
2719 ct_button = pref_checkbox_new_int(group, _("Disable File Filtering"),
2720 options->file_filter.disable, &c_options->file_filter.disable);
2723 group = pref_group_new(vbox, FALSE, _("Grouping sidecar extensions"), GTK_ORIENTATION_VERTICAL);
2725 sidecar_ext_entry = gtk_entry_new();
2726 gtk_entry_set_text(GTK_ENTRY(sidecar_ext_entry), options->sidecar.ext);
2727 gtk_box_pack_start(GTK_BOX(group), sidecar_ext_entry, FALSE, FALSE, 0);
2728 gtk_widget_show(sidecar_ext_entry);
2730 group = pref_group_new(vbox, TRUE, _("File types"), GTK_ORIENTATION_VERTICAL);
2732 frame = pref_group_parent(group);
2733 g_signal_connect(G_OBJECT(ct_button), "toggled",
2734 G_CALLBACK(filter_disable_cb), frame);
2735 gtk_widget_set_sensitive(frame, !options->file_filter.disable);
2737 scrolled = gtk_scrolled_window_new(NULL, NULL);
2738 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2739 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2740 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2741 gtk_widget_show(scrolled);
2743 filter_store = gtk_list_store_new(1, G_TYPE_POINTER);
2744 filter_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(filter_store));
2745 g_object_unref(filter_store);
2746 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
2747 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
2749 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), FALSE);
2751 column = gtk_tree_view_column_new();
2752 gtk_tree_view_column_set_title(column, _("Filter"));
2753 gtk_tree_view_column_set_resizable(column, TRUE);
2755 renderer = gtk_cell_renderer_toggle_new();
2756 g_signal_connect(G_OBJECT(renderer), "toggled",
2757 G_CALLBACK(filter_store_enable_cb), filter_store);
2758 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2759 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2760 GINT_TO_POINTER(FE_ENABLE), NULL);
2762 renderer = gtk_cell_renderer_text_new();
2763 g_signal_connect(G_OBJECT(renderer), "edited",
2764 G_CALLBACK(filter_store_ext_edit_cb), filter_store);
2765 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2766 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2767 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2768 GINT_TO_POINTER(FE_EXTENSION), NULL);
2769 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2771 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), TRUE);
2772 gtk_tree_view_set_search_column(GTK_TREE_VIEW(filter_view), FILETYPES_COLUMN_FILTER);
2773 gtk_tree_view_set_search_equal_func(GTK_TREE_VIEW(filter_view), search_function_cb, NULL, NULL);
2775 column = gtk_tree_view_column_new();
2776 gtk_tree_view_column_set_title(column, _("Description"));
2777 gtk_tree_view_column_set_resizable(column, TRUE);
2778 gtk_tree_view_column_set_fixed_width(column, 200);
2779 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
2781 renderer = gtk_cell_renderer_text_new();
2782 g_signal_connect(G_OBJECT(renderer), "edited",
2783 G_CALLBACK(filter_store_desc_edit_cb), filter_store);
2784 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2785 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2786 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2787 GINT_TO_POINTER(FE_DESCRIPTION), NULL);
2788 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2789 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);
2790 gtk_tree_view_column_set_sort_column_id(column, FILETYPES_COLUMN_DESCRIPTION);
2792 column = gtk_tree_view_column_new();
2793 gtk_tree_view_column_set_title(column, _("Class"));
2794 gtk_tree_view_column_set_resizable(column, TRUE);
2795 renderer = gtk_cell_renderer_combo_new();
2796 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE,
2797 "model", create_class_model(),
2802 g_signal_connect(G_OBJECT(renderer), "edited",
2803 G_CALLBACK(filter_store_class_edit_cb), filter_store);
2804 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2805 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2806 GINT_TO_POINTER(FE_CLASS), NULL);
2807 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2808 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(filter_store), FILETYPES_COLUMN_CLASS, filter_table_sort_cb, GINT_TO_POINTER(FILETYPES_COLUMN_CLASS), NULL);
2809 gtk_tree_view_column_set_sort_column_id(column, FILETYPES_COLUMN_CLASS);
2811 column = gtk_tree_view_column_new();
2812 gtk_tree_view_column_set_title(column, _("Writable"));
2813 gtk_tree_view_column_set_resizable(column, FALSE);
2814 renderer = gtk_cell_renderer_toggle_new();
2815 g_signal_connect(G_OBJECT(renderer), "toggled",
2816 G_CALLBACK(filter_store_writable_cb), filter_store);
2817 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2818 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2819 GINT_TO_POINTER(FE_WRITABLE), NULL);
2820 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2821 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);
2822 gtk_tree_view_column_set_sort_column_id(column, FILETYPES_COLUMN_WRITABLE);
2824 column = gtk_tree_view_column_new();
2825 gtk_tree_view_column_set_title(column, _("Sidecar is allowed"));
2826 gtk_tree_view_column_set_resizable(column, FALSE);
2827 renderer = gtk_cell_renderer_toggle_new();
2828 g_signal_connect(G_OBJECT(renderer), "toggled",
2829 G_CALLBACK(filter_store_sidecar_cb), filter_store);
2830 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2831 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2832 GINT_TO_POINTER(FE_ALLOW_SIDECAR), NULL);
2833 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2834 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);
2835 gtk_tree_view_column_set_sort_column_id(column, FILETYPES_COLUMN_SIDECAR);
2837 filter_store_populate();
2838 gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
2839 gtk_widget_show(filter_view);
2841 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2843 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2844 G_CALLBACK(filter_default_cb), filter_view);
2845 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2846 gtk_widget_show(button);
2848 button = pref_button_new(NULL, GTK_STOCK_REMOVE, NULL, FALSE,
2849 G_CALLBACK(filter_remove_cb), filter_view);
2850 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2851 gtk_widget_show(button);
2853 button = pref_button_new(NULL, GTK_STOCK_ADD, NULL, FALSE,
2854 G_CALLBACK(filter_add_cb), filter_view);
2855 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2856 gtk_widget_show(button);
2860 static void config_tab_metadata(GtkWidget *notebook)
2865 GtkWidget *ct_button;
2869 vbox = scrolled_notebook_page(notebook, _("Metadata"));
2872 group = pref_group_new(vbox, FALSE, _("Metadata writing process"), GTK_ORIENTATION_VERTICAL);
2874 label = pref_label_new(group, _("Warning: Geeqie is built without Exiv2. Some options are disabled."));
2876 label = pref_label_new(group, _("Metadata are written in the following order. The process ends after first success."));
2877 #if GTK_CHECK_VERSION(3,16,0)
2878 gtk_label_set_xalign(GTK_LABEL(label), 0.0);
2879 gtk_label_set_yalign(GTK_LABEL(label), 0.5);
2881 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2884 ct_button = pref_checkbox_new_int(group, _("1) Save metadata in image files, or sidecar files, according to the XMP standard"),
2885 options->metadata.save_in_image_file, &c_options->metadata.save_in_image_file);
2887 gtk_widget_set_sensitive(ct_button, FALSE);
2890 pref_checkbox_new_int(group, _("2) Save metadata in '.metadata' folder, local to image folder (non-standard)"),
2891 options->metadata.enable_metadata_dirs, &c_options->metadata.enable_metadata_dirs);
2893 text = g_strdup_printf(_("3) Save metadata in Geeqie private directory '%s'"), get_metadata_cache_dir());
2894 label = pref_label_new(group, text);
2895 #if GTK_CHECK_VERSION(3,16,0)
2896 gtk_label_set_xalign(GTK_LABEL(label), 0.0);
2897 gtk_label_set_yalign(GTK_LABEL(label), 0.5);
2899 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2901 gtk_misc_set_padding(GTK_MISC(label), 22, 0);
2904 group = pref_group_new(vbox, FALSE, _("Step 1: Write to image files"), GTK_ORIENTATION_VERTICAL);
2906 gtk_widget_set_sensitive(group, FALSE);
2909 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2910 pref_checkbox_link_sensitivity(ct_button, hbox);
2912 pref_checkbox_new_int(hbox, _("Store metadata also in legacy IPTC tags (converted according to IPTC4XMP standard)"),
2913 options->metadata.save_legacy_IPTC, &c_options->metadata.save_legacy_IPTC);
2915 pref_checkbox_new_int(hbox, _("Warn if the image files are unwritable"),
2916 options->metadata.warn_on_write_problems, &c_options->metadata.warn_on_write_problems);
2918 pref_checkbox_new_int(hbox, _("Ask before writing to image files"),
2919 options->metadata.confirm_write, &c_options->metadata.confirm_write);
2921 pref_checkbox_new_int(hbox, _("Create sidecar files named image.ext.xmp (as opposed to image.xmp)"),
2922 options->metadata.sidecar_extended_name, &c_options->metadata.sidecar_extended_name);
2924 group = pref_group_new(vbox, FALSE, _("Step 2 and 3: write to Geeqie private files"), GTK_ORIENTATION_VERTICAL);
2926 gtk_widget_set_sensitive(group, FALSE);
2929 pref_checkbox_new_int(group, _("Use GQview legacy metadata format (supports only keywords and comments) instead of XMP"),
2930 options->metadata.save_legacy_format, &c_options->metadata.save_legacy_format);
2933 group = pref_group_new(vbox, FALSE, _("Miscellaneous"), GTK_ORIENTATION_VERTICAL);
2934 pref_checkbox_new_int(group, _("Write the same description tags (keywords, comment, etc.) to all grouped sidecars"),
2935 options->metadata.sync_grouped_files, &c_options->metadata.sync_grouped_files);
2937 pref_checkbox_new_int(group, _("Allow keywords to differ only in case"),
2938 options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
2940 ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"),
2941 options->metadata.write_orientation, &c_options->metadata.write_orientation);
2943 gtk_widget_set_sensitive(ct_button, FALSE);
2946 group = pref_group_new(vbox, FALSE, _("Auto-save options"), GTK_ORIENTATION_VERTICAL);
2948 ct_button = pref_checkbox_new_int(group, _("Write metadata after timeout"),
2949 options->metadata.confirm_after_timeout, &c_options->metadata.confirm_after_timeout);
2951 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2952 pref_checkbox_link_sensitivity(ct_button, hbox);
2954 pref_spin_new_int(hbox, _("Timeout (seconds):"), NULL, 0, 900, 1,
2955 options->metadata.confirm_timeout, &c_options->metadata.confirm_timeout);
2957 pref_checkbox_new_int(group, _("Write metadata on image change"),
2958 options->metadata.confirm_on_image_change, &c_options->metadata.confirm_on_image_change);
2960 pref_checkbox_new_int(group, _("Write metadata on directory change"),
2961 options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
2963 group = pref_group_new(vbox, FALSE, _("Pre-load metadata"), GTK_ORIENTATION_VERTICAL);
2965 ct_button = pref_checkbox_new_int(group, _("Read metadata in background"),
2966 options->read_metadata_in_idle, &c_options->read_metadata_in_idle);
2967 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");
2972 typedef struct _KeywordFindData KeywordFindData;
2973 struct _KeywordFindData
2980 GtkWidget *button_close;
2981 GtkWidget *button_stop;
2982 GtkWidget *button_start;
2983 GtkWidget *progress;
2991 guint idle_id; /* event source id */
2994 #define KEYWORD_DIALOG_WIDTH 400
2996 static void keywords_find_folder(KeywordFindData *kfd, FileData *dir_fd)
2998 GList *list_d = NULL;
2999 GList *list_f = NULL;
3003 filelist_read(dir_fd, &list_f, &list_d);
3007 filelist_read(dir_fd, &list_f, NULL);
3010 list_f = filelist_filter(list_f, FALSE);
3011 list_d = filelist_filter(list_d, TRUE);
3013 kfd->list = g_list_concat(list_f, kfd->list);
3014 kfd->list_dir = g_list_concat(list_d, kfd->list_dir);
3017 static void keywords_find_reset(KeywordFindData *kfd)
3019 filelist_free(kfd->list);
3022 filelist_free(kfd->list_dir);
3023 kfd->list_dir = NULL;
3026 static void keywords_find_close_cb(GenericDialog *fd, gpointer data)
3028 KeywordFindData *kfd = data;
3030 if (!gtk_widget_get_sensitive(kfd->button_close)) return;
3032 keywords_find_reset(kfd);
3033 generic_dialog_close(kfd->gd);
3037 static void keywords_find_finish(KeywordFindData *kfd)
3039 keywords_find_reset(kfd);
3041 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("done"));
3042 spinner_set_interval(kfd->spinner, -1);
3044 gtk_widget_set_sensitive(kfd->group, TRUE);
3045 gtk_widget_set_sensitive(kfd->button_start, TRUE);
3046 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
3047 gtk_widget_set_sensitive(kfd->button_close, TRUE);
3050 static void keywords_find_stop_cb(GenericDialog *fd, gpointer data)
3052 KeywordFindData *kfd = data;
3054 g_idle_remove_by_data(kfd);
3056 keywords_find_finish(kfd);
3059 static gboolean keywords_find_file(gpointer data)
3061 KeywordFindData *kfd = data;
3063 GtkTextBuffer *buffer;
3071 fd = kfd->list->data;
3072 kfd->list = g_list_remove(kfd->list, fd);
3074 keywords = metadata_read_list(fd, KEYWORD_KEY, METADATA_PLAIN);
3075 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3079 gtk_text_buffer_get_end_iter(buffer, &iter);
3080 tmp = g_strconcat(keywords->data, "\n", NULL);
3081 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
3083 keywords = keywords->next;
3086 gtk_entry_set_text(GTK_ENTRY(kfd->progress), fd->path);
3087 file_data_unref(fd);
3088 string_list_free(keywords);
3092 else if (kfd->list_dir)
3096 fd = kfd->list_dir->data;
3097 kfd->list_dir = g_list_remove(kfd->list_dir, fd);
3099 keywords_find_folder(kfd, fd);
3101 file_data_unref(fd);
3106 keywords_find_finish(kfd);
3111 static void keywords_find_start_cb(GenericDialog *fd, gpointer data)
3113 KeywordFindData *kfd = data;
3116 if (kfd->list || !gtk_widget_get_sensitive(kfd->button_start)) return;
3118 path = remove_trailing_slash((gtk_entry_get_text(GTK_ENTRY(kfd->entry))));
3119 parse_out_relatives(path);
3123 warning_dialog(_("Invalid folder"),
3124 _("The specified folder can not be found."),
3125 GTK_STOCK_DIALOG_WARNING, kfd->gd->dialog);
3131 gtk_widget_set_sensitive(kfd->group, FALSE);
3132 gtk_widget_set_sensitive(kfd->button_start, FALSE);
3133 gtk_widget_set_sensitive(kfd->button_stop, TRUE);
3134 gtk_widget_set_sensitive(kfd->button_close, FALSE);
3135 spinner_set_interval(kfd->spinner, SPINNER_SPEED);
3137 dir_fd = file_data_new_dir(path);
3138 keywords_find_folder(kfd, dir_fd);
3139 file_data_unref(dir_fd);
3140 kfd->idle_id = g_idle_add(keywords_find_file, kfd);
3146 static void keywords_find_dialog(GtkWidget *widget, const gchar *path)
3148 KeywordFindData *kfd;
3152 kfd = g_new0(KeywordFindData, 1);
3154 kfd->gd = generic_dialog_new(_("Search for keywords"),
3155 "search_for_keywords",
3158 gtk_window_set_default_size(GTK_WINDOW(kfd->gd->dialog), KEYWORD_DIALOG_WIDTH, -1);
3159 kfd->gd->cancel_cb = keywords_find_close_cb;
3160 kfd->button_close = generic_dialog_add_button(kfd->gd, GTK_STOCK_CLOSE, NULL,
3161 keywords_find_close_cb, FALSE);
3162 kfd->button_start = generic_dialog_add_button(kfd->gd, GTK_STOCK_OK, _("S_tart"),
3163 keywords_find_start_cb, FALSE);
3164 kfd->button_stop = generic_dialog_add_button(kfd->gd, GTK_STOCK_STOP, NULL,
3165 keywords_find_stop_cb, FALSE);
3166 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
3168 generic_dialog_add_message(kfd->gd, NULL, _("Search for keywords"), NULL, FALSE);
3170 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0);
3171 pref_spacer(hbox, PREF_PAD_INDENT);
3172 kfd->group = pref_box_new(hbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
3174 hbox = pref_box_new(kfd->group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3175 pref_label_new(hbox, _("Folder:"));
3177 label = tab_completion_new(&kfd->entry, path, NULL, NULL, NULL, NULL);
3178 tab_completion_add_select_button(kfd->entry,_("Select folder") , TRUE);
3179 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
3180 gtk_widget_show(label);
3182 pref_checkbox_new_int(kfd->group, _("Include subfolders"), FALSE, &kfd->recurse);
3184 pref_line(kfd->gd->vbox, PREF_PAD_SPACE);
3185 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3187 kfd->progress = gtk_entry_new();
3188 gtk_widget_set_can_focus(kfd->progress, FALSE);
3189 gtk_editable_set_editable(GTK_EDITABLE(kfd->progress), FALSE);
3190 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("click start to begin"));
3191 gtk_box_pack_start(GTK_BOX(hbox), kfd->progress, TRUE, TRUE, 0);
3192 gtk_widget_show(kfd->progress);
3194 kfd->spinner = spinner_new(NULL, -1);
3195 gtk_box_pack_start(GTK_BOX(hbox), kfd->spinner, FALSE, FALSE, 0);
3196 gtk_widget_show(kfd->spinner);
3200 gtk_widget_show(kfd->gd->dialog);
3203 static void keywords_find_cb(GtkWidget *widget, gpointer data)
3205 const gchar *path = layout_get_path(NULL);
3207 if (!path || !*path) path = homedir();
3208 keywords_find_dialog(widget, path);
3211 static void config_tab_keywords_save()
3213 GtkTextIter start, end;
3214 GtkTextBuffer *buffer;
3215 GList *kw_list = NULL;
3221 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3222 gtk_text_buffer_get_bounds(buffer, &start, &end);
3224 buffer_text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
3226 kw_split = strtok(buffer_text, "\n");
3227 while (kw_split != NULL)
3233 if (g_strcmp0(work->data, kw_split) == 0)
3242 kw_list = g_list_append(kw_list, g_strdup(kw_split));
3244 kw_split = strtok(NULL, "\n");
3247 keyword_list_set(kw_list);
3249 string_list_free(kw_list);
3250 g_free(buffer_text);
3253 static void config_tab_keywords(GtkWidget *notebook)
3259 GtkWidget *scrolled;
3261 GtkTextBuffer *buffer;
3264 vbox = scrolled_notebook_page(notebook, _("Keywords"));
3266 group = pref_group_new(vbox, TRUE, _("Edit keywords autocompletion list"), GTK_ORIENTATION_VERTICAL);
3268 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3270 button = pref_button_new(hbox, GTK_STOCK_EXECUTE, _("Search"), FALSE,
3271 G_CALLBACK(keywords_find_cb), keyword_text);
3272 gtk_widget_set_tooltip_text(button, "Search for existing keywords");
3275 keyword_text = gtk_text_view_new();
3276 gtk_widget_set_size_request(keyword_text, 20, 20);
3277 scrolled = gtk_scrolled_window_new(NULL, NULL);
3278 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3279 gtk_widget_show(scrolled);
3281 gtk_container_add(GTK_CONTAINER(scrolled), keyword_text);
3282 gtk_widget_show(keyword_text);
3284 gtk_text_view_set_editable(GTK_TEXT_VIEW(keyword_text), TRUE);
3286 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3287 gtk_text_buffer_create_tag(buffer, "monospace",
3288 "family", "monospace", NULL);
3290 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(keyword_text), GTK_WRAP_WORD);
3291 gtk_text_buffer_get_start_iter(buffer, &iter);
3292 gtk_text_buffer_create_mark(buffer, "end", &iter, FALSE);
3295 path = g_build_filename(get_rc_dir(), "keywords", NULL);
3297 GList *kwl = keyword_list_get();
3298 kwl = g_list_first(kwl);
3301 gtk_text_buffer_get_end_iter (buffer, &iter);
3302 tmp = g_strconcat(kwl->data, "\n", NULL);
3303 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
3308 gtk_text_buffer_set_modified(buffer, FALSE);
3315 static void intent_menu_cb(GtkWidget *combo, gpointer data)
3317 gint *option = data;
3319 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
3323 *option = INTENT_PERCEPTUAL;
3326 *option = INTENT_RELATIVE_COLORIMETRIC;
3329 *option = INTENT_SATURATION;
3332 *option = INTENT_ABSOLUTE_COLORIMETRIC;
3337 static void add_intent_menu(GtkWidget *table, gint column, gint row, const gchar *text,
3338 gint option, gint *option_c)
3345 pref_table_label(table, column, row, text, 0.0);
3347 combo = gtk_combo_box_text_new();
3349 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Perceptual"));
3350 if (option == INTENT_PERCEPTUAL) current = 0;
3351 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Relative Colorimetric"));
3352 if (option == INTENT_RELATIVE_COLORIMETRIC) current = 1;
3353 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Saturation"));
3354 if (option == INTENT_SATURATION) current = 2;
3355 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Absolute Colorimetric"));
3356 if (option == INTENT_ABSOLUTE_COLORIMETRIC) current = 3;
3358 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
3360 gtk_widget_set_tooltip_text(combo,"Refer to the lcms documentation for the defaults used when the selected Intent is not available");
3362 g_signal_connect(G_OBJECT(combo), "changed",
3363 G_CALLBACK(intent_menu_cb), option_c);
3365 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
3366 gtk_widget_show(combo);
3370 static void config_tab_color(GtkWidget *notebook)
3379 vbox = scrolled_notebook_page(notebook, _("Color management"));
3381 group = pref_group_new(vbox, FALSE, _("Input profiles"), GTK_ORIENTATION_VERTICAL);
3383 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3386 table = pref_table_new(group, 3, COLOR_PROFILE_INPUTS + 1, FALSE, FALSE);
3387 gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
3389 label = pref_table_label(table, 0, 0, _("Type"), 0.0);
3390 pref_label_bold(label, TRUE, FALSE);
3392 label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
3393 pref_label_bold(label, TRUE, FALSE);
3395 label = pref_table_label(table, 2, 0, _("File"), 0.0);
3396 pref_label_bold(label, TRUE, FALSE);
3398 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
3403 buf = g_strdup_printf(_("Input %d:"), i + COLOR_PROFILE_FILE);
3404 pref_table_label(table, 0, i + 1, buf, 1.0);
3407 entry = gtk_entry_new();
3408 gtk_entry_set_max_length(GTK_ENTRY(entry), EDITOR_NAME_MAX_LENGTH);
3409 if (options->color_profile.input_name[i])
3411 gtk_entry_set_text(GTK_ENTRY(entry), options->color_profile.input_name[i]);
3413 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, i + 1, i + 2,
3414 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3415 gtk_widget_show(entry);
3416 color_profile_input_name_entry[i] = entry;
3418 tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, ".icc", "ICC Files", NULL);
3419 tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
3420 gtk_widget_set_size_request(entry, 160, -1);
3421 gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
3422 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3423 gtk_widget_show(tabcomp);
3424 color_profile_input_file_entry[i] = entry;
3427 group = pref_group_new(vbox, FALSE, _("Screen profile"), GTK_ORIENTATION_VERTICAL);
3429 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3431 pref_checkbox_new_int(group, _("Use system screen profile if available"),
3432 options->color_profile.use_x11_screen_profile, &c_options->color_profile.use_x11_screen_profile);
3434 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3436 pref_table_label(table, 0, 0, _("Screen:"), 1.0);
3437 tabcomp = tab_completion_new(&color_profile_screen_file_entry,
3438 options->color_profile.screen_file, NULL, ".icc", "ICC Files", NULL);
3439 tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
3440 gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
3442 add_intent_menu(table, 0, 1, _("Render Intent:"), options->color_profile.render_intent, &c_options->color_profile.render_intent);
3444 gtk_table_attach(GTK_TABLE(table), tabcomp, 1, 2,
3446 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3448 gtk_widget_show(tabcomp);
3451 /* advanced entry tab */
3452 static void use_geeqie_trash_cb(GtkWidget *widget, gpointer data)
3454 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3456 c_options->file_ops.use_system_trash = FALSE;
3457 c_options->file_ops.no_trash = FALSE;
3461 static void use_system_trash_cb(GtkWidget *widget, gpointer data)
3463 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3465 c_options->file_ops.use_system_trash = TRUE;
3466 c_options->file_ops.no_trash = FALSE;
3470 static void use_no_cache_cb(GtkWidget *widget, gpointer data)
3472 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3474 c_options->file_ops.no_trash = TRUE;
3478 static void config_tab_behavior(GtkWidget *notebook)
3485 GtkWidget *ct_button;
3489 GtkWidget *with_rename;
3490 GtkWidget *collections_on_top;
3491 GtkWidget *hide_window_in_fullscreen;
3492 GtkWidget *checkbox;
3495 vbox = scrolled_notebook_page(notebook, _("Behavior"));
3497 group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
3499 pref_checkbox_new_int(group, _("Confirm permanent file delete"),
3500 options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
3501 pref_checkbox_new_int(group, _("Confirm move file to Trash"),
3502 options->file_ops.confirm_move_to_trash, &c_options->file_ops.confirm_move_to_trash);
3503 pref_checkbox_new_int(group, _("Enable Delete key"),
3504 options->file_ops.enable_delete_key, &c_options->file_ops.enable_delete_key);
3506 ct_button = pref_radiobutton_new(group, NULL, _("Use Geeqie trash location"),
3507 !options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_geeqie_trash_cb),NULL);
3509 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3510 pref_checkbox_link_sensitivity(ct_button, hbox);
3512 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
3513 pref_label_new(hbox, _("Folder:"));
3515 tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL, NULL, NULL);
3516 tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
3517 gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
3518 gtk_widget_show(tabcomp);
3520 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3521 pref_checkbox_link_sensitivity(ct_button, hbox);
3523 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
3524 spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MiB"),
3525 0, 2048, 1, options->file_ops.safe_delete_folder_maxsize, &c_options->file_ops.safe_delete_folder_maxsize);
3526 gtk_widget_set_tooltip_markup(spin, _("Set to 0 for unlimited size"));
3527 button = pref_button_new(NULL, NULL, _("View"), FALSE,
3528 G_CALLBACK(safe_delete_view_cb), NULL);
3529 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3530 gtk_widget_show(button);
3532 button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
3533 G_CALLBACK(safe_delete_clear_cb), NULL);
3534 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3535 pref_radiobutton_new(group, ct_button, _("Use system Trash bin"),
3536 options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_system_trash_cb), NULL);
3538 pref_radiobutton_new(group, ct_button, _("Use no trash at all"),
3539 options->file_ops.no_trash, G_CALLBACK(use_no_cache_cb), NULL);
3541 gtk_widget_show(button);
3543 pref_spacer(group, PREF_PAD_GROUP);
3546 group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
3548 pref_checkbox_new_int(group, _("Descend folders in tree view"),
3549 options->tree_descend_subdirs, &c_options->tree_descend_subdirs);
3551 pref_checkbox_new_int(group, _("In place renaming"),
3552 options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
3554 pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
3555 options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
3557 tmp = pref_checkbox_new_int(group, _("Circular selection lists"),
3558 options->circular_selection_lists, &c_options->circular_selection_lists);
3559 gtk_widget_set_tooltip_text(tmp, _("Traverse selection lists in a circular manner"));
3561 marks = pref_checkbox_new_int(group, _("Save marks on exit"),
3562 options->marks_save, &c_options->marks_save);
3563 gtk_widget_set_tooltip_text(marks,"Note that marks linked to a keyword will be saved irrespective of this setting");
3565 with_rename = pref_checkbox_new_int(group, _("Use \"With Rename\" as default for Copy/Move dialogs"),
3566 options->with_rename, &c_options->with_rename);
3567 gtk_widget_set_tooltip_text(with_rename,"Change the default button for Copy/Move dialogs");
3569 collections_on_top = pref_checkbox_new_int(group, _("Open collections on top"),
3570 options->collections_on_top, &c_options->collections_on_top);
3571 gtk_widget_set_tooltip_text(collections_on_top,"Open collections window on top");
3573 hide_window_in_fullscreen = pref_checkbox_new_int(group, _("Hide window in fullscreen"),
3574 options->hide_window_in_fullscreen, &c_options->hide_window_in_fullscreen);
3575 gtk_widget_set_tooltip_text(hide_window_in_fullscreen,"When alt-tabbing, prevent Geeqie window showing twice");
3577 pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
3578 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
3580 pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
3581 16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
3583 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3584 add_dnd_default_action_selection_menu(table, 0, 0, _("Drag`n drop default action:"), options->dnd_default_action, &c_options->dnd_default_action);
3586 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3587 add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
3589 pref_spacer(group, PREF_PAD_GROUP);
3591 group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
3593 pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
3594 options->progressive_key_scrolling, &c_options->progressive_key_scrolling);
3595 pref_spin_new_int(group, _("Keyboard scrolling step multiplier:"), NULL,
3596 1, 32, 1, options->keyboard_scroll_step, (int *)&c_options->keyboard_scroll_step);
3597 pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
3598 options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
3599 pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
3600 options->image_lm_click_nav, &c_options->image_lm_click_nav);
3601 pref_checkbox_new_int(group, _("Open archive by left click on image"),
3602 options->image_l_click_archive, &c_options->image_l_click_archive);
3603 pref_checkbox_new_int(group, _("Play video by left click on image"),
3604 options->image_l_click_video, &c_options->image_l_click_video);
3605 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3606 add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
3608 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3609 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3610 add_mouse_selection_menu(table, 0, 0, _("Mouse button Back:"), options->mouse_button_8, &c_options->mouse_button_8);
3611 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3612 add_mouse_selection_menu(table, 0, 0, _("Mouse button Forward:"), options->mouse_button_9, &c_options->mouse_button_9);
3614 pref_spacer(group, PREF_PAD_GROUP);
3616 group = pref_group_new(vbox, FALSE, _("GPU"), GTK_ORIENTATION_VERTICAL);
3618 checkbox = pref_checkbox_new_int(group, _("Override disable GPU"),
3619 options->override_disable_gpu, &c_options->override_disable_gpu);
3620 gtk_widget_set_tooltip_text(checkbox, "Contact the developers for usage");
3623 pref_spacer(group, PREF_PAD_GROUP);
3625 group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
3627 pref_spin_new_int(group, _("Debug level:"), NULL,
3628 DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
3630 pref_checkbox_new_int(group, _("Timer data"),
3631 options->log_window.timer_data, &c_options->log_window.timer_data);
3633 pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
3634 1, 99999, 1, options->log_window_lines, &options->log_window_lines);
3638 /* accelerators tab */
3639 static void config_tab_accelerators(GtkWidget *notebook)
3645 GtkWidget *scrolled;
3646 GtkWidget *accel_view;
3647 GtkCellRenderer *renderer;
3648 GtkTreeSelection *selection;
3649 GtkTreeViewColumn *column;
3651 vbox = scrolled_notebook_page(notebook, _("Keyboard"));
3653 group = pref_group_new(vbox, TRUE, _("Accelerators"), GTK_ORIENTATION_VERTICAL);
3655 scrolled = gtk_scrolled_window_new(NULL, NULL);
3656 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
3657 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
3658 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3659 gtk_widget_show(scrolled);
3661 accel_store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
3663 accel_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(accel_store));
3664 g_object_unref(accel_store);
3665 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(accel_view));
3666 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
3668 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(accel_view), FALSE);
3670 renderer = gtk_cell_renderer_text_new();
3672 column = gtk_tree_view_column_new_with_attributes(_("Action"),
3677 gtk_tree_view_column_set_sort_column_id(column, AE_ACTION);
3678 gtk_tree_view_column_set_resizable(column, TRUE);
3679 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3682 renderer = gtk_cell_renderer_accel_new();
3683 g_signal_connect(G_OBJECT(renderer), "accel-cleared",
3684 G_CALLBACK(accel_store_cleared_cb), accel_store);
3685 g_signal_connect(G_OBJECT(renderer), "accel-edited",
3686 G_CALLBACK(accel_store_edited_cb), accel_store);
3689 g_object_set (renderer,
3691 "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
3694 column = gtk_tree_view_column_new_with_attributes(_("KEY"),
3699 gtk_tree_view_column_set_sort_column_id(column, AE_KEY);
3700 gtk_tree_view_column_set_resizable(column, TRUE);
3701 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3703 renderer = gtk_cell_renderer_text_new();
3705 column = gtk_tree_view_column_new_with_attributes(_("Tooltip"),
3710 gtk_tree_view_column_set_sort_column_id(column, AE_TOOLTIP);
3711 gtk_tree_view_column_set_resizable(column, TRUE);
3712 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3714 renderer = gtk_cell_renderer_text_new();
3716 column = gtk_tree_view_column_new_with_attributes("Accel",
3721 gtk_tree_view_column_set_sort_column_id(column, AE_ACCEL);
3722 gtk_tree_view_column_set_resizable(column, TRUE);
3723 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3725 accel_store_populate();
3726 gtk_container_add(GTK_CONTAINER(scrolled), accel_view);
3727 gtk_widget_show(accel_view);
3729 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3731 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
3732 G_CALLBACK(accel_default_cb), accel_view);
3733 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3734 gtk_widget_show(button);
3736 button = pref_button_new(NULL, NULL, _("Reset selected"), FALSE,
3737 G_CALLBACK(accel_reset_cb), accel_view);
3738 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3739 gtk_widget_show(button);
3742 /* toolbar main tab */
3743 static void config_tab_toolbar_main(GtkWidget *notebook)
3746 GtkWidget *toolbardata;
3749 lw = layout_window_list->data;
3751 vbox = scrolled_notebook_page(notebook, _("Toolbar Main"));
3753 toolbardata = toolbar_select_new(lw, TOOLBAR_MAIN);
3754 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3755 gtk_widget_show(vbox);
3758 /* toolbar status tab */
3759 static void config_tab_toolbar_status(GtkWidget *notebook)
3762 GtkWidget *toolbardata;
3765 lw = layout_window_list->data;
3767 vbox = scrolled_notebook_page(notebook, _("Toolbar Status"));
3769 toolbardata = toolbar_select_new(lw, TOOLBAR_STATUS);
3770 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3771 gtk_widget_show(vbox);
3775 static gint extension_sort_cb(gconstpointer a, gconstpointer b)
3777 return g_strcmp0((gchar *)a, (gchar *)b);
3780 static void config_tab_advanced(GtkWidget *notebook)
3784 GSList *formats_list;
3785 GList *extensions_list = NULL;
3788 GdkPixbufFormat *fm;
3790 GString *types_string = g_string_new(NULL);
3791 GtkWidget *types_string_label;
3792 GtkWidget *threads_string_label;
3793 GtkWidget *dupes_threads_spin;
3795 vbox = scrolled_notebook_page(notebook, _("Advanced"));
3796 group = pref_group_new(vbox, FALSE, _("External preview extraction"), GTK_ORIENTATION_VERTICAL);
3798 pref_checkbox_new_int(group, _("Use external preview extraction - Requires restart"), options->external_preview.enable, &c_options->external_preview.enable);
3800 pref_spacer(group, PREF_PAD_GROUP);
3802 formats_list = gdk_pixbuf_get_formats();
3804 while (formats_list)
3806 fm = formats_list->data;
3807 extensions = gdk_pixbuf_format_get_extensions(fm);
3810 while (extensions[i])
3812 extensions_list = g_list_insert_sorted(extensions_list, g_strdup(extensions[i]), extension_sort_cb);
3816 g_strfreev(extensions);
3817 formats_list = formats_list->next;
3820 while (extensions_list)
3822 if (types_string->len == 0)
3824 types_string = g_string_append(types_string, extensions_list->data);
3828 types_string = g_string_append(types_string, ", ");
3829 types_string = g_string_append(types_string, extensions_list->data);
3832 extensions_list = extensions_list->next;
3835 types_string = g_string_prepend(types_string, _("Usable file types:\n"));
3836 types_string_label = pref_label_new(group, types_string->str);
3837 gtk_label_set_line_wrap(GTK_LABEL(types_string_label), TRUE);
3839 pref_spacer(group, PREF_PAD_GROUP);
3841 group = pref_group_new(vbox, FALSE, _("File identification tool"), GTK_ORIENTATION_VERTICAL);
3842 external_preview_select_entry = gtk_entry_new();
3843 tabcomp = tab_completion_new(&external_preview_select_entry, options->external_preview.select, NULL, NULL, NULL, NULL);
3844 tab_completion_add_select_button(external_preview_select_entry, _("Select file identification tool"), FALSE);
3845 gtk_box_pack_start(GTK_BOX(group), tabcomp, TRUE, TRUE, 0);
3846 gtk_widget_show(tabcomp);
3848 group = pref_group_new(vbox, FALSE, _("Preview extraction tool"), GTK_ORIENTATION_VERTICAL);
3849 external_preview_extract_entry = gtk_entry_new();
3850 tabcomp = tab_completion_new(&external_preview_extract_entry, options->external_preview.extract, NULL, NULL, NULL, NULL);
3851 tab_completion_add_select_button(external_preview_extract_entry, _("Select preview extraction tool"), FALSE);
3852 gtk_box_pack_start(GTK_BOX(group), tabcomp, TRUE, TRUE, 0);
3853 gtk_widget_show(tabcomp);
3855 gtk_widget_show(vbox);
3857 g_slist_free(formats_list);
3858 string_list_free(extensions_list);
3859 g_string_free(types_string, TRUE);
3861 pref_spacer(group, PREF_PAD_GROUP);
3863 pref_line(vbox, PREF_PAD_SPACE);
3864 group = pref_group_new(vbox, FALSE, _("Thread pool limits"), GTK_ORIENTATION_VERTICAL);
3866 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.");
3867 gtk_label_set_line_wrap(GTK_LABEL(threads_string_label), TRUE);
3869 pref_spacer(vbox, PREF_PAD_GROUP);
3871 dupes_threads_spin = pref_spin_new_int(vbox, _("Duplicate check:"), _("max. threads"), 0, get_cpu_cores(), 1, options->threads.duplicates, &c_options->threads.duplicates);
3872 gtk_widget_set_tooltip_markup(dupes_threads_spin, _("Set to 0 for unlimited"));
3876 static void config_tab_stereo(GtkWidget *notebook)
3884 GtkWidget *fs_button;
3885 vbox = scrolled_notebook_page(notebook, _("Stereo"));
3887 group = pref_group_new(vbox, FALSE, _("Windowed stereo mode"), GTK_ORIENTATION_VERTICAL);
3889 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3890 add_stereo_mode_menu(table, 0, 0, _("Windowed stereo mode"), options->stereo.mode, &c_options->stereo.mode, FALSE);
3892 table = pref_table_new(group, 2, 2, TRUE, FALSE);
3893 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3894 pref_checkbox_new_int(box, _("Mirror left image"),
3895 options->stereo.mode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.mirror_left);
3896 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3897 pref_checkbox_new_int(box, _("Flip left image"),
3898 options->stereo.mode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.flip_left);
3899 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3900 pref_checkbox_new_int(box, _("Mirror right image"),
3901 options->stereo.mode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.mirror_right);
3902 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3903 pref_checkbox_new_int(box, _("Flip right image"),
3904 options->stereo.mode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.flip_right);
3905 pref_checkbox_new_int(group, _("Swap left and right images"),
3906 options->stereo.mode & PR_STEREO_SWAP, &c_options->stereo.tmp.swap);
3907 pref_checkbox_new_int(group, _("Disable stereo mode on single image source"),
3908 options->stereo.mode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.temp_disable);
3910 group = pref_group_new(vbox, FALSE, _("Fullscreen stereo mode"), GTK_ORIENTATION_VERTICAL);
3911 fs_button = pref_checkbox_new_int(group, _("Use different settings for fullscreen"),
3912 options->stereo.enable_fsmode, &c_options->stereo.enable_fsmode);
3913 box2 = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
3914 pref_checkbox_link_sensitivity(fs_button, box2);
3915 table = pref_table_new(box2, 2, 1, FALSE, FALSE);
3916 add_stereo_mode_menu(table, 0, 0, _("Fullscreen stereo mode"), options->stereo.fsmode, &c_options->stereo.fsmode, TRUE);
3917 table = pref_table_new(box2, 2, 2, TRUE, FALSE);
3918 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3919 pref_checkbox_new_int(box, _("Mirror left image"),
3920 options->stereo.fsmode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.fs_mirror_left);
3921 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3922 pref_checkbox_new_int(box, _("Flip left image"),
3923 options->stereo.fsmode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.fs_flip_left);
3924 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3925 pref_checkbox_new_int(box, _("Mirror right image"),
3926 options->stereo.fsmode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.fs_mirror_right);
3927 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3928 pref_checkbox_new_int(box, _("Flip right image"),
3929 options->stereo.fsmode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.fs_flip_right);
3930 pref_checkbox_new_int(box2, _("Swap left and right images"),
3931 options->stereo.fsmode & PR_STEREO_SWAP, &c_options->stereo.tmp.fs_swap);
3932 pref_checkbox_new_int(box2, _("Disable stereo mode on single image source"),
3933 options->stereo.fsmode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.fs_temp_disable);
3935 group2 = pref_group_new(box2, FALSE, _("Fixed position"), GTK_ORIENTATION_VERTICAL);
3936 table = pref_table_new(group2, 5, 3, FALSE, FALSE);
3937 pref_table_spin_new_int(table, 0, 0, _("Width"), NULL,
3938 1, 5000, 1, options->stereo.fixed_w, &c_options->stereo.fixed_w);
3939 pref_table_spin_new_int(table, 3, 0, _("Height"), NULL,
3940 1, 5000, 1, options->stereo.fixed_h, &c_options->stereo.fixed_h);
3941 pref_table_spin_new_int(table, 0, 1, _("Left X"), NULL,
3942 0, 5000, 1, options->stereo.fixed_x1, &c_options->stereo.fixed_x1);
3943 pref_table_spin_new_int(table, 3, 1, _("Left Y"), NULL,
3944 0, 5000, 1, options->stereo.fixed_y1, &c_options->stereo.fixed_y1);
3945 pref_table_spin_new_int(table, 0, 2, _("Right X"), NULL,
3946 0, 5000, 1, options->stereo.fixed_x2, &c_options->stereo.fixed_x2);
3947 pref_table_spin_new_int(table, 3, 2, _("Right Y"), NULL,
3948 0, 5000, 1, options->stereo.fixed_y2, &c_options->stereo.fixed_y2);
3952 /* Main preferences window */
3953 static void config_window_create(LayoutWindow *lw)
3955 GtkWidget *win_vbox;
3957 GtkWidget *notebook;
3959 GtkWidget *ct_button;
3961 if (!c_options) c_options = init_options(NULL);
3963 configwindow = window_new(GTK_WINDOW_TOPLEVEL, "preferences", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Preferences"));
3964 DEBUG_NAME(configwindow);
3965 gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
3966 g_signal_connect(G_OBJECT(configwindow), "delete_event",
3967 G_CALLBACK(config_window_delete), NULL);
3968 if (options->save_dialog_window_positions)
3970 gtk_window_resize(GTK_WINDOW(configwindow), lw->options.preferences_window.w, lw->options.preferences_window.h);
3971 gtk_window_move(GTK_WINDOW(configwindow), lw->options.preferences_window.x, lw->options.preferences_window.y);
3975 gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
3977 gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
3978 gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
3980 win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
3981 gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
3982 gtk_widget_show(win_vbox);
3984 notebook = gtk_notebook_new();
3985 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_LEFT);
3986 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE);
3987 gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
3989 config_tab_general(notebook);
3990 config_tab_image(notebook);
3991 config_tab_osd(notebook);
3992 config_tab_windows(notebook);
3993 config_tab_accelerators(notebook);
3994 config_tab_files(notebook);
3995 config_tab_metadata(notebook);
3996 config_tab_keywords(notebook);
3997 config_tab_color(notebook);
3998 config_tab_stereo(notebook);
3999 config_tab_behavior(notebook);
4000 config_tab_toolbar_main(notebook);
4001 config_tab_toolbar_status(notebook);
4002 config_tab_advanced(notebook);
4004 gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), lw->options.preferences_window.page_number);
4006 hbox = gtk_hbutton_box_new();
4007 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
4008 gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
4009 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
4010 gtk_widget_show(hbox);
4012 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
4013 G_CALLBACK(config_window_help_cb), notebook);
4014 gtk_container_add(GTK_CONTAINER(hbox), button);
4015 gtk_widget_set_can_default(button, TRUE);
4016 gtk_widget_show(button);
4018 button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
4019 G_CALLBACK(config_window_ok_cb), notebook);
4020 gtk_container_add(GTK_CONTAINER(hbox), button);
4021 gtk_widget_set_can_default(button, TRUE);
4022 gtk_widget_grab_default(button);
4023 gtk_widget_show(button);
4027 button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
4028 G_CALLBACK(config_window_close_cb), NULL);
4029 gtk_container_add(GTK_CONTAINER(hbox), button);
4030 gtk_widget_set_can_default(button, TRUE);
4031 gtk_widget_show(button);
4033 if (!generic_dialog_get_alternative_button_order(configwindow))
4035 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
4038 gtk_widget_show(notebook);
4040 gtk_widget_show(configwindow);
4044 *-----------------------------------------------------------------------------
4045 * config window show (public)
4046 *-----------------------------------------------------------------------------
4049 void show_config_window(LayoutWindow *lw)
4053 gtk_window_present(GTK_WINDOW(configwindow));
4057 config_window_create(lw);
4066 void show_about_window(LayoutWindow *lw)
4068 GdkPixbuf *pixbuf_logo;
4069 GdkPixbuf *pixbuf_icon;
4070 gchar *authors[1000];
4075 gchar *timezone_path;
4078 #define LINE_LENGTH 1000
4079 gchar line[LINE_LENGTH];
4081 copyright = g_string_new(NULL);
4082 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");
4084 timezone_path = g_build_filename(get_rc_dir(), TIMEZONE_DATABASE_FILE, NULL);
4085 if (g_file_test(timezone_path, G_FILE_TEST_EXISTS))
4087 cd = ZDOpenDatabase(timezone_path);
4090 copyright = g_string_append(copyright, ZDGetNotice(cd));
4094 log_printf("Error: Init of timezone database %s failed\n", timezone_path);
4096 ZDCloseDatabase(cd);
4098 g_free(timezone_path);
4101 path = g_build_filename(gq_helpdir, "AUTHORS", NULL);
4102 fp = fopen(path, "r");
4105 while(fgets(line, LINE_LENGTH, fp))
4107 /* get rid of ending \n from fgets */
4108 line[strlen(line) - 1] = '\0';
4109 authors[i_authors] = g_strdup(line);
4112 authors[i_authors] = NULL;
4117 comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
4118 "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
4120 pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
4121 pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
4122 gtk_show_about_dialog(GTK_WINDOW(lw->window),
4123 "title", _("About Geeqie"),
4125 "program-name", GQ_APPNAME,
4127 "logo", pixbuf_logo,
4128 "icon", pixbuf_icon,
4129 "website", GQ_WEBSITE,
4130 "website-label", "Website",
4131 "comments", comment,
4133 "translator-credits", _("translator-credits"),
4134 "wrap-license", TRUE,
4135 "license", copyright->str,
4138 g_string_free(copyright, TRUE);
4141 while(n < i_authors)
4151 static void image_overlay_set_text_colours()
4153 c_options->image_overlay.text_red = options->image_overlay.text_red;
4154 c_options->image_overlay.text_green = options->image_overlay.text_green;
4155 c_options->image_overlay.text_blue = options->image_overlay.text_blue;
4156 c_options->image_overlay.text_alpha = options->image_overlay.text_alpha;
4157 c_options->image_overlay.background_red = options->image_overlay.background_red;
4158 c_options->image_overlay.background_green = options->image_overlay.background_green;
4159 c_options->image_overlay.background_blue = options->image_overlay.background_blue;
4160 c_options->image_overlay.background_alpha = options->image_overlay.background_alpha;
4164 *-----------------------------------------------------------------------------
4165 * timezone database routines
4166 *-----------------------------------------------------------------------------
4169 static void timezone_async_ready_cb(GObject *source_object, GAsyncResult *res, gpointer data)
4171 GError *error = NULL;
4173 gchar *tmp_filename;
4174 gchar *timezone_bin;
4175 gchar *tmp_dir = NULL;
4178 if (!g_cancellable_is_cancelled(tz->cancellable))
4180 generic_dialog_close(tz->gd);
4184 if (g_file_copy_finish(G_FILE(source_object), res, &error))
4186 tmp_filename = g_file_get_path(tz->tmp_g_file);
4187 fd = file_data_new_simple(tmp_filename);
4188 tmp_dir = open_archive(fd);
4192 timezone_bin = g_build_filename(tmp_dir, TIMEZONE_DATABASE_VERSION, TIMEZONE_DATABASE_FILE, NULL);
4193 if (isfile(timezone_bin))
4195 move_file(timezone_bin, tz->timezone_database_user);
4199 warning_dialog(_("Warning: Cannot open timezone database file"), _("See the Log Window"), GTK_STOCK_DIALOG_WARNING, NULL);
4202 g_free(timezone_bin);
4203 g_free(tmp_dir); // The folder in /tmp is deleted in exit_program_final()
4207 warning_dialog(_("Warning: Cannot open timezone database file"), _("See the Log Window"), GTK_STOCK_DIALOG_WARNING, NULL);
4209 g_free(tmp_filename);
4210 file_data_unref(fd);
4214 file_util_warning_dialog(_("Error: Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
4217 g_file_delete(tz->tmp_g_file, NULL, &error);
4218 g_object_unref(tz->tmp_g_file);
4219 tz->tmp_g_file = NULL;
4220 g_object_unref(tz->cancellable);
4221 g_object_unref(tz->timezone_database_gq);
4224 static void timezone_progress_cb(goffset current_num_bytes, goffset total_num_bytes, gpointer data)
4228 if (!g_cancellable_is_cancelled(tz->cancellable))
4230 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(tz->progress), (gdouble)current_num_bytes / total_num_bytes);
4234 static void timezone_cancel_button_cb(GenericDialog *gd, gpointer data)
4238 g_cancellable_cancel(tz->cancellable);
4241 static void timezone_database_install_cb(GtkWidget *widget, gpointer data)
4244 GError *error = NULL;
4245 GFileIOStream *io_stream;
4252 tz->tmp_g_file = g_file_new_tmp("geeqie_timezone_XXXXXX", &io_stream, &error);
4256 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
4257 log_printf("Error: Download timezone database failed:\n%s", error->message);
4258 g_error_free(error);
4259 g_object_unref(tz->tmp_g_file);
4263 tz->timezone_database_gq = g_file_new_for_uri(TIMEZONE_DATABASE_WEB);
4265 tz->gd = generic_dialog_new(_("Timezone database"), "download_timezone_database", NULL, TRUE, timezone_cancel_button_cb, tz);
4267 generic_dialog_add_message(tz->gd, GTK_STOCK_DIALOG_INFO, _("Downloading timezone database"), NULL, FALSE);
4269 tz->progress = gtk_progress_bar_new();
4270 gtk_box_pack_start(GTK_BOX(tz->gd->vbox), tz->progress, FALSE, FALSE, 0);
4271 gtk_widget_show(tz->progress);
4273 gtk_widget_show(tz->gd->dialog);
4274 tz->cancellable = g_cancellable_new();
4275 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);
4277 gtk_button_set_label(GTK_BUTTON(widget), _("Update"));
4280 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */