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[] =
115 gchar *format_class_list[] = {
126 /* config memory values */
127 static ConfOptions *c_options = NULL;
134 static GtkWidget *configwindow = NULL;
135 static GtkListStore *filter_store = NULL;
136 static GtkTreeStore *accel_store = NULL;
138 static GtkWidget *safe_delete_path_entry;
140 static GtkWidget *color_profile_input_file_entry[COLOR_PROFILE_INPUTS];
141 static GtkWidget *color_profile_input_name_entry[COLOR_PROFILE_INPUTS];
142 static GtkWidget *color_profile_screen_file_entry;
143 static GtkWidget *external_preview_select_entry;
144 static GtkWidget *external_preview_extract_entry;
146 static GtkWidget *sidecar_ext_entry;
147 static GtkWidget *help_search_engine_entry;
150 #define CONFIG_WINDOW_DEF_WIDTH 700
151 #define CONFIG_WINDOW_DEF_HEIGHT 600
154 *-----------------------------------------------------------------------------
155 * option widget callbacks (private)
156 *-----------------------------------------------------------------------------
159 static void zoom_increment_cb(GtkWidget *spin, gpointer data)
161 c_options->image.zoom_increment = (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) * 100.0 + 0.01);
164 static void slideshow_delay_hours_cb(GtkWidget *spin, gpointer data)
166 gint mins_secs_tenths, delay;
168 mins_secs_tenths = c_options->slideshow.delay %
169 (3600 * SLIDESHOW_SUBSECOND_PRECISION);
171 delay = (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
172 (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
175 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
176 SLIDESHOW_SUBSECOND_PRECISION;
179 static void slideshow_delay_minutes_cb(GtkWidget *spin, gpointer data)
181 gint hours, secs_tenths, delay;
183 hours = c_options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
184 secs_tenths = c_options->slideshow.delay % (60 * SLIDESHOW_SUBSECOND_PRECISION);
186 delay = hours * (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
187 (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
188 (60 * SLIDESHOW_SUBSECOND_PRECISION) + secs_tenths);
190 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
191 SLIDESHOW_SUBSECOND_PRECISION;
194 static void slideshow_delay_seconds_cb(GtkWidget *spin, gpointer data)
196 gint hours_mins, delay;
198 hours_mins = c_options->slideshow.delay / (60 * SLIDESHOW_SUBSECOND_PRECISION);
200 delay = (hours_mins * (60 * SLIDESHOW_SUBSECOND_PRECISION)) +
201 (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
202 (gdouble)(SLIDESHOW_SUBSECOND_PRECISION) + 0.01);
204 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
205 SLIDESHOW_SUBSECOND_PRECISION;
209 *-----------------------------------------------------------------------------
210 * sync program to config window routine (private)
211 *-----------------------------------------------------------------------------
214 void config_entry_to_option(GtkWidget *entry, gchar **option, gchar *(*func)(const gchar *))
220 buf = gtk_entry_get_text(GTK_ENTRY(entry));
221 if (buf && strlen(buf) > 0)
226 *option = g_strdup(buf);
231 static gboolean accel_apply_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
233 gchar *accel_path, *accel;
235 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, AE_KEY, &accel, -1);
237 if (accel_path && accel_path[0])
240 gtk_accelerator_parse(accel, &key.accel_key, &key.accel_mods);
241 gtk_accel_map_change_entry(accel_path, key.accel_key, key.accel_mods, TRUE);
251 static void config_window_apply(void)
253 gboolean refresh = FALSE;
258 config_entry_to_option(safe_delete_path_entry, &options->file_ops.safe_delete_path, remove_trailing_slash);
260 if (options->file_filter.show_hidden_files != c_options->file_filter.show_hidden_files) refresh = TRUE;
261 if (options->file_filter.show_parent_directory != c_options->file_filter.show_parent_directory) refresh = TRUE;
262 if (options->file_filter.show_dot_directory != c_options->file_filter.show_dot_directory) refresh = TRUE;
263 if (options->file_sort.case_sensitive != c_options->file_sort.case_sensitive) refresh = TRUE;
264 if (options->file_sort.natural != c_options->file_sort.natural) refresh = TRUE;
265 if (options->file_filter.disable_file_extension_checks != c_options->file_filter.disable_file_extension_checks) refresh = TRUE;
266 if (options->file_filter.disable != c_options->file_filter.disable) refresh = TRUE;
268 options->file_ops.confirm_delete = c_options->file_ops.confirm_delete;
269 options->file_ops.enable_delete_key = c_options->file_ops.enable_delete_key;
270 options->file_ops.confirm_move_to_trash = c_options->file_ops.confirm_move_to_trash;
271 options->file_ops.use_system_trash = c_options->file_ops.use_system_trash;
272 options->file_ops.no_trash = c_options->file_ops.no_trash;
273 options->file_ops.safe_delete_folder_maxsize = c_options->file_ops.safe_delete_folder_maxsize;
274 options->tools_restore_state = c_options->tools_restore_state;
275 options->save_window_positions = c_options->save_window_positions;
276 options->use_saved_window_positions_for_new_windows = c_options->use_saved_window_positions_for_new_windows;
277 options->save_window_workspace = c_options->save_window_workspace;
278 options->save_dialog_window_positions = c_options->save_dialog_window_positions;
279 options->show_window_ids = c_options->show_window_ids;
280 options->image.scroll_reset_method = c_options->image.scroll_reset_method;
281 options->image.zoom_2pass = c_options->image.zoom_2pass;
282 options->image.fit_window_to_image = c_options->image.fit_window_to_image;
283 options->image.limit_window_size = c_options->image.limit_window_size;
284 options->image.zoom_to_fit_allow_expand = c_options->image.zoom_to_fit_allow_expand;
285 options->image.max_window_size = c_options->image.max_window_size;
286 options->image.limit_autofit_size = c_options->image.limit_autofit_size;
287 options->image.max_autofit_size = c_options->image.max_autofit_size;
288 options->image.max_enlargement_size = c_options->image.max_enlargement_size;
289 options->image.use_clutter_renderer = c_options->image.use_clutter_renderer;
290 options->image.tile_size = c_options->image.tile_size;
291 options->progressive_key_scrolling = c_options->progressive_key_scrolling;
292 options->keyboard_scroll_step = c_options->keyboard_scroll_step;
294 if (options->thumbnails.max_width != c_options->thumbnails.max_width
295 || options->thumbnails.max_height != c_options->thumbnails.max_height
296 || options->thumbnails.quality != c_options->thumbnails.quality)
298 thumb_format_changed = TRUE;
300 options->thumbnails.max_width = c_options->thumbnails.max_width;
301 options->thumbnails.max_height = c_options->thumbnails.max_height;
302 options->thumbnails.quality = c_options->thumbnails.quality;
304 options->thumbnails.enable_caching = c_options->thumbnails.enable_caching;
305 options->thumbnails.cache_into_dirs = c_options->thumbnails.cache_into_dirs;
306 options->thumbnails.use_exif = c_options->thumbnails.use_exif;
307 options->thumbnails.use_color_management = c_options->thumbnails.use_color_management;
308 options->thumbnails.collection_preview = c_options->thumbnails.collection_preview;
309 options->thumbnails.use_ft_metadata = c_options->thumbnails.use_ft_metadata;
310 // options->thumbnails.use_ft_metadata_small = c_options->thumbnails.use_ft_metadata_small;
311 options->thumbnails.spec_standard = c_options->thumbnails.spec_standard;
312 options->metadata.enable_metadata_dirs = c_options->metadata.enable_metadata_dirs;
313 options->file_filter.show_hidden_files = c_options->file_filter.show_hidden_files;
314 options->file_filter.show_parent_directory = c_options->file_filter.show_parent_directory;
315 options->file_filter.show_dot_directory = c_options->file_filter.show_dot_directory;
316 options->file_filter.disable_file_extension_checks = c_options->file_filter.disable_file_extension_checks;
318 options->file_sort.case_sensitive = c_options->file_sort.case_sensitive;
319 options->file_sort.natural = c_options->file_sort.natural;
320 options->file_filter.disable = c_options->file_filter.disable;
322 config_entry_to_option(sidecar_ext_entry, &options->sidecar.ext, NULL);
323 sidecar_ext_parse(options->sidecar.ext);
325 options->slideshow.random = c_options->slideshow.random;
326 options->slideshow.repeat = c_options->slideshow.repeat;
327 options->slideshow.delay = c_options->slideshow.delay;
329 options->mousewheel_scrolls = c_options->mousewheel_scrolls;
330 options->image_lm_click_nav = c_options->image_lm_click_nav;
331 options->image_l_click_archive = c_options->image_l_click_archive;
332 options->image_l_click_video = c_options->image_l_click_video;
333 options->image_l_click_video_editor = c_options->image_l_click_video_editor;
335 options->file_ops.enable_in_place_rename = c_options->file_ops.enable_in_place_rename;
337 options->image.tile_cache_max = c_options->image.tile_cache_max;
338 options->image.image_cache_max = c_options->image.image_cache_max;
340 options->image.zoom_quality = c_options->image.zoom_quality;
342 options->image.zoom_increment = c_options->image.zoom_increment;
344 options->image.zoom_style = c_options->image.zoom_style;
346 options->image.enable_read_ahead = c_options->image.enable_read_ahead;
349 if (options->image.use_custom_border_color != c_options->image.use_custom_border_color
350 || options->image.use_custom_border_color_in_fullscreen != c_options->image.use_custom_border_color_in_fullscreen
351 || !gdk_color_equal(&options->image.border_color, &c_options->image.border_color))
353 options->image.use_custom_border_color_in_fullscreen = c_options->image.use_custom_border_color_in_fullscreen;
354 options->image.use_custom_border_color = c_options->image.use_custom_border_color;
355 options->image.border_color = c_options->image.border_color;
356 layout_colors_update();
357 view_window_colors_update();
360 options->image.alpha_color_1 = c_options->image.alpha_color_1;
361 options->image.alpha_color_2 = c_options->image.alpha_color_2;
363 options->fullscreen.screen = c_options->fullscreen.screen;
364 options->fullscreen.clean_flip = c_options->fullscreen.clean_flip;
365 options->fullscreen.disable_saver = c_options->fullscreen.disable_saver;
366 options->fullscreen.above = c_options->fullscreen.above;
367 if (c_options->image_overlay.template_string)
368 set_image_overlay_template_string(&options->image_overlay.template_string,
369 c_options->image_overlay.template_string);
370 if (c_options->image_overlay.font)
371 set_image_overlay_font_string(&options->image_overlay.font,
372 c_options->image_overlay.font);
373 options->image_overlay.text_red = c_options->image_overlay.text_red;
374 options->image_overlay.text_green = c_options->image_overlay.text_green;
375 options->image_overlay.text_blue = c_options->image_overlay.text_blue;
376 options->image_overlay.text_alpha = c_options->image_overlay.text_alpha;
377 options->image_overlay.background_red = c_options->image_overlay.background_red;
378 options->image_overlay.background_green = c_options->image_overlay.background_green;
379 options->image_overlay.background_blue = c_options->image_overlay.background_blue;
380 options->image_overlay.background_alpha = c_options->image_overlay.background_alpha;
381 options->update_on_time_change = c_options->update_on_time_change;
382 options->image.exif_proof_rotate_enable = c_options->image.exif_proof_rotate_enable;
384 options->duplicates_similarity_threshold = c_options->duplicates_similarity_threshold;
385 options->rot_invariant_sim = c_options->rot_invariant_sim;
387 options->tree_descend_subdirs = c_options->tree_descend_subdirs;
389 options->view_dir_list_single_click_enter = c_options->view_dir_list_single_click_enter;
390 options->circular_selection_lists = c_options->circular_selection_lists;
392 options->open_recent_list_maxsize = c_options->open_recent_list_maxsize;
393 options->dnd_icon_size = c_options->dnd_icon_size;
394 options->clipboard_selection = c_options->clipboard_selection;
395 options->dnd_default_action = c_options->dnd_default_action;
397 options->metadata.save_in_image_file = c_options->metadata.save_in_image_file;
398 options->metadata.save_legacy_IPTC = c_options->metadata.save_legacy_IPTC;
399 options->metadata.warn_on_write_problems = c_options->metadata.warn_on_write_problems;
400 options->metadata.save_legacy_format = c_options->metadata.save_legacy_format;
401 options->metadata.sync_grouped_files = c_options->metadata.sync_grouped_files;
402 options->metadata.confirm_write = c_options->metadata.confirm_write;
403 options->metadata.sidecar_extended_name = c_options->metadata.sidecar_extended_name;
404 options->metadata.confirm_timeout = c_options->metadata.confirm_timeout;
405 options->metadata.confirm_after_timeout = c_options->metadata.confirm_after_timeout;
406 options->metadata.confirm_on_image_change = c_options->metadata.confirm_on_image_change;
407 options->metadata.confirm_on_dir_change = c_options->metadata.confirm_on_dir_change;
408 options->metadata.keywords_case_sensitive = c_options->metadata.keywords_case_sensitive;
409 options->metadata.write_orientation = c_options->metadata.write_orientation;
410 options->stereo.mode = (c_options->stereo.mode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
411 (c_options->stereo.tmp.mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
412 (c_options->stereo.tmp.flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
413 (c_options->stereo.tmp.mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
414 (c_options->stereo.tmp.flip_left ? PR_STEREO_FLIP_LEFT : 0) |
415 (c_options->stereo.tmp.swap ? PR_STEREO_SWAP : 0) |
416 (c_options->stereo.tmp.temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
417 options->stereo.fsmode = (c_options->stereo.fsmode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
418 (c_options->stereo.tmp.fs_mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
419 (c_options->stereo.tmp.fs_flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
420 (c_options->stereo.tmp.fs_mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
421 (c_options->stereo.tmp.fs_flip_left ? PR_STEREO_FLIP_LEFT : 0) |
422 (c_options->stereo.tmp.fs_swap ? PR_STEREO_SWAP : 0) |
423 (c_options->stereo.tmp.fs_temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
424 options->stereo.enable_fsmode = c_options->stereo.enable_fsmode;
425 options->stereo.fixed_w = c_options->stereo.fixed_w;
426 options->stereo.fixed_h = c_options->stereo.fixed_h;
427 options->stereo.fixed_x1 = c_options->stereo.fixed_x1;
428 options->stereo.fixed_y1 = c_options->stereo.fixed_y1;
429 options->stereo.fixed_x2 = c_options->stereo.fixed_x2;
430 options->stereo.fixed_y2 = c_options->stereo.fixed_y2;
432 options->info_keywords.height = c_options->info_keywords.height;
433 options->info_title.height = c_options->info_title.height;
434 options->info_comment.height = c_options->info_comment.height;
435 options->info_rating.height = c_options->info_rating.height;
437 options->show_predefined_keyword_tree = c_options->show_predefined_keyword_tree;
438 options->expand_menu_toolbar = c_options->expand_menu_toolbar;
440 options->marks_save = c_options->marks_save;
441 options->with_rename = c_options->with_rename;
442 options->collections_on_top = c_options->collections_on_top;
443 options->hide_window_in_fullscreen = c_options->hide_window_in_fullscreen;
444 config_entry_to_option(help_search_engine_entry, &options->help_search_engine, NULL);
446 options->external_preview.enable = c_options->external_preview.enable;
447 config_entry_to_option(external_preview_select_entry, &options->external_preview.select, NULL);
448 config_entry_to_option(external_preview_extract_entry, &options->external_preview.extract, NULL);
450 options->read_metadata_in_idle = c_options->read_metadata_in_idle;
452 options->star_rating.star = c_options->star_rating.star;
453 options->star_rating.rejected = c_options->star_rating.rejected;
455 options->threads.duplicates = c_options->threads.duplicates > 0 ? c_options->threads.duplicates : -1;
458 set_debug_level(debug_c);
462 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
464 config_entry_to_option(color_profile_input_name_entry[i], &options->color_profile.input_name[i], NULL);
465 config_entry_to_option(color_profile_input_file_entry[i], &options->color_profile.input_file[i], NULL);
467 config_entry_to_option(color_profile_screen_file_entry, &options->color_profile.screen_file, NULL);
468 options->color_profile.use_x11_screen_profile = c_options->color_profile.use_x11_screen_profile;
469 if (options->color_profile.render_intent != c_options->color_profile.render_intent)
471 options->color_profile.render_intent = c_options->color_profile.render_intent;
476 options->mouse_button_8 = c_options->mouse_button_8;
477 options->mouse_button_9 = c_options->mouse_button_9;
479 options->override_disable_gpu = c_options->override_disable_gpu;
481 config_tab_keywords_save();
483 image_options_sync();
488 layout_refresh(NULL);
491 if (accel_store) gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_apply_cb, NULL);
493 toolbar_apply(TOOLBAR_MAIN);
494 toolbar_apply(TOOLBAR_STATUS);
498 *-----------------------------------------------------------------------------
499 * config window main button callbacks (private)
500 *-----------------------------------------------------------------------------
503 static void config_window_close_cb(GtkWidget *widget, gpointer data)
505 gtk_widget_destroy(configwindow);
510 static void config_window_help_cb(GtkWidget *widget, gpointer data)
512 GtkWidget *notebook = data;
515 static gchar *html_section[] =
517 "GuideOptionsGeneral.html",
518 "GuideOptionsImage.html",
519 "GuideOptionsOSD.html",
520 "GuideOptionsWindow.html",
521 "GuideOptionsKeyboard.html",
522 "GuideOptionsFiltering.html",
523 "GuideOptionsMetadata.html",
524 "GuideOptionsKeywords.html",
525 "GuideOptionsColor.html",
526 "GuideOptionsStereo.html",
527 "GuideOptionsBehavior.html",
528 "GuideOptionsToolbar.html",
529 "GuideOptionsToolbar.html",
530 "GuideOptionsAdvanced.html"
533 i = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
534 help_window_show(html_section[i]);
537 static gboolean config_window_delete(GtkWidget *widget, GdkEventAny *event, gpointer data)
539 config_window_close_cb(NULL, NULL);
543 static void config_window_ok_cb(GtkWidget *widget, gpointer data)
546 GtkNotebook *notebook = data;
554 lw = layout_window_list->data;
556 window = gtk_widget_get_window(widget);
557 gdk_window_get_root_origin(window, &x, &y);
558 w = gdk_window_get_width(window);
559 h = gdk_window_get_height(window);
560 page_number = gtk_notebook_get_current_page(notebook);
562 lw->options.preferences_window.x = x;
563 lw->options.preferences_window.y = y;
564 lw->options.preferences_window.w = w;
565 lw->options.preferences_window.h = h;
566 lw->options.preferences_window.page_number = page_number;
568 config_window_apply();
569 layout_util_sync(lw);
570 save_options(options);
571 config_window_close_cb(NULL, NULL);
575 *-----------------------------------------------------------------------------
576 * config window setup (private)
577 *-----------------------------------------------------------------------------
580 static void quality_menu_cb(GtkWidget *combo, gpointer data)
584 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
588 *option = GDK_INTERP_NEAREST;
591 *option = GDK_INTERP_TILES;
594 *option = GDK_INTERP_BILINEAR;
599 static void dnd_default_action_selection_menu_cb(GtkWidget *combo, gpointer data)
603 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
607 *option = DND_ACTION_ASK;
610 *option = DND_ACTION_COPY;
613 *option = DND_ACTION_MOVE;
617 static void clipboard_selection_menu_cb(GtkWidget *combo, gpointer data)
621 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
624 *option = CLIPBOARD_PRIMARY;
627 *option = CLIPBOARD_CLIPBOARD;
630 *option = CLIPBOARD_BOTH;
633 *option = CLIPBOARD_BOTH;
637 static void add_quality_menu(GtkWidget *table, gint column, gint row, const gchar *text,
638 guint option, guint *option_c)
645 pref_table_label(table, column, row, text, 0.0);
647 combo = gtk_combo_box_text_new();
649 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Nearest (worst, but fastest)"));
650 if (option == GDK_INTERP_NEAREST) current = 0;
651 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Tiles"));
652 if (option == GDK_INTERP_TILES) current = 1;
653 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Bilinear (best, but slowest)"));
654 if (option == GDK_INTERP_BILINEAR) current = 2;
656 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
658 g_signal_connect(G_OBJECT(combo), "changed",
659 G_CALLBACK(quality_menu_cb), option_c);
661 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
662 gtk_widget_show(combo);
665 static void add_dnd_default_action_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text, DnDAction option, DnDAction *option_c)
672 pref_table_label(table, column, row, text, 0.0);
674 combo = gtk_combo_box_text_new();
676 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Ask"));
677 if (option == DND_ACTION_ASK) current = 0;
678 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Copy"));
679 if (option == DND_ACTION_COPY) current = 1;
680 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Move"));
681 if (option == DND_ACTION_MOVE) current = 2;
683 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
685 g_signal_connect(G_OBJECT(combo), "changed",
686 G_CALLBACK(dnd_default_action_selection_menu_cb), option_c);
688 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
689 gtk_widget_show(combo);
692 static void add_clipboard_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
693 gint option, gint *option_c)
700 pref_table_label(table, column, row, text, 0.0);
702 combo = gtk_combo_box_text_new();
704 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Primary"));
705 if (option == CLIPBOARD_PRIMARY) current = 0;
706 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Clipboard"));
707 if (option == CLIPBOARD_CLIPBOARD) current = 1;
708 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Both"));
709 if (option == CLIPBOARD_BOTH) current = 2;
711 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
713 g_signal_connect(G_OBJECT(combo), "changed",
714 G_CALLBACK(clipboard_selection_menu_cb), option_c);
716 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
717 gtk_widget_show(combo);
720 static void zoom_style_selection_menu_cb(GtkWidget *combo, gpointer data)
724 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
727 *option = ZOOM_GEOMETRIC;
730 *option = ZOOM_ARITHMETIC;
733 *option = ZOOM_GEOMETRIC;
737 static void add_zoom_style_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text, ZoomStyle option, ZoomStyle *option_c)
744 pref_table_label(table, column, row, text, 0.0);
746 combo = gtk_combo_box_text_new();
748 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Geometric"));
749 if (option == ZOOM_GEOMETRIC) current = 0;
750 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Arithmetic"));
751 if (option == ZOOM_ARITHMETIC) current = 1;
753 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
755 g_signal_connect(G_OBJECT(combo), "changed", G_CALLBACK(zoom_style_selection_menu_cb), option_c);
757 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
758 gtk_widget_show(combo);
761 typedef struct _UseableMouseItems UseableMouseItems;
762 struct _UseableMouseItems
764 gchar *name; /* GtkActionEntry terminology */
769 static const UseableMouseItems useable_mouse_items[] = {
771 {"FirstImage", N_("First Image"), GTK_STOCK_GOTO_TOP},
772 {"PrevImage", N_("Previous Image"), GTK_STOCK_GO_UP},
773 {"NextImage", N_("Next Image"), GTK_STOCK_GO_DOWN},
774 {"LastImage", N_("Last Image"), GTK_STOCK_GOTO_BOTTOM},
775 {"Back", N_("Back"), GTK_STOCK_GO_BACK},
776 {"Forward", N_("Forward"), GTK_STOCK_GO_FORWARD},
777 {"Home", N_("Home"), GTK_STOCK_HOME},
778 {"Up", N_("Up"), GTK_STOCK_GO_UP},
779 {"FirstPage", N_("First page"), GTK_STOCK_MEDIA_PREVIOUS},
780 {"LastPage", N_("Last Page"), GTK_STOCK_MEDIA_NEXT},
781 {"NextPage", N_("Next page"), GTK_STOCK_MEDIA_FORWARD},
782 {"PrevPage", N_("Previous Page"), GTK_STOCK_MEDIA_REWIND},
783 {"NewWindow", N_("New _window"), GTK_STOCK_NEW},
784 {"NewCollection", N_("New collection"), GTK_STOCK_INDEX},
785 {"OpenCollection", N_("Open collection"), GTK_STOCK_OPEN},
786 {"Search", N_("Search"), GTK_STOCK_FIND},
787 {"FindDupes", N_("Find duplicates"), GTK_STOCK_FIND},
788 {"NewFolder", N_("New folder"),GTK_STOCK_DIRECTORY},
789 {"Copy", N_("Copy"), GTK_STOCK_COPY},
790 {"Move", N_("Move"), PIXBUF_INLINE_ICON_MOVE},
791 {"Rename", N_("Rename"), PIXBUF_INLINE_ICON_RENAME},
792 {"Delete", N_("Delete"), GTK_STOCK_DELETE},
793 {"CloseWindow", N_("Close Window"), GTK_STOCK_CLOSE},
794 {"PanView", N_("Pan view"), PIXBUF_INLINE_ICON_PANORAMA},
795 {"SelectAll", N_("Select all"), PIXBUF_INLINE_ICON_SELECT_ALL},
796 {"SelectNone", N_("Select none"), PIXBUF_INLINE_ICON_SELECT_NONE},
797 {"SelectInvert", N_("Select invert"), PIXBUF_INLINE_ICON_SELECT_INVERT},
798 {"ShowFileFilter", N_("Show file filter"), PIXBUF_INLINE_ICON_FILE_FILTER},
799 {"RectangularSelection", N_("Select rectangle"), PIXBUF_INLINE_ICON_SELECT_RECTANGLE},
800 {"Print", N_("Print"), GTK_STOCK_PRINT},
801 {"Preferences", N_("Preferences"), GTK_STOCK_PREFERENCES},
802 {"LayoutConfig", N_("Configure this window"), GTK_STOCK_PREFERENCES},
803 {"Maintenance", N_("Cache maintenance"), PIXBUF_INLINE_ICON_MAINTENANCE},
804 {"RotateCW", N_("Rotate clockwise 90°"), PIXBUF_INLINE_ICON_CW},
805 {"RotateCCW", N_("Rotate counterclockwise 90°"), PIXBUF_INLINE_ICON_CCW},
806 {"Rotate180", N_("Rotate 180°"), PIXBUF_INLINE_ICON_180},
807 {"Mirror", N_("Mirror"), PIXBUF_INLINE_ICON_MIRROR},
808 {"Flip", N_("Flip"), PIXBUF_INLINE_ICON_FLIP},
809 {"AlterNone", N_("Original state"), PIXBUF_INLINE_ICON_ORIGINAL},
810 {"ZoomIn", N_("Zoom in"), GTK_STOCK_ZOOM_IN},
811 {"ZoomOut", N_("Zoom out"), GTK_STOCK_ZOOM_OUT},
812 {"Zoom100", N_("Zoom 1:1"), GTK_STOCK_ZOOM_100},
813 {"ZoomFit", N_("Zoom to fit"), GTK_STOCK_ZOOM_FIT},
814 {"ZoomFillHor", N_("Fit Horizontaly"), PIXBUF_INLINE_ICON_ZOOMFILLHOR},
815 {"ZoomFillVert", N_("Fit vertically"), PIXBUF_INLINE_ICON_ZOOMFILLVERT},
816 {"Zoom200", N_("Zoom 2:1"), GTK_STOCK_FILE},
817 {"Zoom300", N_("Zoom 3:1"), GTK_STOCK_FILE},
818 {"Zoom400", N_("Zoom 4:1"), GTK_STOCK_FILE},
819 {"Zoom50", N_("Zoom 1:2"), GTK_STOCK_FILE},
820 {"Zoom33", N_("Zoom1:3"), GTK_STOCK_FILE},
821 {"Zoom25", N_("Zoom 1:4"), GTK_STOCK_FILE},
822 {"ConnectZoomIn", N_("Connected Zoom in"), GTK_STOCK_ZOOM_IN},
823 {"SplitPaneSync", N_("Split Pane Sync"), PIXBUF_INLINE_SPLIT_PANE_SYNC},
824 {"Grayscale", N_("Grayscale"), PIXBUF_INLINE_ICON_GRAYSCALE},
825 {"OverUnderExposed", N_("Over Under Exposed"), PIXBUF_INLINE_ICON_EXPOSURE},
826 {"HideTools", N_("Hide file list"), PIXBUF_INLINE_ICON_HIDETOOLS},
827 {"SlideShowPause", N_("Pause slideshow"), GTK_STOCK_MEDIA_PAUSE},
828 {"SlideShowFaster", N_("Slideshow Faster"), GTK_STOCK_FILE},
829 {"SlideShowSlower", N_("Slideshow Slower"), GTK_STOCK_FILE},
830 {"Refresh", N_("Refresh"), GTK_STOCK_REFRESH},
831 {"HelpContents", N_("Help"), GTK_STOCK_HELP},
832 {"ExifWin", N_("Exif window"), PIXBUF_INLINE_ICON_EXIF},
833 {"Thumbnails", N_("Show thumbnails"), PIXBUF_INLINE_ICON_THUMB},
834 {"ShowMarks", N_("Show marks"), PIXBUF_INLINE_ICON_MARKS},
835 {"DrawRectangle", N_("Draw Rectangle"), PIXBUF_INLINE_ICON_DRAW_RECTANGLE},
836 {"FloatTools", N_("Float file list"), PIXBUF_INLINE_ICON_FLOAT},
837 {"SBar", N_("Info sidebar"), PIXBUF_INLINE_ICON_INFO},
838 {"SBarSort", N_("Sort manager"), PIXBUF_INLINE_ICON_SORT},
839 {"Quit", N_("Quit"), GTK_STOCK_QUIT},
843 static void mouse_buttons_selection_menu_cb(GtkWidget *combo, gpointer data)
845 gchar **option = data;
848 label = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(combo));
850 const UseableMouseItems *list = useable_mouse_items;
854 if (g_strcmp0(list->label, label) == 0)
862 *option = g_strdup(list->name);
866 static void add_mouse_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
867 gchar *option, gchar **option_c)
875 pref_table_label(table, column, row, text, 0.0);
877 combo = gtk_combo_box_text_new();
879 const UseableMouseItems *list = useable_mouse_items;
883 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), list->label);
884 if (g_strcmp0(list->name, option) == 0)
892 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
894 g_signal_connect(G_OBJECT(combo), "changed",
895 G_CALLBACK(mouse_buttons_selection_menu_cb), option_c);
897 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
898 gtk_widget_show(combo);
901 static void thumb_size_menu_cb(GtkWidget *combo, gpointer data)
905 n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
908 if ((guint) n < sizeof(thumb_size_list) / sizeof(ThumbSize))
910 c_options->thumbnails.max_width = thumb_size_list[n].w;
911 c_options->thumbnails.max_height = thumb_size_list[n].h;
915 c_options->thumbnails.max_width = options->thumbnails.max_width;
916 c_options->thumbnails.max_height = options->thumbnails.max_height;
920 static void add_thumb_size_menu(GtkWidget *table, gint column, gint row, gchar *text)
926 c_options->thumbnails.max_width = options->thumbnails.max_width;
927 c_options->thumbnails.max_height = options->thumbnails.max_height;
929 pref_table_label(table, column, row, text, 0.0);
931 combo = gtk_combo_box_text_new();
934 for (i = 0; (guint) i < sizeof(thumb_size_list) / sizeof(ThumbSize); i++)
939 w = thumb_size_list[i].w;
940 h = thumb_size_list[i].h;
942 buf = g_strdup_printf("%d x %d", w, h);
943 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
946 if (w == options->thumbnails.max_width && h == options->thumbnails.max_height) current = i;
953 buf = g_strdup_printf("%s %d x %d", _("Custom"), options->thumbnails.max_width, options->thumbnails.max_height);
954 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
960 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
961 g_signal_connect(G_OBJECT(combo), "changed",
962 G_CALLBACK(thumb_size_menu_cb), NULL);
964 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
965 gtk_widget_show(combo);
968 static void stereo_mode_menu_cb(GtkWidget *combo, gpointer data)
972 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
976 *option = PR_STEREO_NONE;
979 *option = PR_STEREO_ANAGLYPH_RC;
982 *option = PR_STEREO_ANAGLYPH_GM;
985 *option = PR_STEREO_ANAGLYPH_YB;
988 *option = PR_STEREO_ANAGLYPH_GRAY_RC;
991 *option = PR_STEREO_ANAGLYPH_GRAY_GM;
994 *option = PR_STEREO_ANAGLYPH_GRAY_YB;
997 *option = PR_STEREO_ANAGLYPH_DB_RC;
1000 *option = PR_STEREO_ANAGLYPH_DB_GM;
1003 *option = PR_STEREO_ANAGLYPH_DB_YB;
1006 *option = PR_STEREO_HORIZ;
1009 *option = PR_STEREO_HORIZ | PR_STEREO_HALF;
1012 *option = PR_STEREO_VERT;
1015 *option = PR_STEREO_VERT | PR_STEREO_HALF;
1018 *option = PR_STEREO_FIXED;
1023 static void add_stereo_mode_menu(GtkWidget *table, gint column, gint row, const gchar *text,
1024 gint option, gint *option_c, gboolean add_fixed)
1031 pref_table_label(table, column, row, text, 0.0);
1033 combo = gtk_combo_box_text_new();
1035 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Single image"));
1037 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Red-Cyan"));
1038 if (option & PR_STEREO_ANAGLYPH_RC) current = 1;
1039 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Green-Magenta"));
1040 if (option & PR_STEREO_ANAGLYPH_GM) current = 2;
1041 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Yellow-Blue"));
1042 if (option & PR_STEREO_ANAGLYPH_YB) current = 3;
1043 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Red-Cyan"));
1044 if (option & PR_STEREO_ANAGLYPH_GRAY_RC) current = 4;
1045 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Green-Magenta"));
1046 if (option & PR_STEREO_ANAGLYPH_GRAY_GM) current = 5;
1047 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Yellow-Blue"));
1048 if (option & PR_STEREO_ANAGLYPH_GRAY_YB) current = 6;
1049 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Red-Cyan"));
1050 if (option & PR_STEREO_ANAGLYPH_DB_RC) current = 7;
1051 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Green-Magenta"));
1052 if (option & PR_STEREO_ANAGLYPH_DB_GM) current = 8;
1053 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Yellow-Blue"));
1054 if (option & PR_STEREO_ANAGLYPH_DB_YB) current = 9;
1056 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side"));
1057 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side Half size"));
1058 if (option & PR_STEREO_HORIZ)
1061 if (option & PR_STEREO_HALF) current = 11;
1064 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom"));
1065 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom Half size"));
1066 if (option & PR_STEREO_VERT)
1069 if (option & PR_STEREO_HALF) current = 13;
1074 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Fixed position"));
1075 if (option & PR_STEREO_FIXED) current = 14;
1078 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
1080 g_signal_connect(G_OBJECT(combo), "changed",
1081 G_CALLBACK(stereo_mode_menu_cb), option_c);
1083 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
1084 gtk_widget_show(combo);
1087 static void video_menu_cb(GtkWidget *combo, gpointer data)
1089 gchar **option = data;
1091 EditorDescription *ed = g_list_nth_data(editor_list_get(), gtk_combo_box_get_active(GTK_COMBO_BOX(combo)));
1095 static void video_menu_populate(gpointer data, gpointer user_data)
1097 GtkWidget *combo = user_data;
1098 EditorDescription *ed = data;
1100 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), ed->name);
1103 static void add_video_menu(GtkWidget *table, gint column, gint row, const gchar *text,
1104 gchar *option, gchar **option_c)
1108 /* use lists since they are sorted */
1109 GList *eds = editor_list_get();
1113 pref_table_label(table, column, row, text, 0.0);
1115 combo = gtk_combo_box_text_new();
1116 g_list_foreach(eds,video_menu_populate,(gpointer)combo);
1117 current = option ? g_list_index(eds,g_hash_table_lookup(editors,option)): -1;
1119 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
1121 g_signal_connect(G_OBJECT(combo), "changed",
1122 G_CALLBACK(video_menu_cb), option_c);
1124 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
1125 gtk_widget_show(combo);
1128 static void filter_store_populate(void)
1132 if (!filter_store) return;
1134 gtk_list_store_clear(filter_store);
1136 work = filter_get_list();
1145 gtk_list_store_append(filter_store, &iter);
1146 gtk_list_store_set(filter_store, &iter, 0, fe, -1);
1150 static void filter_store_ext_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1151 gchar *new_text, gpointer data)
1153 GtkWidget *model = data;
1154 FilterEntry *fe = data;
1158 if (!new_text || strlen(new_text) < 1) return;
1160 tpath = gtk_tree_path_new_from_string(path_str);
1161 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1162 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1164 g_free(fe->extensions);
1165 fe->extensions = g_strdup(new_text);
1167 gtk_tree_path_free(tpath);
1171 static void filter_store_class_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1172 gchar *new_text, gpointer data)
1174 GtkWidget *model = data;
1175 FilterEntry *fe = data;
1180 if (!new_text || !new_text[0]) return;
1182 tpath = gtk_tree_path_new_from_string(path_str);
1183 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1184 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1186 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
1188 if (strcmp(new_text, _(format_class_list[i])) == 0)
1195 gtk_tree_path_free(tpath);
1199 static void filter_store_desc_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1200 gchar *new_text, gpointer data)
1202 GtkWidget *model = data;
1207 if (!new_text || !new_text[0]) return;
1209 tpath = gtk_tree_path_new_from_string(path_str);
1210 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1211 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1213 g_free(fe->description);
1214 fe->description = g_strdup(new_text);
1216 gtk_tree_path_free(tpath);
1219 static void filter_store_enable_cb(GtkCellRendererToggle *renderer,
1220 gchar *path_str, gpointer data)
1222 GtkWidget *model = data;
1227 tpath = gtk_tree_path_new_from_string(path_str);
1228 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1229 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1231 fe->enabled = !fe->enabled;
1233 gtk_tree_path_free(tpath);
1237 static void filter_store_writable_cb(GtkCellRendererToggle *renderer,
1238 gchar *path_str, gpointer data)
1240 GtkWidget *model = data;
1245 tpath = gtk_tree_path_new_from_string(path_str);
1246 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1247 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1249 fe->writable = !fe->writable;
1250 if (fe->writable) fe->allow_sidecar = FALSE;
1252 gtk_tree_path_free(tpath);
1256 static void filter_store_sidecar_cb(GtkCellRendererToggle *renderer,
1257 gchar *path_str, gpointer data)
1259 GtkWidget *model = data;
1264 tpath = gtk_tree_path_new_from_string(path_str);
1265 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1266 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1268 fe->allow_sidecar = !fe->allow_sidecar;
1269 if (fe->allow_sidecar) fe->writable = FALSE;
1271 gtk_tree_path_free(tpath);
1275 static void filter_set_func(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
1276 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
1280 gtk_tree_model_get(tree_model, iter, 0, &fe, -1);
1282 switch (GPOINTER_TO_INT(data))
1285 g_object_set(GTK_CELL_RENDERER(cell),
1286 "active", fe->enabled, NULL);
1289 g_object_set(GTK_CELL_RENDERER(cell),
1290 "text", fe->extensions, NULL);
1292 case FE_DESCRIPTION:
1293 g_object_set(GTK_CELL_RENDERER(cell),
1294 "text", fe->description, NULL);
1297 g_object_set(GTK_CELL_RENDERER(cell),
1298 "text", _(format_class_list[fe->file_class]), NULL);
1301 g_object_set(GTK_CELL_RENDERER(cell),
1302 "active", fe->writable, NULL);
1304 case FE_ALLOW_SIDECAR:
1305 g_object_set(GTK_CELL_RENDERER(cell),
1306 "active", fe->allow_sidecar, NULL);
1311 static gboolean filter_add_scroll(gpointer data)
1315 GtkCellRenderer *cell;
1316 GtkTreeViewColumn *column;
1319 rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(filter_store), NULL);
1320 path = gtk_tree_path_new_from_indices(rows-1, -1);
1322 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data), 0);
1324 list_cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column));
1325 cell = g_list_last(list_cells)->data;
1327 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1328 path, column, FALSE, 0.0, 0.0 );
1329 gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(data),
1330 path, column, cell, TRUE);
1332 gtk_tree_path_free(path);
1333 g_list_free(list_cells);
1338 static void filter_add_cb(GtkWidget *widget, gpointer data)
1340 filter_add_unique("description", ".new", FORMAT_CLASS_IMAGE, TRUE, FALSE, TRUE);
1341 filter_store_populate();
1343 g_idle_add((GSourceFunc)filter_add_scroll, data);
1346 static void filter_remove_cb(GtkWidget *widget, gpointer data)
1348 GtkWidget *filter_view = data;
1349 GtkTreeSelection *selection;
1353 if (!filter_store) return;
1354 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1355 if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) return;
1356 gtk_tree_model_get(GTK_TREE_MODEL(filter_store), &iter, 0, &fe, -1);
1359 filter_remove_entry(fe);
1361 filter_store_populate();
1364 static gboolean filter_default_ok_scroll(GtkTreeView *data)
1368 GtkTreeViewColumn *column;
1370 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(filter_store), &iter);
1371 path = gtk_tree_model_get_path(GTK_TREE_MODEL(filter_store), &iter);
1372 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1374 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1378 gtk_tree_path_free(path);
1383 static void filter_default_ok_cb(GenericDialog *gd, gpointer data)
1386 filter_add_defaults();
1388 filter_store_populate();
1390 g_idle_add((GSourceFunc)filter_default_ok_scroll, gd->data);
1393 static void dummy_cancel_cb(GenericDialog *gd, gpointer data)
1395 /* no op, only so cancel button appears */
1398 static void filter_default_cb(GtkWidget *widget, gpointer data)
1402 gd = generic_dialog_new(_("Reset filters"),
1403 "reset_filter", widget, TRUE,
1404 dummy_cancel_cb, data);
1405 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset filters"),
1406 _("This will reset the file filters to the defaults.\nContinue?"), TRUE);
1407 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, filter_default_ok_cb, TRUE);
1408 gtk_widget_show(gd->dialog);
1411 static void filter_disable_cb(GtkWidget *widget, gpointer data)
1413 GtkWidget *frame = data;
1415 gtk_widget_set_sensitive(frame,
1416 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
1419 static void safe_delete_view_cb(GtkWidget *widget, gpointer data)
1421 layout_set_path(NULL, gtk_entry_get_text(GTK_ENTRY(safe_delete_path_entry)));
1424 static void safe_delete_clear_ok_cb(GenericDialog *gd, gpointer data)
1426 file_util_trash_clear();
1429 static void safe_delete_clear_cb(GtkWidget *widget, gpointer data)
1433 gd = generic_dialog_new(_("Clear trash"),
1434 "clear_trash", widget, TRUE,
1435 dummy_cancel_cb, NULL);
1436 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear trash"),
1437 _("This will remove the trash contents."), FALSE);
1438 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, safe_delete_clear_ok_cb, TRUE);
1439 entry = gtk_entry_new();
1440 gtk_widget_set_can_focus(entry, FALSE);
1441 gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE);
1442 if (options->file_ops.safe_delete_path) gtk_entry_set_text(GTK_ENTRY(entry), options->file_ops.safe_delete_path);
1443 gtk_box_pack_start(GTK_BOX(gd->vbox), entry, FALSE, FALSE, 0);
1444 gtk_widget_show(entry);
1445 gtk_widget_show(gd->dialog);
1448 static void image_overlay_template_view_changed_cb(GtkWidget *widget, gpointer data)
1450 GtkWidget *pTextView;
1451 GtkTextBuffer *pTextBuffer;
1455 pTextView = GTK_WIDGET(data);
1457 pTextBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pTextView));
1458 gtk_text_buffer_get_start_iter(pTextBuffer, &iStart);
1459 gtk_text_buffer_get_end_iter(pTextBuffer, &iEnd);
1461 set_image_overlay_template_string(&c_options->image_overlay.template_string,
1462 gtk_text_buffer_get_text(pTextBuffer, &iStart, &iEnd, TRUE));
1465 static void image_overlay_default_template_ok_cb(GenericDialog *gd, gpointer data)
1467 GtkTextView *text_view = data;
1468 GtkTextBuffer *buffer;
1470 set_default_image_overlay_template_string(&options->image_overlay.template_string);
1471 if (!configwindow) return;
1473 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
1474 gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1477 static void image_overlay_default_template_cb(GtkWidget *widget, gpointer data)
1481 gd = generic_dialog_new(_("Reset image overlay template string"),
1482 "reset_image_overlay_template_string", widget, TRUE,
1483 dummy_cancel_cb, data);
1484 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset image overlay template string"),
1485 _("This will reset the image overlay template string to the default.\nContinue?"), TRUE);
1486 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, image_overlay_default_template_ok_cb, TRUE);
1487 gtk_widget_show(gd->dialog);
1490 static void image_overlay_help_cb(GtkWidget *widget, gpointer data)
1492 help_window_show("GuideOptionsOSD.html");
1495 static void image_overlay_set_font_cb(GtkWidget *widget, gpointer data)
1497 #if GTK_CHECK_VERSION(3,4,0)
1500 PangoFontDescription *font_desc;
1502 dialog = gtk_font_chooser_dialog_new("Image Overlay Font", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1503 gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), options->image_overlay.font);
1505 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1507 font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
1508 font = pango_font_description_to_string(font_desc);
1509 g_free(c_options->image_overlay.font);
1510 c_options->image_overlay.font = g_strdup(font);
1514 gtk_widget_destroy(dialog);
1518 font = gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget));
1519 c_options->image_overlay.font = g_strdup(font);
1523 static void image_overlay_set_text_colour_cb(GtkWidget *widget, gpointer data)
1526 #if GTK_CHECK_VERSION(3,4,0)
1529 dialog = gtk_color_chooser_dialog_new("Image Overlay Text Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1530 colour.red = options->image_overlay.text_red;
1531 colour.green = options->image_overlay.text_green;
1532 colour.blue = options->image_overlay.text_blue;
1533 colour.alpha = options->image_overlay.text_alpha;
1534 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1535 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1537 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1539 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1540 c_options->image_overlay.text_red = colour.red*255;
1541 c_options->image_overlay.text_green = colour.green*255;
1542 c_options->image_overlay.text_blue = colour.blue*255;
1543 c_options->image_overlay.text_alpha = colour.alpha*255;
1545 gtk_widget_destroy(dialog);
1548 GtkColorSelection *colorsel;
1550 dialog = gtk_color_selection_dialog_new("Image Overlay Text Colour");
1551 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1552 colour.red = options->image_overlay.text_red*257;
1553 colour.green = options->image_overlay.text_green*257;
1554 colour.blue = options->image_overlay.text_blue*257;
1555 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1556 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1557 gtk_color_selection_set_current_color(colorsel, &colour);
1558 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.text_alpha*257);
1560 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1562 gtk_color_selection_get_current_color(colorsel, &colour);
1563 c_options->image_overlay.text_red = colour.red/257;
1564 c_options->image_overlay.text_green = colour.green/257;
1565 c_options->image_overlay.text_blue = colour.blue/257;
1566 c_options->image_overlay.text_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1568 gtk_widget_destroy (dialog);
1573 static void image_overlay_set_background_colour_cb(GtkWidget *widget, gpointer data)
1576 #if GTK_CHECK_VERSION(3,4,0)
1579 dialog = gtk_color_chooser_dialog_new("Image Overlay Background Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1580 colour.red = options->image_overlay.background_red;
1581 colour.green = options->image_overlay.background_green;
1582 colour.blue = options->image_overlay.background_blue;
1583 colour.alpha = options->image_overlay.background_alpha;
1584 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1585 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1587 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1589 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1590 c_options->image_overlay.background_red = colour.red*255;
1591 c_options->image_overlay.background_green = colour.green*255;
1592 c_options->image_overlay.background_blue = colour.blue*255;
1593 c_options->image_overlay.background_alpha = colour.alpha*255;
1595 gtk_widget_destroy(dialog);
1598 GtkColorSelection *colorsel;
1600 dialog = gtk_color_selection_dialog_new("Image Overlay Background Colour");
1601 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1602 colour.red = options->image_overlay.background_red*257;
1603 colour.green = options->image_overlay.background_green*257;
1604 colour.blue = options->image_overlay.background_blue*257;
1605 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1606 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1607 gtk_color_selection_set_current_color(colorsel, &colour);
1608 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.background_alpha*257);
1610 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1612 gtk_color_selection_get_current_color(colorsel, &colour);
1613 c_options->image_overlay.background_red = colour.red/257;
1614 c_options->image_overlay.background_green = colour.green/257;
1615 c_options->image_overlay.background_blue = colour.blue/257;
1616 c_options->image_overlay.background_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1618 gtk_widget_destroy(dialog);
1622 static void accel_store_populate(void)
1625 GList *groups, *actions;
1627 const gchar *accel_path;
1631 if (!accel_store || !layout_window_list || !layout_window_list->data) return;
1633 gtk_tree_store_clear(accel_store);
1634 lw = layout_window_list->data; /* get the actions from the first window, it should not matter, they should be the same in all windows */
1636 g_assert(lw && lw->ui_manager);
1637 groups = gtk_ui_manager_get_action_groups(lw->ui_manager);
1640 actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
1643 action = GTK_ACTION(actions->data);
1644 accel_path = gtk_action_get_accel_path(action);
1645 if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
1647 gchar *label, *label2, *tooltip, *accel;
1648 g_object_get(action,
1649 "tooltip", &tooltip,
1653 if (pango_parse_markup(label, -1, '_', NULL, &label2, NULL, NULL) && label2)
1659 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1663 gtk_tree_store_append(accel_store, &iter, NULL);
1664 gtk_tree_store_set(accel_store, &iter,
1667 AE_TOOLTIP, tooltip ? tooltip : "",
1668 AE_ACCEL, accel_path,
1676 actions = actions->next;
1679 groups = groups->next;
1683 static void accel_store_cleared_cb(GtkCellRendererAccel *accel, gchar *path_string, gpointer user_data)
1688 static gboolean accel_remove_key_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1690 gchar *accel1 = data;
1695 gtk_tree_model_get(model, iter, AE_KEY, &accel2, -1);
1697 gtk_accelerator_parse(accel1, &key1.accel_key, &key1.accel_mods);
1698 gtk_accelerator_parse(accel2, &key2.accel_key, &key2.accel_mods);
1700 if (key1.accel_key == key2.accel_key && key1.accel_mods == key2.accel_mods)
1702 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1703 DEBUG_1("accelerator key '%s' is already used, removing.", accel1);
1712 static void accel_store_edited_cb(GtkCellRendererAccel *accel, gchar *path_string, guint accel_key, GdkModifierType accel_mods, guint hardware_keycode, gpointer user_data)
1714 GtkTreeModel *model = (GtkTreeModel *)accel_store;
1718 GtkAccelKey old_key, key;
1719 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
1721 gtk_tree_model_get_iter(model, &iter, path);
1722 gtk_tree_model_get(model, &iter, AE_ACCEL, &accel_path, -1);
1724 /* test if the accelerator can be stored without conflicts*/
1725 gtk_accel_map_lookup_entry(accel_path, &old_key);
1727 /* change the key and read it back (change may fail on keys hardcoded in gtk)*/
1728 gtk_accel_map_change_entry(accel_path, accel_key, accel_mods, TRUE);
1729 gtk_accel_map_lookup_entry(accel_path, &key);
1731 /* restore the original for now, the key will be really changed when the changes are confirmed */
1732 gtk_accel_map_change_entry(accel_path, old_key.accel_key, old_key.accel_mods, TRUE);
1734 acc = gtk_accelerator_name(key.accel_key, key.accel_mods);
1735 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, acc);
1737 gtk_tree_store_set(accel_store, &iter, AE_KEY, acc, -1);
1738 gtk_tree_path_free(path);
1742 static gboolean accel_default_scroll(GtkTreeView *data)
1746 GtkTreeViewColumn *column;
1748 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(accel_store), &iter);
1749 path = gtk_tree_model_get_path(GTK_TREE_MODEL(accel_store), &iter);
1750 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1752 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1756 gtk_tree_path_free(path);
1761 static void accel_default_cb(GtkWidget *widget, gpointer data)
1763 accel_store_populate();
1765 g_idle_add((GSourceFunc)accel_default_scroll, data);
1768 void accel_remove_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1770 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1773 void accel_reset_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1776 gchar *accel_path, *accel;
1778 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, -1);
1779 gtk_accel_map_lookup_entry(accel_path, &key);
1780 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1782 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, accel);
1784 gtk_tree_store_set(accel_store, iter, AE_KEY, accel, -1);
1789 static void accel_reset_cb(GtkWidget *widget, gpointer data)
1791 GtkTreeSelection *selection;
1793 if (!accel_store) return;
1794 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data));
1795 gtk_tree_selection_selected_foreach(selection, &accel_reset_selection, NULL);
1800 static GtkWidget *scrolled_notebook_page(GtkWidget *notebook, const gchar *title)
1804 GtkWidget *scrolled;
1805 GtkWidget *viewport;
1807 scrolled = gtk_scrolled_window_new(NULL, NULL);
1808 gtk_container_set_border_width(GTK_CONTAINER(scrolled), PREF_PAD_BORDER);
1809 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1810 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1811 label = gtk_label_new(title);
1812 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, label);
1813 gtk_widget_show(scrolled);
1815 viewport = gtk_viewport_new(NULL, NULL);
1816 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1817 gtk_container_add(GTK_CONTAINER(scrolled), viewport);
1818 gtk_widget_show(viewport);
1820 vbox = gtk_vbox_new(FALSE, 0);
1821 gtk_container_add(GTK_CONTAINER(viewport), vbox);
1822 gtk_widget_show(vbox);
1827 static void cache_standard_cb(GtkWidget *widget, gpointer data)
1829 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1831 c_options->thumbnails.spec_standard =TRUE;
1832 c_options->thumbnails.cache_into_dirs = FALSE;
1836 static void cache_geeqie_cb(GtkWidget *widget, gpointer data)
1838 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1840 c_options->thumbnails.spec_standard =FALSE;
1841 c_options->thumbnails.cache_into_dirs = FALSE;
1845 static void cache_local_cb(GtkWidget *widget, gpointer data)
1847 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1849 c_options->thumbnails.cache_into_dirs = TRUE;
1850 c_options->thumbnails.spec_standard =FALSE;
1854 static void help_search_engine_entry_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1855 GdkEvent *event, gpointer userdata)
1857 if (pos == GTK_ENTRY_ICON_PRIMARY)
1859 gtk_entry_set_text(GTK_ENTRY(userdata), HELP_SEARCH_ENGINE);
1863 gtk_entry_set_text(GTK_ENTRY(userdata), "");
1867 static void star_rating_star_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1868 GdkEvent *event, gpointer userdata)
1870 gchar *rating_symbol;
1872 if (pos == GTK_ENTRY_ICON_PRIMARY)
1874 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_STAR);
1875 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1876 g_free(rating_symbol);
1880 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1881 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1882 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1886 static void star_rating_rejected_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1887 GdkEvent *event, gpointer userdata)
1889 gchar *rating_symbol;
1891 if (pos == GTK_ENTRY_ICON_PRIMARY)
1893 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_REJECTED);
1894 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1895 g_free(rating_symbol);
1899 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1900 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1901 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1905 static guint star_rating_symbol_test(GtkWidget *widget, gpointer data)
1907 GtkContainer *hbox = data;
1908 GString *str = g_string_new(NULL);
1909 GtkEntry *hex_code_entry;
1910 gchar *hex_code_full;
1913 guint64 hex_value = 0;
1915 list = gtk_container_get_children(hbox);
1917 hex_code_entry = g_list_nth_data(list, 2);
1918 hex_code_full = g_strdup(gtk_entry_get_text(hex_code_entry));
1920 hex_code = g_strsplit(hex_code_full, "+", 2);
1921 if (hex_code[0] && hex_code[1])
1923 hex_value = strtoull(hex_code[1], NULL, 16);
1925 if (!hex_value || hex_value > 0x10FFFF)
1927 hex_value = 0x003F; // Unicode 'Question Mark'
1929 str = g_string_append_unichar(str, (gunichar)hex_value);
1930 gtk_label_set_text(g_list_nth_data(list, 1), str->str);
1932 g_strfreev(hex_code);
1933 g_string_free(str, TRUE);
1934 g_free(hex_code_full);
1939 static void star_rating_star_test_cb(GtkWidget *widget, gpointer data)
1941 guint64 star_symbol;
1943 star_symbol = star_rating_symbol_test(widget, data);
1944 c_options->star_rating.star = star_symbol;
1947 static void star_rating_rejected_test_cb(GtkWidget *widget, gpointer data)
1949 guint64 rejected_symbol;
1951 rejected_symbol = star_rating_symbol_test(widget, data);
1952 c_options->star_rating.rejected = rejected_symbol;
1955 /* general options tab */
1956 static void timezone_database_install_cb(GtkWidget *widget, gpointer data);
1957 typedef struct _TZData TZData;
1961 GCancellable *cancellable;
1963 GtkWidget *progress;
1965 GFile *timezone_database_gq;
1966 gchar *timezone_database_user;
1969 static void config_tab_general(GtkWidget *notebook)
1974 GtkWidget *group_frame;
1975 GtkWidget *subgroup;
1977 GtkWidget *ct_button;
1980 gint hours, minutes, remainder;
1982 GtkWidget *star_rating_entry;
1984 gchar *rating_symbol;
1987 GNetworkMonitor *net_mon;
1988 GSocketConnectable *geeqie_org;
1989 gboolean internet_available;
1992 vbox = scrolled_notebook_page(notebook, _("General"));
1994 group = pref_group_new(vbox, FALSE, _("Thumbnails"), GTK_ORIENTATION_VERTICAL);
1996 table = pref_table_new(group, 2, 2, FALSE, FALSE);
1997 add_thumb_size_menu(table, 0, 0, _("Size:"));
1998 add_quality_menu(table, 0, 1, _("Quality:"), options->thumbnails.quality, &c_options->thumbnails.quality);
2000 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2001 pref_label_new(hbox, _("Custom size: "));
2002 pref_spin_new_int(hbox, _("Width:"), NULL, 1, 512, 1, options->thumbnails.max_width, &c_options->thumbnails.max_width);
2003 pref_spin_new_int(hbox, _("Height:"), NULL, 1, 512, 1, options->thumbnails.max_height, &c_options->thumbnails.max_height);
2005 ct_button = pref_checkbox_new_int(group, _("Cache thumbnails and sim. files"),
2006 options->thumbnails.enable_caching, &c_options->thumbnails.enable_caching);
2008 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2009 pref_checkbox_link_sensitivity(ct_button, subgroup);
2011 c_options->thumbnails.spec_standard = options->thumbnails.spec_standard;
2012 c_options->thumbnails.cache_into_dirs = options->thumbnails.cache_into_dirs;
2013 group_frame = pref_frame_new(subgroup, TRUE, _("Use Geeqie thumbnail style and cache"),
2014 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2015 button = pref_radiobutton_new(group_frame, NULL, get_thumbnails_cache_dir(),
2016 !options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
2017 G_CALLBACK(cache_geeqie_cb), NULL);
2019 group_frame = pref_frame_new(subgroup, TRUE,
2020 _("Store thumbnails local to image folder (non-standard)"),
2021 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2022 pref_radiobutton_new(group_frame, button, "*/.thumbnails",
2023 !options->thumbnails.spec_standard && options->thumbnails.cache_into_dirs,
2024 G_CALLBACK(cache_local_cb), NULL);
2026 group_frame = pref_frame_new(subgroup, TRUE,
2027 _("Use standard thumbnail style and cache, shared with other applications"),
2028 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2029 pref_radiobutton_new(group_frame, button, get_thumbnails_standard_cache_dir(),
2030 options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
2031 G_CALLBACK(cache_standard_cb), NULL);
2033 pref_checkbox_new_int(group, _("Use EXIF thumbnails when available (EXIF thumbnails may be outdated)"),
2034 options->thumbnails.use_exif, &c_options->thumbnails.use_exif);
2036 pref_checkbox_new_int(group, _("Thumbnail color management"),
2037 options->thumbnails.use_color_management, &c_options->thumbnails.use_color_management);
2039 spin = pref_spin_new_int(group, _("Collection preview:"), NULL,
2041 options->thumbnails.collection_preview, &c_options->thumbnails.collection_preview);
2042 gtk_widget_set_tooltip_text(spin, _("The maximum number of thumbnails shown in a Collection preview montage"));
2044 #ifdef HAVE_FFMPEGTHUMBNAILER_METADATA
2045 pref_checkbox_new_int(group, _("Use embedded metadata in video files as thumbnails when available"),
2046 options->thumbnails.use_ft_metadata, &c_options->thumbnails.use_ft_metadata);
2048 // pref_checkbox_new_int(group, _("Ignore embedded metadata if size is too small"),
2049 // options->thumbnails.use_ft_metadata_small, &c_options->thumbnails.use_ft_metadata_small);
2052 pref_spacer(group, PREF_PAD_GROUP);
2054 group = pref_group_new(vbox, FALSE, _("Star Rating"), GTK_ORIENTATION_VERTICAL);
2056 c_options->star_rating.star = options->star_rating.star;
2057 c_options->star_rating.rejected = options->star_rating.rejected;
2059 str = g_string_new(NULL);
2060 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2061 pref_label_new(hbox, _("Star character: "));
2062 str = g_string_append_unichar(str, options->star_rating.star);
2063 pref_label_new(hbox, g_strdup(str->str));
2064 rating_symbol = g_strdup_printf("U+%X", options->star_rating.star);
2065 star_rating_entry = gtk_entry_new();
2066 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
2067 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
2068 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
2069 gtk_widget_show(star_rating_entry);
2070 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
2071 G_CALLBACK(star_rating_star_test_cb), hbox);
2072 gtk_widget_set_tooltip_text(button, _("Display selected character"));
2073 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2074 gtk_widget_show(button);
2075 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."));
2076 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2077 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2078 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2079 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2080 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2081 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2082 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2083 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2084 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
2085 G_CALLBACK(star_rating_star_icon_cb),
2088 g_string_free(str, TRUE);
2089 g_free(rating_symbol);
2091 str = g_string_new(NULL);
2092 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2093 pref_label_new(hbox, _("Rejected character: "));
2094 str = g_string_append_unichar(str, options->star_rating.rejected);
2095 pref_label_new(hbox, g_strdup(str->str));
2096 rating_symbol = g_strdup_printf("U+%X", options->star_rating.rejected);
2097 star_rating_entry = gtk_entry_new();
2098 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
2099 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
2100 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
2101 gtk_widget_show(star_rating_entry);
2102 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
2103 G_CALLBACK(star_rating_rejected_test_cb), hbox);
2104 gtk_widget_set_tooltip_text(button, _("Display selected character"));
2105 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2106 gtk_widget_show(button);
2107 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."));
2108 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2109 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2110 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2111 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2112 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2113 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2114 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2115 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2116 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
2117 G_CALLBACK(star_rating_rejected_icon_cb),
2120 g_string_free(str, TRUE);
2121 g_free(rating_symbol);
2123 pref_spacer(group, PREF_PAD_GROUP);
2125 group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
2127 c_options->slideshow.delay = options->slideshow.delay;
2128 hours = options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2129 remainder = options->slideshow.delay % (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2130 minutes = remainder / (60 * SLIDESHOW_SUBSECOND_PRECISION);
2131 seconds = (gdouble)(remainder % (60 * SLIDESHOW_SUBSECOND_PRECISION)) /
2132 SLIDESHOW_SUBSECOND_PRECISION;
2134 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2136 spin = pref_spin_new(hbox, _("Delay between image change hrs:mins:secs.dec"), NULL,
2138 options->slideshow.delay ? hours : 0.0,
2139 G_CALLBACK(slideshow_delay_hours_cb), NULL);
2140 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2141 spin = pref_spin_new(hbox, ":" , NULL,
2143 options->slideshow.delay ? minutes: 0.0,
2144 G_CALLBACK(slideshow_delay_minutes_cb), NULL);
2145 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2146 spin = pref_spin_new(hbox, ":", NULL,
2147 SLIDESHOW_MIN_SECONDS, 59, 1.0, 1,
2148 options->slideshow.delay ? seconds : 10.0,
2149 G_CALLBACK(slideshow_delay_seconds_cb), NULL);
2150 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2152 pref_checkbox_new_int(group, _("Random"), options->slideshow.random, &c_options->slideshow.random);
2153 pref_checkbox_new_int(group, _("Repeat"), options->slideshow.repeat, &c_options->slideshow.repeat);
2155 pref_spacer(group, PREF_PAD_GROUP);
2157 group = pref_group_new(vbox, FALSE, _("Image loading and caching"), GTK_ORIENTATION_VERTICAL);
2159 pref_spin_new_int(group, _("Decoded image cache size (MiB):"), NULL,
2160 0, 99999, 1, options->image.image_cache_max, &c_options->image.image_cache_max);
2161 pref_checkbox_new_int(group, _("Preload next image"),
2162 options->image.enable_read_ahead, &c_options->image.enable_read_ahead);
2164 pref_checkbox_new_int(group, _("Refresh on file change"),
2165 options->update_on_time_change, &c_options->update_on_time_change);
2168 pref_spacer(group, PREF_PAD_GROUP);
2170 group = pref_group_new(vbox, FALSE, _("Expand menu and toolbar"), GTK_ORIENTATION_VERTICAL);
2172 pref_checkbox_new_int(group, _("Expand menu and toolbar (NOTE! Geeqie must be restarted for change to take effect)"),
2173 options->expand_menu_toolbar, &c_options->expand_menu_toolbar);
2174 gtk_widget_set_tooltip_text(group, _("Expand the menu and toolbar to the full width of the window"));
2176 pref_spacer(group, PREF_PAD_GROUP);
2178 net_mon = g_network_monitor_get_default();
2179 geeqie_org = g_network_address_parse_uri(GQ_WEBSITE, 80, NULL);
2180 internet_available = g_network_monitor_can_reach(net_mon, geeqie_org, NULL, NULL);
2181 g_object_unref(geeqie_org);
2183 group = pref_group_new(vbox, FALSE, _("Timezone database"), GTK_ORIENTATION_VERTICAL);
2184 hbox = pref_box_new(group, TRUE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2186 if (!internet_available)
2188 gtk_widget_set_sensitive(group, FALSE);
2191 tz = g_new0(TZData, 1);
2193 path = path_from_utf8(TIMEZONE_DATABASE);
2194 basename = g_path_get_basename(path);
2195 tz->timezone_database_user = g_build_filename(get_rc_dir(), basename, NULL);
2199 if (isfile(tz->timezone_database_user))
2201 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Update"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2205 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Install"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2208 if (!internet_available)
2210 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"));
2214 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"));
2216 gtk_widget_show(button);
2218 pref_spacer(group, PREF_PAD_GROUP);
2220 group = pref_group_new(vbox, FALSE, _("On-line help search engine"), GTK_ORIENTATION_VERTICAL);
2222 help_search_engine_entry = gtk_entry_new();
2223 gtk_entry_set_text(GTK_ENTRY(help_search_engine_entry), options->help_search_engine);
2224 gtk_box_pack_start(GTK_BOX(group), help_search_engine_entry, FALSE, FALSE, 0);
2225 gtk_widget_show(help_search_engine_entry);
2227 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"));
2229 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2230 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2231 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2232 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2233 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2234 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2235 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2236 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2237 g_signal_connect(GTK_ENTRY(help_search_engine_entry), "icon-press",
2238 G_CALLBACK(help_search_engine_entry_icon_cb),
2239 help_search_engine_entry);
2243 static void config_tab_image(GtkWidget *notebook)
2248 GtkWidget *ct_button;
2249 GtkWidget *enlargement_button;
2252 GtkWidget *two_pass;
2254 GtkWidget *gpu_accel;
2257 vbox = scrolled_notebook_page(notebook, _("Image"));
2259 group = pref_group_new(vbox, FALSE, _("Zoom"), GTK_ORIENTATION_VERTICAL);
2261 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2262 add_quality_menu(table, 0, 0, _("Quality:"), options->image.zoom_quality, &c_options->image.zoom_quality);
2263 if (options->image.use_clutter_renderer && !options->disable_gpu)
2265 gtk_widget_set_sensitive(table, FALSE);
2269 gpu_accel = pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library (Requires restart)"),
2270 options->image.use_clutter_renderer, &c_options->image.use_clutter_renderer);
2271 if (options->disable_gpu && !options->override_disable_gpu)
2273 gtk_widget_set_sensitive(gpu_accel, FALSE);
2277 two_pass = pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"),
2278 options->image.zoom_2pass, &c_options->image.zoom_2pass);
2279 if (options->image.use_clutter_renderer && !options->disable_gpu)
2281 gtk_widget_set_sensitive(two_pass, FALSE);
2284 c_options->image.zoom_increment = options->image.zoom_increment;
2285 spin = pref_spin_new(group, _("Zoom increment:"), NULL,
2286 0.01, 4.0, 0.01, 2, (gdouble)options->image.zoom_increment / 100.0,
2287 G_CALLBACK(zoom_increment_cb), NULL);
2288 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2290 c_options->image.zoom_style = options->image.zoom_style;
2291 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2292 add_zoom_style_selection_menu(table, 0, 0, _("Zoom style:"), options->image.zoom_style, &c_options->image.zoom_style);
2294 group = pref_group_new(vbox, FALSE, _("Fit image to window"), GTK_ORIENTATION_VERTICAL);
2296 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2297 enlargement_button = pref_checkbox_new_int(hbox, _("Allow enlargement of image (max. size in %)"),
2298 options->image.zoom_to_fit_allow_expand, &c_options->image.zoom_to_fit_allow_expand);
2299 spin = pref_spin_new_int(hbox, NULL, NULL,
2301 options->image.max_enlargement_size, &c_options->image.max_enlargement_size);
2302 pref_checkbox_link_sensitivity(enlargement_button, spin);
2303 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."));
2305 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2306 ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (% of actual window):"),
2307 options->image.limit_autofit_size, &c_options->image.limit_autofit_size);
2308 spin = pref_spin_new_int(hbox, NULL, NULL,
2310 options->image.max_autofit_size, &c_options->image.max_autofit_size);
2311 pref_checkbox_link_sensitivity(ct_button, spin);
2312 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."));
2314 group = pref_group_new(vbox, FALSE, _("Tile size"), GTK_ORIENTATION_VERTICAL);
2315 gtk_widget_set_sensitive(group, !options->image.use_clutter_renderer);
2317 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2318 spin = pref_spin_new_int(hbox, _("Pixels"), _("(Requires restart)"),
2320 options->image.tile_size, &c_options->image.tile_size);
2321 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."));
2323 group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
2325 pref_checkbox_new_int(group, _("Use custom border color in window mode"),
2326 options->image.use_custom_border_color, &c_options->image.use_custom_border_color);
2328 pref_checkbox_new_int(group, _("Use custom border color in fullscreen mode"),
2329 options->image.use_custom_border_color_in_fullscreen, &c_options->image.use_custom_border_color_in_fullscreen);
2331 pref_color_button_new(group, _("Border color"), &options->image.border_color,
2332 G_CALLBACK(pref_color_button_set_cb), &c_options->image.border_color);
2334 c_options->image.border_color = options->image.border_color;
2336 pref_color_button_new(group, _("Alpha channel color 1"), &options->image.alpha_color_1,
2337 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_1);
2339 pref_color_button_new(group, _("Alpha channel color 2"), &options->image.alpha_color_2,
2340 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_2);
2342 c_options->image.alpha_color_1 = options->image.alpha_color_1;
2343 c_options->image.alpha_color_2 = options->image.alpha_color_2;
2345 group = pref_group_new(vbox, FALSE, _("Convenience"), GTK_ORIENTATION_VERTICAL);
2347 pref_checkbox_new_int(group, _("Auto rotate proofs using Exif information"),
2348 options->image.exif_proof_rotate_enable, &c_options->image.exif_proof_rotate_enable);
2353 static void save_default_window_layout_cb(GtkWidget *widget, gpointer data)
2355 LayoutWindow *lw = NULL;
2356 gchar *default_path;
2359 /* Get current lw */
2362 tmp_id = lw->options.id;
2363 lw->options.id = g_strdup("lw_default");
2365 default_path = g_build_filename(get_rc_dir(), DEFAULT_WINDOW_LAYOUT, NULL);
2366 save_default_layout_options_to_file(default_path, options, lw);
2367 g_free(lw->options.id);
2368 lw->options.id = tmp_id;
2369 g_free(default_path);
2372 #if GTK_CHECK_VERSION(3,22,0)
2373 static gboolean popover_cb(gpointer data)
2375 GtkPopover *popover = data;
2377 gtk_popover_popdown(popover);
2382 static void default_layout_changed_cb(GtkWidget *button, GtkPopover *popover)
2384 gtk_popover_popup(popover);
2386 g_timeout_add(2000, popover_cb, popover);
2389 static GtkWidget *create_popover(GtkWidget *parent, GtkWidget *child, GtkPositionType pos)
2393 popover = gtk_popover_new(parent);
2394 gtk_popover_set_position(GTK_POPOVER (popover), pos);
2395 gtk_container_add (GTK_CONTAINER(popover), child);
2396 gtk_container_set_border_width(GTK_CONTAINER (popover), 6);
2397 gtk_widget_show (child);
2403 static void config_tab_windows(GtkWidget *notebook)
2408 GtkWidget *subgroup;
2410 GtkWidget *ct_button;
2413 vbox = scrolled_notebook_page(notebook, _("Windows"));
2415 group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
2417 ct_button = pref_checkbox_new_int(group, _("Remember session"),
2418 options->save_window_positions, &c_options->save_window_positions);
2420 button = pref_checkbox_new_int(group, _("Use saved window positions also for new windows"),
2421 options->use_saved_window_positions_for_new_windows, &c_options->use_saved_window_positions_for_new_windows);
2422 pref_checkbox_link_sensitivity(ct_button, button);
2424 button = pref_checkbox_new_int(group, _("Remember window workspace"),
2425 options->save_window_workspace, &c_options->save_window_workspace);
2426 pref_checkbox_link_sensitivity(ct_button, button);
2428 pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
2429 options->tools_restore_state, &c_options->tools_restore_state);
2431 pref_checkbox_new_int(group, _("Remember dialog window positions"),
2432 options->save_dialog_window_positions, &c_options->save_dialog_window_positions);
2434 pref_checkbox_new_int(group, _("Show window IDs"),
2435 options->show_window_ids, &c_options->show_window_ids);
2437 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2438 pref_label_new(subgroup, _("Use current layout for default: "));
2439 button = pref_button_new(subgroup, NULL, _("Set"), FALSE, G_CALLBACK(save_default_window_layout_cb), NULL);
2441 #if GTK_CHECK_VERSION(3,22,0)
2444 popover = create_popover(button, gtk_label_new(_("Current window layout\nhas been set as default")), GTK_POS_TOP);
2445 gtk_popover_set_modal(GTK_POPOVER (popover), FALSE);
2446 g_signal_connect(button, "clicked", G_CALLBACK(default_layout_changed_cb), popover);
2449 group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
2451 pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
2452 options->image.fit_window_to_image, &c_options->image.fit_window_to_image);
2454 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2455 ct_button = pref_checkbox_new_int(hbox, _("Limit size when auto-sizing window (%):"),
2456 options->image.limit_window_size, &c_options->image.limit_window_size);
2457 spin = pref_spin_new_int(hbox, NULL, NULL,
2459 options->image.max_window_size, &c_options->image.max_window_size);
2460 pref_checkbox_link_sensitivity(ct_button, spin);
2462 group = pref_group_new(vbox, FALSE, _("Full screen"), GTK_ORIENTATION_VERTICAL);
2464 c_options->fullscreen.screen = options->fullscreen.screen;
2465 c_options->fullscreen.above = options->fullscreen.above;
2466 hbox = fullscreen_prefs_selection_new(_("Location:"), &c_options->fullscreen.screen, &c_options->fullscreen.above);
2467 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2468 gtk_widget_show(hbox);
2470 pref_checkbox_new_int(group, _("Smooth image flip"),
2471 options->fullscreen.clean_flip, &c_options->fullscreen.clean_flip);
2472 pref_checkbox_new_int(group, _("Disable screen saver"),
2473 options->fullscreen.disable_saver, &c_options->fullscreen.disable_saver);
2476 #define PRE_FORMATTED_COLUMNS 5
2477 static void config_tab_osd(GtkWidget *notebook)
2483 GtkWidget *image_overlay_template_view;
2484 GtkWidget *scrolled;
2485 GtkWidget *scrolled_pre_formatted;
2486 GtkTextBuffer *buffer;
2488 GtkWidget *subgroup;
2490 vbox = scrolled_notebook_page(notebook, _("OSD"));
2492 image_overlay_template_view = gtk_text_view_new();
2494 group = pref_group_new(vbox, FALSE, _("Overlay Screen Display"), GTK_ORIENTATION_VERTICAL);
2496 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2498 scrolled_pre_formatted = osd_new(PRE_FORMATTED_COLUMNS, image_overlay_template_view);
2499 gtk_widget_set_size_request(scrolled_pre_formatted, 200, 150);
2500 gtk_box_pack_start(GTK_BOX(subgroup), scrolled_pre_formatted, FALSE, FALSE, 0);
2501 gtk_widget_show(scrolled_pre_formatted);
2502 gtk_widget_show(subgroup);
2504 pref_line(group, PREF_PAD_GAP);
2506 pref_label_new(group, _("Image overlay template"));
2508 scrolled = gtk_scrolled_window_new(NULL, NULL);
2509 gtk_widget_set_size_request(scrolled, 200, 150);
2510 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2511 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
2512 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2513 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 5);
2514 gtk_widget_show(scrolled);
2516 gtk_widget_set_tooltip_markup(image_overlay_template_view,
2517 _("Extensive formatting options are shown in the Help file"));
2519 gtk_container_add(GTK_CONTAINER(scrolled), image_overlay_template_view);
2520 gtk_widget_show(image_overlay_template_view);
2522 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2524 #if GTK_CHECK_VERSION(3,4,0)
2525 button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
2526 G_CALLBACK(image_overlay_set_font_cb), notebook);
2528 button = gtk_font_button_new();
2529 gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Image Overlay Font");
2530 gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->image_overlay.font);
2531 g_signal_connect(G_OBJECT(button), "font-set",
2532 G_CALLBACK(image_overlay_set_font_cb),NULL);
2534 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2535 gtk_widget_show(button);
2537 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Text"), FALSE,
2538 G_CALLBACK(image_overlay_set_text_colour_cb), NULL);
2539 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2540 gtk_widget_show(button);
2542 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Background"), FALSE,
2543 G_CALLBACK(image_overlay_set_background_colour_cb), NULL);
2544 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2545 gtk_widget_show(button);
2546 image_overlay_set_text_colours();
2548 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2549 G_CALLBACK(image_overlay_default_template_cb), image_overlay_template_view);
2550 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2551 gtk_widget_show(button);
2553 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
2554 G_CALLBACK(image_overlay_help_cb), NULL);
2555 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2556 gtk_widget_show(button);
2558 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_overlay_template_view));
2559 if (options->image_overlay.template_string) gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
2560 g_signal_connect(G_OBJECT(buffer), "changed",
2561 G_CALLBACK(image_overlay_template_view_changed_cb), image_overlay_template_view);
2563 pref_line(group, PREF_PAD_GAP);
2565 group = pref_group_new(vbox, FALSE, _("Exif, XMP or IPTC tags"), GTK_ORIENTATION_VERTICAL);
2566 hbox = gtk_hbox_new(FALSE, 0);
2567 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2568 gtk_widget_show(hbox);
2569 label = gtk_label_new(_("%Exif.Image.Orientation%"));
2570 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2571 gtk_widget_show(label);
2572 pref_spacer(group,TRUE);
2574 group = pref_group_new(vbox, FALSE, _("Field separators"), GTK_ORIENTATION_VERTICAL);
2575 hbox = gtk_hbox_new(FALSE, 0);
2576 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2577 gtk_widget_show(hbox);
2578 label = gtk_label_new(_("Separator shown only if both fields are non-null:\n%formatted.ShutterSpeed%|%formatted.ISOSpeedRating%"));
2579 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2580 gtk_widget_show(label);
2581 pref_spacer(group,TRUE);
2583 group = pref_group_new(vbox, FALSE, _("Field maximum length"), GTK_ORIENTATION_VERTICAL);
2584 hbox = gtk_hbox_new(FALSE, 0);
2585 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2586 gtk_widget_show(hbox);
2587 label = gtk_label_new(_("%path:39%"));
2588 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2589 gtk_widget_show(label);
2590 pref_spacer(group,TRUE);
2592 group = pref_group_new(vbox, FALSE, _("Pre- and post- text"), GTK_ORIENTATION_VERTICAL);
2593 hbox = gtk_hbox_new(FALSE, 0);
2594 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2595 gtk_widget_show(hbox);
2596 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%"));
2597 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2598 gtk_widget_show(label);
2599 pref_spacer(group,TRUE);
2601 group = pref_group_new(vbox, FALSE, _("Pango markup"), GTK_ORIENTATION_VERTICAL);
2602 hbox = gtk_hbox_new(FALSE, 0);
2603 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2604 gtk_widget_show(hbox);
2605 label = gtk_label_new(_("<b>bold</b>\n<u>underline</u>\n<i>italic</i>\n<s>strikethrough</s>"));
2606 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2607 gtk_widget_show(label);
2610 static GtkTreeModel *create_class_model(void)
2612 GtkListStore *model;
2616 /* create list store */
2617 model = gtk_list_store_new(1, G_TYPE_STRING);
2618 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
2620 gtk_list_store_append(model, &iter);
2621 gtk_list_store_set(model, &iter, 0, _(format_class_list[i]), -1);
2623 return GTK_TREE_MODEL (model);
2628 static void config_tab_files(GtkWidget *notebook)
2635 GtkWidget *ct_button;
2636 GtkWidget *scrolled;
2637 GtkWidget *filter_view;
2638 GtkCellRenderer *renderer;
2639 GtkTreeSelection *selection;
2640 GtkTreeViewColumn *column;
2642 vbox = scrolled_notebook_page(notebook, _("Files"));
2644 group = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2646 pref_checkbox_new_int(group, _("Show hidden files or folders"),
2647 options->file_filter.show_hidden_files, &c_options->file_filter.show_hidden_files);
2648 pref_checkbox_new_int(group, _("Show parent folder (..)"),
2649 options->file_filter.show_parent_directory, &c_options->file_filter.show_parent_directory);
2650 pref_checkbox_new_int(group, _("Case sensitive sort"),
2651 options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
2652 pref_checkbox_new_int(group, _("Natural sort order"),
2653 options->file_sort.natural, &c_options->file_sort.natural);
2654 pref_checkbox_new_int(group, _("Disable file extension checks"),
2655 options->file_filter.disable_file_extension_checks, &c_options->file_filter.disable_file_extension_checks);
2657 ct_button = pref_checkbox_new_int(group, _("Disable File Filtering"),
2658 options->file_filter.disable, &c_options->file_filter.disable);
2661 group = pref_group_new(vbox, FALSE, _("Grouping sidecar extensions"), GTK_ORIENTATION_VERTICAL);
2663 sidecar_ext_entry = gtk_entry_new();
2664 gtk_entry_set_text(GTK_ENTRY(sidecar_ext_entry), options->sidecar.ext);
2665 gtk_box_pack_start(GTK_BOX(group), sidecar_ext_entry, FALSE, FALSE, 0);
2666 gtk_widget_show(sidecar_ext_entry);
2668 group = pref_group_new(vbox, TRUE, _("File types"), GTK_ORIENTATION_VERTICAL);
2670 frame = pref_group_parent(group);
2671 g_signal_connect(G_OBJECT(ct_button), "toggled",
2672 G_CALLBACK(filter_disable_cb), frame);
2673 gtk_widget_set_sensitive(frame, !options->file_filter.disable);
2675 scrolled = gtk_scrolled_window_new(NULL, NULL);
2676 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2677 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2678 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2679 gtk_widget_show(scrolled);
2681 filter_store = gtk_list_store_new(1, G_TYPE_POINTER);
2682 filter_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(filter_store));
2683 g_object_unref(filter_store);
2684 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
2685 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
2687 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), FALSE);
2689 column = gtk_tree_view_column_new();
2690 gtk_tree_view_column_set_title(column, _("Filter"));
2691 gtk_tree_view_column_set_resizable(column, TRUE);
2693 renderer = gtk_cell_renderer_toggle_new();
2694 g_signal_connect(G_OBJECT(renderer), "toggled",
2695 G_CALLBACK(filter_store_enable_cb), filter_store);
2696 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2697 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2698 GINT_TO_POINTER(FE_ENABLE), NULL);
2700 renderer = gtk_cell_renderer_text_new();
2701 g_signal_connect(G_OBJECT(renderer), "edited",
2702 G_CALLBACK(filter_store_ext_edit_cb), filter_store);
2703 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2704 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2705 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2706 GINT_TO_POINTER(FE_EXTENSION), NULL);
2707 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2709 column = gtk_tree_view_column_new();
2710 gtk_tree_view_column_set_title(column, _("Description"));
2711 gtk_tree_view_column_set_resizable(column, TRUE);
2712 gtk_tree_view_column_set_fixed_width(column, 200);
2713 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
2715 renderer = gtk_cell_renderer_text_new();
2716 g_signal_connect(G_OBJECT(renderer), "edited",
2717 G_CALLBACK(filter_store_desc_edit_cb), filter_store);
2718 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2719 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2720 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2721 GINT_TO_POINTER(FE_DESCRIPTION), NULL);
2722 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2724 column = gtk_tree_view_column_new();
2725 gtk_tree_view_column_set_title(column, _("Class"));
2726 gtk_tree_view_column_set_resizable(column, TRUE);
2727 renderer = gtk_cell_renderer_combo_new();
2728 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE,
2729 "model", create_class_model(),
2734 g_signal_connect(G_OBJECT(renderer), "edited",
2735 G_CALLBACK(filter_store_class_edit_cb), filter_store);
2736 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2737 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2738 GINT_TO_POINTER(FE_CLASS), NULL);
2739 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2741 column = gtk_tree_view_column_new();
2742 gtk_tree_view_column_set_title(column, _("Writable"));
2743 gtk_tree_view_column_set_resizable(column, FALSE);
2744 renderer = gtk_cell_renderer_toggle_new();
2745 g_signal_connect(G_OBJECT(renderer), "toggled",
2746 G_CALLBACK(filter_store_writable_cb), filter_store);
2747 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2748 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2749 GINT_TO_POINTER(FE_WRITABLE), NULL);
2750 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2752 column = gtk_tree_view_column_new();
2753 gtk_tree_view_column_set_title(column, _("Sidecar is allowed"));
2754 gtk_tree_view_column_set_resizable(column, FALSE);
2755 renderer = gtk_cell_renderer_toggle_new();
2756 g_signal_connect(G_OBJECT(renderer), "toggled",
2757 G_CALLBACK(filter_store_sidecar_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_ALLOW_SIDECAR), NULL);
2761 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2764 filter_store_populate();
2765 gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
2766 gtk_widget_show(filter_view);
2768 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2770 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2771 G_CALLBACK(filter_default_cb), filter_view);
2772 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2773 gtk_widget_show(button);
2775 button = pref_button_new(NULL, GTK_STOCK_REMOVE, NULL, FALSE,
2776 G_CALLBACK(filter_remove_cb), filter_view);
2777 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2778 gtk_widget_show(button);
2780 button = pref_button_new(NULL, GTK_STOCK_ADD, NULL, FALSE,
2781 G_CALLBACK(filter_add_cb), filter_view);
2782 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2783 gtk_widget_show(button);
2787 static void config_tab_metadata(GtkWidget *notebook)
2792 GtkWidget *ct_button;
2796 vbox = scrolled_notebook_page(notebook, _("Metadata"));
2799 group = pref_group_new(vbox, FALSE, _("Metadata writing process"), GTK_ORIENTATION_VERTICAL);
2801 label = pref_label_new(group, _("Warning: Geeqie is built without Exiv2. Some options are disabled."));
2803 label = pref_label_new(group, _("Metadata are written in the following order. The process ends after first success."));
2804 #if GTK_CHECK_VERSION(3,16,0)
2805 gtk_label_set_xalign(GTK_LABEL(label), 0.0);
2806 gtk_label_set_yalign(GTK_LABEL(label), 0.5);
2808 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2811 ct_button = pref_checkbox_new_int(group, _("1) Save metadata in image files, or sidecar files, according to the XMP standard"),
2812 options->metadata.save_in_image_file, &c_options->metadata.save_in_image_file);
2814 gtk_widget_set_sensitive(ct_button, FALSE);
2817 pref_checkbox_new_int(group, _("2) Save metadata in '.metadata' folder, local to image folder (non-standard)"),
2818 options->metadata.enable_metadata_dirs, &c_options->metadata.enable_metadata_dirs);
2820 text = g_strdup_printf(_("3) Save metadata in Geeqie private directory '%s'"), get_metadata_cache_dir());
2821 label = pref_label_new(group, text);
2822 #if GTK_CHECK_VERSION(3,16,0)
2823 gtk_label_set_xalign(GTK_LABEL(label), 0.0);
2824 gtk_label_set_yalign(GTK_LABEL(label), 0.5);
2826 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2828 gtk_misc_set_padding(GTK_MISC(label), 22, 0);
2831 group = pref_group_new(vbox, FALSE, _("Step 1: Write to image files"), GTK_ORIENTATION_VERTICAL);
2833 gtk_widget_set_sensitive(group, FALSE);
2836 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2837 pref_checkbox_link_sensitivity(ct_button, hbox);
2839 pref_checkbox_new_int(hbox, _("Store metadata also in legacy IPTC tags (converted according to IPTC4XMP standard)"),
2840 options->metadata.save_legacy_IPTC, &c_options->metadata.save_legacy_IPTC);
2842 pref_checkbox_new_int(hbox, _("Warn if the image files are unwritable"),
2843 options->metadata.warn_on_write_problems, &c_options->metadata.warn_on_write_problems);
2845 pref_checkbox_new_int(hbox, _("Ask before writing to image files"),
2846 options->metadata.confirm_write, &c_options->metadata.confirm_write);
2848 pref_checkbox_new_int(hbox, _("Create sidecar files named image.ext.xmp (as opposed to image.xmp)"),
2849 options->metadata.sidecar_extended_name, &c_options->metadata.sidecar_extended_name);
2851 group = pref_group_new(vbox, FALSE, _("Step 2 and 3: write to Geeqie private files"), GTK_ORIENTATION_VERTICAL);
2853 gtk_widget_set_sensitive(group, FALSE);
2856 pref_checkbox_new_int(group, _("Use GQview legacy metadata format (supports only keywords and comments) instead of XMP"),
2857 options->metadata.save_legacy_format, &c_options->metadata.save_legacy_format);
2860 group = pref_group_new(vbox, FALSE, _("Miscellaneous"), GTK_ORIENTATION_VERTICAL);
2861 pref_checkbox_new_int(group, _("Write the same description tags (keywords, comment, etc.) to all grouped sidecars"),
2862 options->metadata.sync_grouped_files, &c_options->metadata.sync_grouped_files);
2864 pref_checkbox_new_int(group, _("Allow keywords to differ only in case"),
2865 options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
2867 ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"),
2868 options->metadata.write_orientation, &c_options->metadata.write_orientation);
2870 gtk_widget_set_sensitive(ct_button, FALSE);
2873 group = pref_group_new(vbox, FALSE, _("Auto-save options"), GTK_ORIENTATION_VERTICAL);
2875 ct_button = pref_checkbox_new_int(group, _("Write metadata after timeout"),
2876 options->metadata.confirm_after_timeout, &c_options->metadata.confirm_after_timeout);
2878 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2879 pref_checkbox_link_sensitivity(ct_button, hbox);
2881 pref_spin_new_int(hbox, _("Timeout (seconds):"), NULL, 0, 900, 1,
2882 options->metadata.confirm_timeout, &c_options->metadata.confirm_timeout);
2884 pref_checkbox_new_int(group, _("Write metadata on image change"),
2885 options->metadata.confirm_on_image_change, &c_options->metadata.confirm_on_image_change);
2887 pref_checkbox_new_int(group, _("Write metadata on directory change"),
2888 options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
2890 group = pref_group_new(vbox, FALSE, _("Pre-load metadata"), GTK_ORIENTATION_VERTICAL);
2892 ct_button = pref_checkbox_new_int(group, _("Read metadata in background"),
2893 options->read_metadata_in_idle, &c_options->read_metadata_in_idle);
2894 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");
2899 typedef struct _KeywordFindData KeywordFindData;
2900 struct _KeywordFindData
2907 GtkWidget *button_close;
2908 GtkWidget *button_stop;
2909 GtkWidget *button_start;
2910 GtkWidget *progress;
2918 guint idle_id; /* event source id */
2921 #define KEYWORD_DIALOG_WIDTH 400
2923 static void keywords_find_folder(KeywordFindData *kfd, FileData *dir_fd)
2925 GList *list_d = NULL;
2926 GList *list_f = NULL;
2930 filelist_read(dir_fd, &list_f, &list_d);
2934 filelist_read(dir_fd, &list_f, NULL);
2937 list_f = filelist_filter(list_f, FALSE);
2938 list_d = filelist_filter(list_d, TRUE);
2940 kfd->list = g_list_concat(list_f, kfd->list);
2941 kfd->list_dir = g_list_concat(list_d, kfd->list_dir);
2944 static void keywords_find_reset(KeywordFindData *kfd)
2946 filelist_free(kfd->list);
2949 filelist_free(kfd->list_dir);
2950 kfd->list_dir = NULL;
2953 static void keywords_find_close_cb(GenericDialog *fd, gpointer data)
2955 KeywordFindData *kfd = data;
2957 if (!gtk_widget_get_sensitive(kfd->button_close)) return;
2959 keywords_find_reset(kfd);
2960 generic_dialog_close(kfd->gd);
2964 static void keywords_find_finish(KeywordFindData *kfd)
2966 keywords_find_reset(kfd);
2968 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("done"));
2969 spinner_set_interval(kfd->spinner, -1);
2971 gtk_widget_set_sensitive(kfd->group, TRUE);
2972 gtk_widget_set_sensitive(kfd->button_start, TRUE);
2973 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2974 gtk_widget_set_sensitive(kfd->button_close, TRUE);
2977 static void keywords_find_stop_cb(GenericDialog *fd, gpointer data)
2979 KeywordFindData *kfd = data;
2981 g_idle_remove_by_data(kfd);
2983 keywords_find_finish(kfd);
2986 static gboolean keywords_find_file(gpointer data)
2988 KeywordFindData *kfd = data;
2990 GtkTextBuffer *buffer;
2998 fd = kfd->list->data;
2999 kfd->list = g_list_remove(kfd->list, fd);
3001 keywords = metadata_read_list(fd, KEYWORD_KEY, METADATA_PLAIN);
3002 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3006 gtk_text_buffer_get_end_iter(buffer, &iter);
3007 tmp = g_strconcat(keywords->data, "\n", NULL);
3008 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
3010 keywords = keywords->next;
3013 gtk_entry_set_text(GTK_ENTRY(kfd->progress), fd->path);
3014 file_data_unref(fd);
3015 string_list_free(keywords);
3019 else if (kfd->list_dir)
3023 fd = kfd->list_dir->data;
3024 kfd->list_dir = g_list_remove(kfd->list_dir, fd);
3026 keywords_find_folder(kfd, fd);
3028 file_data_unref(fd);
3033 keywords_find_finish(kfd);
3038 static void keywords_find_start_cb(GenericDialog *fd, gpointer data)
3040 KeywordFindData *kfd = data;
3043 if (kfd->list || !gtk_widget_get_sensitive(kfd->button_start)) return;
3045 path = remove_trailing_slash((gtk_entry_get_text(GTK_ENTRY(kfd->entry))));
3046 parse_out_relatives(path);
3050 warning_dialog(_("Invalid folder"),
3051 _("The specified folder can not be found."),
3052 GTK_STOCK_DIALOG_WARNING, kfd->gd->dialog);
3058 gtk_widget_set_sensitive(kfd->group, FALSE);
3059 gtk_widget_set_sensitive(kfd->button_start, FALSE);
3060 gtk_widget_set_sensitive(kfd->button_stop, TRUE);
3061 gtk_widget_set_sensitive(kfd->button_close, FALSE);
3062 spinner_set_interval(kfd->spinner, SPINNER_SPEED);
3064 dir_fd = file_data_new_dir(path);
3065 keywords_find_folder(kfd, dir_fd);
3066 file_data_unref(dir_fd);
3067 kfd->idle_id = g_idle_add(keywords_find_file, kfd);
3073 static void keywords_find_dialog(GtkWidget *widget, const gchar *path)
3075 KeywordFindData *kfd;
3079 kfd = g_new0(KeywordFindData, 1);
3081 kfd->gd = generic_dialog_new(_("Search for keywords"),
3082 "search_for_keywords",
3085 gtk_window_set_default_size(GTK_WINDOW(kfd->gd->dialog), KEYWORD_DIALOG_WIDTH, -1);
3086 kfd->gd->cancel_cb = keywords_find_close_cb;
3087 kfd->button_close = generic_dialog_add_button(kfd->gd, GTK_STOCK_CLOSE, NULL,
3088 keywords_find_close_cb, FALSE);
3089 kfd->button_start = generic_dialog_add_button(kfd->gd, GTK_STOCK_OK, _("S_tart"),
3090 keywords_find_start_cb, FALSE);
3091 kfd->button_stop = generic_dialog_add_button(kfd->gd, GTK_STOCK_STOP, NULL,
3092 keywords_find_stop_cb, FALSE);
3093 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
3095 generic_dialog_add_message(kfd->gd, NULL, _("Search for keywords"), NULL, FALSE);
3097 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0);
3098 pref_spacer(hbox, PREF_PAD_INDENT);
3099 kfd->group = pref_box_new(hbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
3101 hbox = pref_box_new(kfd->group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3102 pref_label_new(hbox, _("Folder:"));
3104 label = tab_completion_new(&kfd->entry, path, NULL, NULL, NULL, NULL);
3105 tab_completion_add_select_button(kfd->entry,_("Select folder") , TRUE);
3106 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
3107 gtk_widget_show(label);
3109 pref_checkbox_new_int(kfd->group, _("Include subfolders"), FALSE, &kfd->recurse);
3111 pref_line(kfd->gd->vbox, PREF_PAD_SPACE);
3112 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3114 kfd->progress = gtk_entry_new();
3115 gtk_widget_set_can_focus(kfd->progress, FALSE);
3116 gtk_editable_set_editable(GTK_EDITABLE(kfd->progress), FALSE);
3117 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("click start to begin"));
3118 gtk_box_pack_start(GTK_BOX(hbox), kfd->progress, TRUE, TRUE, 0);
3119 gtk_widget_show(kfd->progress);
3121 kfd->spinner = spinner_new(NULL, -1);
3122 gtk_box_pack_start(GTK_BOX(hbox), kfd->spinner, FALSE, FALSE, 0);
3123 gtk_widget_show(kfd->spinner);
3127 gtk_widget_show(kfd->gd->dialog);
3130 static void keywords_find_cb(GtkWidget *widget, gpointer data)
3132 const gchar *path = layout_get_path(NULL);
3134 if (!path || !*path) path = homedir();
3135 keywords_find_dialog(widget, path);
3138 static void config_tab_keywords_save()
3140 GtkTextIter start, end;
3141 GtkTextBuffer *buffer;
3142 GList *kw_list = NULL;
3148 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3149 gtk_text_buffer_get_bounds(buffer, &start, &end);
3151 buffer_text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
3153 kw_split = strtok(buffer_text, "\n");
3154 while (kw_split != NULL)
3160 if (g_strcmp0(work->data, kw_split) == 0)
3169 kw_list = g_list_append(kw_list, g_strdup(kw_split));
3171 kw_split = strtok(NULL, "\n");
3174 keyword_list_set(kw_list);
3176 string_list_free(kw_list);
3177 g_free(buffer_text);
3180 static void config_tab_keywords(GtkWidget *notebook)
3186 GtkWidget *scrolled;
3188 GtkTextBuffer *buffer;
3191 vbox = scrolled_notebook_page(notebook, _("Keywords"));
3193 group = pref_group_new(vbox, TRUE, _("Edit keywords autocompletion list"), GTK_ORIENTATION_VERTICAL);
3195 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3197 button = pref_button_new(hbox, GTK_STOCK_EXECUTE, _("Search"), FALSE,
3198 G_CALLBACK(keywords_find_cb), keyword_text);
3199 gtk_widget_set_tooltip_text(button, "Search for existing keywords");
3202 keyword_text = gtk_text_view_new();
3203 gtk_widget_set_size_request(keyword_text, 20, 20);
3204 scrolled = gtk_scrolled_window_new(NULL, NULL);
3205 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3206 gtk_widget_show(scrolled);
3208 gtk_container_add(GTK_CONTAINER(scrolled), keyword_text);
3209 gtk_widget_show(keyword_text);
3211 gtk_text_view_set_editable(GTK_TEXT_VIEW(keyword_text), TRUE);
3213 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3214 gtk_text_buffer_create_tag(buffer, "monospace",
3215 "family", "monospace", NULL);
3217 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(keyword_text), GTK_WRAP_WORD);
3218 gtk_text_buffer_get_start_iter(buffer, &iter);
3219 gtk_text_buffer_create_mark(buffer, "end", &iter, FALSE);
3222 path = g_build_filename(get_rc_dir(), "keywords", NULL);
3224 GList *kwl = keyword_list_get();
3225 kwl = g_list_first(kwl);
3228 gtk_text_buffer_get_end_iter (buffer, &iter);
3229 tmp = g_strconcat(kwl->data, "\n", NULL);
3230 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
3235 gtk_text_buffer_set_modified(buffer, FALSE);
3242 static void intent_menu_cb(GtkWidget *combo, gpointer data)
3244 gint *option = data;
3246 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
3250 *option = INTENT_PERCEPTUAL;
3253 *option = INTENT_RELATIVE_COLORIMETRIC;
3256 *option = INTENT_SATURATION;
3259 *option = INTENT_ABSOLUTE_COLORIMETRIC;
3264 static void add_intent_menu(GtkWidget *table, gint column, gint row, const gchar *text,
3265 gint option, gint *option_c)
3272 pref_table_label(table, column, row, text, 0.0);
3274 combo = gtk_combo_box_text_new();
3276 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Perceptual"));
3277 if (option == INTENT_PERCEPTUAL) current = 0;
3278 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Relative Colorimetric"));
3279 if (option == INTENT_RELATIVE_COLORIMETRIC) current = 1;
3280 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Saturation"));
3281 if (option == INTENT_SATURATION) current = 2;
3282 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Absolute Colorimetric"));
3283 if (option == INTENT_ABSOLUTE_COLORIMETRIC) current = 3;
3285 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
3287 gtk_widget_set_tooltip_text(combo,"Refer to the lcms documentation for the defaults used when the selected Intent is not available");
3289 g_signal_connect(G_OBJECT(combo), "changed",
3290 G_CALLBACK(intent_menu_cb), option_c);
3292 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
3293 gtk_widget_show(combo);
3297 static void config_tab_color(GtkWidget *notebook)
3306 vbox = scrolled_notebook_page(notebook, _("Color management"));
3308 group = pref_group_new(vbox, FALSE, _("Input profiles"), GTK_ORIENTATION_VERTICAL);
3310 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3313 table = pref_table_new(group, 3, COLOR_PROFILE_INPUTS + 1, FALSE, FALSE);
3314 gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
3316 label = pref_table_label(table, 0, 0, _("Type"), 0.0);
3317 pref_label_bold(label, TRUE, FALSE);
3319 label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
3320 pref_label_bold(label, TRUE, FALSE);
3322 label = pref_table_label(table, 2, 0, _("File"), 0.0);
3323 pref_label_bold(label, TRUE, FALSE);
3325 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
3330 buf = g_strdup_printf(_("Input %d:"), i + COLOR_PROFILE_FILE);
3331 pref_table_label(table, 0, i + 1, buf, 1.0);
3334 entry = gtk_entry_new();
3335 gtk_entry_set_max_length(GTK_ENTRY(entry), EDITOR_NAME_MAX_LENGTH);
3336 if (options->color_profile.input_name[i])
3338 gtk_entry_set_text(GTK_ENTRY(entry), options->color_profile.input_name[i]);
3340 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, i + 1, i + 2,
3341 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3342 gtk_widget_show(entry);
3343 color_profile_input_name_entry[i] = entry;
3345 tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, ".icc", "ICC Files", NULL);
3346 tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
3347 gtk_widget_set_size_request(entry, 160, -1);
3348 gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
3349 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3350 gtk_widget_show(tabcomp);
3351 color_profile_input_file_entry[i] = entry;
3354 group = pref_group_new(vbox, FALSE, _("Screen profile"), GTK_ORIENTATION_VERTICAL);
3356 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3358 pref_checkbox_new_int(group, _("Use system screen profile if available"),
3359 options->color_profile.use_x11_screen_profile, &c_options->color_profile.use_x11_screen_profile);
3361 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3363 pref_table_label(table, 0, 0, _("Screen:"), 1.0);
3364 tabcomp = tab_completion_new(&color_profile_screen_file_entry,
3365 options->color_profile.screen_file, NULL, ".icc", "ICC Files", NULL);
3366 tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
3367 gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
3369 add_intent_menu(table, 0, 1, _("Render Intent:"), options->color_profile.render_intent, &c_options->color_profile.render_intent);
3371 gtk_table_attach(GTK_TABLE(table), tabcomp, 1, 2,
3373 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3375 gtk_widget_show(tabcomp);
3378 /* advanced entry tab */
3379 static void use_geeqie_trash_cb(GtkWidget *widget, gpointer data)
3381 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3383 c_options->file_ops.use_system_trash = FALSE;
3384 c_options->file_ops.no_trash = FALSE;
3388 static void use_system_trash_cb(GtkWidget *widget, gpointer data)
3390 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3392 c_options->file_ops.use_system_trash = TRUE;
3393 c_options->file_ops.no_trash = FALSE;
3397 static void use_no_cache_cb(GtkWidget *widget, gpointer data)
3399 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3401 c_options->file_ops.no_trash = TRUE;
3405 static void config_tab_behavior(GtkWidget *notebook)
3412 GtkWidget *ct_button;
3416 GtkWidget *with_rename;
3417 GtkWidget *collections_on_top;
3418 GtkWidget *hide_window_in_fullscreen;
3419 GtkWidget *checkbox;
3422 vbox = scrolled_notebook_page(notebook, _("Behavior"));
3424 group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
3426 pref_checkbox_new_int(group, _("Confirm permanent file delete"),
3427 options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
3428 pref_checkbox_new_int(group, _("Confirm move file to Trash"),
3429 options->file_ops.confirm_move_to_trash, &c_options->file_ops.confirm_move_to_trash);
3430 pref_checkbox_new_int(group, _("Enable Delete key"),
3431 options->file_ops.enable_delete_key, &c_options->file_ops.enable_delete_key);
3433 ct_button = pref_radiobutton_new(group, NULL, _("Use Geeqie trash location"),
3434 !options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_geeqie_trash_cb),NULL);
3436 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3437 pref_checkbox_link_sensitivity(ct_button, hbox);
3439 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
3440 pref_label_new(hbox, _("Folder:"));
3442 tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL, NULL, NULL);
3443 tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
3444 gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
3445 gtk_widget_show(tabcomp);
3447 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3448 pref_checkbox_link_sensitivity(ct_button, hbox);
3450 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
3451 spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MiB"),
3452 0, 2048, 1, options->file_ops.safe_delete_folder_maxsize, &c_options->file_ops.safe_delete_folder_maxsize);
3453 gtk_widget_set_tooltip_markup(spin, _("Set to 0 for unlimited size"));
3454 button = pref_button_new(NULL, NULL, _("View"), FALSE,
3455 G_CALLBACK(safe_delete_view_cb), NULL);
3456 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3457 gtk_widget_show(button);
3459 button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
3460 G_CALLBACK(safe_delete_clear_cb), NULL);
3461 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3462 pref_radiobutton_new(group, ct_button, _("Use system Trash bin"),
3463 options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_system_trash_cb), NULL);
3465 pref_radiobutton_new(group, ct_button, _("Use no trash at all"),
3466 options->file_ops.no_trash, G_CALLBACK(use_no_cache_cb), NULL);
3468 gtk_widget_show(button);
3470 pref_spacer(group, PREF_PAD_GROUP);
3473 group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
3475 pref_checkbox_new_int(group, _("Descend folders in tree view"),
3476 options->tree_descend_subdirs, &c_options->tree_descend_subdirs);
3478 pref_checkbox_new_int(group, _("In place renaming"),
3479 options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
3481 pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
3482 options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
3484 tmp = pref_checkbox_new_int(group, _("Circular selection lists"),
3485 options->circular_selection_lists, &c_options->circular_selection_lists);
3486 gtk_widget_set_tooltip_text(tmp, _("Traverse selection lists in a circular manner"));
3488 marks = pref_checkbox_new_int(group, _("Save marks on exit"),
3489 options->marks_save, &c_options->marks_save);
3490 gtk_widget_set_tooltip_text(marks,"Note that marks linked to a keyword will be saved irrespective of this setting");
3492 with_rename = pref_checkbox_new_int(group, _("Use \"With Rename\" as default for Copy/Move dialogs"),
3493 options->with_rename, &c_options->with_rename);
3494 gtk_widget_set_tooltip_text(with_rename,"Change the default button for Copy/Move dialogs");
3496 collections_on_top = pref_checkbox_new_int(group, _("Open collections on top"),
3497 options->collections_on_top, &c_options->collections_on_top);
3498 gtk_widget_set_tooltip_text(collections_on_top,"Open collections window on top");
3500 hide_window_in_fullscreen = pref_checkbox_new_int(group, _("Hide window in fullscreen"),
3501 options->hide_window_in_fullscreen, &c_options->hide_window_in_fullscreen);
3502 gtk_widget_set_tooltip_text(hide_window_in_fullscreen,"When alt-tabbing, prevent Geeqie window showing twice");
3504 pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
3505 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
3507 pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
3508 16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
3510 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3511 add_dnd_default_action_selection_menu(table, 0, 0, _("Drag`n drop default action:"), options->dnd_default_action, &c_options->dnd_default_action);
3513 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3514 add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
3516 pref_spacer(group, PREF_PAD_GROUP);
3518 group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
3520 pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
3521 options->progressive_key_scrolling, &c_options->progressive_key_scrolling);
3522 pref_spin_new_int(group, _("Keyboard scrolling step multiplier:"), NULL,
3523 1, 32, 1, options->keyboard_scroll_step, (int *)&c_options->keyboard_scroll_step);
3524 pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
3525 options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
3526 pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
3527 options->image_lm_click_nav, &c_options->image_lm_click_nav);
3528 pref_checkbox_new_int(group, _("Open archive by left click on image"),
3529 options->image_l_click_archive, &c_options->image_l_click_archive);
3530 pref_checkbox_new_int(group, _("Play video by left click on image"),
3531 options->image_l_click_video, &c_options->image_l_click_video);
3532 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3533 add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
3535 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3536 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3537 add_mouse_selection_menu(table, 0, 0, _("Mouse button Back:"), options->mouse_button_8, &c_options->mouse_button_8);
3538 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3539 add_mouse_selection_menu(table, 0, 0, _("Mouse button Forward:"), options->mouse_button_9, &c_options->mouse_button_9);
3541 pref_spacer(group, PREF_PAD_GROUP);
3543 group = pref_group_new(vbox, FALSE, _("GPU"), GTK_ORIENTATION_VERTICAL);
3545 checkbox = pref_checkbox_new_int(group, _("Override disable GPU"),
3546 options->override_disable_gpu, &c_options->override_disable_gpu);
3547 gtk_widget_set_tooltip_text(checkbox, "Contact the developers for usage");
3550 pref_spacer(group, PREF_PAD_GROUP);
3552 group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
3554 pref_spin_new_int(group, _("Debug level:"), NULL,
3555 DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
3557 pref_checkbox_new_int(group, _("Timer data"),
3558 options->log_window.timer_data, &c_options->log_window.timer_data);
3560 pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
3561 1, 99999, 1, options->log_window_lines, &options->log_window_lines);
3565 /* accelerators tab */
3566 static void config_tab_accelerators(GtkWidget *notebook)
3572 GtkWidget *scrolled;
3573 GtkWidget *accel_view;
3574 GtkCellRenderer *renderer;
3575 GtkTreeSelection *selection;
3576 GtkTreeViewColumn *column;
3578 vbox = scrolled_notebook_page(notebook, _("Keyboard"));
3580 group = pref_group_new(vbox, TRUE, _("Accelerators"), GTK_ORIENTATION_VERTICAL);
3582 scrolled = gtk_scrolled_window_new(NULL, NULL);
3583 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
3584 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
3585 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3586 gtk_widget_show(scrolled);
3588 accel_store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
3590 accel_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(accel_store));
3591 g_object_unref(accel_store);
3592 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(accel_view));
3593 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
3595 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(accel_view), FALSE);
3597 renderer = gtk_cell_renderer_text_new();
3599 column = gtk_tree_view_column_new_with_attributes(_("Action"),
3604 gtk_tree_view_column_set_sort_column_id(column, AE_ACTION);
3605 gtk_tree_view_column_set_resizable(column, TRUE);
3606 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3609 renderer = gtk_cell_renderer_accel_new();
3610 g_signal_connect(G_OBJECT(renderer), "accel-cleared",
3611 G_CALLBACK(accel_store_cleared_cb), accel_store);
3612 g_signal_connect(G_OBJECT(renderer), "accel-edited",
3613 G_CALLBACK(accel_store_edited_cb), accel_store);
3616 g_object_set (renderer,
3618 "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
3621 column = gtk_tree_view_column_new_with_attributes(_("KEY"),
3626 gtk_tree_view_column_set_sort_column_id(column, AE_KEY);
3627 gtk_tree_view_column_set_resizable(column, TRUE);
3628 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3630 renderer = gtk_cell_renderer_text_new();
3632 column = gtk_tree_view_column_new_with_attributes(_("Tooltip"),
3637 gtk_tree_view_column_set_sort_column_id(column, AE_TOOLTIP);
3638 gtk_tree_view_column_set_resizable(column, TRUE);
3639 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3641 renderer = gtk_cell_renderer_text_new();
3643 column = gtk_tree_view_column_new_with_attributes("Accel",
3648 gtk_tree_view_column_set_sort_column_id(column, AE_ACCEL);
3649 gtk_tree_view_column_set_resizable(column, TRUE);
3650 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3652 accel_store_populate();
3653 gtk_container_add(GTK_CONTAINER(scrolled), accel_view);
3654 gtk_widget_show(accel_view);
3656 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3658 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
3659 G_CALLBACK(accel_default_cb), accel_view);
3660 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3661 gtk_widget_show(button);
3663 button = pref_button_new(NULL, NULL, _("Reset selected"), FALSE,
3664 G_CALLBACK(accel_reset_cb), accel_view);
3665 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3666 gtk_widget_show(button);
3669 /* toolbar main tab */
3670 static void config_tab_toolbar_main(GtkWidget *notebook)
3673 GtkWidget *toolbardata;
3676 lw = layout_window_list->data;
3678 vbox = scrolled_notebook_page(notebook, _("Toolbar Main"));
3680 toolbardata = toolbar_select_new(lw, TOOLBAR_MAIN);
3681 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3682 gtk_widget_show(vbox);
3685 /* toolbar status tab */
3686 static void config_tab_toolbar_status(GtkWidget *notebook)
3689 GtkWidget *toolbardata;
3692 lw = layout_window_list->data;
3694 vbox = scrolled_notebook_page(notebook, _("Toolbar Status"));
3696 toolbardata = toolbar_select_new(lw, TOOLBAR_STATUS);
3697 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3698 gtk_widget_show(vbox);
3702 static gint extension_sort_cb(gconstpointer a, gconstpointer b)
3704 return g_strcmp0((gchar *)a, (gchar *)b);
3707 static void config_tab_advanced(GtkWidget *notebook)
3711 GSList *formats_list;
3712 GList *extensions_list = NULL;
3715 GdkPixbufFormat *fm;
3717 GString *types_string = g_string_new(NULL);
3718 GtkWidget *types_string_label;
3719 GtkWidget *threads_string_label;
3720 GtkWidget *dupes_threads_spin;
3722 vbox = scrolled_notebook_page(notebook, _("Advanced"));
3723 group = pref_group_new(vbox, FALSE, _("External preview extraction"), GTK_ORIENTATION_VERTICAL);
3725 pref_checkbox_new_int(group, _("Use external preview extraction - Requires restart"), options->external_preview.enable, &c_options->external_preview.enable);
3727 pref_spacer(group, PREF_PAD_GROUP);
3729 formats_list = gdk_pixbuf_get_formats();
3731 while (formats_list)
3733 fm = formats_list->data;
3734 extensions = gdk_pixbuf_format_get_extensions(fm);
3737 while (extensions[i])
3739 extensions_list = g_list_insert_sorted(extensions_list, g_strdup(extensions[i]), extension_sort_cb);
3743 g_strfreev(extensions);
3744 formats_list = formats_list->next;
3747 while (extensions_list)
3749 if (types_string->len == 0)
3751 types_string = g_string_append(types_string, extensions_list->data);
3755 types_string = g_string_append(types_string, ", ");
3756 types_string = g_string_append(types_string, extensions_list->data);
3759 extensions_list = extensions_list->next;
3762 types_string = g_string_prepend(types_string, _("Usable file types:\n"));
3763 types_string_label = pref_label_new(group, types_string->str);
3764 gtk_label_set_line_wrap(GTK_LABEL(types_string_label), TRUE);
3766 pref_spacer(group, PREF_PAD_GROUP);
3768 group = pref_group_new(vbox, FALSE, _("File identification tool"), GTK_ORIENTATION_VERTICAL);
3769 external_preview_select_entry = gtk_entry_new();
3770 tabcomp = tab_completion_new(&external_preview_select_entry, options->external_preview.select, NULL, NULL, NULL, NULL);
3771 tab_completion_add_select_button(external_preview_select_entry, _("Select file identification tool"), FALSE);
3772 gtk_box_pack_start(GTK_BOX(group), tabcomp, TRUE, TRUE, 0);
3773 gtk_widget_show(tabcomp);
3775 group = pref_group_new(vbox, FALSE, _("Preview extraction tool"), GTK_ORIENTATION_VERTICAL);
3776 external_preview_extract_entry = gtk_entry_new();
3777 tabcomp = tab_completion_new(&external_preview_extract_entry, options->external_preview.extract, NULL, NULL, NULL, NULL);
3778 tab_completion_add_select_button(external_preview_extract_entry, _("Select preview extraction tool"), FALSE);
3779 gtk_box_pack_start(GTK_BOX(group), tabcomp, TRUE, TRUE, 0);
3780 gtk_widget_show(tabcomp);
3782 gtk_widget_show(vbox);
3784 g_slist_free(formats_list);
3785 string_list_free(extensions_list);
3786 g_string_free(types_string, TRUE);
3788 pref_spacer(group, PREF_PAD_GROUP);
3790 pref_line(vbox, PREF_PAD_SPACE);
3791 group = pref_group_new(vbox, FALSE, _("Thread pool limits"), GTK_ORIENTATION_VERTICAL);
3793 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.");
3794 gtk_label_set_line_wrap(GTK_LABEL(threads_string_label), TRUE);
3796 pref_spacer(vbox, PREF_PAD_GROUP);
3798 dupes_threads_spin = pref_spin_new_int(vbox, _("Duplicate check:"), _("max. threads"), 0, get_cpu_cores(), 1, options->threads.duplicates, &c_options->threads.duplicates);
3799 gtk_widget_set_tooltip_markup(dupes_threads_spin, _("Set to 0 for unlimited"));
3803 static void config_tab_stereo(GtkWidget *notebook)
3811 GtkWidget *fs_button;
3812 vbox = scrolled_notebook_page(notebook, _("Stereo"));
3814 group = pref_group_new(vbox, FALSE, _("Windowed stereo mode"), GTK_ORIENTATION_VERTICAL);
3816 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3817 add_stereo_mode_menu(table, 0, 0, _("Windowed stereo mode"), options->stereo.mode, &c_options->stereo.mode, FALSE);
3819 table = pref_table_new(group, 2, 2, TRUE, FALSE);
3820 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3821 pref_checkbox_new_int(box, _("Mirror left image"),
3822 options->stereo.mode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.mirror_left);
3823 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3824 pref_checkbox_new_int(box, _("Flip left image"),
3825 options->stereo.mode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.flip_left);
3826 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3827 pref_checkbox_new_int(box, _("Mirror right image"),
3828 options->stereo.mode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.mirror_right);
3829 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3830 pref_checkbox_new_int(box, _("Flip right image"),
3831 options->stereo.mode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.flip_right);
3832 pref_checkbox_new_int(group, _("Swap left and right images"),
3833 options->stereo.mode & PR_STEREO_SWAP, &c_options->stereo.tmp.swap);
3834 pref_checkbox_new_int(group, _("Disable stereo mode on single image source"),
3835 options->stereo.mode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.temp_disable);
3837 group = pref_group_new(vbox, FALSE, _("Fullscreen stereo mode"), GTK_ORIENTATION_VERTICAL);
3838 fs_button = pref_checkbox_new_int(group, _("Use different settings for fullscreen"),
3839 options->stereo.enable_fsmode, &c_options->stereo.enable_fsmode);
3840 box2 = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
3841 pref_checkbox_link_sensitivity(fs_button, box2);
3842 table = pref_table_new(box2, 2, 1, FALSE, FALSE);
3843 add_stereo_mode_menu(table, 0, 0, _("Fullscreen stereo mode"), options->stereo.fsmode, &c_options->stereo.fsmode, TRUE);
3844 table = pref_table_new(box2, 2, 2, TRUE, FALSE);
3845 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3846 pref_checkbox_new_int(box, _("Mirror left image"),
3847 options->stereo.fsmode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.fs_mirror_left);
3848 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3849 pref_checkbox_new_int(box, _("Flip left image"),
3850 options->stereo.fsmode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.fs_flip_left);
3851 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3852 pref_checkbox_new_int(box, _("Mirror right image"),
3853 options->stereo.fsmode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.fs_mirror_right);
3854 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3855 pref_checkbox_new_int(box, _("Flip right image"),
3856 options->stereo.fsmode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.fs_flip_right);
3857 pref_checkbox_new_int(box2, _("Swap left and right images"),
3858 options->stereo.fsmode & PR_STEREO_SWAP, &c_options->stereo.tmp.fs_swap);
3859 pref_checkbox_new_int(box2, _("Disable stereo mode on single image source"),
3860 options->stereo.fsmode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.fs_temp_disable);
3862 group2 = pref_group_new(box2, FALSE, _("Fixed position"), GTK_ORIENTATION_VERTICAL);
3863 table = pref_table_new(group2, 5, 3, FALSE, FALSE);
3864 pref_table_spin_new_int(table, 0, 0, _("Width"), NULL,
3865 1, 5000, 1, options->stereo.fixed_w, &c_options->stereo.fixed_w);
3866 pref_table_spin_new_int(table, 3, 0, _("Height"), NULL,
3867 1, 5000, 1, options->stereo.fixed_h, &c_options->stereo.fixed_h);
3868 pref_table_spin_new_int(table, 0, 1, _("Left X"), NULL,
3869 0, 5000, 1, options->stereo.fixed_x1, &c_options->stereo.fixed_x1);
3870 pref_table_spin_new_int(table, 3, 1, _("Left Y"), NULL,
3871 0, 5000, 1, options->stereo.fixed_y1, &c_options->stereo.fixed_y1);
3872 pref_table_spin_new_int(table, 0, 2, _("Right X"), NULL,
3873 0, 5000, 1, options->stereo.fixed_x2, &c_options->stereo.fixed_x2);
3874 pref_table_spin_new_int(table, 3, 2, _("Right Y"), NULL,
3875 0, 5000, 1, options->stereo.fixed_y2, &c_options->stereo.fixed_y2);
3879 /* Main preferences window */
3880 static void config_window_create(LayoutWindow *lw)
3882 GtkWidget *win_vbox;
3884 GtkWidget *notebook;
3886 GtkWidget *ct_button;
3888 if (!c_options) c_options = init_options(NULL);
3890 configwindow = window_new(GTK_WINDOW_TOPLEVEL, "preferences", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Preferences"));
3891 DEBUG_NAME(configwindow);
3892 gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
3893 g_signal_connect(G_OBJECT(configwindow), "delete_event",
3894 G_CALLBACK(config_window_delete), NULL);
3895 if (options->save_dialog_window_positions)
3897 gtk_window_resize(GTK_WINDOW(configwindow), lw->options.preferences_window.w, lw->options.preferences_window.h);
3898 gtk_window_move(GTK_WINDOW(configwindow), lw->options.preferences_window.x, lw->options.preferences_window.y);
3902 gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
3904 gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
3905 gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
3907 win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
3908 gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
3909 gtk_widget_show(win_vbox);
3911 notebook = gtk_notebook_new();
3912 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_LEFT);
3913 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE);
3914 gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
3916 config_tab_general(notebook);
3917 config_tab_image(notebook);
3918 config_tab_osd(notebook);
3919 config_tab_windows(notebook);
3920 config_tab_accelerators(notebook);
3921 config_tab_files(notebook);
3922 config_tab_metadata(notebook);
3923 config_tab_keywords(notebook);
3924 config_tab_color(notebook);
3925 config_tab_stereo(notebook);
3926 config_tab_behavior(notebook);
3927 config_tab_toolbar_main(notebook);
3928 config_tab_toolbar_status(notebook);
3929 config_tab_advanced(notebook);
3931 gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), lw->options.preferences_window.page_number);
3933 hbox = gtk_hbutton_box_new();
3934 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
3935 gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
3936 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
3937 gtk_widget_show(hbox);
3939 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
3940 G_CALLBACK(config_window_help_cb), notebook);
3941 gtk_container_add(GTK_CONTAINER(hbox), button);
3942 gtk_widget_set_can_default(button, TRUE);
3943 gtk_widget_show(button);
3945 button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
3946 G_CALLBACK(config_window_ok_cb), notebook);
3947 gtk_container_add(GTK_CONTAINER(hbox), button);
3948 gtk_widget_set_can_default(button, TRUE);
3949 gtk_widget_grab_default(button);
3950 gtk_widget_show(button);
3954 button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
3955 G_CALLBACK(config_window_close_cb), NULL);
3956 gtk_container_add(GTK_CONTAINER(hbox), button);
3957 gtk_widget_set_can_default(button, TRUE);
3958 gtk_widget_show(button);
3960 if (!generic_dialog_get_alternative_button_order(configwindow))
3962 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
3965 gtk_widget_show(notebook);
3967 gtk_widget_show(configwindow);
3971 *-----------------------------------------------------------------------------
3972 * config window show (public)
3973 *-----------------------------------------------------------------------------
3976 void show_config_window(LayoutWindow *lw)
3980 gtk_window_present(GTK_WINDOW(configwindow));
3984 config_window_create(lw);
3993 void show_about_window(LayoutWindow *lw)
3995 GdkPixbuf *pixbuf_logo;
3996 GdkPixbuf *pixbuf_icon;
3997 gchar *authors[1000];
4002 gchar *timezone_path;
4006 #define LINE_LENGTH 1000
4007 gchar line[LINE_LENGTH];
4009 copyright = g_string_new(NULL);
4010 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");
4012 path = path_from_utf8(TIMEZONE_DATABASE);
4013 basename = g_path_get_basename(path);
4014 timezone_path = g_build_filename(get_rc_dir(), basename, NULL);
4015 if (g_file_test(timezone_path, G_FILE_TEST_EXISTS))
4017 cd = ZDOpenDatabase(timezone_path);
4020 copyright = g_string_append(copyright, ZDGetNotice(cd));
4021 ZDCloseDatabase(cd);
4025 g_free(timezone_path);
4029 path = g_build_filename(gq_helpdir, "AUTHORS", NULL);
4030 fp = fopen(path, "r");
4033 while(fgets(line, LINE_LENGTH, fp))
4035 /* get rid of ending \n from fgets */
4036 line[strlen(line) - 1] = '\0';
4037 authors[i_authors] = g_strdup(line);
4040 authors[i_authors] = NULL;
4045 comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
4046 "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
4048 pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
4049 pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
4050 gtk_show_about_dialog(GTK_WINDOW(lw->window),
4051 "title", _("About Geeqie"),
4053 "program-name", GQ_APPNAME,
4055 "logo", pixbuf_logo,
4056 "icon", pixbuf_icon,
4057 "website", GQ_WEBSITE,
4058 "website-label", "Website",
4059 "comments", comment,
4061 "translator-credits", _("translator-credits"),
4062 "wrap-license", TRUE,
4063 "license", copyright->str,
4066 g_string_free(copyright, TRUE);
4069 while(n < i_authors)
4079 static void image_overlay_set_text_colours()
4081 c_options->image_overlay.text_red = options->image_overlay.text_red;
4082 c_options->image_overlay.text_green = options->image_overlay.text_green;
4083 c_options->image_overlay.text_blue = options->image_overlay.text_blue;
4084 c_options->image_overlay.text_alpha = options->image_overlay.text_alpha;
4085 c_options->image_overlay.background_red = options->image_overlay.background_red;
4086 c_options->image_overlay.background_green = options->image_overlay.background_green;
4087 c_options->image_overlay.background_blue = options->image_overlay.background_blue;
4088 c_options->image_overlay.background_alpha = options->image_overlay.background_alpha;
4092 *-----------------------------------------------------------------------------
4093 * timezone database routines
4094 *-----------------------------------------------------------------------------
4097 static void timezone_async_ready_cb(GObject *source_object, GAsyncResult *res, gpointer data)
4099 GError *error = NULL;
4101 gchar *tmp_filename;
4103 if (!g_cancellable_is_cancelled(tz->cancellable))
4105 generic_dialog_close(tz->gd);
4109 if (g_file_copy_finish(G_FILE(source_object), res, &error))
4111 tmp_filename = g_file_get_parse_name(tz->tmp_g_file);
4112 move_file(tmp_filename, tz->timezone_database_user);
4113 g_free(tmp_filename);
4117 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
4120 g_file_delete(tz->tmp_g_file, NULL, &error);
4121 g_object_unref(tz->tmp_g_file);
4122 tz->tmp_g_file = NULL;
4123 g_object_unref(tz->cancellable);
4124 g_object_unref(tz->timezone_database_gq);
4127 static void timezone_progress_cb(goffset current_num_bytes, goffset total_num_bytes, gpointer data)
4131 if (!g_cancellable_is_cancelled(tz->cancellable))
4133 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(tz->progress), (gdouble)current_num_bytes / total_num_bytes);
4137 static void timezone_cancel_button_cb(GenericDialog *gd, gpointer data)
4141 g_cancellable_cancel(tz->cancellable);
4144 static void timezone_database_install_cb(GtkWidget *widget, gpointer data)
4147 GError *error = NULL;
4148 GFileIOStream *io_stream;
4155 tz->tmp_g_file = g_file_new_tmp("geeqie_timezone_XXXXXX", &io_stream, &error);
4159 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
4160 log_printf("Error: Download timezone database failed:\n%s", error->message);
4161 g_error_free(error);
4162 g_object_unref(tz->tmp_g_file);
4166 tz->timezone_database_gq = g_file_new_for_uri(TIMEZONE_DATABASE);
4168 tz->gd = generic_dialog_new(_("Timezone database"), "download_timezone_database", NULL, TRUE, timezone_cancel_button_cb, tz);
4170 generic_dialog_add_message(tz->gd, GTK_STOCK_DIALOG_INFO, _("Downloading timezone database"), NULL, FALSE);
4172 tz->progress = gtk_progress_bar_new();
4173 gtk_box_pack_start(GTK_BOX(tz->gd->vbox), tz->progress, FALSE, FALSE, 0);
4174 gtk_widget_show(tz->progress);
4176 gtk_widget_show(tz->gd->dialog);
4177 tz->cancellable = g_cancellable_new();
4178 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);
4180 gtk_button_set_label(GTK_BUTTON(widget), _("Update"));
4183 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */