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[] = {
125 /* config memory values */
126 static ConfOptions *c_options = NULL;
133 static GtkWidget *configwindow = NULL;
134 static GtkListStore *filter_store = NULL;
135 static GtkTreeStore *accel_store = NULL;
137 static GtkWidget *safe_delete_path_entry;
139 static GtkWidget *color_profile_input_file_entry[COLOR_PROFILE_INPUTS];
140 static GtkWidget *color_profile_input_name_entry[COLOR_PROFILE_INPUTS];
141 static GtkWidget *color_profile_screen_file_entry;
142 static GtkWidget *external_preview_select_entry;
143 static GtkWidget *external_preview_extract_entry;
145 static GtkWidget *sidecar_ext_entry;
146 static GtkWidget *help_search_engine_entry;
149 #define CONFIG_WINDOW_DEF_WIDTH 700
150 #define CONFIG_WINDOW_DEF_HEIGHT 600
153 *-----------------------------------------------------------------------------
154 * option widget callbacks (private)
155 *-----------------------------------------------------------------------------
158 static void zoom_increment_cb(GtkWidget *spin, gpointer data)
160 c_options->image.zoom_increment = (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) * 100.0 + 0.01);
163 static void slideshow_delay_hours_cb(GtkWidget *spin, gpointer data)
165 gint mins_secs_tenths, delay;
167 mins_secs_tenths = c_options->slideshow.delay %
168 (3600 * SLIDESHOW_SUBSECOND_PRECISION);
170 delay = (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
171 (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
174 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
175 SLIDESHOW_SUBSECOND_PRECISION;
178 static void slideshow_delay_minutes_cb(GtkWidget *spin, gpointer data)
180 gint hours, secs_tenths, delay;
182 hours = c_options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
183 secs_tenths = c_options->slideshow.delay % (60 * SLIDESHOW_SUBSECOND_PRECISION);
185 delay = hours * (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
186 (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
187 (60 * SLIDESHOW_SUBSECOND_PRECISION) + secs_tenths);
189 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
190 SLIDESHOW_SUBSECOND_PRECISION;
193 static void slideshow_delay_seconds_cb(GtkWidget *spin, gpointer data)
195 gint hours_mins, delay;
197 hours_mins = c_options->slideshow.delay / (60 * SLIDESHOW_SUBSECOND_PRECISION);
199 delay = (hours_mins * (60 * SLIDESHOW_SUBSECOND_PRECISION)) +
200 (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
201 (gdouble)(SLIDESHOW_SUBSECOND_PRECISION) + 0.01);
203 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
204 SLIDESHOW_SUBSECOND_PRECISION;
208 *-----------------------------------------------------------------------------
209 * sync program to config window routine (private)
210 *-----------------------------------------------------------------------------
213 void config_entry_to_option(GtkWidget *entry, gchar **option, gchar *(*func)(const gchar *))
219 buf = gtk_entry_get_text(GTK_ENTRY(entry));
220 if (buf && strlen(buf) > 0)
225 *option = g_strdup(buf);
230 static gboolean accel_apply_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
232 gchar *accel_path, *accel;
234 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, AE_KEY, &accel, -1);
236 if (accel_path && accel_path[0])
239 gtk_accelerator_parse(accel, &key.accel_key, &key.accel_mods);
240 gtk_accel_map_change_entry(accel_path, key.accel_key, key.accel_mods, TRUE);
250 static void config_window_apply(void)
252 gboolean refresh = FALSE;
257 config_entry_to_option(safe_delete_path_entry, &options->file_ops.safe_delete_path, remove_trailing_slash);
259 if (options->file_filter.show_hidden_files != c_options->file_filter.show_hidden_files) refresh = TRUE;
260 if (options->file_filter.show_parent_directory != c_options->file_filter.show_parent_directory) refresh = TRUE;
261 if (options->file_filter.show_dot_directory != c_options->file_filter.show_dot_directory) refresh = TRUE;
262 if (options->file_sort.case_sensitive != c_options->file_sort.case_sensitive) refresh = TRUE;
263 if (options->file_sort.natural != c_options->file_sort.natural) refresh = TRUE;
264 if (options->file_filter.disable_file_extension_checks != c_options->file_filter.disable_file_extension_checks) refresh = TRUE;
265 if (options->file_filter.disable != c_options->file_filter.disable) refresh = TRUE;
267 options->file_ops.confirm_delete = c_options->file_ops.confirm_delete;
268 options->file_ops.enable_delete_key = c_options->file_ops.enable_delete_key;
269 options->file_ops.confirm_move_to_trash = c_options->file_ops.confirm_move_to_trash;
270 options->file_ops.use_system_trash = c_options->file_ops.use_system_trash;
271 options->file_ops.no_trash = c_options->file_ops.no_trash;
272 options->file_ops.safe_delete_folder_maxsize = c_options->file_ops.safe_delete_folder_maxsize;
273 options->tools_restore_state = c_options->tools_restore_state;
274 options->save_window_positions = c_options->save_window_positions;
275 options->use_saved_window_positions_for_new_windows = c_options->use_saved_window_positions_for_new_windows;
276 options->save_window_workspace = c_options->save_window_workspace;
277 options->save_dialog_window_positions = c_options->save_dialog_window_positions;
278 options->show_window_ids = c_options->show_window_ids;
279 options->image.scroll_reset_method = c_options->image.scroll_reset_method;
280 options->image.zoom_2pass = c_options->image.zoom_2pass;
281 options->image.fit_window_to_image = c_options->image.fit_window_to_image;
282 options->image.limit_window_size = c_options->image.limit_window_size;
283 options->image.zoom_to_fit_allow_expand = c_options->image.zoom_to_fit_allow_expand;
284 options->image.max_window_size = c_options->image.max_window_size;
285 options->image.limit_autofit_size = c_options->image.limit_autofit_size;
286 options->image.max_autofit_size = c_options->image.max_autofit_size;
287 options->image.max_enlargement_size = c_options->image.max_enlargement_size;
288 options->image.use_clutter_renderer = c_options->image.use_clutter_renderer;
289 options->progressive_key_scrolling = c_options->progressive_key_scrolling;
290 options->keyboard_scroll_step = c_options->keyboard_scroll_step;
292 if (options->thumbnails.max_width != c_options->thumbnails.max_width
293 || options->thumbnails.max_height != c_options->thumbnails.max_height
294 || options->thumbnails.quality != c_options->thumbnails.quality)
296 thumb_format_changed = TRUE;
298 options->thumbnails.max_width = c_options->thumbnails.max_width;
299 options->thumbnails.max_height = c_options->thumbnails.max_height;
300 options->thumbnails.quality = c_options->thumbnails.quality;
302 options->thumbnails.enable_caching = c_options->thumbnails.enable_caching;
303 options->thumbnails.cache_into_dirs = c_options->thumbnails.cache_into_dirs;
304 options->thumbnails.use_exif = c_options->thumbnails.use_exif;
305 options->thumbnails.use_color_management = c_options->thumbnails.use_color_management;
306 options->thumbnails.collection_preview = c_options->thumbnails.collection_preview;
307 options->thumbnails.use_ft_metadata = c_options->thumbnails.use_ft_metadata;
308 // options->thumbnails.use_ft_metadata_small = c_options->thumbnails.use_ft_metadata_small;
309 options->thumbnails.spec_standard = c_options->thumbnails.spec_standard;
310 options->metadata.enable_metadata_dirs = c_options->metadata.enable_metadata_dirs;
311 options->file_filter.show_hidden_files = c_options->file_filter.show_hidden_files;
312 options->file_filter.show_parent_directory = c_options->file_filter.show_parent_directory;
313 options->file_filter.show_dot_directory = c_options->file_filter.show_dot_directory;
314 options->file_filter.disable_file_extension_checks = c_options->file_filter.disable_file_extension_checks;
316 options->file_sort.case_sensitive = c_options->file_sort.case_sensitive;
317 options->file_sort.natural = c_options->file_sort.natural;
318 options->file_filter.disable = c_options->file_filter.disable;
320 config_entry_to_option(sidecar_ext_entry, &options->sidecar.ext, NULL);
321 sidecar_ext_parse(options->sidecar.ext);
323 options->slideshow.random = c_options->slideshow.random;
324 options->slideshow.repeat = c_options->slideshow.repeat;
325 options->slideshow.delay = c_options->slideshow.delay;
327 options->mousewheel_scrolls = c_options->mousewheel_scrolls;
328 options->image_lm_click_nav = c_options->image_lm_click_nav;
329 options->image_l_click_video = c_options->image_l_click_video;
330 options->image_l_click_video_editor = c_options->image_l_click_video_editor;
332 options->file_ops.enable_in_place_rename = c_options->file_ops.enable_in_place_rename;
334 options->image.tile_cache_max = c_options->image.tile_cache_max;
335 options->image.image_cache_max = c_options->image.image_cache_max;
337 options->image.zoom_quality = c_options->image.zoom_quality;
339 options->image.zoom_increment = c_options->image.zoom_increment;
341 options->image.enable_read_ahead = c_options->image.enable_read_ahead;
344 if (options->image.use_custom_border_color != c_options->image.use_custom_border_color
345 || options->image.use_custom_border_color_in_fullscreen != c_options->image.use_custom_border_color_in_fullscreen
346 || !gdk_color_equal(&options->image.border_color, &c_options->image.border_color))
348 options->image.use_custom_border_color_in_fullscreen = c_options->image.use_custom_border_color_in_fullscreen;
349 options->image.use_custom_border_color = c_options->image.use_custom_border_color;
350 options->image.border_color = c_options->image.border_color;
351 layout_colors_update();
352 view_window_colors_update();
355 options->image.alpha_color_1 = c_options->image.alpha_color_1;
356 options->image.alpha_color_2 = c_options->image.alpha_color_2;
358 options->fullscreen.screen = c_options->fullscreen.screen;
359 options->fullscreen.clean_flip = c_options->fullscreen.clean_flip;
360 options->fullscreen.disable_saver = c_options->fullscreen.disable_saver;
361 options->fullscreen.above = c_options->fullscreen.above;
362 if (c_options->image_overlay.template_string)
363 set_image_overlay_template_string(&options->image_overlay.template_string,
364 c_options->image_overlay.template_string);
365 if (c_options->image_overlay.font)
366 set_image_overlay_font_string(&options->image_overlay.font,
367 c_options->image_overlay.font);
368 options->image_overlay.text_red = c_options->image_overlay.text_red;
369 options->image_overlay.text_green = c_options->image_overlay.text_green;
370 options->image_overlay.text_blue = c_options->image_overlay.text_blue;
371 options->image_overlay.text_alpha = c_options->image_overlay.text_alpha;
372 options->image_overlay.background_red = c_options->image_overlay.background_red;
373 options->image_overlay.background_green = c_options->image_overlay.background_green;
374 options->image_overlay.background_blue = c_options->image_overlay.background_blue;
375 options->image_overlay.background_alpha = c_options->image_overlay.background_alpha;
376 options->update_on_time_change = c_options->update_on_time_change;
377 options->image.exif_proof_rotate_enable = c_options->image.exif_proof_rotate_enable;
379 options->duplicates_similarity_threshold = c_options->duplicates_similarity_threshold;
380 options->rot_invariant_sim = c_options->rot_invariant_sim;
382 options->tree_descend_subdirs = c_options->tree_descend_subdirs;
384 options->view_dir_list_single_click_enter = c_options->view_dir_list_single_click_enter;
385 options->circular_selection_lists = c_options->circular_selection_lists;
387 options->open_recent_list_maxsize = c_options->open_recent_list_maxsize;
388 options->dnd_icon_size = c_options->dnd_icon_size;
389 options->clipboard_selection = c_options->clipboard_selection;
390 options->dnd_default_action = c_options->dnd_default_action;
392 options->metadata.save_in_image_file = c_options->metadata.save_in_image_file;
393 options->metadata.save_legacy_IPTC = c_options->metadata.save_legacy_IPTC;
394 options->metadata.warn_on_write_problems = c_options->metadata.warn_on_write_problems;
395 options->metadata.save_legacy_format = c_options->metadata.save_legacy_format;
396 options->metadata.sync_grouped_files = c_options->metadata.sync_grouped_files;
397 options->metadata.confirm_write = c_options->metadata.confirm_write;
398 options->metadata.sidecar_extended_name = c_options->metadata.sidecar_extended_name;
399 options->metadata.confirm_timeout = c_options->metadata.confirm_timeout;
400 options->metadata.confirm_after_timeout = c_options->metadata.confirm_after_timeout;
401 options->metadata.confirm_on_image_change = c_options->metadata.confirm_on_image_change;
402 options->metadata.confirm_on_dir_change = c_options->metadata.confirm_on_dir_change;
403 options->metadata.keywords_case_sensitive = c_options->metadata.keywords_case_sensitive;
404 options->metadata.write_orientation = c_options->metadata.write_orientation;
405 options->stereo.mode = (c_options->stereo.mode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
406 (c_options->stereo.tmp.mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
407 (c_options->stereo.tmp.flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
408 (c_options->stereo.tmp.mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
409 (c_options->stereo.tmp.flip_left ? PR_STEREO_FLIP_LEFT : 0) |
410 (c_options->stereo.tmp.swap ? PR_STEREO_SWAP : 0) |
411 (c_options->stereo.tmp.temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
412 options->stereo.fsmode = (c_options->stereo.fsmode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
413 (c_options->stereo.tmp.fs_mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
414 (c_options->stereo.tmp.fs_flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
415 (c_options->stereo.tmp.fs_mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
416 (c_options->stereo.tmp.fs_flip_left ? PR_STEREO_FLIP_LEFT : 0) |
417 (c_options->stereo.tmp.fs_swap ? PR_STEREO_SWAP : 0) |
418 (c_options->stereo.tmp.fs_temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
419 options->stereo.enable_fsmode = c_options->stereo.enable_fsmode;
420 options->stereo.fixed_w = c_options->stereo.fixed_w;
421 options->stereo.fixed_h = c_options->stereo.fixed_h;
422 options->stereo.fixed_x1 = c_options->stereo.fixed_x1;
423 options->stereo.fixed_y1 = c_options->stereo.fixed_y1;
424 options->stereo.fixed_x2 = c_options->stereo.fixed_x2;
425 options->stereo.fixed_y2 = c_options->stereo.fixed_y2;
427 options->info_keywords.height = c_options->info_keywords.height;
428 options->info_title.height = c_options->info_title.height;
429 options->info_comment.height = c_options->info_comment.height;
430 options->info_rating.height = c_options->info_rating.height;
432 options->show_predefined_keyword_tree = c_options->show_predefined_keyword_tree;
433 options->expand_menu_toolbar = c_options->expand_menu_toolbar;
435 options->marks_save = c_options->marks_save;
436 options->with_rename = c_options->with_rename;
437 options->collections_on_top = c_options->collections_on_top;
438 options->hide_window_in_fullscreen = c_options->hide_window_in_fullscreen;
439 config_entry_to_option(help_search_engine_entry, &options->help_search_engine, NULL);
441 options->external_preview.enable = c_options->external_preview.enable;
442 config_entry_to_option(external_preview_select_entry, &options->external_preview.select, NULL);
443 config_entry_to_option(external_preview_extract_entry, &options->external_preview.extract, NULL);
445 options->read_metadata_in_idle = c_options->read_metadata_in_idle;
447 options->star_rating.star = c_options->star_rating.star;
448 options->star_rating.rejected = c_options->star_rating.rejected;
450 options->threads.duplicates = c_options->threads.duplicates > 0 ? c_options->threads.duplicates : -1;
453 set_debug_level(debug_c);
457 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
459 config_entry_to_option(color_profile_input_name_entry[i], &options->color_profile.input_name[i], NULL);
460 config_entry_to_option(color_profile_input_file_entry[i], &options->color_profile.input_file[i], NULL);
462 config_entry_to_option(color_profile_screen_file_entry, &options->color_profile.screen_file, NULL);
463 options->color_profile.use_x11_screen_profile = c_options->color_profile.use_x11_screen_profile;
464 if (options->color_profile.render_intent != c_options->color_profile.render_intent)
466 options->color_profile.render_intent = c_options->color_profile.render_intent;
471 options->mouse_button_8 = c_options->mouse_button_8;
472 options->mouse_button_9 = c_options->mouse_button_9;
474 options->override_disable_gpu = c_options->override_disable_gpu;
476 config_tab_keywords_save();
478 image_options_sync();
483 layout_refresh(NULL);
486 if (accel_store) gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_apply_cb, NULL);
488 toolbar_apply(TOOLBAR_MAIN);
489 toolbar_apply(TOOLBAR_STATUS);
493 *-----------------------------------------------------------------------------
494 * config window main button callbacks (private)
495 *-----------------------------------------------------------------------------
498 static void config_window_close_cb(GtkWidget *widget, gpointer data)
500 gtk_widget_destroy(configwindow);
505 static void config_window_help_cb(GtkWidget *widget, gpointer data)
507 GtkWidget *notebook = data;
510 static gchar *html_section[] =
512 "GuideOptionsGeneral.html",
513 "GuideOptionsImage.html",
514 "GuideOptionsOSD.html",
515 "GuideOptionsWindow.html",
516 "GuideOptionsKeyboard.html",
517 "GuideOptionsFiltering.html",
518 "GuideOptionsMetadata.html",
519 "GuideOptionsKeywords.html",
520 "GuideOptionsColor.html",
521 "GuideOptionsStereo.html",
522 "GuideOptionsBehavior.html",
523 "GuideOptionsToolbar.html",
524 "GuideOptionsToolbar.html",
525 "GuideOptionsAdvanced.html"
528 i = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
529 help_window_show(html_section[i]);
532 static gboolean config_window_delete(GtkWidget *widget, GdkEventAny *event, gpointer data)
534 config_window_close_cb(NULL, NULL);
538 static void config_window_ok_cb(GtkWidget *widget, gpointer data)
541 GtkNotebook *notebook = data;
549 lw = layout_window_list->data;
551 window = gtk_widget_get_window(widget);
552 gdk_window_get_root_origin(window, &x, &y);
553 w = gdk_window_get_width(window);
554 h = gdk_window_get_height(window);
555 page_number = gtk_notebook_get_current_page(notebook);
557 lw->options.preferences_window.x = x;
558 lw->options.preferences_window.y = y;
559 lw->options.preferences_window.w = w;
560 lw->options.preferences_window.h = h;
561 lw->options.preferences_window.page_number = page_number;
563 config_window_apply();
564 layout_util_sync(lw);
565 save_options(options);
566 config_window_close_cb(NULL, NULL);
570 *-----------------------------------------------------------------------------
571 * config window setup (private)
572 *-----------------------------------------------------------------------------
575 static void quality_menu_cb(GtkWidget *combo, gpointer data)
579 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
583 *option = GDK_INTERP_NEAREST;
586 *option = GDK_INTERP_TILES;
589 *option = GDK_INTERP_BILINEAR;
594 static void dnd_default_action_selection_menu_cb(GtkWidget *combo, gpointer data)
598 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
602 *option = DND_ACTION_ASK;
605 *option = DND_ACTION_COPY;
608 *option = DND_ACTION_MOVE;
612 static void clipboard_selection_menu_cb(GtkWidget *combo, gpointer data)
616 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
619 *option = CLIPBOARD_PRIMARY;
622 *option = CLIPBOARD_CLIPBOARD;
625 *option = CLIPBOARD_BOTH;
628 *option = CLIPBOARD_BOTH;
632 static void add_quality_menu(GtkWidget *table, gint column, gint row, const gchar *text,
633 guint option, guint *option_c)
640 pref_table_label(table, column, row, text, 0.0);
642 combo = gtk_combo_box_text_new();
644 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Nearest (worst, but fastest)"));
645 if (option == GDK_INTERP_NEAREST) current = 0;
646 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Tiles"));
647 if (option == GDK_INTERP_TILES) current = 1;
648 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Bilinear (best, but slowest)"));
649 if (option == GDK_INTERP_BILINEAR) current = 2;
651 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
653 g_signal_connect(G_OBJECT(combo), "changed",
654 G_CALLBACK(quality_menu_cb), option_c);
656 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
657 gtk_widget_show(combo);
660 static void add_dnd_default_action_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text, DnDAction option, DnDAction *option_c)
667 pref_table_label(table, column, row, text, 0.0);
669 combo = gtk_combo_box_text_new();
671 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Ask"));
672 if (option == DND_ACTION_ASK) current = 0;
673 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Copy"));
674 if (option == DND_ACTION_COPY) current = 1;
675 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Move"));
676 if (option == DND_ACTION_MOVE) current = 2;
678 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
680 g_signal_connect(G_OBJECT(combo), "changed",
681 G_CALLBACK(dnd_default_action_selection_menu_cb), option_c);
683 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
684 gtk_widget_show(combo);
687 static void add_clipboard_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
688 gint option, gint *option_c)
695 pref_table_label(table, column, row, text, 0.0);
697 combo = gtk_combo_box_text_new();
699 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Primary"));
700 if (option == CLIPBOARD_PRIMARY) current = 0;
701 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Clipboard"));
702 if (option == CLIPBOARD_CLIPBOARD) current = 1;
703 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Both"));
704 if (option == CLIPBOARD_BOTH) current = 2;
706 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
708 g_signal_connect(G_OBJECT(combo), "changed",
709 G_CALLBACK(clipboard_selection_menu_cb), option_c);
711 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
712 gtk_widget_show(combo);
715 typedef struct _UseableMouseItems UseableMouseItems;
716 struct _UseableMouseItems
718 gchar *name; /* GtkActionEntry terminology */
723 static const UseableMouseItems useable_mouse_items[] = {
725 {"FirstImage", N_("First Image"), GTK_STOCK_GOTO_TOP},
726 {"PrevImage", N_("Previous Image"), GTK_STOCK_GO_UP},
727 {"NextImage", N_("Next Image"), GTK_STOCK_GO_DOWN},
728 {"LastImage", N_("Last Image"), GTK_STOCK_GOTO_BOTTOM},
729 {"Back", N_("Back"), GTK_STOCK_GO_BACK},
730 {"Forward", N_("Forward"), GTK_STOCK_GO_FORWARD},
731 {"Home", N_("Home"), GTK_STOCK_HOME},
732 {"Up", N_("Up"), GTK_STOCK_GO_UP},
733 {"FirstPage", N_("First page"), GTK_STOCK_MEDIA_PREVIOUS},
734 {"LastPage", N_("Last Page"), GTK_STOCK_MEDIA_NEXT},
735 {"NextPage", N_("Next page"), GTK_STOCK_MEDIA_FORWARD},
736 {"PrevPage", N_("Previous Page"), GTK_STOCK_MEDIA_REWIND},
737 {"NewWindow", N_("New _window"), GTK_STOCK_NEW},
738 {"NewCollection", N_("New collection"), GTK_STOCK_INDEX},
739 {"OpenCollection", N_("Open collection"), GTK_STOCK_OPEN},
740 {"Search", N_("Search"), GTK_STOCK_FIND},
741 {"FindDupes", N_("Find duplicates"), GTK_STOCK_FIND},
742 {"NewFolder", N_("New folder"),GTK_STOCK_DIRECTORY},
743 {"Copy", N_("Copy"), GTK_STOCK_COPY},
744 {"Move", N_("Move"), PIXBUF_INLINE_ICON_MOVE},
745 {"Rename", N_("Rename"), PIXBUF_INLINE_ICON_RENAME},
746 {"Delete", N_("Delete"), GTK_STOCK_DELETE},
747 {"CloseWindow", N_("Close Window"), GTK_STOCK_CLOSE},
748 {"PanView", N_("Pan view"), PIXBUF_INLINE_ICON_PANORAMA},
749 {"SelectAll", N_("Select all"), PIXBUF_INLINE_ICON_SELECT_ALL},
750 {"SelectNone", N_("Select none"), PIXBUF_INLINE_ICON_SELECT_NONE},
751 {"SelectInvert", N_("Select invert"), PIXBUF_INLINE_ICON_SELECT_INVERT},
752 {"ShowFileFilter", N_("Show file filter"), PIXBUF_INLINE_ICON_FILE_FILTER},
753 {"RectangularSelection", N_("Select rectangle"), PIXBUF_INLINE_ICON_SELECT_RECTANGLE},
754 {"Print", N_("Print"), GTK_STOCK_PRINT},
755 {"Preferences", N_("Preferences"), GTK_STOCK_PREFERENCES},
756 {"LayoutConfig", N_("Configure this window"), GTK_STOCK_PREFERENCES},
757 {"Maintenance", N_("Cache maintenance"), PIXBUF_INLINE_ICON_MAINTENANCE},
758 {"RotateCW", N_("Rotate clockwise 90°"), PIXBUF_INLINE_ICON_CW},
759 {"RotateCCW", N_("Rotate counterclockwise 90°"), PIXBUF_INLINE_ICON_CCW},
760 {"Rotate180", N_("Rotate 180°"), PIXBUF_INLINE_ICON_180},
761 {"Mirror", N_("Mirror"), PIXBUF_INLINE_ICON_MIRROR},
762 {"Flip", N_("Flip"), PIXBUF_INLINE_ICON_FLIP},
763 {"AlterNone", N_("Original state"), PIXBUF_INLINE_ICON_ORIGINAL},
764 {"ZoomIn", N_("Zoom in"), GTK_STOCK_ZOOM_IN},
765 {"ZoomOut", N_("Zoom out"), GTK_STOCK_ZOOM_OUT},
766 {"Zoom100", N_("Zoom 1:1"), GTK_STOCK_ZOOM_100},
767 {"ZoomFit", N_("Zoom to fit"), GTK_STOCK_ZOOM_FIT},
768 {"ZoomFillHor", N_("Fit Horizontaly"), PIXBUF_INLINE_ICON_ZOOMFILLHOR},
769 {"ZoomFillVert", N_("Fit vertically"), PIXBUF_INLINE_ICON_ZOOMFILLVERT},
770 {"Zoom200", N_("Zoom 2:1"), GTK_STOCK_FILE},
771 {"Zoom300", N_("Zoom 3:1"), GTK_STOCK_FILE},
772 {"Zoom400", N_("Zoom 4:1"), GTK_STOCK_FILE},
773 {"Zoom50", N_("Zoom 1:2"), GTK_STOCK_FILE},
774 {"Zoom33", N_("Zoom1:3"), GTK_STOCK_FILE},
775 {"Zoom25", N_("Zoom 1:4"), GTK_STOCK_FILE},
776 {"ConnectZoomIn", N_("Connected Zoom in"), GTK_STOCK_ZOOM_IN},
777 {"SplitPaneSync", N_("Split Pane Sync"), PIXBUF_INLINE_SPLIT_PANE_SYNC},
778 {"Grayscale", N_("Grayscale"), PIXBUF_INLINE_ICON_GRAYSCALE},
779 {"OverUnderExposed", N_("Over Under Exposed"), PIXBUF_INLINE_ICON_EXPOSURE},
780 {"HideTools", N_("Hide file list"), PIXBUF_INLINE_ICON_HIDETOOLS},
781 {"SlideShowPause", N_("Pause slideshow"), GTK_STOCK_MEDIA_PAUSE},
782 {"SlideShowFaster", N_("Slideshow Faster"), GTK_STOCK_FILE},
783 {"SlideShowSlower", N_("Slideshow Slower"), GTK_STOCK_FILE},
784 {"Refresh", N_("Refresh"), GTK_STOCK_REFRESH},
785 {"HelpContents", N_("Help"), GTK_STOCK_HELP},
786 {"ExifWin", N_("Exif window"), PIXBUF_INLINE_ICON_EXIF},
787 {"Thumbnails", N_("Show thumbnails"), PIXBUF_INLINE_ICON_THUMB},
788 {"ShowMarks", N_("Show marks"), PIXBUF_INLINE_ICON_MARKS},
789 {"DrawRectangle", N_("Draw Rectangle"), PIXBUF_INLINE_ICON_DRAW_RECTANGLE},
790 {"FloatTools", N_("Float file list"), PIXBUF_INLINE_ICON_FLOAT},
791 {"SBar", N_("Info sidebar"), PIXBUF_INLINE_ICON_INFO},
792 {"SBarSort", N_("Sort manager"), PIXBUF_INLINE_ICON_SORT},
793 {"Quit", N_("Quit"), GTK_STOCK_QUIT},
797 static void mouse_buttons_selection_menu_cb(GtkWidget *combo, gpointer data)
799 gchar **option = data;
802 label = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(combo));
804 const UseableMouseItems *list = useable_mouse_items;
808 if (g_strcmp0(list->label, label) == 0)
816 *option = g_strdup(list->name);
820 static void add_mouse_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
821 gchar *option, gchar **option_c)
829 pref_table_label(table, column, row, text, 0.0);
831 combo = gtk_combo_box_text_new();
833 const UseableMouseItems *list = useable_mouse_items;
837 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), list->label);
838 if (g_strcmp0(list->name, option) == 0)
846 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
848 g_signal_connect(G_OBJECT(combo), "changed",
849 G_CALLBACK(mouse_buttons_selection_menu_cb), option_c);
851 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
852 gtk_widget_show(combo);
855 static void thumb_size_menu_cb(GtkWidget *combo, gpointer data)
859 n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
862 if ((guint) n < sizeof(thumb_size_list) / sizeof(ThumbSize))
864 c_options->thumbnails.max_width = thumb_size_list[n].w;
865 c_options->thumbnails.max_height = thumb_size_list[n].h;
869 c_options->thumbnails.max_width = options->thumbnails.max_width;
870 c_options->thumbnails.max_height = options->thumbnails.max_height;
874 static void add_thumb_size_menu(GtkWidget *table, gint column, gint row, gchar *text)
880 c_options->thumbnails.max_width = options->thumbnails.max_width;
881 c_options->thumbnails.max_height = options->thumbnails.max_height;
883 pref_table_label(table, column, row, text, 0.0);
885 combo = gtk_combo_box_text_new();
888 for (i = 0; (guint) i < sizeof(thumb_size_list) / sizeof(ThumbSize); i++)
893 w = thumb_size_list[i].w;
894 h = thumb_size_list[i].h;
896 buf = g_strdup_printf("%d x %d", w, h);
897 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
900 if (w == options->thumbnails.max_width && h == options->thumbnails.max_height) current = i;
907 buf = g_strdup_printf("%s %d x %d", _("Custom"), options->thumbnails.max_width, options->thumbnails.max_height);
908 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
914 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
915 g_signal_connect(G_OBJECT(combo), "changed",
916 G_CALLBACK(thumb_size_menu_cb), NULL);
918 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
919 gtk_widget_show(combo);
922 static void stereo_mode_menu_cb(GtkWidget *combo, gpointer data)
926 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
930 *option = PR_STEREO_NONE;
933 *option = PR_STEREO_ANAGLYPH_RC;
936 *option = PR_STEREO_ANAGLYPH_GM;
939 *option = PR_STEREO_ANAGLYPH_YB;
942 *option = PR_STEREO_ANAGLYPH_GRAY_RC;
945 *option = PR_STEREO_ANAGLYPH_GRAY_GM;
948 *option = PR_STEREO_ANAGLYPH_GRAY_YB;
951 *option = PR_STEREO_ANAGLYPH_DB_RC;
954 *option = PR_STEREO_ANAGLYPH_DB_GM;
957 *option = PR_STEREO_ANAGLYPH_DB_YB;
960 *option = PR_STEREO_HORIZ;
963 *option = PR_STEREO_HORIZ | PR_STEREO_HALF;
966 *option = PR_STEREO_VERT;
969 *option = PR_STEREO_VERT | PR_STEREO_HALF;
972 *option = PR_STEREO_FIXED;
977 static void add_stereo_mode_menu(GtkWidget *table, gint column, gint row, const gchar *text,
978 gint option, gint *option_c, gboolean add_fixed)
985 pref_table_label(table, column, row, text, 0.0);
987 combo = gtk_combo_box_text_new();
989 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Single image"));
991 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Red-Cyan"));
992 if (option & PR_STEREO_ANAGLYPH_RC) current = 1;
993 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Green-Magenta"));
994 if (option & PR_STEREO_ANAGLYPH_GM) current = 2;
995 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Yellow-Blue"));
996 if (option & PR_STEREO_ANAGLYPH_YB) current = 3;
997 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Red-Cyan"));
998 if (option & PR_STEREO_ANAGLYPH_GRAY_RC) current = 4;
999 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Green-Magenta"));
1000 if (option & PR_STEREO_ANAGLYPH_GRAY_GM) current = 5;
1001 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Yellow-Blue"));
1002 if (option & PR_STEREO_ANAGLYPH_GRAY_YB) current = 6;
1003 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Red-Cyan"));
1004 if (option & PR_STEREO_ANAGLYPH_DB_RC) current = 7;
1005 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Green-Magenta"));
1006 if (option & PR_STEREO_ANAGLYPH_DB_GM) current = 8;
1007 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Yellow-Blue"));
1008 if (option & PR_STEREO_ANAGLYPH_DB_YB) current = 9;
1010 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side"));
1011 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side Half size"));
1012 if (option & PR_STEREO_HORIZ)
1015 if (option & PR_STEREO_HALF) current = 11;
1018 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom"));
1019 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom Half size"));
1020 if (option & PR_STEREO_VERT)
1023 if (option & PR_STEREO_HALF) current = 13;
1028 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Fixed position"));
1029 if (option & PR_STEREO_FIXED) current = 14;
1032 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
1034 g_signal_connect(G_OBJECT(combo), "changed",
1035 G_CALLBACK(stereo_mode_menu_cb), option_c);
1037 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
1038 gtk_widget_show(combo);
1041 static void video_menu_cb(GtkWidget *combo, gpointer data)
1043 gchar **option = data;
1045 EditorDescription *ed = g_list_nth_data(editor_list_get(), gtk_combo_box_get_active(GTK_COMBO_BOX(combo)));
1049 static void video_menu_populate(gpointer data, gpointer user_data)
1051 GtkWidget *combo = user_data;
1052 EditorDescription *ed = data;
1054 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), ed->name);
1057 static void add_video_menu(GtkWidget *table, gint column, gint row, const gchar *text,
1058 gchar *option, gchar **option_c)
1062 /* use lists since they are sorted */
1063 GList *eds = editor_list_get();
1067 pref_table_label(table, column, row, text, 0.0);
1069 combo = gtk_combo_box_text_new();
1070 g_list_foreach(eds,video_menu_populate,(gpointer)combo);
1071 current = option ? g_list_index(eds,g_hash_table_lookup(editors,option)): -1;
1073 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
1075 g_signal_connect(G_OBJECT(combo), "changed",
1076 G_CALLBACK(video_menu_cb), option_c);
1078 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
1079 gtk_widget_show(combo);
1082 static void filter_store_populate(void)
1086 if (!filter_store) return;
1088 gtk_list_store_clear(filter_store);
1090 work = filter_get_list();
1099 gtk_list_store_append(filter_store, &iter);
1100 gtk_list_store_set(filter_store, &iter, 0, fe, -1);
1104 static void filter_store_ext_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1105 gchar *new_text, gpointer data)
1107 GtkWidget *model = data;
1108 FilterEntry *fe = data;
1112 if (!new_text || strlen(new_text) < 1) return;
1114 tpath = gtk_tree_path_new_from_string(path_str);
1115 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1116 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1118 g_free(fe->extensions);
1119 fe->extensions = g_strdup(new_text);
1121 gtk_tree_path_free(tpath);
1125 static void filter_store_class_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1126 gchar *new_text, gpointer data)
1128 GtkWidget *model = data;
1129 FilterEntry *fe = data;
1134 if (!new_text || !new_text[0]) return;
1136 tpath = gtk_tree_path_new_from_string(path_str);
1137 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1138 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1140 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
1142 if (strcmp(new_text, _(format_class_list[i])) == 0)
1149 gtk_tree_path_free(tpath);
1153 static void filter_store_desc_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1154 gchar *new_text, gpointer data)
1156 GtkWidget *model = data;
1161 if (!new_text || !new_text[0]) return;
1163 tpath = gtk_tree_path_new_from_string(path_str);
1164 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1165 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1167 g_free(fe->description);
1168 fe->description = g_strdup(new_text);
1170 gtk_tree_path_free(tpath);
1173 static void filter_store_enable_cb(GtkCellRendererToggle *renderer,
1174 gchar *path_str, gpointer data)
1176 GtkWidget *model = data;
1181 tpath = gtk_tree_path_new_from_string(path_str);
1182 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1183 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1185 fe->enabled = !fe->enabled;
1187 gtk_tree_path_free(tpath);
1191 static void filter_store_writable_cb(GtkCellRendererToggle *renderer,
1192 gchar *path_str, gpointer data)
1194 GtkWidget *model = data;
1199 tpath = gtk_tree_path_new_from_string(path_str);
1200 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1201 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1203 fe->writable = !fe->writable;
1204 if (fe->writable) fe->allow_sidecar = FALSE;
1206 gtk_tree_path_free(tpath);
1210 static void filter_store_sidecar_cb(GtkCellRendererToggle *renderer,
1211 gchar *path_str, gpointer data)
1213 GtkWidget *model = data;
1218 tpath = gtk_tree_path_new_from_string(path_str);
1219 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1220 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1222 fe->allow_sidecar = !fe->allow_sidecar;
1223 if (fe->allow_sidecar) fe->writable = FALSE;
1225 gtk_tree_path_free(tpath);
1229 static void filter_set_func(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
1230 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
1234 gtk_tree_model_get(tree_model, iter, 0, &fe, -1);
1236 switch (GPOINTER_TO_INT(data))
1239 g_object_set(GTK_CELL_RENDERER(cell),
1240 "active", fe->enabled, NULL);
1243 g_object_set(GTK_CELL_RENDERER(cell),
1244 "text", fe->extensions, NULL);
1246 case FE_DESCRIPTION:
1247 g_object_set(GTK_CELL_RENDERER(cell),
1248 "text", fe->description, NULL);
1251 g_object_set(GTK_CELL_RENDERER(cell),
1252 "text", _(format_class_list[fe->file_class]), NULL);
1255 g_object_set(GTK_CELL_RENDERER(cell),
1256 "active", fe->writable, NULL);
1258 case FE_ALLOW_SIDECAR:
1259 g_object_set(GTK_CELL_RENDERER(cell),
1260 "active", fe->allow_sidecar, NULL);
1265 static gboolean filter_add_scroll(gpointer data)
1269 GtkCellRenderer *cell;
1270 GtkTreeViewColumn *column;
1273 rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(filter_store), NULL);
1274 path = gtk_tree_path_new_from_indices(rows-1, -1);
1276 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data), 0);
1278 list_cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column));
1279 cell = g_list_last(list_cells)->data;
1281 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1282 path, column, FALSE, 0.0, 0.0 );
1283 gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(data),
1284 path, column, cell, TRUE);
1286 gtk_tree_path_free(path);
1287 g_list_free(list_cells);
1292 static void filter_add_cb(GtkWidget *widget, gpointer data)
1294 filter_add_unique("description", ".new", FORMAT_CLASS_IMAGE, TRUE, FALSE, TRUE);
1295 filter_store_populate();
1297 g_idle_add((GSourceFunc)filter_add_scroll, data);
1300 static void filter_remove_cb(GtkWidget *widget, gpointer data)
1302 GtkWidget *filter_view = data;
1303 GtkTreeSelection *selection;
1307 if (!filter_store) return;
1308 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1309 if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) return;
1310 gtk_tree_model_get(GTK_TREE_MODEL(filter_store), &iter, 0, &fe, -1);
1313 filter_remove_entry(fe);
1315 filter_store_populate();
1318 static gboolean filter_default_ok_scroll(GtkTreeView *data)
1322 GtkTreeViewColumn *column;
1324 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(filter_store), &iter);
1325 path = gtk_tree_model_get_path(GTK_TREE_MODEL(filter_store), &iter);
1326 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1328 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1332 gtk_tree_path_free(path);
1337 static void filter_default_ok_cb(GenericDialog *gd, gpointer data)
1340 filter_add_defaults();
1342 filter_store_populate();
1344 g_idle_add((GSourceFunc)filter_default_ok_scroll, gd->data);
1347 static void dummy_cancel_cb(GenericDialog *gd, gpointer data)
1349 /* no op, only so cancel button appears */
1352 static void filter_default_cb(GtkWidget *widget, gpointer data)
1356 gd = generic_dialog_new(_("Reset filters"),
1357 "reset_filter", widget, TRUE,
1358 dummy_cancel_cb, data);
1359 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset filters"),
1360 _("This will reset the file filters to the defaults.\nContinue?"), TRUE);
1361 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, filter_default_ok_cb, TRUE);
1362 gtk_widget_show(gd->dialog);
1365 static void filter_disable_cb(GtkWidget *widget, gpointer data)
1367 GtkWidget *frame = data;
1369 gtk_widget_set_sensitive(frame,
1370 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
1373 static void safe_delete_view_cb(GtkWidget *widget, gpointer data)
1375 layout_set_path(NULL, gtk_entry_get_text(GTK_ENTRY(safe_delete_path_entry)));
1378 static void safe_delete_clear_ok_cb(GenericDialog *gd, gpointer data)
1380 file_util_trash_clear();
1383 static void safe_delete_clear_cb(GtkWidget *widget, gpointer data)
1387 gd = generic_dialog_new(_("Clear trash"),
1388 "clear_trash", widget, TRUE,
1389 dummy_cancel_cb, NULL);
1390 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear trash"),
1391 _("This will remove the trash contents."), FALSE);
1392 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, safe_delete_clear_ok_cb, TRUE);
1393 entry = gtk_entry_new();
1394 gtk_widget_set_can_focus(entry, FALSE);
1395 gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE);
1396 if (options->file_ops.safe_delete_path) gtk_entry_set_text(GTK_ENTRY(entry), options->file_ops.safe_delete_path);
1397 gtk_box_pack_start(GTK_BOX(gd->vbox), entry, FALSE, FALSE, 0);
1398 gtk_widget_show(entry);
1399 gtk_widget_show(gd->dialog);
1402 static void image_overlay_template_view_changed_cb(GtkWidget *widget, gpointer data)
1404 GtkWidget *pTextView;
1405 GtkTextBuffer *pTextBuffer;
1409 pTextView = GTK_WIDGET(data);
1411 pTextBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pTextView));
1412 gtk_text_buffer_get_start_iter(pTextBuffer, &iStart);
1413 gtk_text_buffer_get_end_iter(pTextBuffer, &iEnd);
1415 set_image_overlay_template_string(&c_options->image_overlay.template_string,
1416 gtk_text_buffer_get_text(pTextBuffer, &iStart, &iEnd, TRUE));
1419 static void image_overlay_default_template_ok_cb(GenericDialog *gd, gpointer data)
1421 GtkTextView *text_view = data;
1422 GtkTextBuffer *buffer;
1424 set_default_image_overlay_template_string(&options->image_overlay.template_string);
1425 if (!configwindow) return;
1427 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
1428 gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1431 static void image_overlay_default_template_cb(GtkWidget *widget, gpointer data)
1435 gd = generic_dialog_new(_("Reset image overlay template string"),
1436 "reset_image_overlay_template_string", widget, TRUE,
1437 dummy_cancel_cb, data);
1438 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset image overlay template string"),
1439 _("This will reset the image overlay template string to the default.\nContinue?"), TRUE);
1440 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, image_overlay_default_template_ok_cb, TRUE);
1441 gtk_widget_show(gd->dialog);
1444 static void image_overlay_help_cb(GtkWidget *widget, gpointer data)
1446 help_window_show("GuideOptionsOSD.html");
1449 static void image_overlay_set_font_cb(GtkWidget *widget, gpointer data)
1451 #if GTK_CHECK_VERSION(3,4,0)
1454 PangoFontDescription *font_desc;
1456 dialog = gtk_font_chooser_dialog_new("Image Overlay Font", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1457 gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), options->image_overlay.font);
1459 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1461 font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
1462 font = pango_font_description_to_string(font_desc);
1463 g_free(c_options->image_overlay.font);
1464 c_options->image_overlay.font = g_strdup(font);
1468 gtk_widget_destroy(dialog);
1472 font = gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget));
1473 c_options->image_overlay.font = g_strdup(font);
1477 static void image_overlay_set_text_colour_cb(GtkWidget *widget, gpointer data)
1480 #if GTK_CHECK_VERSION(3,4,0)
1483 dialog = gtk_color_chooser_dialog_new("Image Overlay Text Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1484 colour.red = options->image_overlay.text_red;
1485 colour.green = options->image_overlay.text_green;
1486 colour.blue = options->image_overlay.text_blue;
1487 colour.alpha = options->image_overlay.text_alpha;
1488 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1489 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1491 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1493 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1494 c_options->image_overlay.text_red = colour.red*255;
1495 c_options->image_overlay.text_green = colour.green*255;
1496 c_options->image_overlay.text_blue = colour.blue*255;
1497 c_options->image_overlay.text_alpha = colour.alpha*255;
1499 gtk_widget_destroy(dialog);
1502 GtkColorSelection *colorsel;
1504 dialog = gtk_color_selection_dialog_new("Image Overlay Text Colour");
1505 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1506 colour.red = options->image_overlay.text_red*257;
1507 colour.green = options->image_overlay.text_green*257;
1508 colour.blue = options->image_overlay.text_blue*257;
1509 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1510 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1511 gtk_color_selection_set_current_color(colorsel, &colour);
1512 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.text_alpha*257);
1514 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1516 gtk_color_selection_get_current_color(colorsel, &colour);
1517 c_options->image_overlay.text_red = colour.red/257;
1518 c_options->image_overlay.text_green = colour.green/257;
1519 c_options->image_overlay.text_blue = colour.blue/257;
1520 c_options->image_overlay.text_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1522 gtk_widget_destroy (dialog);
1527 static void image_overlay_set_background_colour_cb(GtkWidget *widget, gpointer data)
1530 #if GTK_CHECK_VERSION(3,4,0)
1533 dialog = gtk_color_chooser_dialog_new("Image Overlay Background Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1534 colour.red = options->image_overlay.background_red;
1535 colour.green = options->image_overlay.background_green;
1536 colour.blue = options->image_overlay.background_blue;
1537 colour.alpha = options->image_overlay.background_alpha;
1538 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1539 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1541 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1543 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1544 c_options->image_overlay.background_red = colour.red*255;
1545 c_options->image_overlay.background_green = colour.green*255;
1546 c_options->image_overlay.background_blue = colour.blue*255;
1547 c_options->image_overlay.background_alpha = colour.alpha*255;
1549 gtk_widget_destroy(dialog);
1552 GtkColorSelection *colorsel;
1554 dialog = gtk_color_selection_dialog_new("Image Overlay Background Colour");
1555 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1556 colour.red = options->image_overlay.background_red*257;
1557 colour.green = options->image_overlay.background_green*257;
1558 colour.blue = options->image_overlay.background_blue*257;
1559 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1560 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1561 gtk_color_selection_set_current_color(colorsel, &colour);
1562 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.background_alpha*257);
1564 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1566 gtk_color_selection_get_current_color(colorsel, &colour);
1567 c_options->image_overlay.background_red = colour.red/257;
1568 c_options->image_overlay.background_green = colour.green/257;
1569 c_options->image_overlay.background_blue = colour.blue/257;
1570 c_options->image_overlay.background_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1572 gtk_widget_destroy(dialog);
1576 static void accel_store_populate(void)
1579 GList *groups, *actions;
1581 const gchar *accel_path;
1585 if (!accel_store || !layout_window_list || !layout_window_list->data) return;
1587 gtk_tree_store_clear(accel_store);
1588 lw = layout_window_list->data; /* get the actions from the first window, it should not matter, they should be the same in all windows */
1590 g_assert(lw && lw->ui_manager);
1591 groups = gtk_ui_manager_get_action_groups(lw->ui_manager);
1594 actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
1597 action = GTK_ACTION(actions->data);
1598 accel_path = gtk_action_get_accel_path(action);
1599 if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
1601 gchar *label, *label2, *tooltip, *accel;
1602 g_object_get(action,
1603 "tooltip", &tooltip,
1607 if (pango_parse_markup(label, -1, '_', NULL, &label2, NULL, NULL) && label2)
1613 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1617 gtk_tree_store_append(accel_store, &iter, NULL);
1618 gtk_tree_store_set(accel_store, &iter,
1621 AE_TOOLTIP, tooltip ? tooltip : "",
1622 AE_ACCEL, accel_path,
1630 actions = actions->next;
1633 groups = groups->next;
1637 static void accel_store_cleared_cb(GtkCellRendererAccel *accel, gchar *path_string, gpointer user_data)
1642 static gboolean accel_remove_key_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1644 gchar *accel1 = data;
1649 gtk_tree_model_get(model, iter, AE_KEY, &accel2, -1);
1651 gtk_accelerator_parse(accel1, &key1.accel_key, &key1.accel_mods);
1652 gtk_accelerator_parse(accel2, &key2.accel_key, &key2.accel_mods);
1654 if (key1.accel_key == key2.accel_key && key1.accel_mods == key2.accel_mods)
1656 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1657 DEBUG_1("accelerator key '%s' is already used, removing.", accel1);
1666 static void accel_store_edited_cb(GtkCellRendererAccel *accel, gchar *path_string, guint accel_key, GdkModifierType accel_mods, guint hardware_keycode, gpointer user_data)
1668 GtkTreeModel *model = (GtkTreeModel *)accel_store;
1672 GtkAccelKey old_key, key;
1673 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
1675 gtk_tree_model_get_iter(model, &iter, path);
1676 gtk_tree_model_get(model, &iter, AE_ACCEL, &accel_path, -1);
1678 /* test if the accelerator can be stored without conflicts*/
1679 gtk_accel_map_lookup_entry(accel_path, &old_key);
1681 /* change the key and read it back (change may fail on keys hardcoded in gtk)*/
1682 gtk_accel_map_change_entry(accel_path, accel_key, accel_mods, TRUE);
1683 gtk_accel_map_lookup_entry(accel_path, &key);
1685 /* restore the original for now, the key will be really changed when the changes are confirmed */
1686 gtk_accel_map_change_entry(accel_path, old_key.accel_key, old_key.accel_mods, TRUE);
1688 acc = gtk_accelerator_name(key.accel_key, key.accel_mods);
1689 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, acc);
1691 gtk_tree_store_set(accel_store, &iter, AE_KEY, acc, -1);
1692 gtk_tree_path_free(path);
1696 static gboolean accel_default_scroll(GtkTreeView *data)
1700 GtkTreeViewColumn *column;
1702 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(accel_store), &iter);
1703 path = gtk_tree_model_get_path(GTK_TREE_MODEL(accel_store), &iter);
1704 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1706 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1710 gtk_tree_path_free(path);
1715 static void accel_default_cb(GtkWidget *widget, gpointer data)
1717 accel_store_populate();
1719 g_idle_add((GSourceFunc)accel_default_scroll, data);
1722 void accel_remove_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1724 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1727 void accel_reset_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1730 gchar *accel_path, *accel;
1732 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, -1);
1733 gtk_accel_map_lookup_entry(accel_path, &key);
1734 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1736 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, accel);
1738 gtk_tree_store_set(accel_store, iter, AE_KEY, accel, -1);
1743 static void accel_reset_cb(GtkWidget *widget, gpointer data)
1745 GtkTreeSelection *selection;
1747 if (!accel_store) return;
1748 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data));
1749 gtk_tree_selection_selected_foreach(selection, &accel_reset_selection, NULL);
1754 static GtkWidget *scrolled_notebook_page(GtkWidget *notebook, const gchar *title)
1758 GtkWidget *scrolled;
1759 GtkWidget *viewport;
1761 scrolled = gtk_scrolled_window_new(NULL, NULL);
1762 gtk_container_set_border_width(GTK_CONTAINER(scrolled), PREF_PAD_BORDER);
1763 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1764 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1765 label = gtk_label_new(title);
1766 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, label);
1767 gtk_widget_show(scrolled);
1769 viewport = gtk_viewport_new(NULL, NULL);
1770 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1771 gtk_container_add(GTK_CONTAINER(scrolled), viewport);
1772 gtk_widget_show(viewport);
1774 vbox = gtk_vbox_new(FALSE, 0);
1775 gtk_container_add(GTK_CONTAINER(viewport), vbox);
1776 gtk_widget_show(vbox);
1781 static void cache_standard_cb(GtkWidget *widget, gpointer data)
1783 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1785 c_options->thumbnails.spec_standard =TRUE;
1786 c_options->thumbnails.cache_into_dirs = FALSE;
1790 static void cache_geeqie_cb(GtkWidget *widget, gpointer data)
1792 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1794 c_options->thumbnails.spec_standard =FALSE;
1795 c_options->thumbnails.cache_into_dirs = FALSE;
1799 static void cache_local_cb(GtkWidget *widget, gpointer data)
1801 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1803 c_options->thumbnails.cache_into_dirs = TRUE;
1804 c_options->thumbnails.spec_standard =FALSE;
1808 static void help_search_engine_entry_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1809 GdkEvent *event, gpointer userdata)
1811 if (pos == GTK_ENTRY_ICON_PRIMARY)
1813 gtk_entry_set_text(GTK_ENTRY(userdata), HELP_SEARCH_ENGINE);
1817 gtk_entry_set_text(GTK_ENTRY(userdata), "");
1821 static void star_rating_star_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1822 GdkEvent *event, gpointer userdata)
1824 gchar *rating_symbol;
1826 if (pos == GTK_ENTRY_ICON_PRIMARY)
1828 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_STAR);
1829 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1830 g_free(rating_symbol);
1834 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1835 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1836 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1840 static void star_rating_rejected_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1841 GdkEvent *event, gpointer userdata)
1843 gchar *rating_symbol;
1845 if (pos == GTK_ENTRY_ICON_PRIMARY)
1847 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_REJECTED);
1848 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1849 g_free(rating_symbol);
1853 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1854 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1855 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1859 static guint star_rating_symbol_test(GtkWidget *widget, gpointer data)
1861 GtkContainer *hbox = data;
1862 GString *str = g_string_new(NULL);
1863 GtkEntry *hex_code_entry;
1864 gchar *hex_code_full;
1867 guint64 hex_value = 0;
1869 list = gtk_container_get_children(hbox);
1871 hex_code_entry = g_list_nth_data(list, 2);
1872 hex_code_full = g_strdup(gtk_entry_get_text(hex_code_entry));
1874 hex_code = g_strsplit(hex_code_full, "+", 2);
1875 if (hex_code[0] && hex_code[1])
1877 hex_value = strtoull(hex_code[1], NULL, 16);
1879 if (!hex_value || hex_value > 0x10FFFF)
1881 hex_value = 0x003F; // Unicode 'Question Mark'
1883 str = g_string_append_unichar(str, (gunichar)hex_value);
1884 gtk_label_set_text(g_list_nth_data(list, 1), str->str);
1886 g_strfreev(hex_code);
1887 g_string_free(str, TRUE);
1888 g_free(hex_code_full);
1893 static void star_rating_star_test_cb(GtkWidget *widget, gpointer data)
1895 guint64 star_symbol;
1897 star_symbol = star_rating_symbol_test(widget, data);
1898 c_options->star_rating.star = star_symbol;
1901 static void star_rating_rejected_test_cb(GtkWidget *widget, gpointer data)
1903 guint64 rejected_symbol;
1905 rejected_symbol = star_rating_symbol_test(widget, data);
1906 c_options->star_rating.rejected = rejected_symbol;
1909 /* general options tab */
1910 static void timezone_database_install_cb(GtkWidget *widget, gpointer data);
1911 typedef struct _TZData TZData;
1915 GCancellable *cancellable;
1917 GtkWidget *progress;
1919 GFile *timezone_database_gq;
1920 gchar *timezone_database_user;
1923 static void config_tab_general(GtkWidget *notebook)
1928 GtkWidget *group_frame;
1929 GtkWidget *subgroup;
1931 GtkWidget *ct_button;
1934 gint hours, minutes, remainder;
1936 GtkWidget *star_rating_entry;
1938 gchar *rating_symbol;
1941 GNetworkMonitor *net_mon;
1942 GSocketConnectable *geeqie_org;
1943 gboolean internet_available;
1946 vbox = scrolled_notebook_page(notebook, _("General"));
1948 group = pref_group_new(vbox, FALSE, _("Thumbnails"), GTK_ORIENTATION_VERTICAL);
1950 table = pref_table_new(group, 2, 2, FALSE, FALSE);
1951 add_thumb_size_menu(table, 0, 0, _("Size:"));
1952 add_quality_menu(table, 0, 1, _("Quality:"), options->thumbnails.quality, &c_options->thumbnails.quality);
1954 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1955 pref_label_new(hbox, _("Custom size: "));
1956 pref_spin_new_int(hbox, _("Width:"), NULL, 1, 512, 1, options->thumbnails.max_width, &c_options->thumbnails.max_width);
1957 pref_spin_new_int(hbox, _("Height:"), NULL, 1, 512, 1, options->thumbnails.max_height, &c_options->thumbnails.max_height);
1959 ct_button = pref_checkbox_new_int(group, _("Cache thumbnails and sim. files"),
1960 options->thumbnails.enable_caching, &c_options->thumbnails.enable_caching);
1962 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1963 pref_checkbox_link_sensitivity(ct_button, subgroup);
1965 c_options->thumbnails.spec_standard = options->thumbnails.spec_standard;
1966 c_options->thumbnails.cache_into_dirs = options->thumbnails.cache_into_dirs;
1967 group_frame = pref_frame_new(subgroup, TRUE, _("Use Geeqie thumbnail style and cache"),
1968 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1969 button = pref_radiobutton_new(group_frame, NULL, get_thumbnails_cache_dir(),
1970 !options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1971 G_CALLBACK(cache_geeqie_cb), NULL);
1973 group_frame = pref_frame_new(subgroup, TRUE,
1974 _("Store thumbnails local to image folder (non-standard)"),
1975 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1976 pref_radiobutton_new(group_frame, button, "*/.thumbnails",
1977 !options->thumbnails.spec_standard && options->thumbnails.cache_into_dirs,
1978 G_CALLBACK(cache_local_cb), NULL);
1980 group_frame = pref_frame_new(subgroup, TRUE,
1981 _("Use standard thumbnail style and cache, shared with other applications"),
1982 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1983 pref_radiobutton_new(group_frame, button, get_thumbnails_standard_cache_dir(),
1984 options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1985 G_CALLBACK(cache_standard_cb), NULL);
1987 pref_checkbox_new_int(group, _("Use EXIF thumbnails when available (EXIF thumbnails may be outdated)"),
1988 options->thumbnails.use_exif, &c_options->thumbnails.use_exif);
1990 pref_checkbox_new_int(group, _("Thumbnail color management"),
1991 options->thumbnails.use_color_management, &c_options->thumbnails.use_color_management);
1993 spin = pref_spin_new_int(group, _("Collection preview:"), NULL,
1995 options->thumbnails.collection_preview, &c_options->thumbnails.collection_preview);
1996 gtk_widget_set_tooltip_text(spin, _("The maximum number of thumbnails shown in a Collection preview montage"));
1998 #ifdef HAVE_FFMPEGTHUMBNAILER_METADATA
1999 pref_checkbox_new_int(group, _("Use embedded metadata in video files as thumbnails when available"),
2000 options->thumbnails.use_ft_metadata, &c_options->thumbnails.use_ft_metadata);
2002 // pref_checkbox_new_int(group, _("Ignore embedded metadata if size is too small"),
2003 // options->thumbnails.use_ft_metadata_small, &c_options->thumbnails.use_ft_metadata_small);
2006 pref_spacer(group, PREF_PAD_GROUP);
2008 group = pref_group_new(vbox, FALSE, _("Star Rating"), GTK_ORIENTATION_VERTICAL);
2010 c_options->star_rating.star = options->star_rating.star;
2011 c_options->star_rating.rejected = options->star_rating.rejected;
2013 str = g_string_new(NULL);
2014 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2015 pref_label_new(hbox, _("Star character: "));
2016 str = g_string_append_unichar(str, options->star_rating.star);
2017 pref_label_new(hbox, g_strdup(str->str));
2018 rating_symbol = g_strdup_printf("U+%X", options->star_rating.star);
2019 star_rating_entry = gtk_entry_new();
2020 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
2021 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
2022 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
2023 gtk_widget_show(star_rating_entry);
2024 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
2025 G_CALLBACK(star_rating_star_test_cb), hbox);
2026 gtk_widget_set_tooltip_text(button, _("Display selected character"));
2027 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2028 gtk_widget_show(button);
2029 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."));
2030 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2031 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2032 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2033 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2034 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2035 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2036 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2037 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2038 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
2039 G_CALLBACK(star_rating_star_icon_cb),
2042 g_string_free(str, TRUE);
2043 g_free(rating_symbol);
2045 str = g_string_new(NULL);
2046 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2047 pref_label_new(hbox, _("Rejected character: "));
2048 str = g_string_append_unichar(str, options->star_rating.rejected);
2049 pref_label_new(hbox, g_strdup(str->str));
2050 rating_symbol = g_strdup_printf("U+%X", options->star_rating.rejected);
2051 star_rating_entry = gtk_entry_new();
2052 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
2053 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
2054 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
2055 gtk_widget_show(star_rating_entry);
2056 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
2057 G_CALLBACK(star_rating_rejected_test_cb), hbox);
2058 gtk_widget_set_tooltip_text(button, _("Display selected character"));
2059 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2060 gtk_widget_show(button);
2061 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."));
2062 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2063 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2064 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2065 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2066 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2067 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2068 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2069 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2070 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
2071 G_CALLBACK(star_rating_rejected_icon_cb),
2074 g_string_free(str, TRUE);
2075 g_free(rating_symbol);
2077 pref_spacer(group, PREF_PAD_GROUP);
2079 group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
2081 c_options->slideshow.delay = options->slideshow.delay;
2082 hours = options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2083 remainder = options->slideshow.delay % (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2084 minutes = remainder / (60 * SLIDESHOW_SUBSECOND_PRECISION);
2085 seconds = (gdouble)(remainder % (60 * SLIDESHOW_SUBSECOND_PRECISION)) /
2086 SLIDESHOW_SUBSECOND_PRECISION;
2088 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2090 spin = pref_spin_new(hbox, _("Delay between image change hrs:mins:secs.dec"), NULL,
2092 options->slideshow.delay ? hours : 0.0,
2093 G_CALLBACK(slideshow_delay_hours_cb), NULL);
2094 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2095 spin = pref_spin_new(hbox, ":" , NULL,
2097 options->slideshow.delay ? minutes: 0.0,
2098 G_CALLBACK(slideshow_delay_minutes_cb), NULL);
2099 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2100 spin = pref_spin_new(hbox, ":", NULL,
2101 SLIDESHOW_MIN_SECONDS, 59, 1.0, 1,
2102 options->slideshow.delay ? seconds : 10.0,
2103 G_CALLBACK(slideshow_delay_seconds_cb), NULL);
2104 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2106 pref_checkbox_new_int(group, _("Random"), options->slideshow.random, &c_options->slideshow.random);
2107 pref_checkbox_new_int(group, _("Repeat"), options->slideshow.repeat, &c_options->slideshow.repeat);
2109 pref_spacer(group, PREF_PAD_GROUP);
2111 group = pref_group_new(vbox, FALSE, _("Image loading and caching"), GTK_ORIENTATION_VERTICAL);
2113 pref_spin_new_int(group, _("Decoded image cache size (MiB):"), NULL,
2114 0, 99999, 1, options->image.image_cache_max, &c_options->image.image_cache_max);
2115 pref_checkbox_new_int(group, _("Preload next image"),
2116 options->image.enable_read_ahead, &c_options->image.enable_read_ahead);
2118 pref_checkbox_new_int(group, _("Refresh on file change"),
2119 options->update_on_time_change, &c_options->update_on_time_change);
2122 pref_spacer(group, PREF_PAD_GROUP);
2124 group = pref_group_new(vbox, FALSE, _("Expand menu and toolbar"), GTK_ORIENTATION_VERTICAL);
2126 pref_checkbox_new_int(group, _("Expand menu and toolbar (NOTE! Geeqie must be restarted for change to take effect)"),
2127 options->expand_menu_toolbar, &c_options->expand_menu_toolbar);
2128 gtk_widget_set_tooltip_text(group, _("Expand the menu and toolbar to the full width of the window"));
2130 pref_spacer(group, PREF_PAD_GROUP);
2132 group = pref_group_new(vbox, FALSE, _("Info sidebar heights"), GTK_ORIENTATION_VERTICAL);
2133 pref_label_new(group, _("NOTE! Geeqie must be restarted for changes to take effect"));
2134 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2135 pref_spin_new_int(hbox, _("Keywords:"), NULL,
2137 options->info_keywords.height, &c_options->info_keywords.height);
2138 pref_spin_new_int(hbox, _("Title:"), NULL,
2140 options->info_title.height, &c_options->info_title.height);
2141 pref_spin_new_int(hbox, _("Comment:"), NULL,
2143 options->info_comment.height, &c_options->info_comment.height);
2144 pref_spin_new_int(hbox, _("Rating:"), NULL,
2146 options->info_rating.height, &c_options->info_rating.height);
2148 pref_spacer(group, PREF_PAD_GROUP);
2150 group = pref_group_new(vbox, FALSE, _("Show predefined keyword tree"), GTK_ORIENTATION_VERTICAL);
2152 pref_checkbox_new_int(group, _("Show predefined keyword tree (NOTE! Geeqie must be restarted for change to take effect)"),
2153 options->show_predefined_keyword_tree, &c_options->show_predefined_keyword_tree);
2155 pref_spacer(group, PREF_PAD_GROUP);
2157 net_mon = g_network_monitor_get_default();
2158 geeqie_org = g_network_address_parse_uri(GQ_WEBSITE, 80, NULL);
2159 internet_available = g_network_monitor_can_reach(net_mon, geeqie_org, NULL, NULL);
2160 g_object_unref(geeqie_org);
2162 group = pref_group_new(vbox, FALSE, _("Timezone database"), GTK_ORIENTATION_VERTICAL);
2163 hbox = pref_box_new(group, TRUE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2165 if (!internet_available)
2167 gtk_widget_set_sensitive(group, FALSE);
2170 tz = g_new0(TZData, 1);
2172 path = path_from_utf8(TIMEZONE_DATABASE);
2173 basename = g_path_get_basename(path);
2174 tz->timezone_database_user = g_build_filename(get_rc_dir(), basename, NULL);
2178 if (isfile(tz->timezone_database_user))
2180 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Update"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2184 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Install"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2187 if (!internet_available)
2189 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"));
2193 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"));
2195 gtk_widget_show(button);
2197 pref_spacer(group, PREF_PAD_GROUP);
2199 group = pref_group_new(vbox, FALSE, _("On-line help search engine"), GTK_ORIENTATION_VERTICAL);
2201 help_search_engine_entry = gtk_entry_new();
2202 gtk_entry_set_text(GTK_ENTRY(help_search_engine_entry), options->help_search_engine);
2203 gtk_box_pack_start(GTK_BOX(group), help_search_engine_entry, FALSE, FALSE, 0);
2204 gtk_widget_show(help_search_engine_entry);
2206 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"));
2208 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2209 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2210 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2211 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2212 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2213 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2214 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2215 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2216 g_signal_connect(GTK_ENTRY(help_search_engine_entry), "icon-press",
2217 G_CALLBACK(help_search_engine_entry_icon_cb),
2218 help_search_engine_entry);
2222 static void config_tab_image(GtkWidget *notebook)
2227 GtkWidget *ct_button;
2228 GtkWidget *enlargement_button;
2231 GtkWidget *two_pass;
2233 GtkWidget *gpu_accel;
2236 vbox = scrolled_notebook_page(notebook, _("Image"));
2238 group = pref_group_new(vbox, FALSE, _("Zoom"), GTK_ORIENTATION_VERTICAL);
2240 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2241 add_quality_menu(table, 0, 0, _("Quality:"), options->image.zoom_quality, &c_options->image.zoom_quality);
2242 if (options->image.use_clutter_renderer && !options->disable_gpu)
2244 gtk_widget_set_sensitive(table, FALSE);
2248 gpu_accel = pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library (Requires restart)"),
2249 options->image.use_clutter_renderer, &c_options->image.use_clutter_renderer);
2250 if (options->disable_gpu && !options->override_disable_gpu)
2252 gtk_widget_set_sensitive(gpu_accel, FALSE);
2256 two_pass = pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"),
2257 options->image.zoom_2pass, &c_options->image.zoom_2pass);
2258 if (options->image.use_clutter_renderer && !options->disable_gpu)
2260 gtk_widget_set_sensitive(two_pass, FALSE);
2263 c_options->image.zoom_increment = options->image.zoom_increment;
2264 spin = pref_spin_new(group, _("Zoom increment:"), NULL,
2265 0.01, 4.0, 0.01, 2, (gdouble)options->image.zoom_increment / 100.0,
2266 G_CALLBACK(zoom_increment_cb), NULL);
2267 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2269 group = pref_group_new(vbox, FALSE, _("Fit image to window"), GTK_ORIENTATION_VERTICAL);
2271 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2272 enlargement_button = pref_checkbox_new_int(hbox, _("Allow enlargement of image (max. size in %)"),
2273 options->image.zoom_to_fit_allow_expand, &c_options->image.zoom_to_fit_allow_expand);
2274 spin = pref_spin_new_int(hbox, NULL, NULL,
2276 options->image.max_enlargement_size, &c_options->image.max_enlargement_size);
2277 pref_checkbox_link_sensitivity(enlargement_button, spin);
2278 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."));
2280 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2281 ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (% of actual window):"),
2282 options->image.limit_autofit_size, &c_options->image.limit_autofit_size);
2283 spin = pref_spin_new_int(hbox, NULL, NULL,
2285 options->image.max_autofit_size, &c_options->image.max_autofit_size);
2286 pref_checkbox_link_sensitivity(ct_button, spin);
2287 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."));
2289 group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
2291 pref_checkbox_new_int(group, _("Use custom border color in window mode"),
2292 options->image.use_custom_border_color, &c_options->image.use_custom_border_color);
2294 pref_checkbox_new_int(group, _("Use custom border color in fullscreen mode"),
2295 options->image.use_custom_border_color_in_fullscreen, &c_options->image.use_custom_border_color_in_fullscreen);
2297 pref_color_button_new(group, _("Border color"), &options->image.border_color,
2298 G_CALLBACK(pref_color_button_set_cb), &c_options->image.border_color);
2300 c_options->image.border_color = options->image.border_color;
2302 pref_color_button_new(group, _("Alpha channel color 1"), &options->image.alpha_color_1,
2303 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_1);
2305 pref_color_button_new(group, _("Alpha channel color 2"), &options->image.alpha_color_2,
2306 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_2);
2308 c_options->image.alpha_color_1 = options->image.alpha_color_1;
2309 c_options->image.alpha_color_2 = options->image.alpha_color_2;
2311 group = pref_group_new(vbox, FALSE, _("Convenience"), GTK_ORIENTATION_VERTICAL);
2313 pref_checkbox_new_int(group, _("Auto rotate proofs using Exif information"),
2314 options->image.exif_proof_rotate_enable, &c_options->image.exif_proof_rotate_enable);
2319 static void save_default_window_layout_cb(GtkWidget *widget, gpointer data)
2321 LayoutWindow *lw = NULL;
2322 gchar *default_path;
2325 /* Get current lw */
2328 tmp_id = lw->options.id;
2329 lw->options.id = g_strdup("lw_default");
2331 default_path = g_build_filename(get_rc_dir(), DEFAULT_WINDOW_LAYOUT, NULL);
2332 save_default_layout_options_to_file(default_path, options, lw);
2333 g_free(lw->options.id);
2334 lw->options.id = tmp_id;
2335 g_free(default_path);
2338 #if GTK_CHECK_VERSION(3,22,0)
2339 static gboolean popover_cb(gpointer data)
2341 GtkPopover *popover = data;
2343 gtk_popover_popdown(popover);
2348 static void default_layout_changed_cb(GtkWidget *button, GtkPopover *popover)
2350 gtk_popover_popup(popover);
2352 g_timeout_add(2000, popover_cb, popover);
2355 static GtkWidget *create_popover(GtkWidget *parent, GtkWidget *child, GtkPositionType pos)
2359 popover = gtk_popover_new(parent);
2360 gtk_popover_set_position(GTK_POPOVER (popover), pos);
2361 gtk_container_add (GTK_CONTAINER(popover), child);
2362 gtk_container_set_border_width(GTK_CONTAINER (popover), 6);
2363 gtk_widget_show (child);
2369 static void config_tab_windows(GtkWidget *notebook)
2374 GtkWidget *subgroup;
2376 GtkWidget *ct_button;
2379 vbox = scrolled_notebook_page(notebook, _("Windows"));
2381 group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
2383 ct_button = pref_checkbox_new_int(group, _("Remember session"),
2384 options->save_window_positions, &c_options->save_window_positions);
2386 button = pref_checkbox_new_int(group, _("Use saved window positions also for new windows"),
2387 options->use_saved_window_positions_for_new_windows, &c_options->use_saved_window_positions_for_new_windows);
2388 pref_checkbox_link_sensitivity(ct_button, button);
2390 button = pref_checkbox_new_int(group, _("Remember window workspace"),
2391 options->save_window_workspace, &c_options->save_window_workspace);
2392 pref_checkbox_link_sensitivity(ct_button, button);
2394 pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
2395 options->tools_restore_state, &c_options->tools_restore_state);
2397 pref_checkbox_new_int(group, _("Remember dialog window positions"),
2398 options->save_dialog_window_positions, &c_options->save_dialog_window_positions);
2400 pref_checkbox_new_int(group, _("Show window IDs"),
2401 options->show_window_ids, &c_options->show_window_ids);
2403 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2404 pref_label_new(subgroup, _("Use current layout for default: "));
2405 button = pref_button_new(subgroup, NULL, _("Set"), FALSE, G_CALLBACK(save_default_window_layout_cb), NULL);
2407 #if GTK_CHECK_VERSION(3,22,0)
2410 popover = create_popover(button, gtk_label_new(_("Current window layout\nhas been set as default")), GTK_POS_TOP);
2411 gtk_popover_set_modal(GTK_POPOVER (popover), FALSE);
2412 g_signal_connect(button, "clicked", G_CALLBACK(default_layout_changed_cb), popover);
2415 group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
2417 pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
2418 options->image.fit_window_to_image, &c_options->image.fit_window_to_image);
2420 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2421 ct_button = pref_checkbox_new_int(hbox, _("Limit size when auto-sizing window (%):"),
2422 options->image.limit_window_size, &c_options->image.limit_window_size);
2423 spin = pref_spin_new_int(hbox, NULL, NULL,
2425 options->image.max_window_size, &c_options->image.max_window_size);
2426 pref_checkbox_link_sensitivity(ct_button, spin);
2428 group = pref_group_new(vbox, FALSE, _("Full screen"), GTK_ORIENTATION_VERTICAL);
2430 c_options->fullscreen.screen = options->fullscreen.screen;
2431 c_options->fullscreen.above = options->fullscreen.above;
2432 hbox = fullscreen_prefs_selection_new(_("Location:"), &c_options->fullscreen.screen, &c_options->fullscreen.above);
2433 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2434 gtk_widget_show(hbox);
2436 pref_checkbox_new_int(group, _("Smooth image flip"),
2437 options->fullscreen.clean_flip, &c_options->fullscreen.clean_flip);
2438 pref_checkbox_new_int(group, _("Disable screen saver"),
2439 options->fullscreen.disable_saver, &c_options->fullscreen.disable_saver);
2442 #define PRE_FORMATTED_COLUMNS 5
2443 static void config_tab_osd(GtkWidget *notebook)
2449 GtkWidget *image_overlay_template_view;
2450 GtkWidget *scrolled;
2451 GtkWidget *scrolled_pre_formatted;
2452 GtkTextBuffer *buffer;
2454 GtkWidget *subgroup;
2456 vbox = scrolled_notebook_page(notebook, _("OSD"));
2458 image_overlay_template_view = gtk_text_view_new();
2460 group = pref_group_new(vbox, FALSE, _("Overlay Screen Display"), GTK_ORIENTATION_VERTICAL);
2462 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2464 scrolled_pre_formatted = osd_new(PRE_FORMATTED_COLUMNS, image_overlay_template_view);
2465 gtk_widget_set_size_request(scrolled_pre_formatted, 200, 150);
2466 gtk_box_pack_start(GTK_BOX(subgroup), scrolled_pre_formatted, FALSE, FALSE, 0);
2467 gtk_widget_show(scrolled_pre_formatted);
2468 gtk_widget_show(subgroup);
2470 pref_line(group, PREF_PAD_GAP);
2472 pref_label_new(group, _("Image overlay template"));
2474 scrolled = gtk_scrolled_window_new(NULL, NULL);
2475 gtk_widget_set_size_request(scrolled, 200, 150);
2476 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2477 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
2478 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2479 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 5);
2480 gtk_widget_show(scrolled);
2482 gtk_widget_set_tooltip_markup(image_overlay_template_view,
2483 _("Extensive formatting options are shown in the Help file"));
2485 gtk_container_add(GTK_CONTAINER(scrolled), image_overlay_template_view);
2486 gtk_widget_show(image_overlay_template_view);
2488 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2490 #if GTK_CHECK_VERSION(3,4,0)
2491 button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
2492 G_CALLBACK(image_overlay_set_font_cb), notebook);
2494 button = gtk_font_button_new();
2495 gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Image Overlay Font");
2496 gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->image_overlay.font);
2497 g_signal_connect(G_OBJECT(button), "font-set",
2498 G_CALLBACK(image_overlay_set_font_cb),NULL);
2500 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2501 gtk_widget_show(button);
2503 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Text"), FALSE,
2504 G_CALLBACK(image_overlay_set_text_colour_cb), NULL);
2505 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2506 gtk_widget_show(button);
2508 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Background"), FALSE,
2509 G_CALLBACK(image_overlay_set_background_colour_cb), NULL);
2510 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2511 gtk_widget_show(button);
2512 image_overlay_set_text_colours();
2514 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2515 G_CALLBACK(image_overlay_default_template_cb), image_overlay_template_view);
2516 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2517 gtk_widget_show(button);
2519 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
2520 G_CALLBACK(image_overlay_help_cb), NULL);
2521 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2522 gtk_widget_show(button);
2524 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_overlay_template_view));
2525 if (options->image_overlay.template_string) gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
2526 g_signal_connect(G_OBJECT(buffer), "changed",
2527 G_CALLBACK(image_overlay_template_view_changed_cb), image_overlay_template_view);
2529 pref_line(group, PREF_PAD_GAP);
2531 group = pref_group_new(vbox, FALSE, _("Exif, XMP or IPTC tags"), GTK_ORIENTATION_VERTICAL);
2532 hbox = gtk_hbox_new(FALSE, 0);
2533 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2534 gtk_widget_show(hbox);
2535 label = gtk_label_new(_("%Exif.Image.Orientation%"));
2536 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2537 gtk_widget_show(label);
2538 pref_spacer(group,TRUE);
2540 group = pref_group_new(vbox, FALSE, _("Field separators"), GTK_ORIENTATION_VERTICAL);
2541 hbox = gtk_hbox_new(FALSE, 0);
2542 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2543 gtk_widget_show(hbox);
2544 label = gtk_label_new(_("Separator shown only if both fields are non-null:\n%formatted.ShutterSpeed%|%formatted.ISOSpeedRating%"));
2545 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2546 gtk_widget_show(label);
2547 pref_spacer(group,TRUE);
2549 group = pref_group_new(vbox, FALSE, _("Field maximum length"), GTK_ORIENTATION_VERTICAL);
2550 hbox = gtk_hbox_new(FALSE, 0);
2551 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2552 gtk_widget_show(hbox);
2553 label = gtk_label_new(_("%path:39%"));
2554 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2555 gtk_widget_show(label);
2556 pref_spacer(group,TRUE);
2558 group = pref_group_new(vbox, FALSE, _("Pre- and post- text"), GTK_ORIENTATION_VERTICAL);
2559 hbox = gtk_hbox_new(FALSE, 0);
2560 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2561 gtk_widget_show(hbox);
2562 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%"));
2563 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2564 gtk_widget_show(label);
2565 pref_spacer(group,TRUE);
2567 group = pref_group_new(vbox, FALSE, _("Pango markup"), GTK_ORIENTATION_VERTICAL);
2568 hbox = gtk_hbox_new(FALSE, 0);
2569 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2570 gtk_widget_show(hbox);
2571 label = gtk_label_new(_("<b>bold</b>\n<u>underline</u>\n<i>italic</i>\n<s>strikethrough</s>"));
2572 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2573 gtk_widget_show(label);
2576 static GtkTreeModel *create_class_model(void)
2578 GtkListStore *model;
2582 /* create list store */
2583 model = gtk_list_store_new(1, G_TYPE_STRING);
2584 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
2586 gtk_list_store_append(model, &iter);
2587 gtk_list_store_set(model, &iter, 0, _(format_class_list[i]), -1);
2589 return GTK_TREE_MODEL (model);
2594 static void config_tab_files(GtkWidget *notebook)
2601 GtkWidget *ct_button;
2602 GtkWidget *scrolled;
2603 GtkWidget *filter_view;
2604 GtkCellRenderer *renderer;
2605 GtkTreeSelection *selection;
2606 GtkTreeViewColumn *column;
2608 vbox = scrolled_notebook_page(notebook, _("Files"));
2610 group = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2612 pref_checkbox_new_int(group, _("Show hidden files or folders"),
2613 options->file_filter.show_hidden_files, &c_options->file_filter.show_hidden_files);
2614 pref_checkbox_new_int(group, _("Show parent folder (..)"),
2615 options->file_filter.show_parent_directory, &c_options->file_filter.show_parent_directory);
2616 pref_checkbox_new_int(group, _("Case sensitive sort"),
2617 options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
2618 pref_checkbox_new_int(group, _("Natural sort order"),
2619 options->file_sort.natural, &c_options->file_sort.natural);
2620 pref_checkbox_new_int(group, _("Disable file extension checks"),
2621 options->file_filter.disable_file_extension_checks, &c_options->file_filter.disable_file_extension_checks);
2623 ct_button = pref_checkbox_new_int(group, _("Disable File Filtering"),
2624 options->file_filter.disable, &c_options->file_filter.disable);
2627 group = pref_group_new(vbox, FALSE, _("Grouping sidecar extensions"), GTK_ORIENTATION_VERTICAL);
2629 sidecar_ext_entry = gtk_entry_new();
2630 gtk_entry_set_text(GTK_ENTRY(sidecar_ext_entry), options->sidecar.ext);
2631 gtk_box_pack_start(GTK_BOX(group), sidecar_ext_entry, FALSE, FALSE, 0);
2632 gtk_widget_show(sidecar_ext_entry);
2634 group = pref_group_new(vbox, TRUE, _("File types"), GTK_ORIENTATION_VERTICAL);
2636 frame = pref_group_parent(group);
2637 g_signal_connect(G_OBJECT(ct_button), "toggled",
2638 G_CALLBACK(filter_disable_cb), frame);
2639 gtk_widget_set_sensitive(frame, !options->file_filter.disable);
2641 scrolled = gtk_scrolled_window_new(NULL, NULL);
2642 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2643 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2644 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2645 gtk_widget_show(scrolled);
2647 filter_store = gtk_list_store_new(1, G_TYPE_POINTER);
2648 filter_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(filter_store));
2649 g_object_unref(filter_store);
2650 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
2651 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
2653 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), FALSE);
2655 column = gtk_tree_view_column_new();
2656 gtk_tree_view_column_set_title(column, _("Filter"));
2657 gtk_tree_view_column_set_resizable(column, TRUE);
2659 renderer = gtk_cell_renderer_toggle_new();
2660 g_signal_connect(G_OBJECT(renderer), "toggled",
2661 G_CALLBACK(filter_store_enable_cb), filter_store);
2662 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2663 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2664 GINT_TO_POINTER(FE_ENABLE), NULL);
2666 renderer = gtk_cell_renderer_text_new();
2667 g_signal_connect(G_OBJECT(renderer), "edited",
2668 G_CALLBACK(filter_store_ext_edit_cb), filter_store);
2669 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2670 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2671 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2672 GINT_TO_POINTER(FE_EXTENSION), NULL);
2673 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2675 column = gtk_tree_view_column_new();
2676 gtk_tree_view_column_set_title(column, _("Description"));
2677 gtk_tree_view_column_set_resizable(column, TRUE);
2678 gtk_tree_view_column_set_fixed_width(column, 200);
2679 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
2681 renderer = gtk_cell_renderer_text_new();
2682 g_signal_connect(G_OBJECT(renderer), "edited",
2683 G_CALLBACK(filter_store_desc_edit_cb), filter_store);
2684 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2685 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2686 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2687 GINT_TO_POINTER(FE_DESCRIPTION), NULL);
2688 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2690 column = gtk_tree_view_column_new();
2691 gtk_tree_view_column_set_title(column, _("Class"));
2692 gtk_tree_view_column_set_resizable(column, TRUE);
2693 renderer = gtk_cell_renderer_combo_new();
2694 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE,
2695 "model", create_class_model(),
2700 g_signal_connect(G_OBJECT(renderer), "edited",
2701 G_CALLBACK(filter_store_class_edit_cb), filter_store);
2702 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2703 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2704 GINT_TO_POINTER(FE_CLASS), NULL);
2705 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2707 column = gtk_tree_view_column_new();
2708 gtk_tree_view_column_set_title(column, _("Writable"));
2709 gtk_tree_view_column_set_resizable(column, FALSE);
2710 renderer = gtk_cell_renderer_toggle_new();
2711 g_signal_connect(G_OBJECT(renderer), "toggled",
2712 G_CALLBACK(filter_store_writable_cb), filter_store);
2713 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2714 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2715 GINT_TO_POINTER(FE_WRITABLE), NULL);
2716 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2718 column = gtk_tree_view_column_new();
2719 gtk_tree_view_column_set_title(column, _("Sidecar is allowed"));
2720 gtk_tree_view_column_set_resizable(column, FALSE);
2721 renderer = gtk_cell_renderer_toggle_new();
2722 g_signal_connect(G_OBJECT(renderer), "toggled",
2723 G_CALLBACK(filter_store_sidecar_cb), filter_store);
2724 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2725 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2726 GINT_TO_POINTER(FE_ALLOW_SIDECAR), NULL);
2727 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2730 filter_store_populate();
2731 gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
2732 gtk_widget_show(filter_view);
2734 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2736 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2737 G_CALLBACK(filter_default_cb), filter_view);
2738 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2739 gtk_widget_show(button);
2741 button = pref_button_new(NULL, GTK_STOCK_REMOVE, NULL, FALSE,
2742 G_CALLBACK(filter_remove_cb), filter_view);
2743 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2744 gtk_widget_show(button);
2746 button = pref_button_new(NULL, GTK_STOCK_ADD, NULL, FALSE,
2747 G_CALLBACK(filter_add_cb), filter_view);
2748 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2749 gtk_widget_show(button);
2753 static void config_tab_metadata(GtkWidget *notebook)
2758 GtkWidget *ct_button;
2762 vbox = scrolled_notebook_page(notebook, _("Metadata"));
2765 group = pref_group_new(vbox, FALSE, _("Metadata writing process"), GTK_ORIENTATION_VERTICAL);
2767 label = pref_label_new(group, _("Warning: Geeqie is built without Exiv2. Some options are disabled."));
2769 label = pref_label_new(group, _("Metadata are written in the following order. The process ends after first success."));
2770 #if GTK_CHECK_VERSION(3,16,0)
2771 gtk_label_set_xalign(GTK_LABEL(label), 0.0);
2772 gtk_label_set_yalign(GTK_LABEL(label), 0.5);
2774 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2777 ct_button = pref_checkbox_new_int(group, _("1) Save metadata in image files, or sidecar files, according to the XMP standard"),
2778 options->metadata.save_in_image_file, &c_options->metadata.save_in_image_file);
2780 gtk_widget_set_sensitive(ct_button, FALSE);
2783 pref_checkbox_new_int(group, _("2) Save metadata in '.metadata' folder, local to image folder (non-standard)"),
2784 options->metadata.enable_metadata_dirs, &c_options->metadata.enable_metadata_dirs);
2786 text = g_strdup_printf(_("3) Save metadata in Geeqie private directory '%s'"), get_metadata_cache_dir());
2787 label = pref_label_new(group, text);
2788 #if GTK_CHECK_VERSION(3,16,0)
2789 gtk_label_set_xalign(GTK_LABEL(label), 0.0);
2790 gtk_label_set_yalign(GTK_LABEL(label), 0.5);
2792 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2794 gtk_misc_set_padding(GTK_MISC(label), 22, 0);
2797 group = pref_group_new(vbox, FALSE, _("Step 1: Write to image files"), GTK_ORIENTATION_VERTICAL);
2799 gtk_widget_set_sensitive(group, FALSE);
2802 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2803 pref_checkbox_link_sensitivity(ct_button, hbox);
2805 pref_checkbox_new_int(hbox, _("Store metadata also in legacy IPTC tags (converted according to IPTC4XMP standard)"),
2806 options->metadata.save_legacy_IPTC, &c_options->metadata.save_legacy_IPTC);
2808 pref_checkbox_new_int(hbox, _("Warn if the image files are unwritable"),
2809 options->metadata.warn_on_write_problems, &c_options->metadata.warn_on_write_problems);
2811 pref_checkbox_new_int(hbox, _("Ask before writing to image files"),
2812 options->metadata.confirm_write, &c_options->metadata.confirm_write);
2814 pref_checkbox_new_int(hbox, _("Create sidecar files named image.ext.xmp (as opposed to image.xmp)"),
2815 options->metadata.sidecar_extended_name, &c_options->metadata.sidecar_extended_name);
2817 group = pref_group_new(vbox, FALSE, _("Step 2 and 3: write to Geeqie private files"), GTK_ORIENTATION_VERTICAL);
2819 gtk_widget_set_sensitive(group, FALSE);
2822 pref_checkbox_new_int(group, _("Use GQview legacy metadata format (supports only keywords and comments) instead of XMP"),
2823 options->metadata.save_legacy_format, &c_options->metadata.save_legacy_format);
2826 group = pref_group_new(vbox, FALSE, _("Miscellaneous"), GTK_ORIENTATION_VERTICAL);
2827 pref_checkbox_new_int(group, _("Write the same description tags (keywords, comment, etc.) to all grouped sidecars"),
2828 options->metadata.sync_grouped_files, &c_options->metadata.sync_grouped_files);
2830 pref_checkbox_new_int(group, _("Allow keywords to differ only in case"),
2831 options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
2833 ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"),
2834 options->metadata.write_orientation, &c_options->metadata.write_orientation);
2836 gtk_widget_set_sensitive(ct_button, FALSE);
2839 group = pref_group_new(vbox, FALSE, _("Auto-save options"), GTK_ORIENTATION_VERTICAL);
2841 ct_button = pref_checkbox_new_int(group, _("Write metadata after timeout"),
2842 options->metadata.confirm_after_timeout, &c_options->metadata.confirm_after_timeout);
2844 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2845 pref_checkbox_link_sensitivity(ct_button, hbox);
2847 pref_spin_new_int(hbox, _("Timeout (seconds):"), NULL, 0, 900, 1,
2848 options->metadata.confirm_timeout, &c_options->metadata.confirm_timeout);
2850 pref_checkbox_new_int(group, _("Write metadata on image change"),
2851 options->metadata.confirm_on_image_change, &c_options->metadata.confirm_on_image_change);
2853 pref_checkbox_new_int(group, _("Write metadata on directory change"),
2854 options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
2856 group = pref_group_new(vbox, FALSE, _("Pre-load metadata"), GTK_ORIENTATION_VERTICAL);
2858 ct_button = pref_checkbox_new_int(group, _("Read metadata in background"),
2859 options->read_metadata_in_idle, &c_options->read_metadata_in_idle);
2860 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");
2865 typedef struct _KeywordFindData KeywordFindData;
2866 struct _KeywordFindData
2873 GtkWidget *button_close;
2874 GtkWidget *button_stop;
2875 GtkWidget *button_start;
2876 GtkWidget *progress;
2884 guint idle_id; /* event source id */
2887 #define KEYWORD_DIALOG_WIDTH 400
2889 static void keywords_find_folder(KeywordFindData *kfd, FileData *dir_fd)
2891 GList *list_d = NULL;
2892 GList *list_f = NULL;
2896 filelist_read(dir_fd, &list_f, &list_d);
2900 filelist_read(dir_fd, &list_f, NULL);
2903 list_f = filelist_filter(list_f, FALSE);
2904 list_d = filelist_filter(list_d, TRUE);
2906 kfd->list = g_list_concat(list_f, kfd->list);
2907 kfd->list_dir = g_list_concat(list_d, kfd->list_dir);
2910 static void keywords_find_reset(KeywordFindData *kfd)
2912 filelist_free(kfd->list);
2915 filelist_free(kfd->list_dir);
2916 kfd->list_dir = NULL;
2919 static void keywords_find_close_cb(GenericDialog *fd, gpointer data)
2921 KeywordFindData *kfd = data;
2923 if (!gtk_widget_get_sensitive(kfd->button_close)) return;
2925 keywords_find_reset(kfd);
2926 generic_dialog_close(kfd->gd);
2930 static void keywords_find_finish(KeywordFindData *kfd)
2932 keywords_find_reset(kfd);
2934 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("done"));
2935 spinner_set_interval(kfd->spinner, -1);
2937 gtk_widget_set_sensitive(kfd->group, TRUE);
2938 gtk_widget_set_sensitive(kfd->button_start, TRUE);
2939 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2940 gtk_widget_set_sensitive(kfd->button_close, TRUE);
2943 static void keywords_find_stop_cb(GenericDialog *fd, gpointer data)
2945 KeywordFindData *kfd = data;
2947 g_idle_remove_by_data(kfd);
2949 keywords_find_finish(kfd);
2952 static gboolean keywords_find_file(gpointer data)
2954 KeywordFindData *kfd = data;
2956 GtkTextBuffer *buffer;
2964 fd = kfd->list->data;
2965 kfd->list = g_list_remove(kfd->list, fd);
2967 keywords = metadata_read_list(fd, KEYWORD_KEY, METADATA_PLAIN);
2968 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2972 gtk_text_buffer_get_end_iter(buffer, &iter);
2973 tmp = g_strconcat(keywords->data, "\n", NULL);
2974 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
2976 keywords = keywords->next;
2979 gtk_entry_set_text(GTK_ENTRY(kfd->progress), fd->path);
2980 file_data_unref(fd);
2981 string_list_free(keywords);
2985 else if (kfd->list_dir)
2989 fd = kfd->list_dir->data;
2990 kfd->list_dir = g_list_remove(kfd->list_dir, fd);
2992 keywords_find_folder(kfd, fd);
2994 file_data_unref(fd);
2999 keywords_find_finish(kfd);
3004 static void keywords_find_start_cb(GenericDialog *fd, gpointer data)
3006 KeywordFindData *kfd = data;
3009 if (kfd->list || !gtk_widget_get_sensitive(kfd->button_start)) return;
3011 path = remove_trailing_slash((gtk_entry_get_text(GTK_ENTRY(kfd->entry))));
3012 parse_out_relatives(path);
3016 warning_dialog(_("Invalid folder"),
3017 _("The specified folder can not be found."),
3018 GTK_STOCK_DIALOG_WARNING, kfd->gd->dialog);
3024 gtk_widget_set_sensitive(kfd->group, FALSE);
3025 gtk_widget_set_sensitive(kfd->button_start, FALSE);
3026 gtk_widget_set_sensitive(kfd->button_stop, TRUE);
3027 gtk_widget_set_sensitive(kfd->button_close, FALSE);
3028 spinner_set_interval(kfd->spinner, SPINNER_SPEED);
3030 dir_fd = file_data_new_dir(path);
3031 keywords_find_folder(kfd, dir_fd);
3032 file_data_unref(dir_fd);
3033 kfd->idle_id = g_idle_add(keywords_find_file, kfd);
3039 static void keywords_find_dialog(GtkWidget *widget, const gchar *path)
3041 KeywordFindData *kfd;
3045 kfd = g_new0(KeywordFindData, 1);
3047 kfd->gd = generic_dialog_new(_("Search for keywords"),
3048 "search_for_keywords",
3051 gtk_window_set_default_size(GTK_WINDOW(kfd->gd->dialog), KEYWORD_DIALOG_WIDTH, -1);
3052 kfd->gd->cancel_cb = keywords_find_close_cb;
3053 kfd->button_close = generic_dialog_add_button(kfd->gd, GTK_STOCK_CLOSE, NULL,
3054 keywords_find_close_cb, FALSE);
3055 kfd->button_start = generic_dialog_add_button(kfd->gd, GTK_STOCK_OK, _("S_tart"),
3056 keywords_find_start_cb, FALSE);
3057 kfd->button_stop = generic_dialog_add_button(kfd->gd, GTK_STOCK_STOP, NULL,
3058 keywords_find_stop_cb, FALSE);
3059 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
3061 generic_dialog_add_message(kfd->gd, NULL, _("Search for keywords"), NULL, FALSE);
3063 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0);
3064 pref_spacer(hbox, PREF_PAD_INDENT);
3065 kfd->group = pref_box_new(hbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
3067 hbox = pref_box_new(kfd->group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3068 pref_label_new(hbox, _("Folder:"));
3070 label = tab_completion_new(&kfd->entry, path, NULL, NULL, NULL, NULL);
3071 tab_completion_add_select_button(kfd->entry,_("Select folder") , TRUE);
3072 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
3073 gtk_widget_show(label);
3075 pref_checkbox_new_int(kfd->group, _("Include subfolders"), FALSE, &kfd->recurse);
3077 pref_line(kfd->gd->vbox, PREF_PAD_SPACE);
3078 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3080 kfd->progress = gtk_entry_new();
3081 gtk_widget_set_can_focus(kfd->progress, FALSE);
3082 gtk_editable_set_editable(GTK_EDITABLE(kfd->progress), FALSE);
3083 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("click start to begin"));
3084 gtk_box_pack_start(GTK_BOX(hbox), kfd->progress, TRUE, TRUE, 0);
3085 gtk_widget_show(kfd->progress);
3087 kfd->spinner = spinner_new(NULL, -1);
3088 gtk_box_pack_start(GTK_BOX(hbox), kfd->spinner, FALSE, FALSE, 0);
3089 gtk_widget_show(kfd->spinner);
3093 gtk_widget_show(kfd->gd->dialog);
3096 static void keywords_find_cb(GtkWidget *widget, gpointer data)
3098 const gchar *path = layout_get_path(NULL);
3100 if (!path || !*path) path = homedir();
3101 keywords_find_dialog(widget, path);
3104 static void config_tab_keywords_save()
3106 GtkTextIter start, end;
3107 GtkTextBuffer *buffer;
3108 GList *kw_list = NULL;
3114 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3115 gtk_text_buffer_get_bounds(buffer, &start, &end);
3117 buffer_text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
3119 kw_split = strtok(buffer_text, "\n");
3120 while (kw_split != NULL)
3126 if (g_strcmp0(work->data, kw_split) == 0)
3135 kw_list = g_list_append(kw_list, g_strdup(kw_split));
3137 kw_split = strtok(NULL, "\n");
3140 keyword_list_set(kw_list);
3142 string_list_free(kw_list);
3143 g_free(buffer_text);
3146 static void config_tab_keywords(GtkWidget *notebook)
3152 GtkWidget *scrolled;
3154 GtkTextBuffer *buffer;
3157 vbox = scrolled_notebook_page(notebook, _("Keywords"));
3159 group = pref_group_new(vbox, TRUE, _("Edit keywords autocompletion list"), GTK_ORIENTATION_VERTICAL);
3161 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3163 button = pref_button_new(hbox, GTK_STOCK_EXECUTE, _("Search"), FALSE,
3164 G_CALLBACK(keywords_find_cb), keyword_text);
3165 gtk_widget_set_tooltip_text(button, "Search for existing keywords");
3168 keyword_text = gtk_text_view_new();
3169 gtk_widget_set_size_request(keyword_text, 20, 20);
3170 scrolled = gtk_scrolled_window_new(NULL, NULL);
3171 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3172 gtk_widget_show(scrolled);
3174 gtk_container_add(GTK_CONTAINER(scrolled), keyword_text);
3175 gtk_widget_show(keyword_text);
3177 gtk_text_view_set_editable(GTK_TEXT_VIEW(keyword_text), TRUE);
3179 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3180 gtk_text_buffer_create_tag(buffer, "monospace",
3181 "family", "monospace", NULL);
3183 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(keyword_text), GTK_WRAP_WORD);
3184 gtk_text_buffer_get_start_iter(buffer, &iter);
3185 gtk_text_buffer_create_mark(buffer, "end", &iter, FALSE);
3188 path = g_build_filename(get_rc_dir(), "keywords", NULL);
3190 GList *kwl = keyword_list_get();
3191 kwl = g_list_first(kwl);
3194 gtk_text_buffer_get_end_iter (buffer, &iter);
3195 tmp = g_strconcat(kwl->data, "\n", NULL);
3196 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
3201 gtk_text_buffer_set_modified(buffer, FALSE);
3208 static void intent_menu_cb(GtkWidget *combo, gpointer data)
3210 gint *option = data;
3212 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
3216 *option = INTENT_PERCEPTUAL;
3219 *option = INTENT_RELATIVE_COLORIMETRIC;
3222 *option = INTENT_SATURATION;
3225 *option = INTENT_ABSOLUTE_COLORIMETRIC;
3230 static void add_intent_menu(GtkWidget *table, gint column, gint row, const gchar *text,
3231 gint option, gint *option_c)
3238 pref_table_label(table, column, row, text, 0.0);
3240 combo = gtk_combo_box_text_new();
3242 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Perceptual"));
3243 if (option == INTENT_PERCEPTUAL) current = 0;
3244 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Relative Colorimetric"));
3245 if (option == INTENT_RELATIVE_COLORIMETRIC) current = 1;
3246 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Saturation"));
3247 if (option == INTENT_SATURATION) current = 2;
3248 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Absolute Colorimetric"));
3249 if (option == INTENT_ABSOLUTE_COLORIMETRIC) current = 3;
3251 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
3253 gtk_widget_set_tooltip_text(combo,"Refer to the lcms documentation for the defaults used when the selected Intent is not available");
3255 g_signal_connect(G_OBJECT(combo), "changed",
3256 G_CALLBACK(intent_menu_cb), option_c);
3258 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
3259 gtk_widget_show(combo);
3263 static void config_tab_color(GtkWidget *notebook)
3272 vbox = scrolled_notebook_page(notebook, _("Color management"));
3274 group = pref_group_new(vbox, FALSE, _("Input profiles"), GTK_ORIENTATION_VERTICAL);
3276 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3279 table = pref_table_new(group, 3, COLOR_PROFILE_INPUTS + 1, FALSE, FALSE);
3280 gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
3282 label = pref_table_label(table, 0, 0, _("Type"), 0.0);
3283 pref_label_bold(label, TRUE, FALSE);
3285 label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
3286 pref_label_bold(label, TRUE, FALSE);
3288 label = pref_table_label(table, 2, 0, _("File"), 0.0);
3289 pref_label_bold(label, TRUE, FALSE);
3291 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
3296 buf = g_strdup_printf(_("Input %d:"), i + COLOR_PROFILE_FILE);
3297 pref_table_label(table, 0, i + 1, buf, 1.0);
3300 entry = gtk_entry_new();
3301 gtk_entry_set_max_length(GTK_ENTRY(entry), EDITOR_NAME_MAX_LENGTH);
3302 if (options->color_profile.input_name[i])
3304 gtk_entry_set_text(GTK_ENTRY(entry), options->color_profile.input_name[i]);
3306 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, i + 1, i + 2,
3307 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3308 gtk_widget_show(entry);
3309 color_profile_input_name_entry[i] = entry;
3311 tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, ".icc", "ICC Files", NULL);
3312 tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
3313 gtk_widget_set_size_request(entry, 160, -1);
3314 gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
3315 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3316 gtk_widget_show(tabcomp);
3317 color_profile_input_file_entry[i] = entry;
3320 group = pref_group_new(vbox, FALSE, _("Screen profile"), GTK_ORIENTATION_VERTICAL);
3322 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3324 pref_checkbox_new_int(group, _("Use system screen profile if available"),
3325 options->color_profile.use_x11_screen_profile, &c_options->color_profile.use_x11_screen_profile);
3327 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3329 pref_table_label(table, 0, 0, _("Screen:"), 1.0);
3330 tabcomp = tab_completion_new(&color_profile_screen_file_entry,
3331 options->color_profile.screen_file, NULL, ".icc", "ICC Files", NULL);
3332 tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
3333 gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
3335 add_intent_menu(table, 0, 1, _("Render Intent:"), options->color_profile.render_intent, &c_options->color_profile.render_intent);
3337 gtk_table_attach(GTK_TABLE(table), tabcomp, 1, 2,
3339 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3341 gtk_widget_show(tabcomp);
3344 /* advanced entry tab */
3345 static void use_geeqie_trash_cb(GtkWidget *widget, gpointer data)
3347 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3349 c_options->file_ops.use_system_trash = FALSE;
3350 c_options->file_ops.no_trash = FALSE;
3354 static void use_system_trash_cb(GtkWidget *widget, gpointer data)
3356 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3358 c_options->file_ops.use_system_trash = TRUE;
3359 c_options->file_ops.no_trash = FALSE;
3363 static void use_no_cache_cb(GtkWidget *widget, gpointer data)
3365 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3367 c_options->file_ops.no_trash = TRUE;
3371 static void config_tab_behavior(GtkWidget *notebook)
3378 GtkWidget *ct_button;
3382 GtkWidget *with_rename;
3383 GtkWidget *collections_on_top;
3384 GtkWidget *hide_window_in_fullscreen;
3385 GtkWidget *checkbox;
3388 vbox = scrolled_notebook_page(notebook, _("Behavior"));
3390 group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
3392 pref_checkbox_new_int(group, _("Confirm permanent file delete"),
3393 options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
3394 pref_checkbox_new_int(group, _("Confirm move file to Trash"),
3395 options->file_ops.confirm_move_to_trash, &c_options->file_ops.confirm_move_to_trash);
3396 pref_checkbox_new_int(group, _("Enable Delete key"),
3397 options->file_ops.enable_delete_key, &c_options->file_ops.enable_delete_key);
3399 ct_button = pref_radiobutton_new(group, NULL, _("Use Geeqie trash location"),
3400 !options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_geeqie_trash_cb),NULL);
3402 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3403 pref_checkbox_link_sensitivity(ct_button, hbox);
3405 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
3406 pref_label_new(hbox, _("Folder:"));
3408 tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL, NULL, NULL);
3409 tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
3410 gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
3411 gtk_widget_show(tabcomp);
3413 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3414 pref_checkbox_link_sensitivity(ct_button, hbox);
3416 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
3417 spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MiB"),
3418 0, 2048, 1, options->file_ops.safe_delete_folder_maxsize, &c_options->file_ops.safe_delete_folder_maxsize);
3419 gtk_widget_set_tooltip_markup(spin, _("Set to 0 for unlimited size"));
3420 button = pref_button_new(NULL, NULL, _("View"), FALSE,
3421 G_CALLBACK(safe_delete_view_cb), NULL);
3422 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3423 gtk_widget_show(button);
3425 button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
3426 G_CALLBACK(safe_delete_clear_cb), NULL);
3427 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3428 pref_radiobutton_new(group, ct_button, _("Use system Trash bin"),
3429 options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_system_trash_cb), NULL);
3431 pref_radiobutton_new(group, ct_button, _("Use no trash at all"),
3432 options->file_ops.no_trash, G_CALLBACK(use_no_cache_cb), NULL);
3434 gtk_widget_show(button);
3436 pref_spacer(group, PREF_PAD_GROUP);
3439 group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
3441 pref_checkbox_new_int(group, _("Descend folders in tree view"),
3442 options->tree_descend_subdirs, &c_options->tree_descend_subdirs);
3444 pref_checkbox_new_int(group, _("In place renaming"),
3445 options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
3447 pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
3448 options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
3450 tmp = pref_checkbox_new_int(group, _("Circular selection lists"),
3451 options->circular_selection_lists, &c_options->circular_selection_lists);
3452 gtk_widget_set_tooltip_text(tmp, _("Traverse selection lists in a circular manner"));
3454 marks = pref_checkbox_new_int(group, _("Save marks on exit"),
3455 options->marks_save, &c_options->marks_save);
3456 gtk_widget_set_tooltip_text(marks,"Note that marks linked to a keyword will be saved irrespective of this setting");
3458 with_rename = pref_checkbox_new_int(group, _("Use \"With Rename\" as default for Copy/Move dialogs"),
3459 options->with_rename, &c_options->with_rename);
3460 gtk_widget_set_tooltip_text(with_rename,"Change the default button for Copy/Move dialogs");
3462 collections_on_top = pref_checkbox_new_int(group, _("Open collections on top"),
3463 options->collections_on_top, &c_options->collections_on_top);
3464 gtk_widget_set_tooltip_text(collections_on_top,"Open collections window on top");
3466 hide_window_in_fullscreen = pref_checkbox_new_int(group, _("Hide window in fullscreen"),
3467 options->hide_window_in_fullscreen, &c_options->hide_window_in_fullscreen);
3468 gtk_widget_set_tooltip_text(hide_window_in_fullscreen,"When alt-tabbing, prevent Geeqie window showing twice");
3470 pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
3471 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
3473 pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
3474 16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
3476 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3477 add_dnd_default_action_selection_menu(table, 0, 0, _("Drag`n drop default action:"), options->dnd_default_action, &c_options->dnd_default_action);
3479 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3480 add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
3482 pref_spacer(group, PREF_PAD_GROUP);
3484 group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
3486 pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
3487 options->progressive_key_scrolling, &c_options->progressive_key_scrolling);
3488 pref_spin_new_int(group, _("Keyboard scrolling step multiplier:"), NULL,
3489 1, 32, 1, options->keyboard_scroll_step, (int *)&c_options->keyboard_scroll_step);
3490 pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
3491 options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
3492 pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
3493 options->image_lm_click_nav, &c_options->image_lm_click_nav);
3494 pref_checkbox_new_int(group, _("Play video by left click on image"),
3495 options->image_l_click_video, &c_options->image_l_click_video);
3496 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3497 add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
3499 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3500 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3501 add_mouse_selection_menu(table, 0, 0, _("Mouse button Back:"), options->mouse_button_8, &c_options->mouse_button_8);
3502 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3503 add_mouse_selection_menu(table, 0, 0, _("Mouse button Forward:"), options->mouse_button_9, &c_options->mouse_button_9);
3505 pref_spacer(group, PREF_PAD_GROUP);
3507 group = pref_group_new(vbox, FALSE, _("GPU"), GTK_ORIENTATION_VERTICAL);
3509 checkbox = pref_checkbox_new_int(group, _("Override disable GPU"),
3510 options->override_disable_gpu, &c_options->override_disable_gpu);
3511 gtk_widget_set_tooltip_text(checkbox, "Contact the developers for usage");
3514 pref_spacer(group, PREF_PAD_GROUP);
3516 group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
3518 pref_spin_new_int(group, _("Debug level:"), NULL,
3519 DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
3521 pref_checkbox_new_int(group, _("Timer data"),
3522 options->log_window.timer_data, &c_options->log_window.timer_data);
3524 pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
3525 1, 99999, 1, options->log_window_lines, &options->log_window_lines);
3529 /* accelerators tab */
3530 static void config_tab_accelerators(GtkWidget *notebook)
3536 GtkWidget *scrolled;
3537 GtkWidget *accel_view;
3538 GtkCellRenderer *renderer;
3539 GtkTreeSelection *selection;
3540 GtkTreeViewColumn *column;
3542 vbox = scrolled_notebook_page(notebook, _("Keyboard"));
3544 group = pref_group_new(vbox, TRUE, _("Accelerators"), GTK_ORIENTATION_VERTICAL);
3546 scrolled = gtk_scrolled_window_new(NULL, NULL);
3547 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
3548 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
3549 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3550 gtk_widget_show(scrolled);
3552 accel_store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
3554 accel_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(accel_store));
3555 g_object_unref(accel_store);
3556 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(accel_view));
3557 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
3559 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(accel_view), FALSE);
3561 renderer = gtk_cell_renderer_text_new();
3563 column = gtk_tree_view_column_new_with_attributes(_("Action"),
3568 gtk_tree_view_column_set_sort_column_id(column, AE_ACTION);
3569 gtk_tree_view_column_set_resizable(column, TRUE);
3570 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3573 renderer = gtk_cell_renderer_accel_new();
3574 g_signal_connect(G_OBJECT(renderer), "accel-cleared",
3575 G_CALLBACK(accel_store_cleared_cb), accel_store);
3576 g_signal_connect(G_OBJECT(renderer), "accel-edited",
3577 G_CALLBACK(accel_store_edited_cb), accel_store);
3580 g_object_set (renderer,
3582 "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
3585 column = gtk_tree_view_column_new_with_attributes(_("KEY"),
3590 gtk_tree_view_column_set_sort_column_id(column, AE_KEY);
3591 gtk_tree_view_column_set_resizable(column, TRUE);
3592 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3594 renderer = gtk_cell_renderer_text_new();
3596 column = gtk_tree_view_column_new_with_attributes(_("Tooltip"),
3601 gtk_tree_view_column_set_sort_column_id(column, AE_TOOLTIP);
3602 gtk_tree_view_column_set_resizable(column, TRUE);
3603 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3605 renderer = gtk_cell_renderer_text_new();
3607 column = gtk_tree_view_column_new_with_attributes("Accel",
3612 gtk_tree_view_column_set_sort_column_id(column, AE_ACCEL);
3613 gtk_tree_view_column_set_resizable(column, TRUE);
3614 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3616 accel_store_populate();
3617 gtk_container_add(GTK_CONTAINER(scrolled), accel_view);
3618 gtk_widget_show(accel_view);
3620 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3622 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
3623 G_CALLBACK(accel_default_cb), accel_view);
3624 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3625 gtk_widget_show(button);
3627 button = pref_button_new(NULL, NULL, _("Reset selected"), FALSE,
3628 G_CALLBACK(accel_reset_cb), accel_view);
3629 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3630 gtk_widget_show(button);
3633 /* toolbar main tab */
3634 static void config_tab_toolbar_main(GtkWidget *notebook)
3637 GtkWidget *toolbardata;
3640 lw = layout_window_list->data;
3642 vbox = scrolled_notebook_page(notebook, _("Toolbar Main"));
3644 toolbardata = toolbar_select_new(lw, TOOLBAR_MAIN);
3645 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3646 gtk_widget_show(vbox);
3649 /* toolbar status tab */
3650 static void config_tab_toolbar_status(GtkWidget *notebook)
3653 GtkWidget *toolbardata;
3656 lw = layout_window_list->data;
3658 vbox = scrolled_notebook_page(notebook, _("Toolbar Status"));
3660 toolbardata = toolbar_select_new(lw, TOOLBAR_STATUS);
3661 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3662 gtk_widget_show(vbox);
3666 static gint extension_sort_cb(gconstpointer a, gconstpointer b)
3668 return g_strcmp0((gchar *)a, (gchar *)b);
3671 static void config_tab_advanced(GtkWidget *notebook)
3675 GSList *formats_list;
3676 GList *extensions_list = NULL;
3679 GdkPixbufFormat *fm;
3681 GString *types_string = g_string_new(NULL);
3682 GtkWidget *types_string_label;
3683 GtkWidget *threads_string_label;
3684 GtkWidget *dupes_threads_spin;
3686 vbox = scrolled_notebook_page(notebook, _("Advanced"));
3687 group = pref_group_new(vbox, FALSE, _("External preview extraction"), GTK_ORIENTATION_VERTICAL);
3689 pref_checkbox_new_int(group, _("Use external preview extraction - Requires restart"), options->external_preview.enable, &c_options->external_preview.enable);
3691 pref_spacer(group, PREF_PAD_GROUP);
3693 formats_list = gdk_pixbuf_get_formats();
3695 while (formats_list)
3697 fm = formats_list->data;
3698 extensions = gdk_pixbuf_format_get_extensions(fm);
3701 while (extensions[i])
3703 extensions_list = g_list_insert_sorted(extensions_list, g_strdup(extensions[i]), extension_sort_cb);
3707 g_strfreev(extensions);
3708 formats_list = formats_list->next;
3711 while (extensions_list)
3713 if (types_string->len == 0)
3715 types_string = g_string_append(types_string, extensions_list->data);
3719 types_string = g_string_append(types_string, ", ");
3720 types_string = g_string_append(types_string, extensions_list->data);
3723 extensions_list = extensions_list->next;
3726 types_string = g_string_prepend(types_string, _("Usable file types:\n"));
3727 types_string_label = pref_label_new(group, types_string->str);
3728 gtk_label_set_line_wrap(GTK_LABEL(types_string_label), TRUE);
3730 pref_spacer(group, PREF_PAD_GROUP);
3732 group = pref_group_new(vbox, FALSE, _("File identification tool"), GTK_ORIENTATION_VERTICAL);
3733 external_preview_select_entry = gtk_entry_new();
3734 tabcomp = tab_completion_new(&external_preview_select_entry, options->external_preview.select, NULL, NULL, NULL, NULL);
3735 tab_completion_add_select_button(external_preview_select_entry, _("Select file identification tool"), FALSE);
3736 gtk_box_pack_start(GTK_BOX(group), tabcomp, TRUE, TRUE, 0);
3737 gtk_widget_show(tabcomp);
3739 group = pref_group_new(vbox, FALSE, _("Preview extraction tool"), GTK_ORIENTATION_VERTICAL);
3740 external_preview_extract_entry = gtk_entry_new();
3741 tabcomp = tab_completion_new(&external_preview_extract_entry, options->external_preview.extract, NULL, NULL, NULL, NULL);
3742 tab_completion_add_select_button(external_preview_extract_entry, _("Select preview extraction tool"), FALSE);
3743 gtk_box_pack_start(GTK_BOX(group), tabcomp, TRUE, TRUE, 0);
3744 gtk_widget_show(tabcomp);
3746 gtk_widget_show(vbox);
3748 g_slist_free(formats_list);
3749 string_list_free(extensions_list);
3750 g_string_free(types_string, TRUE);
3752 pref_spacer(group, PREF_PAD_GROUP);
3754 pref_line(vbox, PREF_PAD_SPACE);
3755 group = pref_group_new(vbox, FALSE, _("Thread pool limits"), GTK_ORIENTATION_VERTICAL);
3757 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 avaialble cores will be used.");
3758 gtk_label_set_line_wrap(GTK_LABEL(threads_string_label), TRUE);
3760 pref_spacer(vbox, PREF_PAD_GROUP);
3762 dupes_threads_spin = pref_spin_new_int(vbox, _("Duplicate check:"), _("max. threads"), 0, get_cpu_cores(), 1, options->threads.duplicates, &c_options->threads.duplicates);
3763 gtk_widget_set_tooltip_markup(dupes_threads_spin, _("Set to 0 for unlimited"));
3767 static void config_tab_stereo(GtkWidget *notebook)
3775 GtkWidget *fs_button;
3776 vbox = scrolled_notebook_page(notebook, _("Stereo"));
3778 group = pref_group_new(vbox, FALSE, _("Windowed stereo mode"), GTK_ORIENTATION_VERTICAL);
3780 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3781 add_stereo_mode_menu(table, 0, 0, _("Windowed stereo mode"), options->stereo.mode, &c_options->stereo.mode, FALSE);
3783 table = pref_table_new(group, 2, 2, TRUE, FALSE);
3784 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3785 pref_checkbox_new_int(box, _("Mirror left image"),
3786 options->stereo.mode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.mirror_left);
3787 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3788 pref_checkbox_new_int(box, _("Flip left image"),
3789 options->stereo.mode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.flip_left);
3790 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3791 pref_checkbox_new_int(box, _("Mirror right image"),
3792 options->stereo.mode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.mirror_right);
3793 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3794 pref_checkbox_new_int(box, _("Flip right image"),
3795 options->stereo.mode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.flip_right);
3796 pref_checkbox_new_int(group, _("Swap left and right images"),
3797 options->stereo.mode & PR_STEREO_SWAP, &c_options->stereo.tmp.swap);
3798 pref_checkbox_new_int(group, _("Disable stereo mode on single image source"),
3799 options->stereo.mode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.temp_disable);
3801 group = pref_group_new(vbox, FALSE, _("Fullscreen stereo mode"), GTK_ORIENTATION_VERTICAL);
3802 fs_button = pref_checkbox_new_int(group, _("Use different settings for fullscreen"),
3803 options->stereo.enable_fsmode, &c_options->stereo.enable_fsmode);
3804 box2 = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
3805 pref_checkbox_link_sensitivity(fs_button, box2);
3806 table = pref_table_new(box2, 2, 1, FALSE, FALSE);
3807 add_stereo_mode_menu(table, 0, 0, _("Fullscreen stereo mode"), options->stereo.fsmode, &c_options->stereo.fsmode, TRUE);
3808 table = pref_table_new(box2, 2, 2, TRUE, FALSE);
3809 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3810 pref_checkbox_new_int(box, _("Mirror left image"),
3811 options->stereo.fsmode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.fs_mirror_left);
3812 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3813 pref_checkbox_new_int(box, _("Flip left image"),
3814 options->stereo.fsmode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.fs_flip_left);
3815 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3816 pref_checkbox_new_int(box, _("Mirror right image"),
3817 options->stereo.fsmode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.fs_mirror_right);
3818 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3819 pref_checkbox_new_int(box, _("Flip right image"),
3820 options->stereo.fsmode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.fs_flip_right);
3821 pref_checkbox_new_int(box2, _("Swap left and right images"),
3822 options->stereo.fsmode & PR_STEREO_SWAP, &c_options->stereo.tmp.fs_swap);
3823 pref_checkbox_new_int(box2, _("Disable stereo mode on single image source"),
3824 options->stereo.fsmode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.fs_temp_disable);
3826 group2 = pref_group_new(box2, FALSE, _("Fixed position"), GTK_ORIENTATION_VERTICAL);
3827 table = pref_table_new(group2, 5, 3, FALSE, FALSE);
3828 pref_table_spin_new_int(table, 0, 0, _("Width"), NULL,
3829 1, 5000, 1, options->stereo.fixed_w, &c_options->stereo.fixed_w);
3830 pref_table_spin_new_int(table, 3, 0, _("Height"), NULL,
3831 1, 5000, 1, options->stereo.fixed_h, &c_options->stereo.fixed_h);
3832 pref_table_spin_new_int(table, 0, 1, _("Left X"), NULL,
3833 0, 5000, 1, options->stereo.fixed_x1, &c_options->stereo.fixed_x1);
3834 pref_table_spin_new_int(table, 3, 1, _("Left Y"), NULL,
3835 0, 5000, 1, options->stereo.fixed_y1, &c_options->stereo.fixed_y1);
3836 pref_table_spin_new_int(table, 0, 2, _("Right X"), NULL,
3837 0, 5000, 1, options->stereo.fixed_x2, &c_options->stereo.fixed_x2);
3838 pref_table_spin_new_int(table, 3, 2, _("Right Y"), NULL,
3839 0, 5000, 1, options->stereo.fixed_y2, &c_options->stereo.fixed_y2);
3843 /* Main preferences window */
3844 static void config_window_create(LayoutWindow *lw)
3846 GtkWidget *win_vbox;
3848 GtkWidget *notebook;
3850 GtkWidget *ct_button;
3852 if (!c_options) c_options = init_options(NULL);
3854 configwindow = window_new(GTK_WINDOW_TOPLEVEL, "preferences", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Preferences"));
3855 DEBUG_NAME(configwindow);
3856 gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
3857 g_signal_connect(G_OBJECT(configwindow), "delete_event",
3858 G_CALLBACK(config_window_delete), NULL);
3859 if (options->save_dialog_window_positions)
3861 gtk_window_resize(GTK_WINDOW(configwindow), lw->options.preferences_window.w, lw->options.preferences_window.h);
3862 gtk_window_move(GTK_WINDOW(configwindow), lw->options.preferences_window.x, lw->options.preferences_window.y);
3866 gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
3868 gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
3869 gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
3871 win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
3872 gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
3873 gtk_widget_show(win_vbox);
3875 notebook = gtk_notebook_new();
3876 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_LEFT);
3877 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE);
3878 gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
3880 config_tab_general(notebook);
3881 config_tab_image(notebook);
3882 config_tab_osd(notebook);
3883 config_tab_windows(notebook);
3884 config_tab_accelerators(notebook);
3885 config_tab_files(notebook);
3886 config_tab_metadata(notebook);
3887 config_tab_keywords(notebook);
3888 config_tab_color(notebook);
3889 config_tab_stereo(notebook);
3890 config_tab_behavior(notebook);
3891 config_tab_toolbar_main(notebook);
3892 config_tab_toolbar_status(notebook);
3893 config_tab_advanced(notebook);
3895 gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), lw->options.preferences_window.page_number);
3897 hbox = gtk_hbutton_box_new();
3898 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
3899 gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
3900 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
3901 gtk_widget_show(hbox);
3903 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
3904 G_CALLBACK(config_window_help_cb), notebook);
3905 gtk_container_add(GTK_CONTAINER(hbox), button);
3906 gtk_widget_set_can_default(button, TRUE);
3907 gtk_widget_show(button);
3909 button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
3910 G_CALLBACK(config_window_ok_cb), notebook);
3911 gtk_container_add(GTK_CONTAINER(hbox), button);
3912 gtk_widget_set_can_default(button, TRUE);
3913 gtk_widget_grab_default(button);
3914 gtk_widget_show(button);
3918 button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
3919 G_CALLBACK(config_window_close_cb), NULL);
3920 gtk_container_add(GTK_CONTAINER(hbox), button);
3921 gtk_widget_set_can_default(button, TRUE);
3922 gtk_widget_show(button);
3924 if (!generic_dialog_get_alternative_button_order(configwindow))
3926 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
3929 gtk_widget_show(notebook);
3931 gtk_widget_show(configwindow);
3935 *-----------------------------------------------------------------------------
3936 * config window show (public)
3937 *-----------------------------------------------------------------------------
3940 void show_config_window(LayoutWindow *lw)
3944 gtk_window_present(GTK_WINDOW(configwindow));
3948 config_window_create(lw);
3957 void show_about_window(LayoutWindow *lw)
3959 GdkPixbuf *pixbuf_logo;
3960 GdkPixbuf *pixbuf_icon;
3961 gchar *authors[1000];
3966 gchar *timezone_path;
3970 #define LINE_LENGTH 1000
3971 gchar line[LINE_LENGTH];
3973 copyright = g_string_new(NULL);
3974 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");
3976 path = path_from_utf8(TIMEZONE_DATABASE);
3977 basename = g_path_get_basename(path);
3978 timezone_path = g_build_filename(get_rc_dir(), basename, NULL);
3979 if (g_file_test(timezone_path, G_FILE_TEST_EXISTS))
3981 cd = ZDOpenDatabase(timezone_path);
3984 copyright = g_string_append(copyright, ZDGetNotice(cd));
3985 ZDCloseDatabase(cd);
3989 g_free(timezone_path);
3993 path = g_build_filename(gq_helpdir, "AUTHORS", NULL);
3994 fp = fopen(path, "r");
3997 while(fgets(line, LINE_LENGTH, fp))
3999 /* get rid of ending \n from fgets */
4000 line[strlen(line) - 1] = '\0';
4001 authors[i_authors] = g_strdup(line);
4004 authors[i_authors] = NULL;
4009 comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
4010 "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
4012 pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
4013 pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
4014 gtk_show_about_dialog(GTK_WINDOW(lw->window),
4015 "title", _("About Geeqie"),
4017 "program-name", GQ_APPNAME,
4019 "logo", pixbuf_logo,
4020 "icon", pixbuf_icon,
4021 "website", GQ_WEBSITE,
4022 "website-label", "Website",
4023 "comments", comment,
4025 "translator-credits", _("translator-credits"),
4026 "wrap-license", TRUE,
4027 "license", copyright->str,
4030 g_string_free(copyright, TRUE);
4033 while(n < i_authors)
4043 static void image_overlay_set_text_colours()
4045 c_options->image_overlay.text_red = options->image_overlay.text_red;
4046 c_options->image_overlay.text_green = options->image_overlay.text_green;
4047 c_options->image_overlay.text_blue = options->image_overlay.text_blue;
4048 c_options->image_overlay.text_alpha = options->image_overlay.text_alpha;
4049 c_options->image_overlay.background_red = options->image_overlay.background_red;
4050 c_options->image_overlay.background_green = options->image_overlay.background_green;
4051 c_options->image_overlay.background_blue = options->image_overlay.background_blue;
4052 c_options->image_overlay.background_alpha = options->image_overlay.background_alpha;
4056 *-----------------------------------------------------------------------------
4057 * timezone database routines
4058 *-----------------------------------------------------------------------------
4061 static void timezone_async_ready_cb(GObject *source_object, GAsyncResult *res, gpointer data)
4063 GError *error = NULL;
4065 gchar *tmp_filename;
4067 if (!g_cancellable_is_cancelled(tz->cancellable))
4069 generic_dialog_close(tz->gd);
4073 if (g_file_copy_finish(G_FILE(source_object), res, &error))
4075 tmp_filename = g_file_get_parse_name(tz->tmp_g_file);
4076 move_file(tmp_filename, tz->timezone_database_user);
4077 g_free(tmp_filename);
4081 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
4084 g_file_delete(tz->tmp_g_file, NULL, &error);
4085 g_object_unref(tz->tmp_g_file);
4086 tz->tmp_g_file = NULL;
4087 g_object_unref(tz->cancellable);
4088 g_object_unref(tz->timezone_database_gq);
4091 static void timezone_progress_cb(goffset current_num_bytes, goffset total_num_bytes, gpointer data)
4095 if (!g_cancellable_is_cancelled(tz->cancellable))
4097 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(tz->progress), (gdouble)current_num_bytes / total_num_bytes);
4101 static void timezone_cancel_button_cb(GenericDialog *gd, gpointer data)
4105 g_cancellable_cancel(tz->cancellable);
4108 static void timezone_database_install_cb(GtkWidget *widget, gpointer data)
4111 GError *error = NULL;
4112 GFileIOStream *io_stream;
4119 tz->tmp_g_file = g_file_new_tmp("geeqie_timezone_XXXXXX", &io_stream, &error);
4123 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
4124 log_printf("Error: Download timezone database failed:\n%s", error->message);
4125 g_error_free(error);
4126 g_object_unref(tz->tmp_g_file);
4130 tz->timezone_database_gq = g_file_new_for_uri(TIMEZONE_DATABASE);
4132 tz->gd = generic_dialog_new(_("Timezone database"), "download_timezone_database", NULL, TRUE, timezone_cancel_button_cb, tz);
4134 generic_dialog_add_message(tz->gd, GTK_STOCK_DIALOG_INFO, _("Downloading timezone database"), NULL, FALSE);
4136 tz->progress = gtk_progress_bar_new();
4137 gtk_box_pack_start(GTK_BOX(tz->gd->vbox), tz->progress, FALSE, FALSE, 0);
4138 gtk_widget_show(tz->progress);
4140 gtk_widget_show(tz->gd->dialog);
4141 tz->cancellable = g_cancellable_new();
4142 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);
4144 gtk_button_set_label(GTK_BUTTON(widget), _("Update"));
4147 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */