2 * Copyright (C) 2006 John Ellis
3 * Copyright (C) 2008 - 2016 The Geeqie Team
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include "preferences.h"
26 #include "bar_keywords.h"
28 #include "cache_maint.h"
33 #include "filefilter.h"
34 #include "fullscreen.h"
36 #include "image-overlay.h"
37 #include "color-man.h"
39 #include "layout_config.h"
40 #include "layout_util.h"
44 #include "pixbuf_util.h"
46 #include "slideshow.h"
50 #include "ui_fileops.h"
52 #include "ui_spinner.h"
53 #include "ui_tabcomp.h"
54 #include "ui_utildlg.h"
56 #include "zonedetect.h"
66 #define EDITOR_NAME_MAX_LENGTH 32
67 #define EDITOR_COMMAND_MAX_LENGTH 1024
69 static void image_overlay_set_text_colours();
71 GtkWidget *keyword_text;
72 static void config_tab_keywords_save();
74 typedef struct _ThumbSize ThumbSize;
81 static ThumbSize thumb_size_list[] =
115 gchar *format_class_list[] = {
126 /* config memory values */
127 static ConfOptions *c_options = NULL;
134 static GtkWidget *configwindow = NULL;
135 static GtkListStore *filter_store = NULL;
136 static GtkTreeStore *accel_store = NULL;
138 static GtkWidget *safe_delete_path_entry;
140 static GtkWidget *color_profile_input_file_entry[COLOR_PROFILE_INPUTS];
141 static GtkWidget *color_profile_input_name_entry[COLOR_PROFILE_INPUTS];
142 static GtkWidget *color_profile_screen_file_entry;
143 static GtkWidget *external_preview_select_entry;
144 static GtkWidget *external_preview_extract_entry;
146 static GtkWidget *sidecar_ext_entry;
147 static GtkWidget *help_search_engine_entry;
150 #define CONFIG_WINDOW_DEF_WIDTH 700
151 #define CONFIG_WINDOW_DEF_HEIGHT 600
154 *-----------------------------------------------------------------------------
155 * option widget callbacks (private)
156 *-----------------------------------------------------------------------------
159 static void zoom_increment_cb(GtkWidget *spin, gpointer data)
161 c_options->image.zoom_increment = (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) * 100.0 + 0.01);
164 static void slideshow_delay_hours_cb(GtkWidget *spin, gpointer data)
166 gint mins_secs_tenths, delay;
168 mins_secs_tenths = c_options->slideshow.delay %
169 (3600 * SLIDESHOW_SUBSECOND_PRECISION);
171 delay = (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
172 (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
175 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
176 SLIDESHOW_SUBSECOND_PRECISION;
179 static void slideshow_delay_minutes_cb(GtkWidget *spin, gpointer data)
181 gint hours, secs_tenths, delay;
183 hours = c_options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
184 secs_tenths = c_options->slideshow.delay % (60 * SLIDESHOW_SUBSECOND_PRECISION);
186 delay = hours * (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
187 (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
188 (60 * SLIDESHOW_SUBSECOND_PRECISION) + secs_tenths);
190 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
191 SLIDESHOW_SUBSECOND_PRECISION;
194 static void slideshow_delay_seconds_cb(GtkWidget *spin, gpointer data)
196 gint hours_mins, delay;
198 hours_mins = c_options->slideshow.delay / (60 * SLIDESHOW_SUBSECOND_PRECISION);
200 delay = (hours_mins * (60 * SLIDESHOW_SUBSECOND_PRECISION)) +
201 (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
202 (gdouble)(SLIDESHOW_SUBSECOND_PRECISION) + 0.01);
204 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
205 SLIDESHOW_SUBSECOND_PRECISION;
209 *-----------------------------------------------------------------------------
210 * sync program to config window routine (private)
211 *-----------------------------------------------------------------------------
214 void config_entry_to_option(GtkWidget *entry, gchar **option, gchar *(*func)(const gchar *))
220 buf = gtk_entry_get_text(GTK_ENTRY(entry));
221 if (buf && strlen(buf) > 0)
226 *option = g_strdup(buf);
231 static gboolean accel_apply_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
233 gchar *accel_path, *accel;
235 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, AE_KEY, &accel, -1);
237 if (accel_path && accel_path[0])
240 gtk_accelerator_parse(accel, &key.accel_key, &key.accel_mods);
241 gtk_accel_map_change_entry(accel_path, key.accel_key, key.accel_mods, TRUE);
251 static void config_window_apply(void)
253 gboolean refresh = FALSE;
258 config_entry_to_option(safe_delete_path_entry, &options->file_ops.safe_delete_path, remove_trailing_slash);
260 if (options->file_filter.show_hidden_files != c_options->file_filter.show_hidden_files) refresh = TRUE;
261 if (options->file_filter.show_parent_directory != c_options->file_filter.show_parent_directory) refresh = TRUE;
262 if (options->file_filter.show_dot_directory != c_options->file_filter.show_dot_directory) refresh = TRUE;
263 if (options->file_sort.case_sensitive != c_options->file_sort.case_sensitive) refresh = TRUE;
264 if (options->file_sort.natural != c_options->file_sort.natural) refresh = TRUE;
265 if (options->file_filter.disable_file_extension_checks != c_options->file_filter.disable_file_extension_checks) refresh = TRUE;
266 if (options->file_filter.disable != c_options->file_filter.disable) refresh = TRUE;
268 options->file_ops.confirm_delete = c_options->file_ops.confirm_delete;
269 options->file_ops.enable_delete_key = c_options->file_ops.enable_delete_key;
270 options->file_ops.confirm_move_to_trash = c_options->file_ops.confirm_move_to_trash;
271 options->file_ops.use_system_trash = c_options->file_ops.use_system_trash;
272 options->file_ops.no_trash = c_options->file_ops.no_trash;
273 options->file_ops.safe_delete_folder_maxsize = c_options->file_ops.safe_delete_folder_maxsize;
274 options->tools_restore_state = c_options->tools_restore_state;
275 options->save_window_positions = c_options->save_window_positions;
276 options->use_saved_window_positions_for_new_windows = c_options->use_saved_window_positions_for_new_windows;
277 options->save_window_workspace = c_options->save_window_workspace;
278 options->save_dialog_window_positions = c_options->save_dialog_window_positions;
279 options->show_window_ids = c_options->show_window_ids;
280 options->image.scroll_reset_method = c_options->image.scroll_reset_method;
281 options->image.zoom_2pass = c_options->image.zoom_2pass;
282 options->image.fit_window_to_image = c_options->image.fit_window_to_image;
283 options->image.limit_window_size = c_options->image.limit_window_size;
284 options->image.zoom_to_fit_allow_expand = c_options->image.zoom_to_fit_allow_expand;
285 options->image.max_window_size = c_options->image.max_window_size;
286 options->image.limit_autofit_size = c_options->image.limit_autofit_size;
287 options->image.max_autofit_size = c_options->image.max_autofit_size;
288 options->image.max_enlargement_size = c_options->image.max_enlargement_size;
289 options->image.use_clutter_renderer = c_options->image.use_clutter_renderer;
290 options->image.tile_size = c_options->image.tile_size;
291 options->progressive_key_scrolling = c_options->progressive_key_scrolling;
292 options->keyboard_scroll_step = c_options->keyboard_scroll_step;
294 if (options->thumbnails.max_width != c_options->thumbnails.max_width
295 || options->thumbnails.max_height != c_options->thumbnails.max_height
296 || options->thumbnails.quality != c_options->thumbnails.quality)
298 thumb_format_changed = TRUE;
300 options->thumbnails.max_width = c_options->thumbnails.max_width;
301 options->thumbnails.max_height = c_options->thumbnails.max_height;
302 options->thumbnails.quality = c_options->thumbnails.quality;
304 options->thumbnails.enable_caching = c_options->thumbnails.enable_caching;
305 options->thumbnails.cache_into_dirs = c_options->thumbnails.cache_into_dirs;
306 options->thumbnails.use_exif = c_options->thumbnails.use_exif;
307 options->thumbnails.use_color_management = c_options->thumbnails.use_color_management;
308 options->thumbnails.collection_preview = c_options->thumbnails.collection_preview;
309 options->thumbnails.use_ft_metadata = c_options->thumbnails.use_ft_metadata;
310 // options->thumbnails.use_ft_metadata_small = c_options->thumbnails.use_ft_metadata_small;
311 options->thumbnails.spec_standard = c_options->thumbnails.spec_standard;
312 options->metadata.enable_metadata_dirs = c_options->metadata.enable_metadata_dirs;
313 options->file_filter.show_hidden_files = c_options->file_filter.show_hidden_files;
314 options->file_filter.show_parent_directory = c_options->file_filter.show_parent_directory;
315 options->file_filter.show_dot_directory = c_options->file_filter.show_dot_directory;
316 options->file_filter.disable_file_extension_checks = c_options->file_filter.disable_file_extension_checks;
318 options->file_sort.case_sensitive = c_options->file_sort.case_sensitive;
319 options->file_sort.natural = c_options->file_sort.natural;
320 options->file_filter.disable = c_options->file_filter.disable;
322 config_entry_to_option(sidecar_ext_entry, &options->sidecar.ext, NULL);
323 sidecar_ext_parse(options->sidecar.ext);
325 options->slideshow.random = c_options->slideshow.random;
326 options->slideshow.repeat = c_options->slideshow.repeat;
327 options->slideshow.delay = c_options->slideshow.delay;
329 options->mousewheel_scrolls = c_options->mousewheel_scrolls;
330 options->image_lm_click_nav = c_options->image_lm_click_nav;
331 options->image_l_click_archive = c_options->image_l_click_archive;
332 options->image_l_click_video = c_options->image_l_click_video;
333 options->image_l_click_video_editor = c_options->image_l_click_video_editor;
335 options->file_ops.enable_in_place_rename = c_options->file_ops.enable_in_place_rename;
337 options->image.tile_cache_max = c_options->image.tile_cache_max;
338 options->image.image_cache_max = c_options->image.image_cache_max;
340 options->image.zoom_quality = c_options->image.zoom_quality;
342 options->image.zoom_increment = c_options->image.zoom_increment;
344 options->image.enable_read_ahead = c_options->image.enable_read_ahead;
347 if (options->image.use_custom_border_color != c_options->image.use_custom_border_color
348 || options->image.use_custom_border_color_in_fullscreen != c_options->image.use_custom_border_color_in_fullscreen
349 || !gdk_color_equal(&options->image.border_color, &c_options->image.border_color))
351 options->image.use_custom_border_color_in_fullscreen = c_options->image.use_custom_border_color_in_fullscreen;
352 options->image.use_custom_border_color = c_options->image.use_custom_border_color;
353 options->image.border_color = c_options->image.border_color;
354 layout_colors_update();
355 view_window_colors_update();
358 options->image.alpha_color_1 = c_options->image.alpha_color_1;
359 options->image.alpha_color_2 = c_options->image.alpha_color_2;
361 options->fullscreen.screen = c_options->fullscreen.screen;
362 options->fullscreen.clean_flip = c_options->fullscreen.clean_flip;
363 options->fullscreen.disable_saver = c_options->fullscreen.disable_saver;
364 options->fullscreen.above = c_options->fullscreen.above;
365 if (c_options->image_overlay.template_string)
366 set_image_overlay_template_string(&options->image_overlay.template_string,
367 c_options->image_overlay.template_string);
368 if (c_options->image_overlay.font)
369 set_image_overlay_font_string(&options->image_overlay.font,
370 c_options->image_overlay.font);
371 options->image_overlay.text_red = c_options->image_overlay.text_red;
372 options->image_overlay.text_green = c_options->image_overlay.text_green;
373 options->image_overlay.text_blue = c_options->image_overlay.text_blue;
374 options->image_overlay.text_alpha = c_options->image_overlay.text_alpha;
375 options->image_overlay.background_red = c_options->image_overlay.background_red;
376 options->image_overlay.background_green = c_options->image_overlay.background_green;
377 options->image_overlay.background_blue = c_options->image_overlay.background_blue;
378 options->image_overlay.background_alpha = c_options->image_overlay.background_alpha;
379 options->update_on_time_change = c_options->update_on_time_change;
380 options->image.exif_proof_rotate_enable = c_options->image.exif_proof_rotate_enable;
382 options->duplicates_similarity_threshold = c_options->duplicates_similarity_threshold;
383 options->rot_invariant_sim = c_options->rot_invariant_sim;
385 options->tree_descend_subdirs = c_options->tree_descend_subdirs;
387 options->view_dir_list_single_click_enter = c_options->view_dir_list_single_click_enter;
388 options->circular_selection_lists = c_options->circular_selection_lists;
390 options->open_recent_list_maxsize = c_options->open_recent_list_maxsize;
391 options->dnd_icon_size = c_options->dnd_icon_size;
392 options->clipboard_selection = c_options->clipboard_selection;
393 options->dnd_default_action = c_options->dnd_default_action;
395 options->metadata.save_in_image_file = c_options->metadata.save_in_image_file;
396 options->metadata.save_legacy_IPTC = c_options->metadata.save_legacy_IPTC;
397 options->metadata.warn_on_write_problems = c_options->metadata.warn_on_write_problems;
398 options->metadata.save_legacy_format = c_options->metadata.save_legacy_format;
399 options->metadata.sync_grouped_files = c_options->metadata.sync_grouped_files;
400 options->metadata.confirm_write = c_options->metadata.confirm_write;
401 options->metadata.sidecar_extended_name = c_options->metadata.sidecar_extended_name;
402 options->metadata.confirm_timeout = c_options->metadata.confirm_timeout;
403 options->metadata.confirm_after_timeout = c_options->metadata.confirm_after_timeout;
404 options->metadata.confirm_on_image_change = c_options->metadata.confirm_on_image_change;
405 options->metadata.confirm_on_dir_change = c_options->metadata.confirm_on_dir_change;
406 options->metadata.keywords_case_sensitive = c_options->metadata.keywords_case_sensitive;
407 options->metadata.write_orientation = c_options->metadata.write_orientation;
408 options->stereo.mode = (c_options->stereo.mode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
409 (c_options->stereo.tmp.mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
410 (c_options->stereo.tmp.flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
411 (c_options->stereo.tmp.mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
412 (c_options->stereo.tmp.flip_left ? PR_STEREO_FLIP_LEFT : 0) |
413 (c_options->stereo.tmp.swap ? PR_STEREO_SWAP : 0) |
414 (c_options->stereo.tmp.temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
415 options->stereo.fsmode = (c_options->stereo.fsmode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
416 (c_options->stereo.tmp.fs_mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
417 (c_options->stereo.tmp.fs_flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
418 (c_options->stereo.tmp.fs_mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
419 (c_options->stereo.tmp.fs_flip_left ? PR_STEREO_FLIP_LEFT : 0) |
420 (c_options->stereo.tmp.fs_swap ? PR_STEREO_SWAP : 0) |
421 (c_options->stereo.tmp.fs_temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
422 options->stereo.enable_fsmode = c_options->stereo.enable_fsmode;
423 options->stereo.fixed_w = c_options->stereo.fixed_w;
424 options->stereo.fixed_h = c_options->stereo.fixed_h;
425 options->stereo.fixed_x1 = c_options->stereo.fixed_x1;
426 options->stereo.fixed_y1 = c_options->stereo.fixed_y1;
427 options->stereo.fixed_x2 = c_options->stereo.fixed_x2;
428 options->stereo.fixed_y2 = c_options->stereo.fixed_y2;
430 options->info_keywords.height = c_options->info_keywords.height;
431 options->info_title.height = c_options->info_title.height;
432 options->info_comment.height = c_options->info_comment.height;
433 options->info_rating.height = c_options->info_rating.height;
435 options->show_predefined_keyword_tree = c_options->show_predefined_keyword_tree;
436 options->expand_menu_toolbar = c_options->expand_menu_toolbar;
438 options->marks_save = c_options->marks_save;
439 options->with_rename = c_options->with_rename;
440 options->collections_on_top = c_options->collections_on_top;
441 options->hide_window_in_fullscreen = c_options->hide_window_in_fullscreen;
442 config_entry_to_option(help_search_engine_entry, &options->help_search_engine, NULL);
444 options->external_preview.enable = c_options->external_preview.enable;
445 config_entry_to_option(external_preview_select_entry, &options->external_preview.select, NULL);
446 config_entry_to_option(external_preview_extract_entry, &options->external_preview.extract, NULL);
448 options->read_metadata_in_idle = c_options->read_metadata_in_idle;
450 options->star_rating.star = c_options->star_rating.star;
451 options->star_rating.rejected = c_options->star_rating.rejected;
453 options->threads.duplicates = c_options->threads.duplicates > 0 ? c_options->threads.duplicates : -1;
456 set_debug_level(debug_c);
460 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
462 config_entry_to_option(color_profile_input_name_entry[i], &options->color_profile.input_name[i], NULL);
463 config_entry_to_option(color_profile_input_file_entry[i], &options->color_profile.input_file[i], NULL);
465 config_entry_to_option(color_profile_screen_file_entry, &options->color_profile.screen_file, NULL);
466 options->color_profile.use_x11_screen_profile = c_options->color_profile.use_x11_screen_profile;
467 if (options->color_profile.render_intent != c_options->color_profile.render_intent)
469 options->color_profile.render_intent = c_options->color_profile.render_intent;
474 options->mouse_button_8 = c_options->mouse_button_8;
475 options->mouse_button_9 = c_options->mouse_button_9;
477 options->override_disable_gpu = c_options->override_disable_gpu;
479 config_tab_keywords_save();
481 image_options_sync();
486 layout_refresh(NULL);
489 if (accel_store) gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_apply_cb, NULL);
491 toolbar_apply(TOOLBAR_MAIN);
492 toolbar_apply(TOOLBAR_STATUS);
496 *-----------------------------------------------------------------------------
497 * config window main button callbacks (private)
498 *-----------------------------------------------------------------------------
501 static void config_window_close_cb(GtkWidget *widget, gpointer data)
503 gtk_widget_destroy(configwindow);
508 static void config_window_help_cb(GtkWidget *widget, gpointer data)
510 GtkWidget *notebook = data;
513 static gchar *html_section[] =
515 "GuideOptionsGeneral.html",
516 "GuideOptionsImage.html",
517 "GuideOptionsOSD.html",
518 "GuideOptionsWindow.html",
519 "GuideOptionsKeyboard.html",
520 "GuideOptionsFiltering.html",
521 "GuideOptionsMetadata.html",
522 "GuideOptionsKeywords.html",
523 "GuideOptionsColor.html",
524 "GuideOptionsStereo.html",
525 "GuideOptionsBehavior.html",
526 "GuideOptionsToolbar.html",
527 "GuideOptionsToolbar.html",
528 "GuideOptionsAdvanced.html"
531 i = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
532 help_window_show(html_section[i]);
535 static gboolean config_window_delete(GtkWidget *widget, GdkEventAny *event, gpointer data)
537 config_window_close_cb(NULL, NULL);
541 static void config_window_ok_cb(GtkWidget *widget, gpointer data)
544 GtkNotebook *notebook = data;
552 lw = layout_window_list->data;
554 window = gtk_widget_get_window(widget);
555 gdk_window_get_root_origin(window, &x, &y);
556 w = gdk_window_get_width(window);
557 h = gdk_window_get_height(window);
558 page_number = gtk_notebook_get_current_page(notebook);
560 lw->options.preferences_window.x = x;
561 lw->options.preferences_window.y = y;
562 lw->options.preferences_window.w = w;
563 lw->options.preferences_window.h = h;
564 lw->options.preferences_window.page_number = page_number;
566 config_window_apply();
567 layout_util_sync(lw);
568 save_options(options);
569 config_window_close_cb(NULL, NULL);
573 *-----------------------------------------------------------------------------
574 * config window setup (private)
575 *-----------------------------------------------------------------------------
578 static void quality_menu_cb(GtkWidget *combo, gpointer data)
582 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
586 *option = GDK_INTERP_NEAREST;
589 *option = GDK_INTERP_TILES;
592 *option = GDK_INTERP_BILINEAR;
597 static void dnd_default_action_selection_menu_cb(GtkWidget *combo, gpointer data)
601 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
605 *option = DND_ACTION_ASK;
608 *option = DND_ACTION_COPY;
611 *option = DND_ACTION_MOVE;
615 static void clipboard_selection_menu_cb(GtkWidget *combo, gpointer data)
619 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
622 *option = CLIPBOARD_PRIMARY;
625 *option = CLIPBOARD_CLIPBOARD;
628 *option = CLIPBOARD_BOTH;
631 *option = CLIPBOARD_BOTH;
635 static void add_quality_menu(GtkWidget *table, gint column, gint row, const gchar *text,
636 guint option, guint *option_c)
643 pref_table_label(table, column, row, text, 0.0);
645 combo = gtk_combo_box_text_new();
647 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Nearest (worst, but fastest)"));
648 if (option == GDK_INTERP_NEAREST) current = 0;
649 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Tiles"));
650 if (option == GDK_INTERP_TILES) current = 1;
651 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Bilinear (best, but slowest)"));
652 if (option == GDK_INTERP_BILINEAR) current = 2;
654 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
656 g_signal_connect(G_OBJECT(combo), "changed",
657 G_CALLBACK(quality_menu_cb), option_c);
659 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
660 gtk_widget_show(combo);
663 static void add_dnd_default_action_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text, DnDAction option, DnDAction *option_c)
670 pref_table_label(table, column, row, text, 0.0);
672 combo = gtk_combo_box_text_new();
674 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Ask"));
675 if (option == DND_ACTION_ASK) current = 0;
676 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Copy"));
677 if (option == DND_ACTION_COPY) current = 1;
678 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Move"));
679 if (option == DND_ACTION_MOVE) current = 2;
681 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
683 g_signal_connect(G_OBJECT(combo), "changed",
684 G_CALLBACK(dnd_default_action_selection_menu_cb), option_c);
686 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
687 gtk_widget_show(combo);
690 static void add_clipboard_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
691 gint option, gint *option_c)
698 pref_table_label(table, column, row, text, 0.0);
700 combo = gtk_combo_box_text_new();
702 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Primary"));
703 if (option == CLIPBOARD_PRIMARY) current = 0;
704 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Clipboard"));
705 if (option == CLIPBOARD_CLIPBOARD) current = 1;
706 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Both"));
707 if (option == CLIPBOARD_BOTH) current = 2;
709 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
711 g_signal_connect(G_OBJECT(combo), "changed",
712 G_CALLBACK(clipboard_selection_menu_cb), option_c);
714 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
715 gtk_widget_show(combo);
718 typedef struct _UseableMouseItems UseableMouseItems;
719 struct _UseableMouseItems
721 gchar *name; /* GtkActionEntry terminology */
726 static const UseableMouseItems useable_mouse_items[] = {
728 {"FirstImage", N_("First Image"), GTK_STOCK_GOTO_TOP},
729 {"PrevImage", N_("Previous Image"), GTK_STOCK_GO_UP},
730 {"NextImage", N_("Next Image"), GTK_STOCK_GO_DOWN},
731 {"LastImage", N_("Last Image"), GTK_STOCK_GOTO_BOTTOM},
732 {"Back", N_("Back"), GTK_STOCK_GO_BACK},
733 {"Forward", N_("Forward"), GTK_STOCK_GO_FORWARD},
734 {"Home", N_("Home"), GTK_STOCK_HOME},
735 {"Up", N_("Up"), GTK_STOCK_GO_UP},
736 {"FirstPage", N_("First page"), GTK_STOCK_MEDIA_PREVIOUS},
737 {"LastPage", N_("Last Page"), GTK_STOCK_MEDIA_NEXT},
738 {"NextPage", N_("Next page"), GTK_STOCK_MEDIA_FORWARD},
739 {"PrevPage", N_("Previous Page"), GTK_STOCK_MEDIA_REWIND},
740 {"NewWindow", N_("New _window"), GTK_STOCK_NEW},
741 {"NewCollection", N_("New collection"), GTK_STOCK_INDEX},
742 {"OpenCollection", N_("Open collection"), GTK_STOCK_OPEN},
743 {"Search", N_("Search"), GTK_STOCK_FIND},
744 {"FindDupes", N_("Find duplicates"), GTK_STOCK_FIND},
745 {"NewFolder", N_("New folder"),GTK_STOCK_DIRECTORY},
746 {"Copy", N_("Copy"), GTK_STOCK_COPY},
747 {"Move", N_("Move"), PIXBUF_INLINE_ICON_MOVE},
748 {"Rename", N_("Rename"), PIXBUF_INLINE_ICON_RENAME},
749 {"Delete", N_("Delete"), GTK_STOCK_DELETE},
750 {"CloseWindow", N_("Close Window"), GTK_STOCK_CLOSE},
751 {"PanView", N_("Pan view"), PIXBUF_INLINE_ICON_PANORAMA},
752 {"SelectAll", N_("Select all"), PIXBUF_INLINE_ICON_SELECT_ALL},
753 {"SelectNone", N_("Select none"), PIXBUF_INLINE_ICON_SELECT_NONE},
754 {"SelectInvert", N_("Select invert"), PIXBUF_INLINE_ICON_SELECT_INVERT},
755 {"ShowFileFilter", N_("Show file filter"), PIXBUF_INLINE_ICON_FILE_FILTER},
756 {"RectangularSelection", N_("Select rectangle"), PIXBUF_INLINE_ICON_SELECT_RECTANGLE},
757 {"Print", N_("Print"), GTK_STOCK_PRINT},
758 {"Preferences", N_("Preferences"), GTK_STOCK_PREFERENCES},
759 {"LayoutConfig", N_("Configure this window"), GTK_STOCK_PREFERENCES},
760 {"Maintenance", N_("Cache maintenance"), PIXBUF_INLINE_ICON_MAINTENANCE},
761 {"RotateCW", N_("Rotate clockwise 90°"), PIXBUF_INLINE_ICON_CW},
762 {"RotateCCW", N_("Rotate counterclockwise 90°"), PIXBUF_INLINE_ICON_CCW},
763 {"Rotate180", N_("Rotate 180°"), PIXBUF_INLINE_ICON_180},
764 {"Mirror", N_("Mirror"), PIXBUF_INLINE_ICON_MIRROR},
765 {"Flip", N_("Flip"), PIXBUF_INLINE_ICON_FLIP},
766 {"AlterNone", N_("Original state"), PIXBUF_INLINE_ICON_ORIGINAL},
767 {"ZoomIn", N_("Zoom in"), GTK_STOCK_ZOOM_IN},
768 {"ZoomOut", N_("Zoom out"), GTK_STOCK_ZOOM_OUT},
769 {"Zoom100", N_("Zoom 1:1"), GTK_STOCK_ZOOM_100},
770 {"ZoomFit", N_("Zoom to fit"), GTK_STOCK_ZOOM_FIT},
771 {"ZoomFillHor", N_("Fit Horizontaly"), PIXBUF_INLINE_ICON_ZOOMFILLHOR},
772 {"ZoomFillVert", N_("Fit vertically"), PIXBUF_INLINE_ICON_ZOOMFILLVERT},
773 {"Zoom200", N_("Zoom 2:1"), GTK_STOCK_FILE},
774 {"Zoom300", N_("Zoom 3:1"), GTK_STOCK_FILE},
775 {"Zoom400", N_("Zoom 4:1"), GTK_STOCK_FILE},
776 {"Zoom50", N_("Zoom 1:2"), GTK_STOCK_FILE},
777 {"Zoom33", N_("Zoom1:3"), GTK_STOCK_FILE},
778 {"Zoom25", N_("Zoom 1:4"), GTK_STOCK_FILE},
779 {"ConnectZoomIn", N_("Connected Zoom in"), GTK_STOCK_ZOOM_IN},
780 {"SplitPaneSync", N_("Split Pane Sync"), PIXBUF_INLINE_SPLIT_PANE_SYNC},
781 {"Grayscale", N_("Grayscale"), PIXBUF_INLINE_ICON_GRAYSCALE},
782 {"OverUnderExposed", N_("Over Under Exposed"), PIXBUF_INLINE_ICON_EXPOSURE},
783 {"HideTools", N_("Hide file list"), PIXBUF_INLINE_ICON_HIDETOOLS},
784 {"SlideShowPause", N_("Pause slideshow"), GTK_STOCK_MEDIA_PAUSE},
785 {"SlideShowFaster", N_("Slideshow Faster"), GTK_STOCK_FILE},
786 {"SlideShowSlower", N_("Slideshow Slower"), GTK_STOCK_FILE},
787 {"Refresh", N_("Refresh"), GTK_STOCK_REFRESH},
788 {"HelpContents", N_("Help"), GTK_STOCK_HELP},
789 {"ExifWin", N_("Exif window"), PIXBUF_INLINE_ICON_EXIF},
790 {"Thumbnails", N_("Show thumbnails"), PIXBUF_INLINE_ICON_THUMB},
791 {"ShowMarks", N_("Show marks"), PIXBUF_INLINE_ICON_MARKS},
792 {"DrawRectangle", N_("Draw Rectangle"), PIXBUF_INLINE_ICON_DRAW_RECTANGLE},
793 {"FloatTools", N_("Float file list"), PIXBUF_INLINE_ICON_FLOAT},
794 {"SBar", N_("Info sidebar"), PIXBUF_INLINE_ICON_INFO},
795 {"SBarSort", N_("Sort manager"), PIXBUF_INLINE_ICON_SORT},
796 {"Quit", N_("Quit"), GTK_STOCK_QUIT},
800 static void mouse_buttons_selection_menu_cb(GtkWidget *combo, gpointer data)
802 gchar **option = data;
805 label = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(combo));
807 const UseableMouseItems *list = useable_mouse_items;
811 if (g_strcmp0(list->label, label) == 0)
819 *option = g_strdup(list->name);
823 static void add_mouse_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
824 gchar *option, gchar **option_c)
832 pref_table_label(table, column, row, text, 0.0);
834 combo = gtk_combo_box_text_new();
836 const UseableMouseItems *list = useable_mouse_items;
840 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), list->label);
841 if (g_strcmp0(list->name, option) == 0)
849 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
851 g_signal_connect(G_OBJECT(combo), "changed",
852 G_CALLBACK(mouse_buttons_selection_menu_cb), option_c);
854 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
855 gtk_widget_show(combo);
858 static void thumb_size_menu_cb(GtkWidget *combo, gpointer data)
862 n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
865 if ((guint) n < sizeof(thumb_size_list) / sizeof(ThumbSize))
867 c_options->thumbnails.max_width = thumb_size_list[n].w;
868 c_options->thumbnails.max_height = thumb_size_list[n].h;
872 c_options->thumbnails.max_width = options->thumbnails.max_width;
873 c_options->thumbnails.max_height = options->thumbnails.max_height;
877 static void add_thumb_size_menu(GtkWidget *table, gint column, gint row, gchar *text)
883 c_options->thumbnails.max_width = options->thumbnails.max_width;
884 c_options->thumbnails.max_height = options->thumbnails.max_height;
886 pref_table_label(table, column, row, text, 0.0);
888 combo = gtk_combo_box_text_new();
891 for (i = 0; (guint) i < sizeof(thumb_size_list) / sizeof(ThumbSize); i++)
896 w = thumb_size_list[i].w;
897 h = thumb_size_list[i].h;
899 buf = g_strdup_printf("%d x %d", w, h);
900 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
903 if (w == options->thumbnails.max_width && h == options->thumbnails.max_height) current = i;
910 buf = g_strdup_printf("%s %d x %d", _("Custom"), options->thumbnails.max_width, options->thumbnails.max_height);
911 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
917 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
918 g_signal_connect(G_OBJECT(combo), "changed",
919 G_CALLBACK(thumb_size_menu_cb), NULL);
921 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
922 gtk_widget_show(combo);
925 static void stereo_mode_menu_cb(GtkWidget *combo, gpointer data)
929 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
933 *option = PR_STEREO_NONE;
936 *option = PR_STEREO_ANAGLYPH_RC;
939 *option = PR_STEREO_ANAGLYPH_GM;
942 *option = PR_STEREO_ANAGLYPH_YB;
945 *option = PR_STEREO_ANAGLYPH_GRAY_RC;
948 *option = PR_STEREO_ANAGLYPH_GRAY_GM;
951 *option = PR_STEREO_ANAGLYPH_GRAY_YB;
954 *option = PR_STEREO_ANAGLYPH_DB_RC;
957 *option = PR_STEREO_ANAGLYPH_DB_GM;
960 *option = PR_STEREO_ANAGLYPH_DB_YB;
963 *option = PR_STEREO_HORIZ;
966 *option = PR_STEREO_HORIZ | PR_STEREO_HALF;
969 *option = PR_STEREO_VERT;
972 *option = PR_STEREO_VERT | PR_STEREO_HALF;
975 *option = PR_STEREO_FIXED;
980 static void add_stereo_mode_menu(GtkWidget *table, gint column, gint row, const gchar *text,
981 gint option, gint *option_c, gboolean add_fixed)
988 pref_table_label(table, column, row, text, 0.0);
990 combo = gtk_combo_box_text_new();
992 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Single image"));
994 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Red-Cyan"));
995 if (option & PR_STEREO_ANAGLYPH_RC) current = 1;
996 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Green-Magenta"));
997 if (option & PR_STEREO_ANAGLYPH_GM) current = 2;
998 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Yellow-Blue"));
999 if (option & PR_STEREO_ANAGLYPH_YB) current = 3;
1000 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Red-Cyan"));
1001 if (option & PR_STEREO_ANAGLYPH_GRAY_RC) current = 4;
1002 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Green-Magenta"));
1003 if (option & PR_STEREO_ANAGLYPH_GRAY_GM) current = 5;
1004 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Yellow-Blue"));
1005 if (option & PR_STEREO_ANAGLYPH_GRAY_YB) current = 6;
1006 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Red-Cyan"));
1007 if (option & PR_STEREO_ANAGLYPH_DB_RC) current = 7;
1008 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Green-Magenta"));
1009 if (option & PR_STEREO_ANAGLYPH_DB_GM) current = 8;
1010 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Yellow-Blue"));
1011 if (option & PR_STEREO_ANAGLYPH_DB_YB) current = 9;
1013 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side"));
1014 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side Half size"));
1015 if (option & PR_STEREO_HORIZ)
1018 if (option & PR_STEREO_HALF) current = 11;
1021 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom"));
1022 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom Half size"));
1023 if (option & PR_STEREO_VERT)
1026 if (option & PR_STEREO_HALF) current = 13;
1031 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Fixed position"));
1032 if (option & PR_STEREO_FIXED) current = 14;
1035 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
1037 g_signal_connect(G_OBJECT(combo), "changed",
1038 G_CALLBACK(stereo_mode_menu_cb), option_c);
1040 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
1041 gtk_widget_show(combo);
1044 static void video_menu_cb(GtkWidget *combo, gpointer data)
1046 gchar **option = data;
1048 EditorDescription *ed = g_list_nth_data(editor_list_get(), gtk_combo_box_get_active(GTK_COMBO_BOX(combo)));
1052 static void video_menu_populate(gpointer data, gpointer user_data)
1054 GtkWidget *combo = user_data;
1055 EditorDescription *ed = data;
1057 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), ed->name);
1060 static void add_video_menu(GtkWidget *table, gint column, gint row, const gchar *text,
1061 gchar *option, gchar **option_c)
1065 /* use lists since they are sorted */
1066 GList *eds = editor_list_get();
1070 pref_table_label(table, column, row, text, 0.0);
1072 combo = gtk_combo_box_text_new();
1073 g_list_foreach(eds,video_menu_populate,(gpointer)combo);
1074 current = option ? g_list_index(eds,g_hash_table_lookup(editors,option)): -1;
1076 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
1078 g_signal_connect(G_OBJECT(combo), "changed",
1079 G_CALLBACK(video_menu_cb), option_c);
1081 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
1082 gtk_widget_show(combo);
1085 static void filter_store_populate(void)
1089 if (!filter_store) return;
1091 gtk_list_store_clear(filter_store);
1093 work = filter_get_list();
1102 gtk_list_store_append(filter_store, &iter);
1103 gtk_list_store_set(filter_store, &iter, 0, fe, -1);
1107 static void filter_store_ext_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1108 gchar *new_text, gpointer data)
1110 GtkWidget *model = data;
1111 FilterEntry *fe = data;
1115 if (!new_text || strlen(new_text) < 1) return;
1117 tpath = gtk_tree_path_new_from_string(path_str);
1118 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1119 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1121 g_free(fe->extensions);
1122 fe->extensions = g_strdup(new_text);
1124 gtk_tree_path_free(tpath);
1128 static void filter_store_class_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1129 gchar *new_text, gpointer data)
1131 GtkWidget *model = data;
1132 FilterEntry *fe = data;
1137 if (!new_text || !new_text[0]) return;
1139 tpath = gtk_tree_path_new_from_string(path_str);
1140 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1141 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1143 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
1145 if (strcmp(new_text, _(format_class_list[i])) == 0)
1152 gtk_tree_path_free(tpath);
1156 static void filter_store_desc_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1157 gchar *new_text, gpointer data)
1159 GtkWidget *model = data;
1164 if (!new_text || !new_text[0]) return;
1166 tpath = gtk_tree_path_new_from_string(path_str);
1167 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1168 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1170 g_free(fe->description);
1171 fe->description = g_strdup(new_text);
1173 gtk_tree_path_free(tpath);
1176 static void filter_store_enable_cb(GtkCellRendererToggle *renderer,
1177 gchar *path_str, gpointer data)
1179 GtkWidget *model = data;
1184 tpath = gtk_tree_path_new_from_string(path_str);
1185 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1186 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1188 fe->enabled = !fe->enabled;
1190 gtk_tree_path_free(tpath);
1194 static void filter_store_writable_cb(GtkCellRendererToggle *renderer,
1195 gchar *path_str, gpointer data)
1197 GtkWidget *model = data;
1202 tpath = gtk_tree_path_new_from_string(path_str);
1203 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1204 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1206 fe->writable = !fe->writable;
1207 if (fe->writable) fe->allow_sidecar = FALSE;
1209 gtk_tree_path_free(tpath);
1213 static void filter_store_sidecar_cb(GtkCellRendererToggle *renderer,
1214 gchar *path_str, gpointer data)
1216 GtkWidget *model = data;
1221 tpath = gtk_tree_path_new_from_string(path_str);
1222 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1223 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1225 fe->allow_sidecar = !fe->allow_sidecar;
1226 if (fe->allow_sidecar) fe->writable = FALSE;
1228 gtk_tree_path_free(tpath);
1232 static void filter_set_func(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
1233 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
1237 gtk_tree_model_get(tree_model, iter, 0, &fe, -1);
1239 switch (GPOINTER_TO_INT(data))
1242 g_object_set(GTK_CELL_RENDERER(cell),
1243 "active", fe->enabled, NULL);
1246 g_object_set(GTK_CELL_RENDERER(cell),
1247 "text", fe->extensions, NULL);
1249 case FE_DESCRIPTION:
1250 g_object_set(GTK_CELL_RENDERER(cell),
1251 "text", fe->description, NULL);
1254 g_object_set(GTK_CELL_RENDERER(cell),
1255 "text", _(format_class_list[fe->file_class]), NULL);
1258 g_object_set(GTK_CELL_RENDERER(cell),
1259 "active", fe->writable, NULL);
1261 case FE_ALLOW_SIDECAR:
1262 g_object_set(GTK_CELL_RENDERER(cell),
1263 "active", fe->allow_sidecar, NULL);
1268 static gboolean filter_add_scroll(gpointer data)
1272 GtkCellRenderer *cell;
1273 GtkTreeViewColumn *column;
1276 rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(filter_store), NULL);
1277 path = gtk_tree_path_new_from_indices(rows-1, -1);
1279 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data), 0);
1281 list_cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column));
1282 cell = g_list_last(list_cells)->data;
1284 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1285 path, column, FALSE, 0.0, 0.0 );
1286 gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(data),
1287 path, column, cell, TRUE);
1289 gtk_tree_path_free(path);
1290 g_list_free(list_cells);
1295 static void filter_add_cb(GtkWidget *widget, gpointer data)
1297 filter_add_unique("description", ".new", FORMAT_CLASS_IMAGE, TRUE, FALSE, TRUE);
1298 filter_store_populate();
1300 g_idle_add((GSourceFunc)filter_add_scroll, data);
1303 static void filter_remove_cb(GtkWidget *widget, gpointer data)
1305 GtkWidget *filter_view = data;
1306 GtkTreeSelection *selection;
1310 if (!filter_store) return;
1311 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1312 if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) return;
1313 gtk_tree_model_get(GTK_TREE_MODEL(filter_store), &iter, 0, &fe, -1);
1316 filter_remove_entry(fe);
1318 filter_store_populate();
1321 static gboolean filter_default_ok_scroll(GtkTreeView *data)
1325 GtkTreeViewColumn *column;
1327 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(filter_store), &iter);
1328 path = gtk_tree_model_get_path(GTK_TREE_MODEL(filter_store), &iter);
1329 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1331 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1335 gtk_tree_path_free(path);
1340 static void filter_default_ok_cb(GenericDialog *gd, gpointer data)
1343 filter_add_defaults();
1345 filter_store_populate();
1347 g_idle_add((GSourceFunc)filter_default_ok_scroll, gd->data);
1350 static void dummy_cancel_cb(GenericDialog *gd, gpointer data)
1352 /* no op, only so cancel button appears */
1355 static void filter_default_cb(GtkWidget *widget, gpointer data)
1359 gd = generic_dialog_new(_("Reset filters"),
1360 "reset_filter", widget, TRUE,
1361 dummy_cancel_cb, data);
1362 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset filters"),
1363 _("This will reset the file filters to the defaults.\nContinue?"), TRUE);
1364 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, filter_default_ok_cb, TRUE);
1365 gtk_widget_show(gd->dialog);
1368 static void filter_disable_cb(GtkWidget *widget, gpointer data)
1370 GtkWidget *frame = data;
1372 gtk_widget_set_sensitive(frame,
1373 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
1376 static void safe_delete_view_cb(GtkWidget *widget, gpointer data)
1378 layout_set_path(NULL, gtk_entry_get_text(GTK_ENTRY(safe_delete_path_entry)));
1381 static void safe_delete_clear_ok_cb(GenericDialog *gd, gpointer data)
1383 file_util_trash_clear();
1386 static void safe_delete_clear_cb(GtkWidget *widget, gpointer data)
1390 gd = generic_dialog_new(_("Clear trash"),
1391 "clear_trash", widget, TRUE,
1392 dummy_cancel_cb, NULL);
1393 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear trash"),
1394 _("This will remove the trash contents."), FALSE);
1395 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, safe_delete_clear_ok_cb, TRUE);
1396 entry = gtk_entry_new();
1397 gtk_widget_set_can_focus(entry, FALSE);
1398 gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE);
1399 if (options->file_ops.safe_delete_path) gtk_entry_set_text(GTK_ENTRY(entry), options->file_ops.safe_delete_path);
1400 gtk_box_pack_start(GTK_BOX(gd->vbox), entry, FALSE, FALSE, 0);
1401 gtk_widget_show(entry);
1402 gtk_widget_show(gd->dialog);
1405 static void image_overlay_template_view_changed_cb(GtkWidget *widget, gpointer data)
1407 GtkWidget *pTextView;
1408 GtkTextBuffer *pTextBuffer;
1412 pTextView = GTK_WIDGET(data);
1414 pTextBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pTextView));
1415 gtk_text_buffer_get_start_iter(pTextBuffer, &iStart);
1416 gtk_text_buffer_get_end_iter(pTextBuffer, &iEnd);
1418 set_image_overlay_template_string(&c_options->image_overlay.template_string,
1419 gtk_text_buffer_get_text(pTextBuffer, &iStart, &iEnd, TRUE));
1422 static void image_overlay_default_template_ok_cb(GenericDialog *gd, gpointer data)
1424 GtkTextView *text_view = data;
1425 GtkTextBuffer *buffer;
1427 set_default_image_overlay_template_string(&options->image_overlay.template_string);
1428 if (!configwindow) return;
1430 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
1431 gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1434 static void image_overlay_default_template_cb(GtkWidget *widget, gpointer data)
1438 gd = generic_dialog_new(_("Reset image overlay template string"),
1439 "reset_image_overlay_template_string", widget, TRUE,
1440 dummy_cancel_cb, data);
1441 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset image overlay template string"),
1442 _("This will reset the image overlay template string to the default.\nContinue?"), TRUE);
1443 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, image_overlay_default_template_ok_cb, TRUE);
1444 gtk_widget_show(gd->dialog);
1447 static void image_overlay_help_cb(GtkWidget *widget, gpointer data)
1449 help_window_show("GuideOptionsOSD.html");
1452 static void image_overlay_set_font_cb(GtkWidget *widget, gpointer data)
1454 #if GTK_CHECK_VERSION(3,4,0)
1457 PangoFontDescription *font_desc;
1459 dialog = gtk_font_chooser_dialog_new("Image Overlay Font", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1460 gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), options->image_overlay.font);
1462 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1464 font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
1465 font = pango_font_description_to_string(font_desc);
1466 g_free(c_options->image_overlay.font);
1467 c_options->image_overlay.font = g_strdup(font);
1471 gtk_widget_destroy(dialog);
1475 font = gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget));
1476 c_options->image_overlay.font = g_strdup(font);
1480 static void image_overlay_set_text_colour_cb(GtkWidget *widget, gpointer data)
1483 #if GTK_CHECK_VERSION(3,4,0)
1486 dialog = gtk_color_chooser_dialog_new("Image Overlay Text Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1487 colour.red = options->image_overlay.text_red;
1488 colour.green = options->image_overlay.text_green;
1489 colour.blue = options->image_overlay.text_blue;
1490 colour.alpha = options->image_overlay.text_alpha;
1491 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1492 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1494 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1496 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1497 c_options->image_overlay.text_red = colour.red*255;
1498 c_options->image_overlay.text_green = colour.green*255;
1499 c_options->image_overlay.text_blue = colour.blue*255;
1500 c_options->image_overlay.text_alpha = colour.alpha*255;
1502 gtk_widget_destroy(dialog);
1505 GtkColorSelection *colorsel;
1507 dialog = gtk_color_selection_dialog_new("Image Overlay Text Colour");
1508 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1509 colour.red = options->image_overlay.text_red*257;
1510 colour.green = options->image_overlay.text_green*257;
1511 colour.blue = options->image_overlay.text_blue*257;
1512 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1513 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1514 gtk_color_selection_set_current_color(colorsel, &colour);
1515 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.text_alpha*257);
1517 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1519 gtk_color_selection_get_current_color(colorsel, &colour);
1520 c_options->image_overlay.text_red = colour.red/257;
1521 c_options->image_overlay.text_green = colour.green/257;
1522 c_options->image_overlay.text_blue = colour.blue/257;
1523 c_options->image_overlay.text_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1525 gtk_widget_destroy (dialog);
1530 static void image_overlay_set_background_colour_cb(GtkWidget *widget, gpointer data)
1533 #if GTK_CHECK_VERSION(3,4,0)
1536 dialog = gtk_color_chooser_dialog_new("Image Overlay Background Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1537 colour.red = options->image_overlay.background_red;
1538 colour.green = options->image_overlay.background_green;
1539 colour.blue = options->image_overlay.background_blue;
1540 colour.alpha = options->image_overlay.background_alpha;
1541 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1542 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1544 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1546 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1547 c_options->image_overlay.background_red = colour.red*255;
1548 c_options->image_overlay.background_green = colour.green*255;
1549 c_options->image_overlay.background_blue = colour.blue*255;
1550 c_options->image_overlay.background_alpha = colour.alpha*255;
1552 gtk_widget_destroy(dialog);
1555 GtkColorSelection *colorsel;
1557 dialog = gtk_color_selection_dialog_new("Image Overlay Background Colour");
1558 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1559 colour.red = options->image_overlay.background_red*257;
1560 colour.green = options->image_overlay.background_green*257;
1561 colour.blue = options->image_overlay.background_blue*257;
1562 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1563 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1564 gtk_color_selection_set_current_color(colorsel, &colour);
1565 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.background_alpha*257);
1567 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1569 gtk_color_selection_get_current_color(colorsel, &colour);
1570 c_options->image_overlay.background_red = colour.red/257;
1571 c_options->image_overlay.background_green = colour.green/257;
1572 c_options->image_overlay.background_blue = colour.blue/257;
1573 c_options->image_overlay.background_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1575 gtk_widget_destroy(dialog);
1579 static void accel_store_populate(void)
1582 GList *groups, *actions;
1584 const gchar *accel_path;
1588 if (!accel_store || !layout_window_list || !layout_window_list->data) return;
1590 gtk_tree_store_clear(accel_store);
1591 lw = layout_window_list->data; /* get the actions from the first window, it should not matter, they should be the same in all windows */
1593 g_assert(lw && lw->ui_manager);
1594 groups = gtk_ui_manager_get_action_groups(lw->ui_manager);
1597 actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
1600 action = GTK_ACTION(actions->data);
1601 accel_path = gtk_action_get_accel_path(action);
1602 if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
1604 gchar *label, *label2, *tooltip, *accel;
1605 g_object_get(action,
1606 "tooltip", &tooltip,
1610 if (pango_parse_markup(label, -1, '_', NULL, &label2, NULL, NULL) && label2)
1616 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1620 gtk_tree_store_append(accel_store, &iter, NULL);
1621 gtk_tree_store_set(accel_store, &iter,
1624 AE_TOOLTIP, tooltip ? tooltip : "",
1625 AE_ACCEL, accel_path,
1633 actions = actions->next;
1636 groups = groups->next;
1640 static void accel_store_cleared_cb(GtkCellRendererAccel *accel, gchar *path_string, gpointer user_data)
1645 static gboolean accel_remove_key_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1647 gchar *accel1 = data;
1652 gtk_tree_model_get(model, iter, AE_KEY, &accel2, -1);
1654 gtk_accelerator_parse(accel1, &key1.accel_key, &key1.accel_mods);
1655 gtk_accelerator_parse(accel2, &key2.accel_key, &key2.accel_mods);
1657 if (key1.accel_key == key2.accel_key && key1.accel_mods == key2.accel_mods)
1659 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1660 DEBUG_1("accelerator key '%s' is already used, removing.", accel1);
1669 static void accel_store_edited_cb(GtkCellRendererAccel *accel, gchar *path_string, guint accel_key, GdkModifierType accel_mods, guint hardware_keycode, gpointer user_data)
1671 GtkTreeModel *model = (GtkTreeModel *)accel_store;
1675 GtkAccelKey old_key, key;
1676 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
1678 gtk_tree_model_get_iter(model, &iter, path);
1679 gtk_tree_model_get(model, &iter, AE_ACCEL, &accel_path, -1);
1681 /* test if the accelerator can be stored without conflicts*/
1682 gtk_accel_map_lookup_entry(accel_path, &old_key);
1684 /* change the key and read it back (change may fail on keys hardcoded in gtk)*/
1685 gtk_accel_map_change_entry(accel_path, accel_key, accel_mods, TRUE);
1686 gtk_accel_map_lookup_entry(accel_path, &key);
1688 /* restore the original for now, the key will be really changed when the changes are confirmed */
1689 gtk_accel_map_change_entry(accel_path, old_key.accel_key, old_key.accel_mods, TRUE);
1691 acc = gtk_accelerator_name(key.accel_key, key.accel_mods);
1692 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, acc);
1694 gtk_tree_store_set(accel_store, &iter, AE_KEY, acc, -1);
1695 gtk_tree_path_free(path);
1699 static gboolean accel_default_scroll(GtkTreeView *data)
1703 GtkTreeViewColumn *column;
1705 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(accel_store), &iter);
1706 path = gtk_tree_model_get_path(GTK_TREE_MODEL(accel_store), &iter);
1707 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1709 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1713 gtk_tree_path_free(path);
1718 static void accel_default_cb(GtkWidget *widget, gpointer data)
1720 accel_store_populate();
1722 g_idle_add((GSourceFunc)accel_default_scroll, data);
1725 void accel_remove_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1727 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1730 void accel_reset_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1733 gchar *accel_path, *accel;
1735 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, -1);
1736 gtk_accel_map_lookup_entry(accel_path, &key);
1737 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1739 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, accel);
1741 gtk_tree_store_set(accel_store, iter, AE_KEY, accel, -1);
1746 static void accel_reset_cb(GtkWidget *widget, gpointer data)
1748 GtkTreeSelection *selection;
1750 if (!accel_store) return;
1751 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data));
1752 gtk_tree_selection_selected_foreach(selection, &accel_reset_selection, NULL);
1757 static GtkWidget *scrolled_notebook_page(GtkWidget *notebook, const gchar *title)
1761 GtkWidget *scrolled;
1762 GtkWidget *viewport;
1764 scrolled = gtk_scrolled_window_new(NULL, NULL);
1765 gtk_container_set_border_width(GTK_CONTAINER(scrolled), PREF_PAD_BORDER);
1766 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1767 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1768 label = gtk_label_new(title);
1769 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, label);
1770 gtk_widget_show(scrolled);
1772 viewport = gtk_viewport_new(NULL, NULL);
1773 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1774 gtk_container_add(GTK_CONTAINER(scrolled), viewport);
1775 gtk_widget_show(viewport);
1777 vbox = gtk_vbox_new(FALSE, 0);
1778 gtk_container_add(GTK_CONTAINER(viewport), vbox);
1779 gtk_widget_show(vbox);
1784 static void cache_standard_cb(GtkWidget *widget, gpointer data)
1786 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1788 c_options->thumbnails.spec_standard =TRUE;
1789 c_options->thumbnails.cache_into_dirs = FALSE;
1793 static void cache_geeqie_cb(GtkWidget *widget, gpointer data)
1795 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1797 c_options->thumbnails.spec_standard =FALSE;
1798 c_options->thumbnails.cache_into_dirs = FALSE;
1802 static void cache_local_cb(GtkWidget *widget, gpointer data)
1804 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1806 c_options->thumbnails.cache_into_dirs = TRUE;
1807 c_options->thumbnails.spec_standard =FALSE;
1811 static void help_search_engine_entry_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1812 GdkEvent *event, gpointer userdata)
1814 if (pos == GTK_ENTRY_ICON_PRIMARY)
1816 gtk_entry_set_text(GTK_ENTRY(userdata), HELP_SEARCH_ENGINE);
1820 gtk_entry_set_text(GTK_ENTRY(userdata), "");
1824 static void star_rating_star_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1825 GdkEvent *event, gpointer userdata)
1827 gchar *rating_symbol;
1829 if (pos == GTK_ENTRY_ICON_PRIMARY)
1831 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_STAR);
1832 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1833 g_free(rating_symbol);
1837 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1838 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1839 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1843 static void star_rating_rejected_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1844 GdkEvent *event, gpointer userdata)
1846 gchar *rating_symbol;
1848 if (pos == GTK_ENTRY_ICON_PRIMARY)
1850 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_REJECTED);
1851 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1852 g_free(rating_symbol);
1856 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1857 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1858 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1862 static guint star_rating_symbol_test(GtkWidget *widget, gpointer data)
1864 GtkContainer *hbox = data;
1865 GString *str = g_string_new(NULL);
1866 GtkEntry *hex_code_entry;
1867 gchar *hex_code_full;
1870 guint64 hex_value = 0;
1872 list = gtk_container_get_children(hbox);
1874 hex_code_entry = g_list_nth_data(list, 2);
1875 hex_code_full = g_strdup(gtk_entry_get_text(hex_code_entry));
1877 hex_code = g_strsplit(hex_code_full, "+", 2);
1878 if (hex_code[0] && hex_code[1])
1880 hex_value = strtoull(hex_code[1], NULL, 16);
1882 if (!hex_value || hex_value > 0x10FFFF)
1884 hex_value = 0x003F; // Unicode 'Question Mark'
1886 str = g_string_append_unichar(str, (gunichar)hex_value);
1887 gtk_label_set_text(g_list_nth_data(list, 1), str->str);
1889 g_strfreev(hex_code);
1890 g_string_free(str, TRUE);
1891 g_free(hex_code_full);
1896 static void star_rating_star_test_cb(GtkWidget *widget, gpointer data)
1898 guint64 star_symbol;
1900 star_symbol = star_rating_symbol_test(widget, data);
1901 c_options->star_rating.star = star_symbol;
1904 static void star_rating_rejected_test_cb(GtkWidget *widget, gpointer data)
1906 guint64 rejected_symbol;
1908 rejected_symbol = star_rating_symbol_test(widget, data);
1909 c_options->star_rating.rejected = rejected_symbol;
1912 /* general options tab */
1913 static void timezone_database_install_cb(GtkWidget *widget, gpointer data);
1914 typedef struct _TZData TZData;
1918 GCancellable *cancellable;
1920 GtkWidget *progress;
1922 GFile *timezone_database_gq;
1923 gchar *timezone_database_user;
1926 static void config_tab_general(GtkWidget *notebook)
1931 GtkWidget *group_frame;
1932 GtkWidget *subgroup;
1934 GtkWidget *ct_button;
1937 gint hours, minutes, remainder;
1939 GtkWidget *star_rating_entry;
1941 gchar *rating_symbol;
1944 GNetworkMonitor *net_mon;
1945 GSocketConnectable *geeqie_org;
1946 gboolean internet_available;
1949 vbox = scrolled_notebook_page(notebook, _("General"));
1951 group = pref_group_new(vbox, FALSE, _("Thumbnails"), GTK_ORIENTATION_VERTICAL);
1953 table = pref_table_new(group, 2, 2, FALSE, FALSE);
1954 add_thumb_size_menu(table, 0, 0, _("Size:"));
1955 add_quality_menu(table, 0, 1, _("Quality:"), options->thumbnails.quality, &c_options->thumbnails.quality);
1957 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1958 pref_label_new(hbox, _("Custom size: "));
1959 pref_spin_new_int(hbox, _("Width:"), NULL, 1, 512, 1, options->thumbnails.max_width, &c_options->thumbnails.max_width);
1960 pref_spin_new_int(hbox, _("Height:"), NULL, 1, 512, 1, options->thumbnails.max_height, &c_options->thumbnails.max_height);
1962 ct_button = pref_checkbox_new_int(group, _("Cache thumbnails and sim. files"),
1963 options->thumbnails.enable_caching, &c_options->thumbnails.enable_caching);
1965 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1966 pref_checkbox_link_sensitivity(ct_button, subgroup);
1968 c_options->thumbnails.spec_standard = options->thumbnails.spec_standard;
1969 c_options->thumbnails.cache_into_dirs = options->thumbnails.cache_into_dirs;
1970 group_frame = pref_frame_new(subgroup, TRUE, _("Use Geeqie thumbnail style and cache"),
1971 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1972 button = pref_radiobutton_new(group_frame, NULL, get_thumbnails_cache_dir(),
1973 !options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1974 G_CALLBACK(cache_geeqie_cb), NULL);
1976 group_frame = pref_frame_new(subgroup, TRUE,
1977 _("Store thumbnails local to image folder (non-standard)"),
1978 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1979 pref_radiobutton_new(group_frame, button, "*/.thumbnails",
1980 !options->thumbnails.spec_standard && options->thumbnails.cache_into_dirs,
1981 G_CALLBACK(cache_local_cb), NULL);
1983 group_frame = pref_frame_new(subgroup, TRUE,
1984 _("Use standard thumbnail style and cache, shared with other applications"),
1985 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1986 pref_radiobutton_new(group_frame, button, get_thumbnails_standard_cache_dir(),
1987 options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1988 G_CALLBACK(cache_standard_cb), NULL);
1990 pref_checkbox_new_int(group, _("Use EXIF thumbnails when available (EXIF thumbnails may be outdated)"),
1991 options->thumbnails.use_exif, &c_options->thumbnails.use_exif);
1993 pref_checkbox_new_int(group, _("Thumbnail color management"),
1994 options->thumbnails.use_color_management, &c_options->thumbnails.use_color_management);
1996 spin = pref_spin_new_int(group, _("Collection preview:"), NULL,
1998 options->thumbnails.collection_preview, &c_options->thumbnails.collection_preview);
1999 gtk_widget_set_tooltip_text(spin, _("The maximum number of thumbnails shown in a Collection preview montage"));
2001 #ifdef HAVE_FFMPEGTHUMBNAILER_METADATA
2002 pref_checkbox_new_int(group, _("Use embedded metadata in video files as thumbnails when available"),
2003 options->thumbnails.use_ft_metadata, &c_options->thumbnails.use_ft_metadata);
2005 // pref_checkbox_new_int(group, _("Ignore embedded metadata if size is too small"),
2006 // options->thumbnails.use_ft_metadata_small, &c_options->thumbnails.use_ft_metadata_small);
2009 pref_spacer(group, PREF_PAD_GROUP);
2011 group = pref_group_new(vbox, FALSE, _("Star Rating"), GTK_ORIENTATION_VERTICAL);
2013 c_options->star_rating.star = options->star_rating.star;
2014 c_options->star_rating.rejected = options->star_rating.rejected;
2016 str = g_string_new(NULL);
2017 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2018 pref_label_new(hbox, _("Star character: "));
2019 str = g_string_append_unichar(str, options->star_rating.star);
2020 pref_label_new(hbox, g_strdup(str->str));
2021 rating_symbol = g_strdup_printf("U+%X", options->star_rating.star);
2022 star_rating_entry = gtk_entry_new();
2023 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
2024 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
2025 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
2026 gtk_widget_show(star_rating_entry);
2027 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
2028 G_CALLBACK(star_rating_star_test_cb), hbox);
2029 gtk_widget_set_tooltip_text(button, _("Display selected character"));
2030 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2031 gtk_widget_show(button);
2032 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."));
2033 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2034 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2035 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2036 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2037 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2038 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2039 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2040 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2041 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
2042 G_CALLBACK(star_rating_star_icon_cb),
2045 g_string_free(str, TRUE);
2046 g_free(rating_symbol);
2048 str = g_string_new(NULL);
2049 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2050 pref_label_new(hbox, _("Rejected character: "));
2051 str = g_string_append_unichar(str, options->star_rating.rejected);
2052 pref_label_new(hbox, g_strdup(str->str));
2053 rating_symbol = g_strdup_printf("U+%X", options->star_rating.rejected);
2054 star_rating_entry = gtk_entry_new();
2055 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
2056 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
2057 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
2058 gtk_widget_show(star_rating_entry);
2059 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
2060 G_CALLBACK(star_rating_rejected_test_cb), hbox);
2061 gtk_widget_set_tooltip_text(button, _("Display selected character"));
2062 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2063 gtk_widget_show(button);
2064 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."));
2065 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2066 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2067 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2068 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2069 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2070 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2071 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2072 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2073 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
2074 G_CALLBACK(star_rating_rejected_icon_cb),
2077 g_string_free(str, TRUE);
2078 g_free(rating_symbol);
2080 pref_spacer(group, PREF_PAD_GROUP);
2082 group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
2084 c_options->slideshow.delay = options->slideshow.delay;
2085 hours = options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2086 remainder = options->slideshow.delay % (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2087 minutes = remainder / (60 * SLIDESHOW_SUBSECOND_PRECISION);
2088 seconds = (gdouble)(remainder % (60 * SLIDESHOW_SUBSECOND_PRECISION)) /
2089 SLIDESHOW_SUBSECOND_PRECISION;
2091 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2093 spin = pref_spin_new(hbox, _("Delay between image change hrs:mins:secs.dec"), NULL,
2095 options->slideshow.delay ? hours : 0.0,
2096 G_CALLBACK(slideshow_delay_hours_cb), NULL);
2097 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2098 spin = pref_spin_new(hbox, ":" , NULL,
2100 options->slideshow.delay ? minutes: 0.0,
2101 G_CALLBACK(slideshow_delay_minutes_cb), NULL);
2102 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2103 spin = pref_spin_new(hbox, ":", NULL,
2104 SLIDESHOW_MIN_SECONDS, 59, 1.0, 1,
2105 options->slideshow.delay ? seconds : 10.0,
2106 G_CALLBACK(slideshow_delay_seconds_cb), NULL);
2107 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2109 pref_checkbox_new_int(group, _("Random"), options->slideshow.random, &c_options->slideshow.random);
2110 pref_checkbox_new_int(group, _("Repeat"), options->slideshow.repeat, &c_options->slideshow.repeat);
2112 pref_spacer(group, PREF_PAD_GROUP);
2114 group = pref_group_new(vbox, FALSE, _("Image loading and caching"), GTK_ORIENTATION_VERTICAL);
2116 pref_spin_new_int(group, _("Decoded image cache size (MiB):"), NULL,
2117 0, 99999, 1, options->image.image_cache_max, &c_options->image.image_cache_max);
2118 pref_checkbox_new_int(group, _("Preload next image"),
2119 options->image.enable_read_ahead, &c_options->image.enable_read_ahead);
2121 pref_checkbox_new_int(group, _("Refresh on file change"),
2122 options->update_on_time_change, &c_options->update_on_time_change);
2125 pref_spacer(group, PREF_PAD_GROUP);
2127 group = pref_group_new(vbox, FALSE, _("Expand menu and toolbar"), GTK_ORIENTATION_VERTICAL);
2129 pref_checkbox_new_int(group, _("Expand menu and toolbar (NOTE! Geeqie must be restarted for change to take effect)"),
2130 options->expand_menu_toolbar, &c_options->expand_menu_toolbar);
2131 gtk_widget_set_tooltip_text(group, _("Expand the menu and toolbar to the full width of the window"));
2133 pref_spacer(group, PREF_PAD_GROUP);
2135 net_mon = g_network_monitor_get_default();
2136 geeqie_org = g_network_address_parse_uri(GQ_WEBSITE, 80, NULL);
2137 internet_available = g_network_monitor_can_reach(net_mon, geeqie_org, NULL, NULL);
2138 g_object_unref(geeqie_org);
2140 group = pref_group_new(vbox, FALSE, _("Timezone database"), GTK_ORIENTATION_VERTICAL);
2141 hbox = pref_box_new(group, TRUE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2143 if (!internet_available)
2145 gtk_widget_set_sensitive(group, FALSE);
2148 tz = g_new0(TZData, 1);
2150 path = path_from_utf8(TIMEZONE_DATABASE);
2151 basename = g_path_get_basename(path);
2152 tz->timezone_database_user = g_build_filename(get_rc_dir(), basename, NULL);
2156 if (isfile(tz->timezone_database_user))
2158 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Update"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2162 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Install"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2165 if (!internet_available)
2167 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"));
2171 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"));
2173 gtk_widget_show(button);
2175 pref_spacer(group, PREF_PAD_GROUP);
2177 group = pref_group_new(vbox, FALSE, _("On-line help search engine"), GTK_ORIENTATION_VERTICAL);
2179 help_search_engine_entry = gtk_entry_new();
2180 gtk_entry_set_text(GTK_ENTRY(help_search_engine_entry), options->help_search_engine);
2181 gtk_box_pack_start(GTK_BOX(group), help_search_engine_entry, FALSE, FALSE, 0);
2182 gtk_widget_show(help_search_engine_entry);
2184 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"));
2186 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2187 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2188 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2189 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2190 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2191 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2192 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2193 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2194 g_signal_connect(GTK_ENTRY(help_search_engine_entry), "icon-press",
2195 G_CALLBACK(help_search_engine_entry_icon_cb),
2196 help_search_engine_entry);
2200 static void config_tab_image(GtkWidget *notebook)
2205 GtkWidget *ct_button;
2206 GtkWidget *enlargement_button;
2209 GtkWidget *two_pass;
2211 GtkWidget *gpu_accel;
2214 vbox = scrolled_notebook_page(notebook, _("Image"));
2216 group = pref_group_new(vbox, FALSE, _("Zoom"), GTK_ORIENTATION_VERTICAL);
2218 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2219 add_quality_menu(table, 0, 0, _("Quality:"), options->image.zoom_quality, &c_options->image.zoom_quality);
2220 if (options->image.use_clutter_renderer && !options->disable_gpu)
2222 gtk_widget_set_sensitive(table, FALSE);
2226 gpu_accel = pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library (Requires restart)"),
2227 options->image.use_clutter_renderer, &c_options->image.use_clutter_renderer);
2228 if (options->disable_gpu && !options->override_disable_gpu)
2230 gtk_widget_set_sensitive(gpu_accel, FALSE);
2234 two_pass = pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"),
2235 options->image.zoom_2pass, &c_options->image.zoom_2pass);
2236 if (options->image.use_clutter_renderer && !options->disable_gpu)
2238 gtk_widget_set_sensitive(two_pass, FALSE);
2241 c_options->image.zoom_increment = options->image.zoom_increment;
2242 spin = pref_spin_new(group, _("Zoom increment:"), NULL,
2243 0.01, 4.0, 0.01, 2, (gdouble)options->image.zoom_increment / 100.0,
2244 G_CALLBACK(zoom_increment_cb), NULL);
2245 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2247 group = pref_group_new(vbox, FALSE, _("Fit image to window"), GTK_ORIENTATION_VERTICAL);
2249 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2250 enlargement_button = pref_checkbox_new_int(hbox, _("Allow enlargement of image (max. size in %)"),
2251 options->image.zoom_to_fit_allow_expand, &c_options->image.zoom_to_fit_allow_expand);
2252 spin = pref_spin_new_int(hbox, NULL, NULL,
2254 options->image.max_enlargement_size, &c_options->image.max_enlargement_size);
2255 pref_checkbox_link_sensitivity(enlargement_button, spin);
2256 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."));
2258 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2259 ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (% of actual window):"),
2260 options->image.limit_autofit_size, &c_options->image.limit_autofit_size);
2261 spin = pref_spin_new_int(hbox, NULL, NULL,
2263 options->image.max_autofit_size, &c_options->image.max_autofit_size);
2264 pref_checkbox_link_sensitivity(ct_button, spin);
2265 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."));
2267 group = pref_group_new(vbox, FALSE, _("Tile size"), GTK_ORIENTATION_VERTICAL);
2268 gtk_widget_set_sensitive(group, !options->image.use_clutter_renderer);
2270 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2271 spin = pref_spin_new_int(hbox, _("Pixels"), _("(Requires restart)"),
2273 options->image.tile_size, &c_options->image.tile_size);
2274 gtk_widget_set_tooltip_text(GTK_WIDGET(hbox), _("This value changes the size of the tiles large images are split into. Increasing the size of the tiles will reduce the tiling effect seen on image changes, but will also slightly increase the delay before the first part of a large image is seen."));
2276 group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
2278 pref_checkbox_new_int(group, _("Use custom border color in window mode"),
2279 options->image.use_custom_border_color, &c_options->image.use_custom_border_color);
2281 pref_checkbox_new_int(group, _("Use custom border color in fullscreen mode"),
2282 options->image.use_custom_border_color_in_fullscreen, &c_options->image.use_custom_border_color_in_fullscreen);
2284 pref_color_button_new(group, _("Border color"), &options->image.border_color,
2285 G_CALLBACK(pref_color_button_set_cb), &c_options->image.border_color);
2287 c_options->image.border_color = options->image.border_color;
2289 pref_color_button_new(group, _("Alpha channel color 1"), &options->image.alpha_color_1,
2290 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_1);
2292 pref_color_button_new(group, _("Alpha channel color 2"), &options->image.alpha_color_2,
2293 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_2);
2295 c_options->image.alpha_color_1 = options->image.alpha_color_1;
2296 c_options->image.alpha_color_2 = options->image.alpha_color_2;
2298 group = pref_group_new(vbox, FALSE, _("Convenience"), GTK_ORIENTATION_VERTICAL);
2300 pref_checkbox_new_int(group, _("Auto rotate proofs using Exif information"),
2301 options->image.exif_proof_rotate_enable, &c_options->image.exif_proof_rotate_enable);
2306 static void save_default_window_layout_cb(GtkWidget *widget, gpointer data)
2308 LayoutWindow *lw = NULL;
2309 gchar *default_path;
2312 /* Get current lw */
2315 tmp_id = lw->options.id;
2316 lw->options.id = g_strdup("lw_default");
2318 default_path = g_build_filename(get_rc_dir(), DEFAULT_WINDOW_LAYOUT, NULL);
2319 save_default_layout_options_to_file(default_path, options, lw);
2320 g_free(lw->options.id);
2321 lw->options.id = tmp_id;
2322 g_free(default_path);
2325 #if GTK_CHECK_VERSION(3,22,0)
2326 static gboolean popover_cb(gpointer data)
2328 GtkPopover *popover = data;
2330 gtk_popover_popdown(popover);
2335 static void default_layout_changed_cb(GtkWidget *button, GtkPopover *popover)
2337 gtk_popover_popup(popover);
2339 g_timeout_add(2000, popover_cb, popover);
2342 static GtkWidget *create_popover(GtkWidget *parent, GtkWidget *child, GtkPositionType pos)
2346 popover = gtk_popover_new(parent);
2347 gtk_popover_set_position(GTK_POPOVER (popover), pos);
2348 gtk_container_add (GTK_CONTAINER(popover), child);
2349 gtk_container_set_border_width(GTK_CONTAINER (popover), 6);
2350 gtk_widget_show (child);
2356 static void config_tab_windows(GtkWidget *notebook)
2361 GtkWidget *subgroup;
2363 GtkWidget *ct_button;
2366 vbox = scrolled_notebook_page(notebook, _("Windows"));
2368 group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
2370 ct_button = pref_checkbox_new_int(group, _("Remember session"),
2371 options->save_window_positions, &c_options->save_window_positions);
2373 button = pref_checkbox_new_int(group, _("Use saved window positions also for new windows"),
2374 options->use_saved_window_positions_for_new_windows, &c_options->use_saved_window_positions_for_new_windows);
2375 pref_checkbox_link_sensitivity(ct_button, button);
2377 button = pref_checkbox_new_int(group, _("Remember window workspace"),
2378 options->save_window_workspace, &c_options->save_window_workspace);
2379 pref_checkbox_link_sensitivity(ct_button, button);
2381 pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
2382 options->tools_restore_state, &c_options->tools_restore_state);
2384 pref_checkbox_new_int(group, _("Remember dialog window positions"),
2385 options->save_dialog_window_positions, &c_options->save_dialog_window_positions);
2387 pref_checkbox_new_int(group, _("Show window IDs"),
2388 options->show_window_ids, &c_options->show_window_ids);
2390 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2391 pref_label_new(subgroup, _("Use current layout for default: "));
2392 button = pref_button_new(subgroup, NULL, _("Set"), FALSE, G_CALLBACK(save_default_window_layout_cb), NULL);
2394 #if GTK_CHECK_VERSION(3,22,0)
2397 popover = create_popover(button, gtk_label_new(_("Current window layout\nhas been set as default")), GTK_POS_TOP);
2398 gtk_popover_set_modal(GTK_POPOVER (popover), FALSE);
2399 g_signal_connect(button, "clicked", G_CALLBACK(default_layout_changed_cb), popover);
2402 group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
2404 pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
2405 options->image.fit_window_to_image, &c_options->image.fit_window_to_image);
2407 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2408 ct_button = pref_checkbox_new_int(hbox, _("Limit size when auto-sizing window (%):"),
2409 options->image.limit_window_size, &c_options->image.limit_window_size);
2410 spin = pref_spin_new_int(hbox, NULL, NULL,
2412 options->image.max_window_size, &c_options->image.max_window_size);
2413 pref_checkbox_link_sensitivity(ct_button, spin);
2415 group = pref_group_new(vbox, FALSE, _("Full screen"), GTK_ORIENTATION_VERTICAL);
2417 c_options->fullscreen.screen = options->fullscreen.screen;
2418 c_options->fullscreen.above = options->fullscreen.above;
2419 hbox = fullscreen_prefs_selection_new(_("Location:"), &c_options->fullscreen.screen, &c_options->fullscreen.above);
2420 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2421 gtk_widget_show(hbox);
2423 pref_checkbox_new_int(group, _("Smooth image flip"),
2424 options->fullscreen.clean_flip, &c_options->fullscreen.clean_flip);
2425 pref_checkbox_new_int(group, _("Disable screen saver"),
2426 options->fullscreen.disable_saver, &c_options->fullscreen.disable_saver);
2429 #define PRE_FORMATTED_COLUMNS 5
2430 static void config_tab_osd(GtkWidget *notebook)
2436 GtkWidget *image_overlay_template_view;
2437 GtkWidget *scrolled;
2438 GtkWidget *scrolled_pre_formatted;
2439 GtkTextBuffer *buffer;
2441 GtkWidget *subgroup;
2443 vbox = scrolled_notebook_page(notebook, _("OSD"));
2445 image_overlay_template_view = gtk_text_view_new();
2447 group = pref_group_new(vbox, FALSE, _("Overlay Screen Display"), GTK_ORIENTATION_VERTICAL);
2449 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2451 scrolled_pre_formatted = osd_new(PRE_FORMATTED_COLUMNS, image_overlay_template_view);
2452 gtk_widget_set_size_request(scrolled_pre_formatted, 200, 150);
2453 gtk_box_pack_start(GTK_BOX(subgroup), scrolled_pre_formatted, FALSE, FALSE, 0);
2454 gtk_widget_show(scrolled_pre_formatted);
2455 gtk_widget_show(subgroup);
2457 pref_line(group, PREF_PAD_GAP);
2459 pref_label_new(group, _("Image overlay template"));
2461 scrolled = gtk_scrolled_window_new(NULL, NULL);
2462 gtk_widget_set_size_request(scrolled, 200, 150);
2463 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2464 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
2465 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2466 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 5);
2467 gtk_widget_show(scrolled);
2469 gtk_widget_set_tooltip_markup(image_overlay_template_view,
2470 _("Extensive formatting options are shown in the Help file"));
2472 gtk_container_add(GTK_CONTAINER(scrolled), image_overlay_template_view);
2473 gtk_widget_show(image_overlay_template_view);
2475 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2477 #if GTK_CHECK_VERSION(3,4,0)
2478 button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
2479 G_CALLBACK(image_overlay_set_font_cb), notebook);
2481 button = gtk_font_button_new();
2482 gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Image Overlay Font");
2483 gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->image_overlay.font);
2484 g_signal_connect(G_OBJECT(button), "font-set",
2485 G_CALLBACK(image_overlay_set_font_cb),NULL);
2487 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2488 gtk_widget_show(button);
2490 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Text"), FALSE,
2491 G_CALLBACK(image_overlay_set_text_colour_cb), NULL);
2492 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2493 gtk_widget_show(button);
2495 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Background"), FALSE,
2496 G_CALLBACK(image_overlay_set_background_colour_cb), NULL);
2497 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2498 gtk_widget_show(button);
2499 image_overlay_set_text_colours();
2501 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2502 G_CALLBACK(image_overlay_default_template_cb), image_overlay_template_view);
2503 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2504 gtk_widget_show(button);
2506 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
2507 G_CALLBACK(image_overlay_help_cb), NULL);
2508 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2509 gtk_widget_show(button);
2511 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_overlay_template_view));
2512 if (options->image_overlay.template_string) gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
2513 g_signal_connect(G_OBJECT(buffer), "changed",
2514 G_CALLBACK(image_overlay_template_view_changed_cb), image_overlay_template_view);
2516 pref_line(group, PREF_PAD_GAP);
2518 group = pref_group_new(vbox, FALSE, _("Exif, XMP or IPTC tags"), GTK_ORIENTATION_VERTICAL);
2519 hbox = gtk_hbox_new(FALSE, 0);
2520 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2521 gtk_widget_show(hbox);
2522 label = gtk_label_new(_("%Exif.Image.Orientation%"));
2523 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2524 gtk_widget_show(label);
2525 pref_spacer(group,TRUE);
2527 group = pref_group_new(vbox, FALSE, _("Field separators"), GTK_ORIENTATION_VERTICAL);
2528 hbox = gtk_hbox_new(FALSE, 0);
2529 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2530 gtk_widget_show(hbox);
2531 label = gtk_label_new(_("Separator shown only if both fields are non-null:\n%formatted.ShutterSpeed%|%formatted.ISOSpeedRating%"));
2532 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2533 gtk_widget_show(label);
2534 pref_spacer(group,TRUE);
2536 group = pref_group_new(vbox, FALSE, _("Field maximum length"), GTK_ORIENTATION_VERTICAL);
2537 hbox = gtk_hbox_new(FALSE, 0);
2538 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2539 gtk_widget_show(hbox);
2540 label = gtk_label_new(_("%path:39%"));
2541 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2542 gtk_widget_show(label);
2543 pref_spacer(group,TRUE);
2545 group = pref_group_new(vbox, FALSE, _("Pre- and post- text"), GTK_ORIENTATION_VERTICAL);
2546 hbox = gtk_hbox_new(FALSE, 0);
2547 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2548 gtk_widget_show(hbox);
2549 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%"));
2550 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2551 gtk_widget_show(label);
2552 pref_spacer(group,TRUE);
2554 group = pref_group_new(vbox, FALSE, _("Pango markup"), GTK_ORIENTATION_VERTICAL);
2555 hbox = gtk_hbox_new(FALSE, 0);
2556 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2557 gtk_widget_show(hbox);
2558 label = gtk_label_new(_("<b>bold</b>\n<u>underline</u>\n<i>italic</i>\n<s>strikethrough</s>"));
2559 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2560 gtk_widget_show(label);
2563 static GtkTreeModel *create_class_model(void)
2565 GtkListStore *model;
2569 /* create list store */
2570 model = gtk_list_store_new(1, G_TYPE_STRING);
2571 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
2573 gtk_list_store_append(model, &iter);
2574 gtk_list_store_set(model, &iter, 0, _(format_class_list[i]), -1);
2576 return GTK_TREE_MODEL (model);
2581 static void config_tab_files(GtkWidget *notebook)
2588 GtkWidget *ct_button;
2589 GtkWidget *scrolled;
2590 GtkWidget *filter_view;
2591 GtkCellRenderer *renderer;
2592 GtkTreeSelection *selection;
2593 GtkTreeViewColumn *column;
2595 vbox = scrolled_notebook_page(notebook, _("Files"));
2597 group = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2599 pref_checkbox_new_int(group, _("Show hidden files or folders"),
2600 options->file_filter.show_hidden_files, &c_options->file_filter.show_hidden_files);
2601 pref_checkbox_new_int(group, _("Show parent folder (..)"),
2602 options->file_filter.show_parent_directory, &c_options->file_filter.show_parent_directory);
2603 pref_checkbox_new_int(group, _("Case sensitive sort"),
2604 options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
2605 pref_checkbox_new_int(group, _("Natural sort order"),
2606 options->file_sort.natural, &c_options->file_sort.natural);
2607 pref_checkbox_new_int(group, _("Disable file extension checks"),
2608 options->file_filter.disable_file_extension_checks, &c_options->file_filter.disable_file_extension_checks);
2610 ct_button = pref_checkbox_new_int(group, _("Disable File Filtering"),
2611 options->file_filter.disable, &c_options->file_filter.disable);
2614 group = pref_group_new(vbox, FALSE, _("Grouping sidecar extensions"), GTK_ORIENTATION_VERTICAL);
2616 sidecar_ext_entry = gtk_entry_new();
2617 gtk_entry_set_text(GTK_ENTRY(sidecar_ext_entry), options->sidecar.ext);
2618 gtk_box_pack_start(GTK_BOX(group), sidecar_ext_entry, FALSE, FALSE, 0);
2619 gtk_widget_show(sidecar_ext_entry);
2621 group = pref_group_new(vbox, TRUE, _("File types"), GTK_ORIENTATION_VERTICAL);
2623 frame = pref_group_parent(group);
2624 g_signal_connect(G_OBJECT(ct_button), "toggled",
2625 G_CALLBACK(filter_disable_cb), frame);
2626 gtk_widget_set_sensitive(frame, !options->file_filter.disable);
2628 scrolled = gtk_scrolled_window_new(NULL, NULL);
2629 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2630 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2631 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2632 gtk_widget_show(scrolled);
2634 filter_store = gtk_list_store_new(1, G_TYPE_POINTER);
2635 filter_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(filter_store));
2636 g_object_unref(filter_store);
2637 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
2638 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
2640 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), FALSE);
2642 column = gtk_tree_view_column_new();
2643 gtk_tree_view_column_set_title(column, _("Filter"));
2644 gtk_tree_view_column_set_resizable(column, TRUE);
2646 renderer = gtk_cell_renderer_toggle_new();
2647 g_signal_connect(G_OBJECT(renderer), "toggled",
2648 G_CALLBACK(filter_store_enable_cb), filter_store);
2649 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2650 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2651 GINT_TO_POINTER(FE_ENABLE), NULL);
2653 renderer = gtk_cell_renderer_text_new();
2654 g_signal_connect(G_OBJECT(renderer), "edited",
2655 G_CALLBACK(filter_store_ext_edit_cb), filter_store);
2656 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2657 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2658 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2659 GINT_TO_POINTER(FE_EXTENSION), NULL);
2660 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2662 column = gtk_tree_view_column_new();
2663 gtk_tree_view_column_set_title(column, _("Description"));
2664 gtk_tree_view_column_set_resizable(column, TRUE);
2665 gtk_tree_view_column_set_fixed_width(column, 200);
2666 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
2668 renderer = gtk_cell_renderer_text_new();
2669 g_signal_connect(G_OBJECT(renderer), "edited",
2670 G_CALLBACK(filter_store_desc_edit_cb), filter_store);
2671 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2672 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2673 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2674 GINT_TO_POINTER(FE_DESCRIPTION), NULL);
2675 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2677 column = gtk_tree_view_column_new();
2678 gtk_tree_view_column_set_title(column, _("Class"));
2679 gtk_tree_view_column_set_resizable(column, TRUE);
2680 renderer = gtk_cell_renderer_combo_new();
2681 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE,
2682 "model", create_class_model(),
2687 g_signal_connect(G_OBJECT(renderer), "edited",
2688 G_CALLBACK(filter_store_class_edit_cb), filter_store);
2689 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2690 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2691 GINT_TO_POINTER(FE_CLASS), NULL);
2692 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2694 column = gtk_tree_view_column_new();
2695 gtk_tree_view_column_set_title(column, _("Writable"));
2696 gtk_tree_view_column_set_resizable(column, FALSE);
2697 renderer = gtk_cell_renderer_toggle_new();
2698 g_signal_connect(G_OBJECT(renderer), "toggled",
2699 G_CALLBACK(filter_store_writable_cb), filter_store);
2700 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2701 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2702 GINT_TO_POINTER(FE_WRITABLE), NULL);
2703 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2705 column = gtk_tree_view_column_new();
2706 gtk_tree_view_column_set_title(column, _("Sidecar is allowed"));
2707 gtk_tree_view_column_set_resizable(column, FALSE);
2708 renderer = gtk_cell_renderer_toggle_new();
2709 g_signal_connect(G_OBJECT(renderer), "toggled",
2710 G_CALLBACK(filter_store_sidecar_cb), filter_store);
2711 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2712 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2713 GINT_TO_POINTER(FE_ALLOW_SIDECAR), NULL);
2714 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2717 filter_store_populate();
2718 gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
2719 gtk_widget_show(filter_view);
2721 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2723 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2724 G_CALLBACK(filter_default_cb), filter_view);
2725 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2726 gtk_widget_show(button);
2728 button = pref_button_new(NULL, GTK_STOCK_REMOVE, NULL, FALSE,
2729 G_CALLBACK(filter_remove_cb), filter_view);
2730 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2731 gtk_widget_show(button);
2733 button = pref_button_new(NULL, GTK_STOCK_ADD, NULL, FALSE,
2734 G_CALLBACK(filter_add_cb), filter_view);
2735 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2736 gtk_widget_show(button);
2740 static void config_tab_metadata(GtkWidget *notebook)
2745 GtkWidget *ct_button;
2749 vbox = scrolled_notebook_page(notebook, _("Metadata"));
2752 group = pref_group_new(vbox, FALSE, _("Metadata writing process"), GTK_ORIENTATION_VERTICAL);
2754 label = pref_label_new(group, _("Warning: Geeqie is built without Exiv2. Some options are disabled."));
2756 label = pref_label_new(group, _("Metadata are written in the following order. The process ends after first success."));
2757 #if GTK_CHECK_VERSION(3,16,0)
2758 gtk_label_set_xalign(GTK_LABEL(label), 0.0);
2759 gtk_label_set_yalign(GTK_LABEL(label), 0.5);
2761 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2764 ct_button = pref_checkbox_new_int(group, _("1) Save metadata in image files, or sidecar files, according to the XMP standard"),
2765 options->metadata.save_in_image_file, &c_options->metadata.save_in_image_file);
2767 gtk_widget_set_sensitive(ct_button, FALSE);
2770 pref_checkbox_new_int(group, _("2) Save metadata in '.metadata' folder, local to image folder (non-standard)"),
2771 options->metadata.enable_metadata_dirs, &c_options->metadata.enable_metadata_dirs);
2773 text = g_strdup_printf(_("3) Save metadata in Geeqie private directory '%s'"), get_metadata_cache_dir());
2774 label = pref_label_new(group, text);
2775 #if GTK_CHECK_VERSION(3,16,0)
2776 gtk_label_set_xalign(GTK_LABEL(label), 0.0);
2777 gtk_label_set_yalign(GTK_LABEL(label), 0.5);
2779 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2781 gtk_misc_set_padding(GTK_MISC(label), 22, 0);
2784 group = pref_group_new(vbox, FALSE, _("Step 1: Write to image files"), GTK_ORIENTATION_VERTICAL);
2786 gtk_widget_set_sensitive(group, FALSE);
2789 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2790 pref_checkbox_link_sensitivity(ct_button, hbox);
2792 pref_checkbox_new_int(hbox, _("Store metadata also in legacy IPTC tags (converted according to IPTC4XMP standard)"),
2793 options->metadata.save_legacy_IPTC, &c_options->metadata.save_legacy_IPTC);
2795 pref_checkbox_new_int(hbox, _("Warn if the image files are unwritable"),
2796 options->metadata.warn_on_write_problems, &c_options->metadata.warn_on_write_problems);
2798 pref_checkbox_new_int(hbox, _("Ask before writing to image files"),
2799 options->metadata.confirm_write, &c_options->metadata.confirm_write);
2801 pref_checkbox_new_int(hbox, _("Create sidecar files named image.ext.xmp (as opposed to image.xmp)"),
2802 options->metadata.sidecar_extended_name, &c_options->metadata.sidecar_extended_name);
2804 group = pref_group_new(vbox, FALSE, _("Step 2 and 3: write to Geeqie private files"), GTK_ORIENTATION_VERTICAL);
2806 gtk_widget_set_sensitive(group, FALSE);
2809 pref_checkbox_new_int(group, _("Use GQview legacy metadata format (supports only keywords and comments) instead of XMP"),
2810 options->metadata.save_legacy_format, &c_options->metadata.save_legacy_format);
2813 group = pref_group_new(vbox, FALSE, _("Miscellaneous"), GTK_ORIENTATION_VERTICAL);
2814 pref_checkbox_new_int(group, _("Write the same description tags (keywords, comment, etc.) to all grouped sidecars"),
2815 options->metadata.sync_grouped_files, &c_options->metadata.sync_grouped_files);
2817 pref_checkbox_new_int(group, _("Allow keywords to differ only in case"),
2818 options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
2820 ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"),
2821 options->metadata.write_orientation, &c_options->metadata.write_orientation);
2823 gtk_widget_set_sensitive(ct_button, FALSE);
2826 group = pref_group_new(vbox, FALSE, _("Auto-save options"), GTK_ORIENTATION_VERTICAL);
2828 ct_button = pref_checkbox_new_int(group, _("Write metadata after timeout"),
2829 options->metadata.confirm_after_timeout, &c_options->metadata.confirm_after_timeout);
2831 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2832 pref_checkbox_link_sensitivity(ct_button, hbox);
2834 pref_spin_new_int(hbox, _("Timeout (seconds):"), NULL, 0, 900, 1,
2835 options->metadata.confirm_timeout, &c_options->metadata.confirm_timeout);
2837 pref_checkbox_new_int(group, _("Write metadata on image change"),
2838 options->metadata.confirm_on_image_change, &c_options->metadata.confirm_on_image_change);
2840 pref_checkbox_new_int(group, _("Write metadata on directory change"),
2841 options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
2843 group = pref_group_new(vbox, FALSE, _("Pre-load metadata"), GTK_ORIENTATION_VERTICAL);
2845 ct_button = pref_checkbox_new_int(group, _("Read metadata in background"),
2846 options->read_metadata_in_idle, &c_options->read_metadata_in_idle);
2847 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");
2852 typedef struct _KeywordFindData KeywordFindData;
2853 struct _KeywordFindData
2860 GtkWidget *button_close;
2861 GtkWidget *button_stop;
2862 GtkWidget *button_start;
2863 GtkWidget *progress;
2871 guint idle_id; /* event source id */
2874 #define KEYWORD_DIALOG_WIDTH 400
2876 static void keywords_find_folder(KeywordFindData *kfd, FileData *dir_fd)
2878 GList *list_d = NULL;
2879 GList *list_f = NULL;
2883 filelist_read(dir_fd, &list_f, &list_d);
2887 filelist_read(dir_fd, &list_f, NULL);
2890 list_f = filelist_filter(list_f, FALSE);
2891 list_d = filelist_filter(list_d, TRUE);
2893 kfd->list = g_list_concat(list_f, kfd->list);
2894 kfd->list_dir = g_list_concat(list_d, kfd->list_dir);
2897 static void keywords_find_reset(KeywordFindData *kfd)
2899 filelist_free(kfd->list);
2902 filelist_free(kfd->list_dir);
2903 kfd->list_dir = NULL;
2906 static void keywords_find_close_cb(GenericDialog *fd, gpointer data)
2908 KeywordFindData *kfd = data;
2910 if (!gtk_widget_get_sensitive(kfd->button_close)) return;
2912 keywords_find_reset(kfd);
2913 generic_dialog_close(kfd->gd);
2917 static void keywords_find_finish(KeywordFindData *kfd)
2919 keywords_find_reset(kfd);
2921 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("done"));
2922 spinner_set_interval(kfd->spinner, -1);
2924 gtk_widget_set_sensitive(kfd->group, TRUE);
2925 gtk_widget_set_sensitive(kfd->button_start, TRUE);
2926 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2927 gtk_widget_set_sensitive(kfd->button_close, TRUE);
2930 static void keywords_find_stop_cb(GenericDialog *fd, gpointer data)
2932 KeywordFindData *kfd = data;
2934 g_idle_remove_by_data(kfd);
2936 keywords_find_finish(kfd);
2939 static gboolean keywords_find_file(gpointer data)
2941 KeywordFindData *kfd = data;
2943 GtkTextBuffer *buffer;
2951 fd = kfd->list->data;
2952 kfd->list = g_list_remove(kfd->list, fd);
2954 keywords = metadata_read_list(fd, KEYWORD_KEY, METADATA_PLAIN);
2955 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2959 gtk_text_buffer_get_end_iter(buffer, &iter);
2960 tmp = g_strconcat(keywords->data, "\n", NULL);
2961 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
2963 keywords = keywords->next;
2966 gtk_entry_set_text(GTK_ENTRY(kfd->progress), fd->path);
2967 file_data_unref(fd);
2968 string_list_free(keywords);
2972 else if (kfd->list_dir)
2976 fd = kfd->list_dir->data;
2977 kfd->list_dir = g_list_remove(kfd->list_dir, fd);
2979 keywords_find_folder(kfd, fd);
2981 file_data_unref(fd);
2986 keywords_find_finish(kfd);
2991 static void keywords_find_start_cb(GenericDialog *fd, gpointer data)
2993 KeywordFindData *kfd = data;
2996 if (kfd->list || !gtk_widget_get_sensitive(kfd->button_start)) return;
2998 path = remove_trailing_slash((gtk_entry_get_text(GTK_ENTRY(kfd->entry))));
2999 parse_out_relatives(path);
3003 warning_dialog(_("Invalid folder"),
3004 _("The specified folder can not be found."),
3005 GTK_STOCK_DIALOG_WARNING, kfd->gd->dialog);
3011 gtk_widget_set_sensitive(kfd->group, FALSE);
3012 gtk_widget_set_sensitive(kfd->button_start, FALSE);
3013 gtk_widget_set_sensitive(kfd->button_stop, TRUE);
3014 gtk_widget_set_sensitive(kfd->button_close, FALSE);
3015 spinner_set_interval(kfd->spinner, SPINNER_SPEED);
3017 dir_fd = file_data_new_dir(path);
3018 keywords_find_folder(kfd, dir_fd);
3019 file_data_unref(dir_fd);
3020 kfd->idle_id = g_idle_add(keywords_find_file, kfd);
3026 static void keywords_find_dialog(GtkWidget *widget, const gchar *path)
3028 KeywordFindData *kfd;
3032 kfd = g_new0(KeywordFindData, 1);
3034 kfd->gd = generic_dialog_new(_("Search for keywords"),
3035 "search_for_keywords",
3038 gtk_window_set_default_size(GTK_WINDOW(kfd->gd->dialog), KEYWORD_DIALOG_WIDTH, -1);
3039 kfd->gd->cancel_cb = keywords_find_close_cb;
3040 kfd->button_close = generic_dialog_add_button(kfd->gd, GTK_STOCK_CLOSE, NULL,
3041 keywords_find_close_cb, FALSE);
3042 kfd->button_start = generic_dialog_add_button(kfd->gd, GTK_STOCK_OK, _("S_tart"),
3043 keywords_find_start_cb, FALSE);
3044 kfd->button_stop = generic_dialog_add_button(kfd->gd, GTK_STOCK_STOP, NULL,
3045 keywords_find_stop_cb, FALSE);
3046 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
3048 generic_dialog_add_message(kfd->gd, NULL, _("Search for keywords"), NULL, FALSE);
3050 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0);
3051 pref_spacer(hbox, PREF_PAD_INDENT);
3052 kfd->group = pref_box_new(hbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
3054 hbox = pref_box_new(kfd->group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3055 pref_label_new(hbox, _("Folder:"));
3057 label = tab_completion_new(&kfd->entry, path, NULL, NULL, NULL, NULL);
3058 tab_completion_add_select_button(kfd->entry,_("Select folder") , TRUE);
3059 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
3060 gtk_widget_show(label);
3062 pref_checkbox_new_int(kfd->group, _("Include subfolders"), FALSE, &kfd->recurse);
3064 pref_line(kfd->gd->vbox, PREF_PAD_SPACE);
3065 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3067 kfd->progress = gtk_entry_new();
3068 gtk_widget_set_can_focus(kfd->progress, FALSE);
3069 gtk_editable_set_editable(GTK_EDITABLE(kfd->progress), FALSE);
3070 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("click start to begin"));
3071 gtk_box_pack_start(GTK_BOX(hbox), kfd->progress, TRUE, TRUE, 0);
3072 gtk_widget_show(kfd->progress);
3074 kfd->spinner = spinner_new(NULL, -1);
3075 gtk_box_pack_start(GTK_BOX(hbox), kfd->spinner, FALSE, FALSE, 0);
3076 gtk_widget_show(kfd->spinner);
3080 gtk_widget_show(kfd->gd->dialog);
3083 static void keywords_find_cb(GtkWidget *widget, gpointer data)
3085 const gchar *path = layout_get_path(NULL);
3087 if (!path || !*path) path = homedir();
3088 keywords_find_dialog(widget, path);
3091 static void config_tab_keywords_save()
3093 GtkTextIter start, end;
3094 GtkTextBuffer *buffer;
3095 GList *kw_list = NULL;
3101 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3102 gtk_text_buffer_get_bounds(buffer, &start, &end);
3104 buffer_text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
3106 kw_split = strtok(buffer_text, "\n");
3107 while (kw_split != NULL)
3113 if (g_strcmp0(work->data, kw_split) == 0)
3122 kw_list = g_list_append(kw_list, g_strdup(kw_split));
3124 kw_split = strtok(NULL, "\n");
3127 keyword_list_set(kw_list);
3129 string_list_free(kw_list);
3130 g_free(buffer_text);
3133 static void config_tab_keywords(GtkWidget *notebook)
3139 GtkWidget *scrolled;
3141 GtkTextBuffer *buffer;
3144 vbox = scrolled_notebook_page(notebook, _("Keywords"));
3146 group = pref_group_new(vbox, TRUE, _("Edit keywords autocompletion list"), GTK_ORIENTATION_VERTICAL);
3148 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3150 button = pref_button_new(hbox, GTK_STOCK_EXECUTE, _("Search"), FALSE,
3151 G_CALLBACK(keywords_find_cb), keyword_text);
3152 gtk_widget_set_tooltip_text(button, "Search for existing keywords");
3155 keyword_text = gtk_text_view_new();
3156 gtk_widget_set_size_request(keyword_text, 20, 20);
3157 scrolled = gtk_scrolled_window_new(NULL, NULL);
3158 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3159 gtk_widget_show(scrolled);
3161 gtk_container_add(GTK_CONTAINER(scrolled), keyword_text);
3162 gtk_widget_show(keyword_text);
3164 gtk_text_view_set_editable(GTK_TEXT_VIEW(keyword_text), TRUE);
3166 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3167 gtk_text_buffer_create_tag(buffer, "monospace",
3168 "family", "monospace", NULL);
3170 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(keyword_text), GTK_WRAP_WORD);
3171 gtk_text_buffer_get_start_iter(buffer, &iter);
3172 gtk_text_buffer_create_mark(buffer, "end", &iter, FALSE);
3175 path = g_build_filename(get_rc_dir(), "keywords", NULL);
3177 GList *kwl = keyword_list_get();
3178 kwl = g_list_first(kwl);
3181 gtk_text_buffer_get_end_iter (buffer, &iter);
3182 tmp = g_strconcat(kwl->data, "\n", NULL);
3183 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
3188 gtk_text_buffer_set_modified(buffer, FALSE);
3195 static void intent_menu_cb(GtkWidget *combo, gpointer data)
3197 gint *option = data;
3199 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
3203 *option = INTENT_PERCEPTUAL;
3206 *option = INTENT_RELATIVE_COLORIMETRIC;
3209 *option = INTENT_SATURATION;
3212 *option = INTENT_ABSOLUTE_COLORIMETRIC;
3217 static void add_intent_menu(GtkWidget *table, gint column, gint row, const gchar *text,
3218 gint option, gint *option_c)
3225 pref_table_label(table, column, row, text, 0.0);
3227 combo = gtk_combo_box_text_new();
3229 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Perceptual"));
3230 if (option == INTENT_PERCEPTUAL) current = 0;
3231 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Relative Colorimetric"));
3232 if (option == INTENT_RELATIVE_COLORIMETRIC) current = 1;
3233 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Saturation"));
3234 if (option == INTENT_SATURATION) current = 2;
3235 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Absolute Colorimetric"));
3236 if (option == INTENT_ABSOLUTE_COLORIMETRIC) current = 3;
3238 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
3240 gtk_widget_set_tooltip_text(combo,"Refer to the lcms documentation for the defaults used when the selected Intent is not available");
3242 g_signal_connect(G_OBJECT(combo), "changed",
3243 G_CALLBACK(intent_menu_cb), option_c);
3245 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
3246 gtk_widget_show(combo);
3250 static void config_tab_color(GtkWidget *notebook)
3259 vbox = scrolled_notebook_page(notebook, _("Color management"));
3261 group = pref_group_new(vbox, FALSE, _("Input profiles"), GTK_ORIENTATION_VERTICAL);
3263 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3266 table = pref_table_new(group, 3, COLOR_PROFILE_INPUTS + 1, FALSE, FALSE);
3267 gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
3269 label = pref_table_label(table, 0, 0, _("Type"), 0.0);
3270 pref_label_bold(label, TRUE, FALSE);
3272 label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
3273 pref_label_bold(label, TRUE, FALSE);
3275 label = pref_table_label(table, 2, 0, _("File"), 0.0);
3276 pref_label_bold(label, TRUE, FALSE);
3278 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
3283 buf = g_strdup_printf(_("Input %d:"), i + COLOR_PROFILE_FILE);
3284 pref_table_label(table, 0, i + 1, buf, 1.0);
3287 entry = gtk_entry_new();
3288 gtk_entry_set_max_length(GTK_ENTRY(entry), EDITOR_NAME_MAX_LENGTH);
3289 if (options->color_profile.input_name[i])
3291 gtk_entry_set_text(GTK_ENTRY(entry), options->color_profile.input_name[i]);
3293 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, i + 1, i + 2,
3294 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3295 gtk_widget_show(entry);
3296 color_profile_input_name_entry[i] = entry;
3298 tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, ".icc", "ICC Files", NULL);
3299 tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
3300 gtk_widget_set_size_request(entry, 160, -1);
3301 gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
3302 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3303 gtk_widget_show(tabcomp);
3304 color_profile_input_file_entry[i] = entry;
3307 group = pref_group_new(vbox, FALSE, _("Screen profile"), GTK_ORIENTATION_VERTICAL);
3309 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3311 pref_checkbox_new_int(group, _("Use system screen profile if available"),
3312 options->color_profile.use_x11_screen_profile, &c_options->color_profile.use_x11_screen_profile);
3314 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3316 pref_table_label(table, 0, 0, _("Screen:"), 1.0);
3317 tabcomp = tab_completion_new(&color_profile_screen_file_entry,
3318 options->color_profile.screen_file, NULL, ".icc", "ICC Files", NULL);
3319 tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
3320 gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
3322 add_intent_menu(table, 0, 1, _("Render Intent:"), options->color_profile.render_intent, &c_options->color_profile.render_intent);
3324 gtk_table_attach(GTK_TABLE(table), tabcomp, 1, 2,
3326 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3328 gtk_widget_show(tabcomp);
3331 /* advanced entry tab */
3332 static void use_geeqie_trash_cb(GtkWidget *widget, gpointer data)
3334 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3336 c_options->file_ops.use_system_trash = FALSE;
3337 c_options->file_ops.no_trash = FALSE;
3341 static void use_system_trash_cb(GtkWidget *widget, gpointer data)
3343 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3345 c_options->file_ops.use_system_trash = TRUE;
3346 c_options->file_ops.no_trash = FALSE;
3350 static void use_no_cache_cb(GtkWidget *widget, gpointer data)
3352 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3354 c_options->file_ops.no_trash = TRUE;
3358 static void config_tab_behavior(GtkWidget *notebook)
3365 GtkWidget *ct_button;
3369 GtkWidget *with_rename;
3370 GtkWidget *collections_on_top;
3371 GtkWidget *hide_window_in_fullscreen;
3372 GtkWidget *checkbox;
3375 vbox = scrolled_notebook_page(notebook, _("Behavior"));
3377 group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
3379 pref_checkbox_new_int(group, _("Confirm permanent file delete"),
3380 options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
3381 pref_checkbox_new_int(group, _("Confirm move file to Trash"),
3382 options->file_ops.confirm_move_to_trash, &c_options->file_ops.confirm_move_to_trash);
3383 pref_checkbox_new_int(group, _("Enable Delete key"),
3384 options->file_ops.enable_delete_key, &c_options->file_ops.enable_delete_key);
3386 ct_button = pref_radiobutton_new(group, NULL, _("Use Geeqie trash location"),
3387 !options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_geeqie_trash_cb),NULL);
3389 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3390 pref_checkbox_link_sensitivity(ct_button, hbox);
3392 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
3393 pref_label_new(hbox, _("Folder:"));
3395 tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL, NULL, NULL);
3396 tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
3397 gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
3398 gtk_widget_show(tabcomp);
3400 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3401 pref_checkbox_link_sensitivity(ct_button, hbox);
3403 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
3404 spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MiB"),
3405 0, 2048, 1, options->file_ops.safe_delete_folder_maxsize, &c_options->file_ops.safe_delete_folder_maxsize);
3406 gtk_widget_set_tooltip_markup(spin, _("Set to 0 for unlimited size"));
3407 button = pref_button_new(NULL, NULL, _("View"), FALSE,
3408 G_CALLBACK(safe_delete_view_cb), NULL);
3409 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3410 gtk_widget_show(button);
3412 button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
3413 G_CALLBACK(safe_delete_clear_cb), NULL);
3414 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3415 pref_radiobutton_new(group, ct_button, _("Use system Trash bin"),
3416 options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_system_trash_cb), NULL);
3418 pref_radiobutton_new(group, ct_button, _("Use no trash at all"),
3419 options->file_ops.no_trash, G_CALLBACK(use_no_cache_cb), NULL);
3421 gtk_widget_show(button);
3423 pref_spacer(group, PREF_PAD_GROUP);
3426 group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
3428 pref_checkbox_new_int(group, _("Descend folders in tree view"),
3429 options->tree_descend_subdirs, &c_options->tree_descend_subdirs);
3431 pref_checkbox_new_int(group, _("In place renaming"),
3432 options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
3434 pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
3435 options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
3437 tmp = pref_checkbox_new_int(group, _("Circular selection lists"),
3438 options->circular_selection_lists, &c_options->circular_selection_lists);
3439 gtk_widget_set_tooltip_text(tmp, _("Traverse selection lists in a circular manner"));
3441 marks = pref_checkbox_new_int(group, _("Save marks on exit"),
3442 options->marks_save, &c_options->marks_save);
3443 gtk_widget_set_tooltip_text(marks,"Note that marks linked to a keyword will be saved irrespective of this setting");
3445 with_rename = pref_checkbox_new_int(group, _("Use \"With Rename\" as default for Copy/Move dialogs"),
3446 options->with_rename, &c_options->with_rename);
3447 gtk_widget_set_tooltip_text(with_rename,"Change the default button for Copy/Move dialogs");
3449 collections_on_top = pref_checkbox_new_int(group, _("Open collections on top"),
3450 options->collections_on_top, &c_options->collections_on_top);
3451 gtk_widget_set_tooltip_text(collections_on_top,"Open collections window on top");
3453 hide_window_in_fullscreen = pref_checkbox_new_int(group, _("Hide window in fullscreen"),
3454 options->hide_window_in_fullscreen, &c_options->hide_window_in_fullscreen);
3455 gtk_widget_set_tooltip_text(hide_window_in_fullscreen,"When alt-tabbing, prevent Geeqie window showing twice");
3457 pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
3458 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
3460 pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
3461 16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
3463 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3464 add_dnd_default_action_selection_menu(table, 0, 0, _("Drag`n drop default action:"), options->dnd_default_action, &c_options->dnd_default_action);
3466 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3467 add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
3469 pref_spacer(group, PREF_PAD_GROUP);
3471 group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
3473 pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
3474 options->progressive_key_scrolling, &c_options->progressive_key_scrolling);
3475 pref_spin_new_int(group, _("Keyboard scrolling step multiplier:"), NULL,
3476 1, 32, 1, options->keyboard_scroll_step, (int *)&c_options->keyboard_scroll_step);
3477 pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
3478 options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
3479 pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
3480 options->image_lm_click_nav, &c_options->image_lm_click_nav);
3481 pref_checkbox_new_int(group, _("Open archive by left click on image"),
3482 options->image_l_click_archive, &c_options->image_l_click_archive);
3483 pref_checkbox_new_int(group, _("Play video by left click on image"),
3484 options->image_l_click_video, &c_options->image_l_click_video);
3485 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3486 add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
3488 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3489 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3490 add_mouse_selection_menu(table, 0, 0, _("Mouse button Back:"), options->mouse_button_8, &c_options->mouse_button_8);
3491 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3492 add_mouse_selection_menu(table, 0, 0, _("Mouse button Forward:"), options->mouse_button_9, &c_options->mouse_button_9);
3494 pref_spacer(group, PREF_PAD_GROUP);
3496 group = pref_group_new(vbox, FALSE, _("GPU"), GTK_ORIENTATION_VERTICAL);
3498 checkbox = pref_checkbox_new_int(group, _("Override disable GPU"),
3499 options->override_disable_gpu, &c_options->override_disable_gpu);
3500 gtk_widget_set_tooltip_text(checkbox, "Contact the developers for usage");
3503 pref_spacer(group, PREF_PAD_GROUP);
3505 group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
3507 pref_spin_new_int(group, _("Debug level:"), NULL,
3508 DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
3510 pref_checkbox_new_int(group, _("Timer data"),
3511 options->log_window.timer_data, &c_options->log_window.timer_data);
3513 pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
3514 1, 99999, 1, options->log_window_lines, &options->log_window_lines);
3518 /* accelerators tab */
3519 static void config_tab_accelerators(GtkWidget *notebook)
3525 GtkWidget *scrolled;
3526 GtkWidget *accel_view;
3527 GtkCellRenderer *renderer;
3528 GtkTreeSelection *selection;
3529 GtkTreeViewColumn *column;
3531 vbox = scrolled_notebook_page(notebook, _("Keyboard"));
3533 group = pref_group_new(vbox, TRUE, _("Accelerators"), GTK_ORIENTATION_VERTICAL);
3535 scrolled = gtk_scrolled_window_new(NULL, NULL);
3536 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
3537 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
3538 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3539 gtk_widget_show(scrolled);
3541 accel_store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
3543 accel_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(accel_store));
3544 g_object_unref(accel_store);
3545 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(accel_view));
3546 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
3548 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(accel_view), FALSE);
3550 renderer = gtk_cell_renderer_text_new();
3552 column = gtk_tree_view_column_new_with_attributes(_("Action"),
3557 gtk_tree_view_column_set_sort_column_id(column, AE_ACTION);
3558 gtk_tree_view_column_set_resizable(column, TRUE);
3559 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3562 renderer = gtk_cell_renderer_accel_new();
3563 g_signal_connect(G_OBJECT(renderer), "accel-cleared",
3564 G_CALLBACK(accel_store_cleared_cb), accel_store);
3565 g_signal_connect(G_OBJECT(renderer), "accel-edited",
3566 G_CALLBACK(accel_store_edited_cb), accel_store);
3569 g_object_set (renderer,
3571 "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
3574 column = gtk_tree_view_column_new_with_attributes(_("KEY"),
3579 gtk_tree_view_column_set_sort_column_id(column, AE_KEY);
3580 gtk_tree_view_column_set_resizable(column, TRUE);
3581 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3583 renderer = gtk_cell_renderer_text_new();
3585 column = gtk_tree_view_column_new_with_attributes(_("Tooltip"),
3590 gtk_tree_view_column_set_sort_column_id(column, AE_TOOLTIP);
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("Accel",
3601 gtk_tree_view_column_set_sort_column_id(column, AE_ACCEL);
3602 gtk_tree_view_column_set_resizable(column, TRUE);
3603 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3605 accel_store_populate();
3606 gtk_container_add(GTK_CONTAINER(scrolled), accel_view);
3607 gtk_widget_show(accel_view);
3609 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3611 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
3612 G_CALLBACK(accel_default_cb), accel_view);
3613 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3614 gtk_widget_show(button);
3616 button = pref_button_new(NULL, NULL, _("Reset selected"), FALSE,
3617 G_CALLBACK(accel_reset_cb), accel_view);
3618 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3619 gtk_widget_show(button);
3622 /* toolbar main tab */
3623 static void config_tab_toolbar_main(GtkWidget *notebook)
3626 GtkWidget *toolbardata;
3629 lw = layout_window_list->data;
3631 vbox = scrolled_notebook_page(notebook, _("Toolbar Main"));
3633 toolbardata = toolbar_select_new(lw, TOOLBAR_MAIN);
3634 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3635 gtk_widget_show(vbox);
3638 /* toolbar status tab */
3639 static void config_tab_toolbar_status(GtkWidget *notebook)
3642 GtkWidget *toolbardata;
3645 lw = layout_window_list->data;
3647 vbox = scrolled_notebook_page(notebook, _("Toolbar Status"));
3649 toolbardata = toolbar_select_new(lw, TOOLBAR_STATUS);
3650 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3651 gtk_widget_show(vbox);
3655 static gint extension_sort_cb(gconstpointer a, gconstpointer b)
3657 return g_strcmp0((gchar *)a, (gchar *)b);
3660 static void config_tab_advanced(GtkWidget *notebook)
3664 GSList *formats_list;
3665 GList *extensions_list = NULL;
3668 GdkPixbufFormat *fm;
3670 GString *types_string = g_string_new(NULL);
3671 GtkWidget *types_string_label;
3672 GtkWidget *threads_string_label;
3673 GtkWidget *dupes_threads_spin;
3675 vbox = scrolled_notebook_page(notebook, _("Advanced"));
3676 group = pref_group_new(vbox, FALSE, _("External preview extraction"), GTK_ORIENTATION_VERTICAL);
3678 pref_checkbox_new_int(group, _("Use external preview extraction - Requires restart"), options->external_preview.enable, &c_options->external_preview.enable);
3680 pref_spacer(group, PREF_PAD_GROUP);
3682 formats_list = gdk_pixbuf_get_formats();
3684 while (formats_list)
3686 fm = formats_list->data;
3687 extensions = gdk_pixbuf_format_get_extensions(fm);
3690 while (extensions[i])
3692 extensions_list = g_list_insert_sorted(extensions_list, g_strdup(extensions[i]), extension_sort_cb);
3696 g_strfreev(extensions);
3697 formats_list = formats_list->next;
3700 while (extensions_list)
3702 if (types_string->len == 0)
3704 types_string = g_string_append(types_string, extensions_list->data);
3708 types_string = g_string_append(types_string, ", ");
3709 types_string = g_string_append(types_string, extensions_list->data);
3712 extensions_list = extensions_list->next;
3715 types_string = g_string_prepend(types_string, _("Usable file types:\n"));
3716 types_string_label = pref_label_new(group, types_string->str);
3717 gtk_label_set_line_wrap(GTK_LABEL(types_string_label), TRUE);
3719 pref_spacer(group, PREF_PAD_GROUP);
3721 group = pref_group_new(vbox, FALSE, _("File identification tool"), GTK_ORIENTATION_VERTICAL);
3722 external_preview_select_entry = gtk_entry_new();
3723 tabcomp = tab_completion_new(&external_preview_select_entry, options->external_preview.select, NULL, NULL, NULL, NULL);
3724 tab_completion_add_select_button(external_preview_select_entry, _("Select file identification tool"), FALSE);
3725 gtk_box_pack_start(GTK_BOX(group), tabcomp, TRUE, TRUE, 0);
3726 gtk_widget_show(tabcomp);
3728 group = pref_group_new(vbox, FALSE, _("Preview extraction tool"), GTK_ORIENTATION_VERTICAL);
3729 external_preview_extract_entry = gtk_entry_new();
3730 tabcomp = tab_completion_new(&external_preview_extract_entry, options->external_preview.extract, NULL, NULL, NULL, NULL);
3731 tab_completion_add_select_button(external_preview_extract_entry, _("Select preview extraction tool"), FALSE);
3732 gtk_box_pack_start(GTK_BOX(group), tabcomp, TRUE, TRUE, 0);
3733 gtk_widget_show(tabcomp);
3735 gtk_widget_show(vbox);
3737 g_slist_free(formats_list);
3738 string_list_free(extensions_list);
3739 g_string_free(types_string, TRUE);
3741 pref_spacer(group, PREF_PAD_GROUP);
3743 pref_line(vbox, PREF_PAD_SPACE);
3744 group = pref_group_new(vbox, FALSE, _("Thread pool limits"), GTK_ORIENTATION_VERTICAL);
3746 threads_string_label = pref_label_new(group, "This option limits the number of threads (or cpu cores)\nthat Geeqie will use when running duplicate checks. The default value is 0, which means all available cores will be used.");
3747 gtk_label_set_line_wrap(GTK_LABEL(threads_string_label), TRUE);
3749 pref_spacer(vbox, PREF_PAD_GROUP);
3751 dupes_threads_spin = pref_spin_new_int(vbox, _("Duplicate check:"), _("max. threads"), 0, get_cpu_cores(), 1, options->threads.duplicates, &c_options->threads.duplicates);
3752 gtk_widget_set_tooltip_markup(dupes_threads_spin, _("Set to 0 for unlimited"));
3756 static void config_tab_stereo(GtkWidget *notebook)
3764 GtkWidget *fs_button;
3765 vbox = scrolled_notebook_page(notebook, _("Stereo"));
3767 group = pref_group_new(vbox, FALSE, _("Windowed stereo mode"), GTK_ORIENTATION_VERTICAL);
3769 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3770 add_stereo_mode_menu(table, 0, 0, _("Windowed stereo mode"), options->stereo.mode, &c_options->stereo.mode, FALSE);
3772 table = pref_table_new(group, 2, 2, TRUE, FALSE);
3773 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3774 pref_checkbox_new_int(box, _("Mirror left image"),
3775 options->stereo.mode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.mirror_left);
3776 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3777 pref_checkbox_new_int(box, _("Flip left image"),
3778 options->stereo.mode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.flip_left);
3779 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3780 pref_checkbox_new_int(box, _("Mirror right image"),
3781 options->stereo.mode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.mirror_right);
3782 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3783 pref_checkbox_new_int(box, _("Flip right image"),
3784 options->stereo.mode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.flip_right);
3785 pref_checkbox_new_int(group, _("Swap left and right images"),
3786 options->stereo.mode & PR_STEREO_SWAP, &c_options->stereo.tmp.swap);
3787 pref_checkbox_new_int(group, _("Disable stereo mode on single image source"),
3788 options->stereo.mode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.temp_disable);
3790 group = pref_group_new(vbox, FALSE, _("Fullscreen stereo mode"), GTK_ORIENTATION_VERTICAL);
3791 fs_button = pref_checkbox_new_int(group, _("Use different settings for fullscreen"),
3792 options->stereo.enable_fsmode, &c_options->stereo.enable_fsmode);
3793 box2 = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
3794 pref_checkbox_link_sensitivity(fs_button, box2);
3795 table = pref_table_new(box2, 2, 1, FALSE, FALSE);
3796 add_stereo_mode_menu(table, 0, 0, _("Fullscreen stereo mode"), options->stereo.fsmode, &c_options->stereo.fsmode, TRUE);
3797 table = pref_table_new(box2, 2, 2, TRUE, FALSE);
3798 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3799 pref_checkbox_new_int(box, _("Mirror left image"),
3800 options->stereo.fsmode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.fs_mirror_left);
3801 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3802 pref_checkbox_new_int(box, _("Flip left image"),
3803 options->stereo.fsmode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.fs_flip_left);
3804 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3805 pref_checkbox_new_int(box, _("Mirror right image"),
3806 options->stereo.fsmode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.fs_mirror_right);
3807 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3808 pref_checkbox_new_int(box, _("Flip right image"),
3809 options->stereo.fsmode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.fs_flip_right);
3810 pref_checkbox_new_int(box2, _("Swap left and right images"),
3811 options->stereo.fsmode & PR_STEREO_SWAP, &c_options->stereo.tmp.fs_swap);
3812 pref_checkbox_new_int(box2, _("Disable stereo mode on single image source"),
3813 options->stereo.fsmode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.fs_temp_disable);
3815 group2 = pref_group_new(box2, FALSE, _("Fixed position"), GTK_ORIENTATION_VERTICAL);
3816 table = pref_table_new(group2, 5, 3, FALSE, FALSE);
3817 pref_table_spin_new_int(table, 0, 0, _("Width"), NULL,
3818 1, 5000, 1, options->stereo.fixed_w, &c_options->stereo.fixed_w);
3819 pref_table_spin_new_int(table, 3, 0, _("Height"), NULL,
3820 1, 5000, 1, options->stereo.fixed_h, &c_options->stereo.fixed_h);
3821 pref_table_spin_new_int(table, 0, 1, _("Left X"), NULL,
3822 0, 5000, 1, options->stereo.fixed_x1, &c_options->stereo.fixed_x1);
3823 pref_table_spin_new_int(table, 3, 1, _("Left Y"), NULL,
3824 0, 5000, 1, options->stereo.fixed_y1, &c_options->stereo.fixed_y1);
3825 pref_table_spin_new_int(table, 0, 2, _("Right X"), NULL,
3826 0, 5000, 1, options->stereo.fixed_x2, &c_options->stereo.fixed_x2);
3827 pref_table_spin_new_int(table, 3, 2, _("Right Y"), NULL,
3828 0, 5000, 1, options->stereo.fixed_y2, &c_options->stereo.fixed_y2);
3832 /* Main preferences window */
3833 static void config_window_create(LayoutWindow *lw)
3835 GtkWidget *win_vbox;
3837 GtkWidget *notebook;
3839 GtkWidget *ct_button;
3841 if (!c_options) c_options = init_options(NULL);
3843 configwindow = window_new(GTK_WINDOW_TOPLEVEL, "preferences", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Preferences"));
3844 DEBUG_NAME(configwindow);
3845 gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
3846 g_signal_connect(G_OBJECT(configwindow), "delete_event",
3847 G_CALLBACK(config_window_delete), NULL);
3848 if (options->save_dialog_window_positions)
3850 gtk_window_resize(GTK_WINDOW(configwindow), lw->options.preferences_window.w, lw->options.preferences_window.h);
3851 gtk_window_move(GTK_WINDOW(configwindow), lw->options.preferences_window.x, lw->options.preferences_window.y);
3855 gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
3857 gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
3858 gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
3860 win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
3861 gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
3862 gtk_widget_show(win_vbox);
3864 notebook = gtk_notebook_new();
3865 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_LEFT);
3866 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE);
3867 gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
3869 config_tab_general(notebook);
3870 config_tab_image(notebook);
3871 config_tab_osd(notebook);
3872 config_tab_windows(notebook);
3873 config_tab_accelerators(notebook);
3874 config_tab_files(notebook);
3875 config_tab_metadata(notebook);
3876 config_tab_keywords(notebook);
3877 config_tab_color(notebook);
3878 config_tab_stereo(notebook);
3879 config_tab_behavior(notebook);
3880 config_tab_toolbar_main(notebook);
3881 config_tab_toolbar_status(notebook);
3882 config_tab_advanced(notebook);
3884 gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), lw->options.preferences_window.page_number);
3886 hbox = gtk_hbutton_box_new();
3887 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
3888 gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
3889 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
3890 gtk_widget_show(hbox);
3892 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
3893 G_CALLBACK(config_window_help_cb), notebook);
3894 gtk_container_add(GTK_CONTAINER(hbox), button);
3895 gtk_widget_set_can_default(button, TRUE);
3896 gtk_widget_show(button);
3898 button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
3899 G_CALLBACK(config_window_ok_cb), notebook);
3900 gtk_container_add(GTK_CONTAINER(hbox), button);
3901 gtk_widget_set_can_default(button, TRUE);
3902 gtk_widget_grab_default(button);
3903 gtk_widget_show(button);
3907 button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
3908 G_CALLBACK(config_window_close_cb), NULL);
3909 gtk_container_add(GTK_CONTAINER(hbox), button);
3910 gtk_widget_set_can_default(button, TRUE);
3911 gtk_widget_show(button);
3913 if (!generic_dialog_get_alternative_button_order(configwindow))
3915 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
3918 gtk_widget_show(notebook);
3920 gtk_widget_show(configwindow);
3924 *-----------------------------------------------------------------------------
3925 * config window show (public)
3926 *-----------------------------------------------------------------------------
3929 void show_config_window(LayoutWindow *lw)
3933 gtk_window_present(GTK_WINDOW(configwindow));
3937 config_window_create(lw);
3946 void show_about_window(LayoutWindow *lw)
3948 GdkPixbuf *pixbuf_logo;
3949 GdkPixbuf *pixbuf_icon;
3950 gchar *authors[1000];
3955 gchar *timezone_path;
3959 #define LINE_LENGTH 1000
3960 gchar line[LINE_LENGTH];
3962 copyright = g_string_new(NULL);
3963 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");
3965 path = path_from_utf8(TIMEZONE_DATABASE);
3966 basename = g_path_get_basename(path);
3967 timezone_path = g_build_filename(get_rc_dir(), basename, NULL);
3968 if (g_file_test(timezone_path, G_FILE_TEST_EXISTS))
3970 cd = ZDOpenDatabase(timezone_path);
3973 copyright = g_string_append(copyright, ZDGetNotice(cd));
3974 ZDCloseDatabase(cd);
3978 g_free(timezone_path);
3982 path = g_build_filename(gq_helpdir, "AUTHORS", NULL);
3983 fp = fopen(path, "r");
3986 while(fgets(line, LINE_LENGTH, fp))
3988 /* get rid of ending \n from fgets */
3989 line[strlen(line) - 1] = '\0';
3990 authors[i_authors] = g_strdup(line);
3993 authors[i_authors] = NULL;
3998 comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
3999 "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
4001 pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
4002 pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
4003 gtk_show_about_dialog(GTK_WINDOW(lw->window),
4004 "title", _("About Geeqie"),
4006 "program-name", GQ_APPNAME,
4008 "logo", pixbuf_logo,
4009 "icon", pixbuf_icon,
4010 "website", GQ_WEBSITE,
4011 "website-label", "Website",
4012 "comments", comment,
4014 "translator-credits", _("translator-credits"),
4015 "wrap-license", TRUE,
4016 "license", copyright->str,
4019 g_string_free(copyright, TRUE);
4022 while(n < i_authors)
4032 static void image_overlay_set_text_colours()
4034 c_options->image_overlay.text_red = options->image_overlay.text_red;
4035 c_options->image_overlay.text_green = options->image_overlay.text_green;
4036 c_options->image_overlay.text_blue = options->image_overlay.text_blue;
4037 c_options->image_overlay.text_alpha = options->image_overlay.text_alpha;
4038 c_options->image_overlay.background_red = options->image_overlay.background_red;
4039 c_options->image_overlay.background_green = options->image_overlay.background_green;
4040 c_options->image_overlay.background_blue = options->image_overlay.background_blue;
4041 c_options->image_overlay.background_alpha = options->image_overlay.background_alpha;
4045 *-----------------------------------------------------------------------------
4046 * timezone database routines
4047 *-----------------------------------------------------------------------------
4050 static void timezone_async_ready_cb(GObject *source_object, GAsyncResult *res, gpointer data)
4052 GError *error = NULL;
4054 gchar *tmp_filename;
4056 if (!g_cancellable_is_cancelled(tz->cancellable))
4058 generic_dialog_close(tz->gd);
4062 if (g_file_copy_finish(G_FILE(source_object), res, &error))
4064 tmp_filename = g_file_get_parse_name(tz->tmp_g_file);
4065 move_file(tmp_filename, tz->timezone_database_user);
4066 g_free(tmp_filename);
4070 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
4073 g_file_delete(tz->tmp_g_file, NULL, &error);
4074 g_object_unref(tz->tmp_g_file);
4075 tz->tmp_g_file = NULL;
4076 g_object_unref(tz->cancellable);
4077 g_object_unref(tz->timezone_database_gq);
4080 static void timezone_progress_cb(goffset current_num_bytes, goffset total_num_bytes, gpointer data)
4084 if (!g_cancellable_is_cancelled(tz->cancellable))
4086 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(tz->progress), (gdouble)current_num_bytes / total_num_bytes);
4090 static void timezone_cancel_button_cb(GenericDialog *gd, gpointer data)
4094 g_cancellable_cancel(tz->cancellable);
4097 static void timezone_database_install_cb(GtkWidget *widget, gpointer data)
4100 GError *error = NULL;
4101 GFileIOStream *io_stream;
4108 tz->tmp_g_file = g_file_new_tmp("geeqie_timezone_XXXXXX", &io_stream, &error);
4112 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
4113 log_printf("Error: Download timezone database failed:\n%s", error->message);
4114 g_error_free(error);
4115 g_object_unref(tz->tmp_g_file);
4119 tz->timezone_database_gq = g_file_new_for_uri(TIMEZONE_DATABASE);
4121 tz->gd = generic_dialog_new(_("Timezone database"), "download_timezone_database", NULL, TRUE, timezone_cancel_button_cb, tz);
4123 generic_dialog_add_message(tz->gd, GTK_STOCK_DIALOG_INFO, _("Downloading timezone database"), NULL, FALSE);
4125 tz->progress = gtk_progress_bar_new();
4126 gtk_box_pack_start(GTK_BOX(tz->gd->vbox), tz->progress, FALSE, FALSE, 0);
4127 gtk_widget_show(tz->progress);
4129 gtk_widget_show(tz->gd->dialog);
4130 tz->cancellable = g_cancellable_new();
4131 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);
4133 gtk_button_set_label(GTK_BUTTON(widget), _("Update"));
4136 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */