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"
43 #include "pixbuf_util.h"
45 #include "slideshow.h"
49 #include "ui_fileops.h"
51 #include "ui_spinner.h"
52 #include "ui_tabcomp.h"
53 #include "ui_utildlg.h"
55 #include "zonedetect.h"
65 #define EDITOR_NAME_MAX_LENGTH 32
66 #define EDITOR_COMMAND_MAX_LENGTH 1024
68 static void image_overlay_set_text_colours();
70 GtkWidget *keyword_text;
71 static void config_tab_keywords_save();
73 typedef struct _ThumbSize ThumbSize;
80 static ThumbSize thumb_size_list[] =
114 gchar *format_class_list[] = {
124 /* config memory values */
125 static ConfOptions *c_options = NULL;
132 static GtkWidget *configwindow = NULL;
133 static GtkListStore *filter_store = NULL;
134 static GtkTreeStore *accel_store = NULL;
136 static GtkWidget *safe_delete_path_entry;
138 static GtkWidget *color_profile_input_file_entry[COLOR_PROFILE_INPUTS];
139 static GtkWidget *color_profile_input_name_entry[COLOR_PROFILE_INPUTS];
140 static GtkWidget *color_profile_screen_file_entry;
141 static GtkWidget *external_preview_select_entry;
142 static GtkWidget *external_preview_extract_entry;
144 static GtkWidget *sidecar_ext_entry;
145 static GtkWidget *help_search_engine_entry;
148 #define CONFIG_WINDOW_DEF_WIDTH 700
149 #define CONFIG_WINDOW_DEF_HEIGHT 600
152 *-----------------------------------------------------------------------------
153 * option widget callbacks (private)
154 *-----------------------------------------------------------------------------
157 static void zoom_increment_cb(GtkWidget *spin, gpointer data)
159 c_options->image.zoom_increment = (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) * 100.0 + 0.01);
162 static void slideshow_delay_hours_cb(GtkWidget *spin, gpointer data)
164 gint mins_secs_tenths, delay;
166 mins_secs_tenths = c_options->slideshow.delay %
167 (3600 * SLIDESHOW_SUBSECOND_PRECISION);
169 delay = (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
170 (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
173 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
174 SLIDESHOW_SUBSECOND_PRECISION;
177 static void slideshow_delay_minutes_cb(GtkWidget *spin, gpointer data)
179 gint hours, secs_tenths, delay;
181 hours = c_options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
182 secs_tenths = c_options->slideshow.delay % (60 * SLIDESHOW_SUBSECOND_PRECISION);
184 delay = hours * (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
185 (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
186 (60 * SLIDESHOW_SUBSECOND_PRECISION) + secs_tenths);
188 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
189 SLIDESHOW_SUBSECOND_PRECISION;
192 static void slideshow_delay_seconds_cb(GtkWidget *spin, gpointer data)
194 gint hours_mins, delay;
196 hours_mins = c_options->slideshow.delay / (60 * SLIDESHOW_SUBSECOND_PRECISION);
198 delay = (hours_mins * (60 * SLIDESHOW_SUBSECOND_PRECISION)) +
199 (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
200 (gdouble)(SLIDESHOW_SUBSECOND_PRECISION) + 0.01);
202 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
203 SLIDESHOW_SUBSECOND_PRECISION;
207 *-----------------------------------------------------------------------------
208 * sync program to config window routine (private)
209 *-----------------------------------------------------------------------------
212 void config_entry_to_option(GtkWidget *entry, gchar **option, gchar *(*func)(const gchar *))
218 buf = gtk_entry_get_text(GTK_ENTRY(entry));
219 if (buf && strlen(buf) > 0)
224 *option = g_strdup(buf);
229 static gboolean accel_apply_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
231 gchar *accel_path, *accel;
233 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, AE_KEY, &accel, -1);
235 if (accel_path && accel_path[0])
238 gtk_accelerator_parse(accel, &key.accel_key, &key.accel_mods);
239 gtk_accel_map_change_entry(accel_path, key.accel_key, key.accel_mods, TRUE);
249 static void config_window_apply(void)
251 gboolean refresh = FALSE;
256 config_entry_to_option(safe_delete_path_entry, &options->file_ops.safe_delete_path, remove_trailing_slash);
258 if (options->file_filter.show_hidden_files != c_options->file_filter.show_hidden_files) refresh = TRUE;
259 if (options->file_filter.show_parent_directory != c_options->file_filter.show_parent_directory) refresh = TRUE;
260 if (options->file_filter.show_dot_directory != c_options->file_filter.show_dot_directory) refresh = TRUE;
261 if (options->file_sort.case_sensitive != c_options->file_sort.case_sensitive) refresh = TRUE;
262 if (options->file_sort.natural != c_options->file_sort.natural) refresh = TRUE;
263 if (options->file_filter.disable_file_extension_checks != c_options->file_filter.disable_file_extension_checks) refresh = TRUE;
264 if (options->file_filter.disable != c_options->file_filter.disable) refresh = TRUE;
266 options->file_ops.confirm_delete = c_options->file_ops.confirm_delete;
267 options->file_ops.enable_delete_key = c_options->file_ops.enable_delete_key;
268 options->file_ops.confirm_move_to_trash = c_options->file_ops.confirm_move_to_trash;
269 options->file_ops.use_system_trash = c_options->file_ops.use_system_trash;
270 options->file_ops.no_trash = c_options->file_ops.no_trash;
271 options->file_ops.safe_delete_folder_maxsize = c_options->file_ops.safe_delete_folder_maxsize;
272 options->tools_restore_state = c_options->tools_restore_state;
273 options->save_window_positions = c_options->save_window_positions;
274 options->use_saved_window_positions_for_new_windows = c_options->use_saved_window_positions_for_new_windows;
275 options->save_window_workspace = c_options->save_window_workspace;
276 options->save_dialog_window_positions = c_options->save_dialog_window_positions;
277 options->show_window_ids = c_options->show_window_ids;
278 options->image.scroll_reset_method = c_options->image.scroll_reset_method;
279 options->image.zoom_2pass = c_options->image.zoom_2pass;
280 options->image.fit_window_to_image = c_options->image.fit_window_to_image;
281 options->image.limit_window_size = c_options->image.limit_window_size;
282 options->image.zoom_to_fit_allow_expand = c_options->image.zoom_to_fit_allow_expand;
283 options->image.max_window_size = c_options->image.max_window_size;
284 options->image.limit_autofit_size = c_options->image.limit_autofit_size;
285 options->image.max_autofit_size = c_options->image.max_autofit_size;
286 options->image.max_enlargement_size = c_options->image.max_enlargement_size;
287 options->image.use_clutter_renderer = c_options->image.use_clutter_renderer;
288 options->progressive_key_scrolling = c_options->progressive_key_scrolling;
289 options->keyboard_scroll_step = c_options->keyboard_scroll_step;
291 if (options->thumbnails.max_width != c_options->thumbnails.max_width
292 || options->thumbnails.max_height != c_options->thumbnails.max_height
293 || options->thumbnails.quality != c_options->thumbnails.quality)
295 thumb_format_changed = TRUE;
297 options->thumbnails.max_width = c_options->thumbnails.max_width;
298 options->thumbnails.max_height = c_options->thumbnails.max_height;
299 options->thumbnails.quality = c_options->thumbnails.quality;
301 options->thumbnails.enable_caching = c_options->thumbnails.enable_caching;
302 options->thumbnails.cache_into_dirs = c_options->thumbnails.cache_into_dirs;
303 options->thumbnails.use_exif = c_options->thumbnails.use_exif;
304 options->thumbnails.use_color_management = c_options->thumbnails.use_color_management;
305 options->thumbnails.collection_preview = c_options->thumbnails.collection_preview;
306 options->thumbnails.use_ft_metadata = c_options->thumbnails.use_ft_metadata;
307 // options->thumbnails.use_ft_metadata_small = c_options->thumbnails.use_ft_metadata_small;
308 options->thumbnails.spec_standard = c_options->thumbnails.spec_standard;
309 options->metadata.enable_metadata_dirs = c_options->metadata.enable_metadata_dirs;
310 options->file_filter.show_hidden_files = c_options->file_filter.show_hidden_files;
311 options->file_filter.show_parent_directory = c_options->file_filter.show_parent_directory;
312 options->file_filter.show_dot_directory = c_options->file_filter.show_dot_directory;
313 options->file_filter.disable_file_extension_checks = c_options->file_filter.disable_file_extension_checks;
315 options->file_sort.case_sensitive = c_options->file_sort.case_sensitive;
316 options->file_sort.natural = c_options->file_sort.natural;
317 options->file_filter.disable = c_options->file_filter.disable;
319 config_entry_to_option(sidecar_ext_entry, &options->sidecar.ext, NULL);
320 sidecar_ext_parse(options->sidecar.ext);
322 options->slideshow.random = c_options->slideshow.random;
323 options->slideshow.repeat = c_options->slideshow.repeat;
324 options->slideshow.delay = c_options->slideshow.delay;
326 options->mousewheel_scrolls = c_options->mousewheel_scrolls;
327 options->image_lm_click_nav = c_options->image_lm_click_nav;
328 options->image_l_click_video = c_options->image_l_click_video;
329 options->image_l_click_video_editor = c_options->image_l_click_video_editor;
331 options->file_ops.enable_in_place_rename = c_options->file_ops.enable_in_place_rename;
333 options->image.tile_cache_max = c_options->image.tile_cache_max;
334 options->image.image_cache_max = c_options->image.image_cache_max;
336 options->image.zoom_quality = c_options->image.zoom_quality;
338 options->image.zoom_increment = c_options->image.zoom_increment;
340 options->image.enable_read_ahead = c_options->image.enable_read_ahead;
343 if (options->image.use_custom_border_color != c_options->image.use_custom_border_color
344 || options->image.use_custom_border_color_in_fullscreen != c_options->image.use_custom_border_color_in_fullscreen
345 || !gdk_color_equal(&options->image.border_color, &c_options->image.border_color))
347 options->image.use_custom_border_color_in_fullscreen = c_options->image.use_custom_border_color_in_fullscreen;
348 options->image.use_custom_border_color = c_options->image.use_custom_border_color;
349 options->image.border_color = c_options->image.border_color;
350 layout_colors_update();
351 view_window_colors_update();
354 options->image.alpha_color_1 = c_options->image.alpha_color_1;
355 options->image.alpha_color_2 = c_options->image.alpha_color_2;
357 options->fullscreen.screen = c_options->fullscreen.screen;
358 options->fullscreen.clean_flip = c_options->fullscreen.clean_flip;
359 options->fullscreen.disable_saver = c_options->fullscreen.disable_saver;
360 options->fullscreen.above = c_options->fullscreen.above;
361 if (c_options->image_overlay.template_string)
362 set_image_overlay_template_string(&options->image_overlay.template_string,
363 c_options->image_overlay.template_string);
364 if (c_options->image_overlay.font)
365 set_image_overlay_font_string(&options->image_overlay.font,
366 c_options->image_overlay.font);
367 options->image_overlay.text_red = c_options->image_overlay.text_red;
368 options->image_overlay.text_green = c_options->image_overlay.text_green;
369 options->image_overlay.text_blue = c_options->image_overlay.text_blue;
370 options->image_overlay.text_alpha = c_options->image_overlay.text_alpha;
371 options->image_overlay.background_red = c_options->image_overlay.background_red;
372 options->image_overlay.background_green = c_options->image_overlay.background_green;
373 options->image_overlay.background_blue = c_options->image_overlay.background_blue;
374 options->image_overlay.background_alpha = c_options->image_overlay.background_alpha;
375 options->update_on_time_change = c_options->update_on_time_change;
376 options->image.exif_proof_rotate_enable = c_options->image.exif_proof_rotate_enable;
378 options->duplicates_similarity_threshold = c_options->duplicates_similarity_threshold;
379 options->rot_invariant_sim = c_options->rot_invariant_sim;
381 options->tree_descend_subdirs = c_options->tree_descend_subdirs;
383 options->view_dir_list_single_click_enter = c_options->view_dir_list_single_click_enter;
384 options->circular_selection_lists = c_options->circular_selection_lists;
386 options->open_recent_list_maxsize = c_options->open_recent_list_maxsize;
387 options->dnd_icon_size = c_options->dnd_icon_size;
388 options->clipboard_selection = c_options->clipboard_selection;
389 options->dnd_default_action = c_options->dnd_default_action;
391 options->metadata.save_in_image_file = c_options->metadata.save_in_image_file;
392 options->metadata.save_legacy_IPTC = c_options->metadata.save_legacy_IPTC;
393 options->metadata.warn_on_write_problems = c_options->metadata.warn_on_write_problems;
394 options->metadata.save_legacy_format = c_options->metadata.save_legacy_format;
395 options->metadata.sync_grouped_files = c_options->metadata.sync_grouped_files;
396 options->metadata.confirm_write = c_options->metadata.confirm_write;
397 options->metadata.sidecar_extended_name = c_options->metadata.sidecar_extended_name;
398 options->metadata.confirm_timeout = c_options->metadata.confirm_timeout;
399 options->metadata.confirm_after_timeout = c_options->metadata.confirm_after_timeout;
400 options->metadata.confirm_on_image_change = c_options->metadata.confirm_on_image_change;
401 options->metadata.confirm_on_dir_change = c_options->metadata.confirm_on_dir_change;
402 options->metadata.keywords_case_sensitive = c_options->metadata.keywords_case_sensitive;
403 options->metadata.write_orientation = c_options->metadata.write_orientation;
404 options->stereo.mode = (c_options->stereo.mode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
405 (c_options->stereo.tmp.mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
406 (c_options->stereo.tmp.flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
407 (c_options->stereo.tmp.mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
408 (c_options->stereo.tmp.flip_left ? PR_STEREO_FLIP_LEFT : 0) |
409 (c_options->stereo.tmp.swap ? PR_STEREO_SWAP : 0) |
410 (c_options->stereo.tmp.temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
411 options->stereo.fsmode = (c_options->stereo.fsmode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
412 (c_options->stereo.tmp.fs_mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
413 (c_options->stereo.tmp.fs_flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
414 (c_options->stereo.tmp.fs_mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
415 (c_options->stereo.tmp.fs_flip_left ? PR_STEREO_FLIP_LEFT : 0) |
416 (c_options->stereo.tmp.fs_swap ? PR_STEREO_SWAP : 0) |
417 (c_options->stereo.tmp.fs_temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
418 options->stereo.enable_fsmode = c_options->stereo.enable_fsmode;
419 options->stereo.fixed_w = c_options->stereo.fixed_w;
420 options->stereo.fixed_h = c_options->stereo.fixed_h;
421 options->stereo.fixed_x1 = c_options->stereo.fixed_x1;
422 options->stereo.fixed_y1 = c_options->stereo.fixed_y1;
423 options->stereo.fixed_x2 = c_options->stereo.fixed_x2;
424 options->stereo.fixed_y2 = c_options->stereo.fixed_y2;
426 options->info_keywords.height = c_options->info_keywords.height;
427 options->info_title.height = c_options->info_title.height;
428 options->info_comment.height = c_options->info_comment.height;
429 options->info_rating.height = c_options->info_rating.height;
431 options->show_predefined_keyword_tree = c_options->show_predefined_keyword_tree;
432 options->expand_menu_toolbar = c_options->expand_menu_toolbar;
434 options->marks_save = c_options->marks_save;
435 options->with_rename = c_options->with_rename;
436 options->collections_on_top = c_options->collections_on_top;
437 options->hide_window_in_fullscreen = c_options->hide_window_in_fullscreen;
438 config_entry_to_option(help_search_engine_entry, &options->help_search_engine, NULL);
440 options->external_preview.enable = c_options->external_preview.enable;
441 config_entry_to_option(external_preview_select_entry, &options->external_preview.select, NULL);
442 config_entry_to_option(external_preview_extract_entry, &options->external_preview.extract, NULL);
444 options->read_metadata_in_idle = c_options->read_metadata_in_idle;
446 options->star_rating.star = c_options->star_rating.star;
447 options->star_rating.rejected = c_options->star_rating.rejected;
449 set_debug_level(debug_c);
453 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
455 config_entry_to_option(color_profile_input_name_entry[i], &options->color_profile.input_name[i], NULL);
456 config_entry_to_option(color_profile_input_file_entry[i], &options->color_profile.input_file[i], NULL);
458 config_entry_to_option(color_profile_screen_file_entry, &options->color_profile.screen_file, NULL);
459 options->color_profile.use_x11_screen_profile = c_options->color_profile.use_x11_screen_profile;
460 if (options->color_profile.render_intent != c_options->color_profile.render_intent)
462 options->color_profile.render_intent = c_options->color_profile.render_intent;
467 options->mouse_button_8 = c_options->mouse_button_8;
468 options->mouse_button_9 = c_options->mouse_button_9;
470 options->override_disable_gpu = c_options->override_disable_gpu;
472 config_tab_keywords_save();
474 image_options_sync();
479 layout_refresh(NULL);
482 if (accel_store) gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_apply_cb, NULL);
484 toolbar_apply(TOOLBAR_MAIN);
485 toolbar_apply(TOOLBAR_STATUS);
489 *-----------------------------------------------------------------------------
490 * config window main button callbacks (private)
491 *-----------------------------------------------------------------------------
494 static void config_window_close_cb(GtkWidget *widget, gpointer data)
496 gtk_widget_destroy(configwindow);
501 static void config_window_help_cb(GtkWidget *widget, gpointer data)
503 GtkWidget *notebook = data;
506 static gchar *html_section[] =
508 "GuideOptionsGeneral.html",
509 "GuideOptionsImage.html",
510 "GuideOptionsOSD.html",
511 "GuideOptionsWindow.html",
512 "GuideOptionsKeyboard.html",
513 "GuideOptionsFiltering.html",
514 "GuideOptionsMetadata.html",
515 "GuideOptionsKeywords.html",
516 "GuideOptionsColor.html",
517 "GuideOptionsStereo.html",
518 "GuideOptionsBehavior.html",
519 "GuideOptionsToolbar.html",
520 "GuideOptionsToolbar.html",
521 "GuideOptionsAdvanced.html"
524 i = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
525 help_window_show(html_section[i]);
528 static gboolean config_window_delete(GtkWidget *widget, GdkEventAny *event, gpointer data)
530 config_window_close_cb(NULL, NULL);
534 static void config_window_ok_cb(GtkWidget *widget, gpointer data)
537 GtkNotebook *notebook = data;
545 lw = layout_window_list->data;
547 window = gtk_widget_get_window(widget);
548 gdk_window_get_root_origin(window, &x, &y);
549 w = gdk_window_get_width(window);
550 h = gdk_window_get_height(window);
551 page_number = gtk_notebook_get_current_page(notebook);
553 lw->options.preferences_window.x = x;
554 lw->options.preferences_window.y = y;
555 lw->options.preferences_window.w = w;
556 lw->options.preferences_window.h = h;
557 lw->options.preferences_window.page_number = page_number;
559 config_window_apply();
560 layout_util_sync(lw);
561 save_options(options);
562 config_window_close_cb(NULL, NULL);
566 *-----------------------------------------------------------------------------
567 * config window setup (private)
568 *-----------------------------------------------------------------------------
571 static void quality_menu_cb(GtkWidget *combo, gpointer data)
575 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
579 *option = GDK_INTERP_NEAREST;
582 *option = GDK_INTERP_TILES;
585 *option = GDK_INTERP_BILINEAR;
590 static void dnd_default_action_selection_menu_cb(GtkWidget *combo, gpointer data)
594 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
598 *option = DND_ACTION_ASK;
601 *option = DND_ACTION_COPY;
604 *option = DND_ACTION_MOVE;
608 static void clipboard_selection_menu_cb(GtkWidget *combo, gpointer data)
612 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
615 *option = CLIPBOARD_PRIMARY;
618 *option = CLIPBOARD_CLIPBOARD;
621 *option = CLIPBOARD_BOTH;
624 *option = CLIPBOARD_BOTH;
628 static void add_quality_menu(GtkWidget *table, gint column, gint row, const gchar *text,
629 guint option, guint *option_c)
636 pref_table_label(table, column, row, text, 0.0);
638 combo = gtk_combo_box_text_new();
640 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Nearest (worst, but fastest)"));
641 if (option == GDK_INTERP_NEAREST) current = 0;
642 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Tiles"));
643 if (option == GDK_INTERP_TILES) current = 1;
644 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Bilinear (best, but slowest)"));
645 if (option == GDK_INTERP_BILINEAR) current = 2;
647 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
649 g_signal_connect(G_OBJECT(combo), "changed",
650 G_CALLBACK(quality_menu_cb), option_c);
652 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
653 gtk_widget_show(combo);
656 static void add_dnd_default_action_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text, DnDAction option, DnDAction *option_c)
663 pref_table_label(table, column, row, text, 0.0);
665 combo = gtk_combo_box_text_new();
667 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Ask"));
668 if (option == DND_ACTION_ASK) current = 0;
669 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Copy"));
670 if (option == DND_ACTION_COPY) current = 1;
671 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Move"));
672 if (option == DND_ACTION_MOVE) current = 2;
674 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
676 g_signal_connect(G_OBJECT(combo), "changed",
677 G_CALLBACK(dnd_default_action_selection_menu_cb), option_c);
679 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
680 gtk_widget_show(combo);
683 static void add_clipboard_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
684 gint option, gint *option_c)
691 pref_table_label(table, column, row, text, 0.0);
693 combo = gtk_combo_box_text_new();
695 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Primary"));
696 if (option == CLIPBOARD_PRIMARY) current = 0;
697 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Clipboard"));
698 if (option == CLIPBOARD_CLIPBOARD) current = 1;
699 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Both"));
700 if (option == CLIPBOARD_BOTH) current = 2;
702 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
704 g_signal_connect(G_OBJECT(combo), "changed",
705 G_CALLBACK(clipboard_selection_menu_cb), option_c);
707 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
708 gtk_widget_show(combo);
711 typedef struct _UseableMouseItems UseableMouseItems;
712 struct _UseableMouseItems
714 gchar *name; /* GtkActionEntry terminology */
719 static const UseableMouseItems useable_mouse_items[] = {
721 {"FirstImage", N_("First Image"), GTK_STOCK_GOTO_TOP},
722 {"PrevImage", N_("Previous Image"), GTK_STOCK_GO_UP},
723 {"NextImage", N_("Next Image"), GTK_STOCK_GO_DOWN},
724 {"LastImage", N_("Last Image"), GTK_STOCK_GOTO_BOTTOM},
725 {"Back", N_("Back"), GTK_STOCK_GO_BACK},
726 {"Forward", N_("Forward"), GTK_STOCK_GO_FORWARD},
727 {"Home", N_("Home"), GTK_STOCK_HOME},
728 {"Up", N_("Up"), GTK_STOCK_GO_UP},
729 {"FirstPage", N_("First page"), GTK_STOCK_MEDIA_PREVIOUS},
730 {"LastPage", N_("Last Page"), GTK_STOCK_MEDIA_NEXT},
731 {"NextPage", N_("Next page"), GTK_STOCK_MEDIA_FORWARD},
732 {"PrevPage", N_("Previous Page"), GTK_STOCK_MEDIA_REWIND},
733 {"NewWindow", N_("New _window"), GTK_STOCK_NEW},
734 {"NewCollection", N_("New collection"), GTK_STOCK_INDEX},
735 {"OpenCollection", N_("Open collection"), GTK_STOCK_OPEN},
736 {"Search", N_("Search"), GTK_STOCK_FIND},
737 {"FindDupes", N_("Find duplicates"), GTK_STOCK_FIND},
738 {"NewFolder", N_("New folder"),GTK_STOCK_DIRECTORY},
739 {"Copy", N_("Copy"), GTK_STOCK_COPY},
740 {"Move", N_("Move"), PIXBUF_INLINE_ICON_MOVE},
741 {"Rename", N_("Rename"), PIXBUF_INLINE_ICON_RENAME},
742 {"Delete", N_("Delete"), GTK_STOCK_DELETE},
743 {"CloseWindow", N_("Close Window"), GTK_STOCK_CLOSE},
744 {"PanView", N_("Pan view"), PIXBUF_INLINE_ICON_PANORAMA},
745 {"SelectAll", N_("Select all"), PIXBUF_INLINE_ICON_SELECT_ALL},
746 {"SelectNone", N_("Select none"), PIXBUF_INLINE_ICON_SELECT_NONE},
747 {"SelectInvert", N_("Select invert"), PIXBUF_INLINE_ICON_SELECT_INVERT},
748 {"ShowFileFilter", N_("Show file filter"), PIXBUF_INLINE_ICON_FILE_FILTER},
749 {"RectangularSelection", N_("Select rectangle"), PIXBUF_INLINE_ICON_SELECT_RECTANGLE},
750 {"Print", N_("Print"), GTK_STOCK_PRINT},
751 {"Preferences", N_("Preferences"), GTK_STOCK_PREFERENCES},
752 {"LayoutConfig", N_("Configure this window"), GTK_STOCK_PREFERENCES},
753 {"Maintenance", N_("Cache maintenance"), PIXBUF_INLINE_ICON_MAINTENANCE},
754 {"RotateCW", N_("Rotate clockwise 90°"), PIXBUF_INLINE_ICON_CW},
755 {"RotateCCW", N_("Rotate counterclockwise 90°"), PIXBUF_INLINE_ICON_CCW},
756 {"Rotate180", N_("Rotate 180°"), PIXBUF_INLINE_ICON_180},
757 {"Mirror", N_("Mirror"), PIXBUF_INLINE_ICON_MIRROR},
758 {"Flip", N_("Flip"), PIXBUF_INLINE_ICON_FLIP},
759 {"AlterNone", N_("Original state"), PIXBUF_INLINE_ICON_ORIGINAL},
760 {"ZoomIn", N_("Zoom in"), GTK_STOCK_ZOOM_IN},
761 {"ZoomOut", N_("Zoom out"), GTK_STOCK_ZOOM_OUT},
762 {"Zoom100", N_("Zoom 1:1"), GTK_STOCK_ZOOM_100},
763 {"ZoomFit", N_("Zoom to fit"), GTK_STOCK_ZOOM_FIT},
764 {"ZoomFillHor", N_("Fit Horizontaly"), PIXBUF_INLINE_ICON_ZOOMFILLHOR},
765 {"ZoomFillVert", N_("Fit vertically"), PIXBUF_INLINE_ICON_ZOOMFILLVERT},
766 {"Zoom200", N_("Zoom 2:1"), GTK_STOCK_FILE},
767 {"Zoom300", N_("Zoom 3:1"), GTK_STOCK_FILE},
768 {"Zoom400", N_("Zoom 4:1"), GTK_STOCK_FILE},
769 {"Zoom50", N_("Zoom 1:2"), GTK_STOCK_FILE},
770 {"Zoom33", N_("Zoom1:3"), GTK_STOCK_FILE},
771 {"Zoom25", N_("Zoom 1:4"), GTK_STOCK_FILE},
772 {"ConnectZoomIn", N_("Connected Zoom in"), GTK_STOCK_ZOOM_IN},
773 {"SplitPaneSync", N_("Split Pane Sync"), PIXBUF_INLINE_SPLIT_PANE_SYNC},
774 {"Grayscale", N_("Grayscale"), PIXBUF_INLINE_ICON_GRAYSCALE},
775 {"OverUnderExposed", N_("Over Under Exposed"), PIXBUF_INLINE_ICON_EXPOSURE},
776 {"HideTools", N_("Hide file list"), PIXBUF_INLINE_ICON_HIDETOOLS},
777 {"SlideShowPause", N_("Pause slideshow"), GTK_STOCK_MEDIA_PAUSE},
778 {"SlideShowFaster", N_("Slideshow Faster"), GTK_STOCK_FILE},
779 {"SlideShowSlower", N_("Slideshow Slower"), GTK_STOCK_FILE},
780 {"Refresh", N_("Refresh"), GTK_STOCK_REFRESH},
781 {"HelpContents", N_("Help"), GTK_STOCK_HELP},
782 {"ExifWin", N_("Exif window"), PIXBUF_INLINE_ICON_EXIF},
783 {"Thumbnails", N_("Show thumbnails"), PIXBUF_INLINE_ICON_THUMB},
784 {"ShowMarks", N_("Show marks"), PIXBUF_INLINE_ICON_MARKS},
785 {"DrawRectangle", N_("Draw Rectangle"), PIXBUF_INLINE_ICON_DRAW_RECTANGLE},
786 {"FloatTools", N_("Float file list"), PIXBUF_INLINE_ICON_FLOAT},
787 {"SBar", N_("Info sidebar"), PIXBUF_INLINE_ICON_INFO},
788 {"SBarSort", N_("Sort manager"), PIXBUF_INLINE_ICON_SORT},
789 {"Quit", N_("Quit"), GTK_STOCK_QUIT},
793 static void mouse_buttons_selection_menu_cb(GtkWidget *combo, gpointer data)
795 gchar **option = data;
798 label = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(combo));
800 const UseableMouseItems *list = useable_mouse_items;
804 if (g_strcmp0(list->label, label) == 0)
812 *option = g_strdup(list->name);
816 static void add_mouse_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
817 gchar *option, gchar **option_c)
825 pref_table_label(table, column, row, text, 0.0);
827 combo = gtk_combo_box_text_new();
829 const UseableMouseItems *list = useable_mouse_items;
833 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), list->label);
834 if (g_strcmp0(list->name, option) == 0)
842 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
844 g_signal_connect(G_OBJECT(combo), "changed",
845 G_CALLBACK(mouse_buttons_selection_menu_cb), option_c);
847 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
848 gtk_widget_show(combo);
851 static void thumb_size_menu_cb(GtkWidget *combo, gpointer data)
855 n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
858 if ((guint) n < sizeof(thumb_size_list) / sizeof(ThumbSize))
860 c_options->thumbnails.max_width = thumb_size_list[n].w;
861 c_options->thumbnails.max_height = thumb_size_list[n].h;
865 c_options->thumbnails.max_width = options->thumbnails.max_width;
866 c_options->thumbnails.max_height = options->thumbnails.max_height;
870 static void add_thumb_size_menu(GtkWidget *table, gint column, gint row, gchar *text)
876 c_options->thumbnails.max_width = options->thumbnails.max_width;
877 c_options->thumbnails.max_height = options->thumbnails.max_height;
879 pref_table_label(table, column, row, text, 0.0);
881 combo = gtk_combo_box_text_new();
884 for (i = 0; (guint) i < sizeof(thumb_size_list) / sizeof(ThumbSize); i++)
889 w = thumb_size_list[i].w;
890 h = thumb_size_list[i].h;
892 buf = g_strdup_printf("%d x %d", w, h);
893 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
896 if (w == options->thumbnails.max_width && h == options->thumbnails.max_height) current = i;
903 buf = g_strdup_printf("%s %d x %d", _("Custom"), options->thumbnails.max_width, options->thumbnails.max_height);
904 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
910 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
911 g_signal_connect(G_OBJECT(combo), "changed",
912 G_CALLBACK(thumb_size_menu_cb), NULL);
914 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
915 gtk_widget_show(combo);
918 static void stereo_mode_menu_cb(GtkWidget *combo, gpointer data)
922 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
926 *option = PR_STEREO_NONE;
929 *option = PR_STEREO_ANAGLYPH_RC;
932 *option = PR_STEREO_ANAGLYPH_GM;
935 *option = PR_STEREO_ANAGLYPH_YB;
938 *option = PR_STEREO_ANAGLYPH_GRAY_RC;
941 *option = PR_STEREO_ANAGLYPH_GRAY_GM;
944 *option = PR_STEREO_ANAGLYPH_GRAY_YB;
947 *option = PR_STEREO_ANAGLYPH_DB_RC;
950 *option = PR_STEREO_ANAGLYPH_DB_GM;
953 *option = PR_STEREO_ANAGLYPH_DB_YB;
956 *option = PR_STEREO_HORIZ;
959 *option = PR_STEREO_HORIZ | PR_STEREO_HALF;
962 *option = PR_STEREO_VERT;
965 *option = PR_STEREO_VERT | PR_STEREO_HALF;
968 *option = PR_STEREO_FIXED;
973 static void add_stereo_mode_menu(GtkWidget *table, gint column, gint row, const gchar *text,
974 gint option, gint *option_c, gboolean add_fixed)
981 pref_table_label(table, column, row, text, 0.0);
983 combo = gtk_combo_box_text_new();
985 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Single image"));
987 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Red-Cyan"));
988 if (option & PR_STEREO_ANAGLYPH_RC) current = 1;
989 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Green-Magenta"));
990 if (option & PR_STEREO_ANAGLYPH_GM) current = 2;
991 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Yellow-Blue"));
992 if (option & PR_STEREO_ANAGLYPH_YB) current = 3;
993 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Red-Cyan"));
994 if (option & PR_STEREO_ANAGLYPH_GRAY_RC) current = 4;
995 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Green-Magenta"));
996 if (option & PR_STEREO_ANAGLYPH_GRAY_GM) current = 5;
997 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Yellow-Blue"));
998 if (option & PR_STEREO_ANAGLYPH_GRAY_YB) current = 6;
999 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Red-Cyan"));
1000 if (option & PR_STEREO_ANAGLYPH_DB_RC) current = 7;
1001 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Green-Magenta"));
1002 if (option & PR_STEREO_ANAGLYPH_DB_GM) current = 8;
1003 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Yellow-Blue"));
1004 if (option & PR_STEREO_ANAGLYPH_DB_YB) current = 9;
1006 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side"));
1007 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side Half size"));
1008 if (option & PR_STEREO_HORIZ)
1011 if (option & PR_STEREO_HALF) current = 11;
1014 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom"));
1015 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom Half size"));
1016 if (option & PR_STEREO_VERT)
1019 if (option & PR_STEREO_HALF) current = 13;
1024 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Fixed position"));
1025 if (option & PR_STEREO_FIXED) current = 14;
1028 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
1030 g_signal_connect(G_OBJECT(combo), "changed",
1031 G_CALLBACK(stereo_mode_menu_cb), option_c);
1033 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
1034 gtk_widget_show(combo);
1037 static void video_menu_cb(GtkWidget *combo, gpointer data)
1039 gchar **option = data;
1041 EditorDescription *ed = g_list_nth_data(editor_list_get(), gtk_combo_box_get_active(GTK_COMBO_BOX(combo)));
1045 static void video_menu_populate(gpointer data, gpointer user_data)
1047 GtkWidget *combo = user_data;
1048 EditorDescription *ed = data;
1050 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), ed->name);
1053 static void add_video_menu(GtkWidget *table, gint column, gint row, const gchar *text,
1054 gchar *option, gchar **option_c)
1058 /* use lists since they are sorted */
1059 GList *eds = editor_list_get();
1063 pref_table_label(table, column, row, text, 0.0);
1065 combo = gtk_combo_box_text_new();
1066 g_list_foreach(eds,video_menu_populate,(gpointer)combo);
1067 current = option ? g_list_index(eds,g_hash_table_lookup(editors,option)): -1;
1069 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
1071 g_signal_connect(G_OBJECT(combo), "changed",
1072 G_CALLBACK(video_menu_cb), option_c);
1074 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
1075 gtk_widget_show(combo);
1078 static void filter_store_populate(void)
1082 if (!filter_store) return;
1084 gtk_list_store_clear(filter_store);
1086 work = filter_get_list();
1095 gtk_list_store_append(filter_store, &iter);
1096 gtk_list_store_set(filter_store, &iter, 0, fe, -1);
1100 static void filter_store_ext_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1101 gchar *new_text, gpointer data)
1103 GtkWidget *model = data;
1104 FilterEntry *fe = data;
1108 if (!new_text || strlen(new_text) < 1) return;
1110 tpath = gtk_tree_path_new_from_string(path_str);
1111 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1112 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1114 g_free(fe->extensions);
1115 fe->extensions = g_strdup(new_text);
1117 gtk_tree_path_free(tpath);
1121 static void filter_store_class_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1122 gchar *new_text, gpointer data)
1124 GtkWidget *model = data;
1125 FilterEntry *fe = data;
1130 if (!new_text || !new_text[0]) return;
1132 tpath = gtk_tree_path_new_from_string(path_str);
1133 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1134 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1136 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
1138 if (strcmp(new_text, _(format_class_list[i])) == 0)
1145 gtk_tree_path_free(tpath);
1149 static void filter_store_desc_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1150 gchar *new_text, gpointer data)
1152 GtkWidget *model = data;
1157 if (!new_text || !new_text[0]) return;
1159 tpath = gtk_tree_path_new_from_string(path_str);
1160 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1161 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1163 g_free(fe->description);
1164 fe->description = g_strdup(new_text);
1166 gtk_tree_path_free(tpath);
1169 static void filter_store_enable_cb(GtkCellRendererToggle *renderer,
1170 gchar *path_str, gpointer data)
1172 GtkWidget *model = data;
1177 tpath = gtk_tree_path_new_from_string(path_str);
1178 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1179 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1181 fe->enabled = !fe->enabled;
1183 gtk_tree_path_free(tpath);
1187 static void filter_store_writable_cb(GtkCellRendererToggle *renderer,
1188 gchar *path_str, gpointer data)
1190 GtkWidget *model = data;
1195 tpath = gtk_tree_path_new_from_string(path_str);
1196 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1197 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1199 fe->writable = !fe->writable;
1200 if (fe->writable) fe->allow_sidecar = FALSE;
1202 gtk_tree_path_free(tpath);
1206 static void filter_store_sidecar_cb(GtkCellRendererToggle *renderer,
1207 gchar *path_str, gpointer data)
1209 GtkWidget *model = data;
1214 tpath = gtk_tree_path_new_from_string(path_str);
1215 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1216 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1218 fe->allow_sidecar = !fe->allow_sidecar;
1219 if (fe->allow_sidecar) fe->writable = FALSE;
1221 gtk_tree_path_free(tpath);
1225 static void filter_set_func(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
1226 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
1230 gtk_tree_model_get(tree_model, iter, 0, &fe, -1);
1232 switch (GPOINTER_TO_INT(data))
1235 g_object_set(GTK_CELL_RENDERER(cell),
1236 "active", fe->enabled, NULL);
1239 g_object_set(GTK_CELL_RENDERER(cell),
1240 "text", fe->extensions, NULL);
1242 case FE_DESCRIPTION:
1243 g_object_set(GTK_CELL_RENDERER(cell),
1244 "text", fe->description, NULL);
1247 g_object_set(GTK_CELL_RENDERER(cell),
1248 "text", _(format_class_list[fe->file_class]), NULL);
1251 g_object_set(GTK_CELL_RENDERER(cell),
1252 "active", fe->writable, NULL);
1254 case FE_ALLOW_SIDECAR:
1255 g_object_set(GTK_CELL_RENDERER(cell),
1256 "active", fe->allow_sidecar, NULL);
1261 static gboolean filter_add_scroll(gpointer data)
1265 GtkCellRenderer *cell;
1266 GtkTreeViewColumn *column;
1269 rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(filter_store), NULL);
1270 path = gtk_tree_path_new_from_indices(rows-1, -1);
1272 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data), 0);
1274 list_cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column));
1275 cell = g_list_last(list_cells)->data;
1277 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1278 path, column, FALSE, 0.0, 0.0 );
1279 gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(data),
1280 path, column, cell, TRUE);
1282 gtk_tree_path_free(path);
1283 g_list_free(list_cells);
1288 static void filter_add_cb(GtkWidget *widget, gpointer data)
1290 filter_add_unique("description", ".new", FORMAT_CLASS_IMAGE, TRUE, FALSE, TRUE);
1291 filter_store_populate();
1293 g_idle_add((GSourceFunc)filter_add_scroll, data);
1296 static void filter_remove_cb(GtkWidget *widget, gpointer data)
1298 GtkWidget *filter_view = data;
1299 GtkTreeSelection *selection;
1303 if (!filter_store) return;
1304 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1305 if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) return;
1306 gtk_tree_model_get(GTK_TREE_MODEL(filter_store), &iter, 0, &fe, -1);
1309 filter_remove_entry(fe);
1311 filter_store_populate();
1314 static gboolean filter_default_ok_scroll(GtkTreeView *data)
1318 GtkTreeViewColumn *column;
1320 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(filter_store), &iter);
1321 path = gtk_tree_model_get_path(GTK_TREE_MODEL(filter_store), &iter);
1322 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1324 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1328 gtk_tree_path_free(path);
1333 static void filter_default_ok_cb(GenericDialog *gd, gpointer data)
1336 filter_add_defaults();
1338 filter_store_populate();
1340 g_idle_add((GSourceFunc)filter_default_ok_scroll, gd->data);
1343 static void dummy_cancel_cb(GenericDialog *gd, gpointer data)
1345 /* no op, only so cancel button appears */
1348 static void filter_default_cb(GtkWidget *widget, gpointer data)
1352 gd = generic_dialog_new(_("Reset filters"),
1353 "reset_filter", widget, TRUE,
1354 dummy_cancel_cb, data);
1355 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset filters"),
1356 _("This will reset the file filters to the defaults.\nContinue?"), TRUE);
1357 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, filter_default_ok_cb, TRUE);
1358 gtk_widget_show(gd->dialog);
1361 static void filter_disable_cb(GtkWidget *widget, gpointer data)
1363 GtkWidget *frame = data;
1365 gtk_widget_set_sensitive(frame,
1366 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
1369 static void safe_delete_view_cb(GtkWidget *widget, gpointer data)
1371 layout_set_path(NULL, gtk_entry_get_text(GTK_ENTRY(safe_delete_path_entry)));
1374 static void safe_delete_clear_ok_cb(GenericDialog *gd, gpointer data)
1376 file_util_trash_clear();
1379 static void safe_delete_clear_cb(GtkWidget *widget, gpointer data)
1383 gd = generic_dialog_new(_("Clear trash"),
1384 "clear_trash", widget, TRUE,
1385 dummy_cancel_cb, NULL);
1386 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear trash"),
1387 _("This will remove the trash contents."), FALSE);
1388 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, safe_delete_clear_ok_cb, TRUE);
1389 entry = gtk_entry_new();
1390 gtk_widget_set_can_focus(entry, FALSE);
1391 gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE);
1392 if (options->file_ops.safe_delete_path) gtk_entry_set_text(GTK_ENTRY(entry), options->file_ops.safe_delete_path);
1393 gtk_box_pack_start(GTK_BOX(gd->vbox), entry, FALSE, FALSE, 0);
1394 gtk_widget_show(entry);
1395 gtk_widget_show(gd->dialog);
1398 static void image_overlay_template_view_changed_cb(GtkWidget *widget, gpointer data)
1400 GtkWidget *pTextView;
1401 GtkTextBuffer *pTextBuffer;
1405 pTextView = GTK_WIDGET(data);
1407 pTextBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pTextView));
1408 gtk_text_buffer_get_start_iter(pTextBuffer, &iStart);
1409 gtk_text_buffer_get_end_iter(pTextBuffer, &iEnd);
1411 set_image_overlay_template_string(&c_options->image_overlay.template_string,
1412 gtk_text_buffer_get_text(pTextBuffer, &iStart, &iEnd, TRUE));
1415 static void image_overlay_default_template_ok_cb(GenericDialog *gd, gpointer data)
1417 GtkTextView *text_view = data;
1418 GtkTextBuffer *buffer;
1420 set_default_image_overlay_template_string(&options->image_overlay.template_string);
1421 if (!configwindow) return;
1423 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
1424 gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1427 static void image_overlay_default_template_cb(GtkWidget *widget, gpointer data)
1431 gd = generic_dialog_new(_("Reset image overlay template string"),
1432 "reset_image_overlay_template_string", widget, TRUE,
1433 dummy_cancel_cb, data);
1434 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset image overlay template string"),
1435 _("This will reset the image overlay template string to the default.\nContinue?"), TRUE);
1436 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, image_overlay_default_template_ok_cb, TRUE);
1437 gtk_widget_show(gd->dialog);
1440 static void image_overlay_help_cb(GtkWidget *widget, gpointer data)
1442 help_window_show("GuideOptionsOSD.html");
1445 static void image_overlay_set_font_cb(GtkWidget *widget, gpointer data)
1447 #if GTK_CHECK_VERSION(3,4,0)
1450 PangoFontDescription *font_desc;
1452 dialog = gtk_font_chooser_dialog_new("Image Overlay Font", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1453 gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), options->image_overlay.font);
1455 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1457 font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
1458 font = pango_font_description_to_string(font_desc);
1459 g_free(c_options->image_overlay.font);
1460 c_options->image_overlay.font = g_strdup(font);
1464 gtk_widget_destroy(dialog);
1468 font = gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget));
1469 c_options->image_overlay.font = g_strdup(font);
1473 static void image_overlay_set_text_colour_cb(GtkWidget *widget, gpointer data)
1476 #if GTK_CHECK_VERSION(3,4,0)
1479 dialog = gtk_color_chooser_dialog_new("Image Overlay Text Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1480 colour.red = options->image_overlay.text_red;
1481 colour.green = options->image_overlay.text_green;
1482 colour.blue = options->image_overlay.text_blue;
1483 colour.alpha = options->image_overlay.text_alpha;
1484 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1485 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1487 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1489 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1490 c_options->image_overlay.text_red = colour.red*255;
1491 c_options->image_overlay.text_green = colour.green*255;
1492 c_options->image_overlay.text_blue = colour.blue*255;
1493 c_options->image_overlay.text_alpha = colour.alpha*255;
1495 gtk_widget_destroy(dialog);
1498 GtkColorSelection *colorsel;
1500 dialog = gtk_color_selection_dialog_new("Image Overlay Text Colour");
1501 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1502 colour.red = options->image_overlay.text_red*257;
1503 colour.green = options->image_overlay.text_green*257;
1504 colour.blue = options->image_overlay.text_blue*257;
1505 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1506 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1507 gtk_color_selection_set_current_color(colorsel, &colour);
1508 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.text_alpha*257);
1510 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1512 gtk_color_selection_get_current_color(colorsel, &colour);
1513 c_options->image_overlay.text_red = colour.red/257;
1514 c_options->image_overlay.text_green = colour.green/257;
1515 c_options->image_overlay.text_blue = colour.blue/257;
1516 c_options->image_overlay.text_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1518 gtk_widget_destroy (dialog);
1523 static void image_overlay_set_background_colour_cb(GtkWidget *widget, gpointer data)
1526 #if GTK_CHECK_VERSION(3,4,0)
1529 dialog = gtk_color_chooser_dialog_new("Image Overlay Background Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1530 colour.red = options->image_overlay.background_red;
1531 colour.green = options->image_overlay.background_green;
1532 colour.blue = options->image_overlay.background_blue;
1533 colour.alpha = options->image_overlay.background_alpha;
1534 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1535 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1537 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1539 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1540 c_options->image_overlay.background_red = colour.red*255;
1541 c_options->image_overlay.background_green = colour.green*255;
1542 c_options->image_overlay.background_blue = colour.blue*255;
1543 c_options->image_overlay.background_alpha = colour.alpha*255;
1545 gtk_widget_destroy(dialog);
1548 GtkColorSelection *colorsel;
1550 dialog = gtk_color_selection_dialog_new("Image Overlay Background Colour");
1551 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1552 colour.red = options->image_overlay.background_red*257;
1553 colour.green = options->image_overlay.background_green*257;
1554 colour.blue = options->image_overlay.background_blue*257;
1555 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1556 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1557 gtk_color_selection_set_current_color(colorsel, &colour);
1558 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.background_alpha*257);
1560 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1562 gtk_color_selection_get_current_color(colorsel, &colour);
1563 c_options->image_overlay.background_red = colour.red/257;
1564 c_options->image_overlay.background_green = colour.green/257;
1565 c_options->image_overlay.background_blue = colour.blue/257;
1566 c_options->image_overlay.background_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1568 gtk_widget_destroy(dialog);
1572 static void accel_store_populate(void)
1575 GList *groups, *actions;
1577 const gchar *accel_path;
1581 if (!accel_store || !layout_window_list || !layout_window_list->data) return;
1583 gtk_tree_store_clear(accel_store);
1584 lw = layout_window_list->data; /* get the actions from the first window, it should not matter, they should be the same in all windows */
1586 g_assert(lw && lw->ui_manager);
1587 groups = gtk_ui_manager_get_action_groups(lw->ui_manager);
1590 actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
1593 action = GTK_ACTION(actions->data);
1594 accel_path = gtk_action_get_accel_path(action);
1595 if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
1597 gchar *label, *label2, *tooltip, *accel;
1598 g_object_get(action,
1599 "tooltip", &tooltip,
1603 if (pango_parse_markup(label, -1, '_', NULL, &label2, NULL, NULL) && label2)
1609 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1613 gtk_tree_store_append(accel_store, &iter, NULL);
1614 gtk_tree_store_set(accel_store, &iter,
1617 AE_TOOLTIP, tooltip ? tooltip : "",
1618 AE_ACCEL, accel_path,
1626 actions = actions->next;
1629 groups = groups->next;
1633 static void accel_store_cleared_cb(GtkCellRendererAccel *accel, gchar *path_string, gpointer user_data)
1638 static gboolean accel_remove_key_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1640 gchar *accel1 = data;
1645 gtk_tree_model_get(model, iter, AE_KEY, &accel2, -1);
1647 gtk_accelerator_parse(accel1, &key1.accel_key, &key1.accel_mods);
1648 gtk_accelerator_parse(accel2, &key2.accel_key, &key2.accel_mods);
1650 if (key1.accel_key == key2.accel_key && key1.accel_mods == key2.accel_mods)
1652 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1653 DEBUG_1("accelerator key '%s' is already used, removing.", accel1);
1662 static void accel_store_edited_cb(GtkCellRendererAccel *accel, gchar *path_string, guint accel_key, GdkModifierType accel_mods, guint hardware_keycode, gpointer user_data)
1664 GtkTreeModel *model = (GtkTreeModel *)accel_store;
1668 GtkAccelKey old_key, key;
1669 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
1671 gtk_tree_model_get_iter(model, &iter, path);
1672 gtk_tree_model_get(model, &iter, AE_ACCEL, &accel_path, -1);
1674 /* test if the accelerator can be stored without conflicts*/
1675 gtk_accel_map_lookup_entry(accel_path, &old_key);
1677 /* change the key and read it back (change may fail on keys hardcoded in gtk)*/
1678 gtk_accel_map_change_entry(accel_path, accel_key, accel_mods, TRUE);
1679 gtk_accel_map_lookup_entry(accel_path, &key);
1681 /* restore the original for now, the key will be really changed when the changes are confirmed */
1682 gtk_accel_map_change_entry(accel_path, old_key.accel_key, old_key.accel_mods, TRUE);
1684 acc = gtk_accelerator_name(key.accel_key, key.accel_mods);
1685 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, acc);
1687 gtk_tree_store_set(accel_store, &iter, AE_KEY, acc, -1);
1688 gtk_tree_path_free(path);
1692 static gboolean accel_default_scroll(GtkTreeView *data)
1696 GtkTreeViewColumn *column;
1698 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(accel_store), &iter);
1699 path = gtk_tree_model_get_path(GTK_TREE_MODEL(accel_store), &iter);
1700 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1702 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1706 gtk_tree_path_free(path);
1711 static void accel_default_cb(GtkWidget *widget, gpointer data)
1713 accel_store_populate();
1715 g_idle_add((GSourceFunc)accel_default_scroll, data);
1718 void accel_remove_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1720 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1723 void accel_reset_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1726 gchar *accel_path, *accel;
1728 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, -1);
1729 gtk_accel_map_lookup_entry(accel_path, &key);
1730 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1732 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, accel);
1734 gtk_tree_store_set(accel_store, iter, AE_KEY, accel, -1);
1739 static void accel_reset_cb(GtkWidget *widget, gpointer data)
1741 GtkTreeSelection *selection;
1743 if (!accel_store) return;
1744 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data));
1745 gtk_tree_selection_selected_foreach(selection, &accel_reset_selection, NULL);
1750 static GtkWidget *scrolled_notebook_page(GtkWidget *notebook, const gchar *title)
1754 GtkWidget *scrolled;
1755 GtkWidget *viewport;
1757 scrolled = gtk_scrolled_window_new(NULL, NULL);
1758 gtk_container_set_border_width(GTK_CONTAINER(scrolled), PREF_PAD_BORDER);
1759 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1760 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1761 label = gtk_label_new(title);
1762 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, label);
1763 gtk_widget_show(scrolled);
1765 viewport = gtk_viewport_new(NULL, NULL);
1766 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1767 gtk_container_add(GTK_CONTAINER(scrolled), viewport);
1768 gtk_widget_show(viewport);
1770 vbox = gtk_vbox_new(FALSE, 0);
1771 gtk_container_add(GTK_CONTAINER(viewport), vbox);
1772 gtk_widget_show(vbox);
1777 static void cache_standard_cb(GtkWidget *widget, gpointer data)
1779 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1781 c_options->thumbnails.spec_standard =TRUE;
1782 c_options->thumbnails.cache_into_dirs = FALSE;
1786 static void cache_geeqie_cb(GtkWidget *widget, gpointer data)
1788 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1790 c_options->thumbnails.spec_standard =FALSE;
1791 c_options->thumbnails.cache_into_dirs = FALSE;
1795 static void cache_local_cb(GtkWidget *widget, gpointer data)
1797 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1799 c_options->thumbnails.cache_into_dirs = TRUE;
1800 c_options->thumbnails.spec_standard =FALSE;
1804 static void help_search_engine_entry_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1805 GdkEvent *event, gpointer userdata)
1807 if (pos == GTK_ENTRY_ICON_PRIMARY)
1809 gtk_entry_set_text(GTK_ENTRY(userdata), HELP_SEARCH_ENGINE);
1813 gtk_entry_set_text(GTK_ENTRY(userdata), "");
1817 static void star_rating_star_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1818 GdkEvent *event, gpointer userdata)
1820 gchar *rating_symbol;
1822 if (pos == GTK_ENTRY_ICON_PRIMARY)
1824 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_STAR);
1825 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1826 g_free(rating_symbol);
1830 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1831 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1832 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1836 static void star_rating_rejected_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1837 GdkEvent *event, gpointer userdata)
1839 gchar *rating_symbol;
1841 if (pos == GTK_ENTRY_ICON_PRIMARY)
1843 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_REJECTED);
1844 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1845 g_free(rating_symbol);
1849 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1850 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1851 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1855 static guint star_rating_symbol_test(GtkWidget *widget, gpointer data)
1857 GtkContainer *hbox = data;
1858 GString *str = g_string_new(NULL);
1859 GtkEntry *hex_code_entry;
1860 gchar *hex_code_full;
1863 guint64 hex_value = 0;
1865 list = gtk_container_get_children(hbox);
1867 hex_code_entry = g_list_nth_data(list, 2);
1868 hex_code_full = g_strdup(gtk_entry_get_text(hex_code_entry));
1870 hex_code = g_strsplit(hex_code_full, "+", 2);
1871 if (hex_code[0] && hex_code[1])
1873 hex_value = strtoull(hex_code[1], NULL, 16);
1875 if (!hex_value || hex_value > 0x10FFFF)
1877 hex_value = 0x003F; // Unicode 'Question Mark'
1879 str = g_string_append_unichar(str, (gunichar)hex_value);
1880 gtk_label_set_text(g_list_nth_data(list, 1), str->str);
1882 g_strfreev(hex_code);
1883 g_string_free(str, TRUE);
1884 g_free(hex_code_full);
1889 static void star_rating_star_test_cb(GtkWidget *widget, gpointer data)
1891 guint64 star_symbol;
1893 star_symbol = star_rating_symbol_test(widget, data);
1894 c_options->star_rating.star = star_symbol;
1897 static void star_rating_rejected_test_cb(GtkWidget *widget, gpointer data)
1899 guint64 rejected_symbol;
1901 rejected_symbol = star_rating_symbol_test(widget, data);
1902 c_options->star_rating.rejected = rejected_symbol;
1905 /* general options tab */
1906 static void timezone_database_install_cb(GtkWidget *widget, gpointer data);
1907 typedef struct _TZData TZData;
1911 GCancellable *cancellable;
1913 GtkWidget *progress;
1915 GFile *timezone_database_gq;
1916 gchar *timezone_database_user;
1919 static void config_tab_general(GtkWidget *notebook)
1924 GtkWidget *group_frame;
1925 GtkWidget *subgroup;
1927 GtkWidget *ct_button;
1930 gint hours, minutes, remainder;
1932 GtkWidget *star_rating_entry;
1934 gchar *rating_symbol;
1937 GNetworkMonitor *net_mon;
1938 GSocketConnectable *geeqie_org;
1939 gboolean internet_available;
1942 vbox = scrolled_notebook_page(notebook, _("General"));
1944 group = pref_group_new(vbox, FALSE, _("Thumbnails"), GTK_ORIENTATION_VERTICAL);
1946 table = pref_table_new(group, 2, 2, FALSE, FALSE);
1947 add_thumb_size_menu(table, 0, 0, _("Size:"));
1948 add_quality_menu(table, 0, 1, _("Quality:"), options->thumbnails.quality, &c_options->thumbnails.quality);
1950 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1951 pref_label_new(hbox, _("Custom size: "));
1952 pref_spin_new_int(hbox, _("Width:"), NULL, 1, 512, 1, options->thumbnails.max_width, &c_options->thumbnails.max_width);
1953 pref_spin_new_int(hbox, _("Height:"), NULL, 1, 512, 1, options->thumbnails.max_height, &c_options->thumbnails.max_height);
1955 ct_button = pref_checkbox_new_int(group, _("Cache thumbnails and sim. files"),
1956 options->thumbnails.enable_caching, &c_options->thumbnails.enable_caching);
1958 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1959 pref_checkbox_link_sensitivity(ct_button, subgroup);
1961 c_options->thumbnails.spec_standard = options->thumbnails.spec_standard;
1962 c_options->thumbnails.cache_into_dirs = options->thumbnails.cache_into_dirs;
1963 group_frame = pref_frame_new(subgroup, TRUE, _("Use Geeqie thumbnail style and cache"),
1964 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1965 button = pref_radiobutton_new(group_frame, NULL, get_thumbnails_cache_dir(),
1966 !options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1967 G_CALLBACK(cache_geeqie_cb), NULL);
1969 group_frame = pref_frame_new(subgroup, TRUE,
1970 _("Store thumbnails local to image folder (non-standard)"),
1971 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1972 pref_radiobutton_new(group_frame, button, "*/.thumbnails",
1973 !options->thumbnails.spec_standard && options->thumbnails.cache_into_dirs,
1974 G_CALLBACK(cache_local_cb), NULL);
1976 group_frame = pref_frame_new(subgroup, TRUE,
1977 _("Use standard thumbnail style and cache, shared with other applications"),
1978 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1979 pref_radiobutton_new(group_frame, button, get_thumbnails_standard_cache_dir(),
1980 options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1981 G_CALLBACK(cache_standard_cb), NULL);
1983 pref_checkbox_new_int(group, _("Use EXIF thumbnails when available (EXIF thumbnails may be outdated)"),
1984 options->thumbnails.use_exif, &c_options->thumbnails.use_exif);
1986 pref_checkbox_new_int(group, _("Thumbnail color management"),
1987 options->thumbnails.use_color_management, &c_options->thumbnails.use_color_management);
1989 spin = pref_spin_new_int(group, _("Collection preview:"), NULL,
1991 options->thumbnails.collection_preview, &c_options->thumbnails.collection_preview);
1992 gtk_widget_set_tooltip_text(spin, _("The maximum number of thumbnails shown in a Collection preview montage"));
1994 #ifdef HAVE_FFMPEGTHUMBNAILER_METADATA
1995 pref_checkbox_new_int(group, _("Use embedded metadata in video files as thumbnails when available"),
1996 options->thumbnails.use_ft_metadata, &c_options->thumbnails.use_ft_metadata);
1998 // pref_checkbox_new_int(group, _("Ignore embedded metadata if size is too small"),
1999 // options->thumbnails.use_ft_metadata_small, &c_options->thumbnails.use_ft_metadata_small);
2002 pref_spacer(group, PREF_PAD_GROUP);
2004 group = pref_group_new(vbox, FALSE, _("Star Rating"), GTK_ORIENTATION_VERTICAL);
2006 c_options->star_rating.star = options->star_rating.star;
2007 c_options->star_rating.rejected = options->star_rating.rejected;
2009 str = g_string_new(NULL);
2010 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2011 pref_label_new(hbox, _("Star character: "));
2012 str = g_string_append_unichar(str, options->star_rating.star);
2013 pref_label_new(hbox, g_strdup(str->str));
2014 rating_symbol = g_strdup_printf("U+%X", options->star_rating.star);
2015 star_rating_entry = gtk_entry_new();
2016 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
2017 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
2018 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
2019 gtk_widget_show(star_rating_entry);
2020 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
2021 G_CALLBACK(star_rating_star_test_cb), hbox);
2022 gtk_widget_set_tooltip_text(button, _("Display selected character"));
2023 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2024 gtk_widget_show(button);
2025 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."));
2026 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2027 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2028 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2029 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2030 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2031 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2032 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2033 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2034 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
2035 G_CALLBACK(star_rating_star_icon_cb),
2038 g_string_free(str, TRUE);
2039 g_free(rating_symbol);
2041 str = g_string_new(NULL);
2042 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2043 pref_label_new(hbox, _("Rejected character: "));
2044 str = g_string_append_unichar(str, options->star_rating.rejected);
2045 pref_label_new(hbox, g_strdup(str->str));
2046 rating_symbol = g_strdup_printf("U+%X", options->star_rating.rejected);
2047 star_rating_entry = gtk_entry_new();
2048 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
2049 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
2050 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
2051 gtk_widget_show(star_rating_entry);
2052 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
2053 G_CALLBACK(star_rating_rejected_test_cb), hbox);
2054 gtk_widget_set_tooltip_text(button, _("Display selected character"));
2055 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2056 gtk_widget_show(button);
2057 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."));
2058 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2059 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2060 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2061 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2062 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2063 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2064 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2065 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2066 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
2067 G_CALLBACK(star_rating_rejected_icon_cb),
2070 g_string_free(str, TRUE);
2071 g_free(rating_symbol);
2073 pref_spacer(group, PREF_PAD_GROUP);
2075 group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
2077 c_options->slideshow.delay = options->slideshow.delay;
2078 hours = options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2079 remainder = options->slideshow.delay % (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2080 minutes = remainder / (60 * SLIDESHOW_SUBSECOND_PRECISION);
2081 seconds = (gdouble)(remainder % (60 * SLIDESHOW_SUBSECOND_PRECISION)) /
2082 SLIDESHOW_SUBSECOND_PRECISION;
2084 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2086 spin = pref_spin_new(hbox, _("Delay between image change hrs:mins:secs.dec"), NULL,
2088 options->slideshow.delay ? hours : 0.0,
2089 G_CALLBACK(slideshow_delay_hours_cb), NULL);
2090 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2091 spin = pref_spin_new(hbox, ":" , NULL,
2093 options->slideshow.delay ? minutes: 0.0,
2094 G_CALLBACK(slideshow_delay_minutes_cb), NULL);
2095 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2096 spin = pref_spin_new(hbox, ":", NULL,
2097 SLIDESHOW_MIN_SECONDS, 59, 1.0, 1,
2098 options->slideshow.delay ? seconds : 10.0,
2099 G_CALLBACK(slideshow_delay_seconds_cb), NULL);
2100 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2102 pref_checkbox_new_int(group, _("Random"), options->slideshow.random, &c_options->slideshow.random);
2103 pref_checkbox_new_int(group, _("Repeat"), options->slideshow.repeat, &c_options->slideshow.repeat);
2105 pref_spacer(group, PREF_PAD_GROUP);
2107 group = pref_group_new(vbox, FALSE, _("Image loading and caching"), GTK_ORIENTATION_VERTICAL);
2109 pref_spin_new_int(group, _("Decoded image cache size (MiB):"), NULL,
2110 0, 99999, 1, options->image.image_cache_max, &c_options->image.image_cache_max);
2111 pref_checkbox_new_int(group, _("Preload next image"),
2112 options->image.enable_read_ahead, &c_options->image.enable_read_ahead);
2114 pref_checkbox_new_int(group, _("Refresh on file change"),
2115 options->update_on_time_change, &c_options->update_on_time_change);
2118 pref_spacer(group, PREF_PAD_GROUP);
2120 group = pref_group_new(vbox, FALSE, _("Expand menu and toolbar"), GTK_ORIENTATION_VERTICAL);
2122 pref_checkbox_new_int(group, _("Expand menu and toolbar (NOTE! Geeqie must be restarted for change to take effect)"),
2123 options->expand_menu_toolbar, &c_options->expand_menu_toolbar);
2124 gtk_widget_set_tooltip_text(group, _("Expand the menu and toolbar to the full width of the window"));
2126 pref_spacer(group, PREF_PAD_GROUP);
2128 group = pref_group_new(vbox, FALSE, _("Info sidebar heights"), GTK_ORIENTATION_VERTICAL);
2129 pref_label_new(group, _("NOTE! Geeqie must be restarted for changes to take effect"));
2130 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2131 pref_spin_new_int(hbox, _("Keywords:"), NULL,
2133 options->info_keywords.height, &c_options->info_keywords.height);
2134 pref_spin_new_int(hbox, _("Title:"), NULL,
2136 options->info_title.height, &c_options->info_title.height);
2137 pref_spin_new_int(hbox, _("Comment:"), NULL,
2139 options->info_comment.height, &c_options->info_comment.height);
2140 pref_spin_new_int(hbox, _("Rating:"), NULL,
2142 options->info_rating.height, &c_options->info_rating.height);
2144 pref_spacer(group, PREF_PAD_GROUP);
2146 group = pref_group_new(vbox, FALSE, _("Show predefined keyword tree"), GTK_ORIENTATION_VERTICAL);
2148 pref_checkbox_new_int(group, _("Show predefined keyword tree (NOTE! Geeqie must be restarted for change to take effect)"),
2149 options->show_predefined_keyword_tree, &c_options->show_predefined_keyword_tree);
2151 pref_spacer(group, PREF_PAD_GROUP);
2153 net_mon = g_network_monitor_get_default();
2154 geeqie_org = g_network_address_parse_uri(GQ_WEBSITE, 80, NULL);
2155 internet_available = g_network_monitor_can_reach(net_mon, geeqie_org, NULL, NULL);
2156 g_object_unref(geeqie_org);
2158 group = pref_group_new(vbox, FALSE, _("Timezone database"), GTK_ORIENTATION_VERTICAL);
2159 hbox = pref_box_new(group, TRUE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2161 if (!internet_available)
2163 gtk_widget_set_sensitive(group, FALSE);
2166 tz = g_new0(TZData, 1);
2168 path = path_from_utf8(TIMEZONE_DATABASE);
2169 basename = g_path_get_basename(path);
2170 tz->timezone_database_user = g_build_filename(get_rc_dir(), basename, NULL);
2174 if (isfile(tz->timezone_database_user))
2176 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Update"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2180 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Install"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2183 if (!internet_available)
2185 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"));
2189 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"));
2191 gtk_widget_show(button);
2193 pref_spacer(group, PREF_PAD_GROUP);
2195 group = pref_group_new(vbox, FALSE, _("On-line help search engine"), GTK_ORIENTATION_VERTICAL);
2197 help_search_engine_entry = gtk_entry_new();
2198 gtk_entry_set_text(GTK_ENTRY(help_search_engine_entry), options->help_search_engine);
2199 gtk_box_pack_start(GTK_BOX(group), help_search_engine_entry, FALSE, FALSE, 0);
2200 gtk_widget_show(help_search_engine_entry);
2202 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"));
2204 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2205 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2206 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2207 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2208 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2209 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2210 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2211 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2212 g_signal_connect(GTK_ENTRY(help_search_engine_entry), "icon-press",
2213 G_CALLBACK(help_search_engine_entry_icon_cb),
2214 help_search_engine_entry);
2218 static void config_tab_image(GtkWidget *notebook)
2223 GtkWidget *ct_button;
2224 GtkWidget *enlargement_button;
2227 GtkWidget *two_pass;
2229 GtkWidget *gpu_accel;
2232 vbox = scrolled_notebook_page(notebook, _("Image"));
2234 group = pref_group_new(vbox, FALSE, _("Zoom"), GTK_ORIENTATION_VERTICAL);
2236 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2237 add_quality_menu(table, 0, 0, _("Quality:"), options->image.zoom_quality, &c_options->image.zoom_quality);
2238 if (options->image.use_clutter_renderer && !options->disable_gpu)
2240 gtk_widget_set_sensitive(table, FALSE);
2244 gpu_accel = pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library (Requires restart)"),
2245 options->image.use_clutter_renderer, &c_options->image.use_clutter_renderer);
2246 if (options->disable_gpu && !options->override_disable_gpu)
2248 gtk_widget_set_sensitive(gpu_accel, FALSE);
2252 two_pass = pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"),
2253 options->image.zoom_2pass, &c_options->image.zoom_2pass);
2254 if (options->image.use_clutter_renderer && !options->disable_gpu)
2256 gtk_widget_set_sensitive(two_pass, FALSE);
2259 c_options->image.zoom_increment = options->image.zoom_increment;
2260 spin = pref_spin_new(group, _("Zoom increment:"), NULL,
2261 0.01, 4.0, 0.01, 2, (gdouble)options->image.zoom_increment / 100.0,
2262 G_CALLBACK(zoom_increment_cb), NULL);
2263 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2265 group = pref_group_new(vbox, FALSE, _("Fit image to window"), GTK_ORIENTATION_VERTICAL);
2267 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2268 enlargement_button = pref_checkbox_new_int(hbox, _("Allow enlargement of image (max. size in %)"),
2269 options->image.zoom_to_fit_allow_expand, &c_options->image.zoom_to_fit_allow_expand);
2270 spin = pref_spin_new_int(hbox, NULL, NULL,
2272 options->image.max_enlargement_size, &c_options->image.max_enlargement_size);
2273 pref_checkbox_link_sensitivity(enlargement_button, spin);
2274 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."));
2276 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2277 ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (% of actual window):"),
2278 options->image.limit_autofit_size, &c_options->image.limit_autofit_size);
2279 spin = pref_spin_new_int(hbox, NULL, NULL,
2281 options->image.max_autofit_size, &c_options->image.max_autofit_size);
2282 pref_checkbox_link_sensitivity(ct_button, spin);
2283 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."));
2285 group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
2287 pref_checkbox_new_int(group, _("Use custom border color in window mode"),
2288 options->image.use_custom_border_color, &c_options->image.use_custom_border_color);
2290 pref_checkbox_new_int(group, _("Use custom border color in fullscreen mode"),
2291 options->image.use_custom_border_color_in_fullscreen, &c_options->image.use_custom_border_color_in_fullscreen);
2293 pref_color_button_new(group, _("Border color"), &options->image.border_color,
2294 G_CALLBACK(pref_color_button_set_cb), &c_options->image.border_color);
2296 c_options->image.border_color = options->image.border_color;
2298 pref_color_button_new(group, _("Alpha channel color 1"), &options->image.alpha_color_1,
2299 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_1);
2301 pref_color_button_new(group, _("Alpha channel color 2"), &options->image.alpha_color_2,
2302 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_2);
2304 c_options->image.alpha_color_1 = options->image.alpha_color_1;
2305 c_options->image.alpha_color_2 = options->image.alpha_color_2;
2307 group = pref_group_new(vbox, FALSE, _("Convenience"), GTK_ORIENTATION_VERTICAL);
2309 pref_checkbox_new_int(group, _("Auto rotate proofs using Exif information"),
2310 options->image.exif_proof_rotate_enable, &c_options->image.exif_proof_rotate_enable);
2315 static void save_default_window_layout_cb(GtkWidget *widget, gpointer data)
2317 LayoutWindow *lw = NULL;
2318 gchar *default_path;
2321 /* Get current lw */
2324 tmp_id = lw->options.id;
2325 lw->options.id = g_strdup("lw_default");
2327 default_path = g_build_filename(get_rc_dir(), DEFAULT_WINDOW_LAYOUT, NULL);
2328 save_default_layout_options_to_file(default_path, options, lw);
2329 g_free(lw->options.id);
2330 lw->options.id = tmp_id;
2331 g_free(default_path);
2334 #if GTK_CHECK_VERSION(3,22,0)
2335 static gboolean popover_cb(gpointer data)
2337 GtkPopover *popover = data;
2339 gtk_popover_popdown(popover);
2344 static void default_layout_changed_cb(GtkWidget *button, GtkPopover *popover)
2346 gtk_popover_popup(popover);
2348 g_timeout_add(2000, popover_cb, popover);
2351 static GtkWidget *create_popover(GtkWidget *parent, GtkWidget *child, GtkPositionType pos)
2355 popover = gtk_popover_new(parent);
2356 gtk_popover_set_position(GTK_POPOVER (popover), pos);
2357 gtk_container_add (GTK_CONTAINER(popover), child);
2358 gtk_container_set_border_width(GTK_CONTAINER (popover), 6);
2359 gtk_widget_show (child);
2365 static void config_tab_windows(GtkWidget *notebook)
2370 GtkWidget *subgroup;
2372 GtkWidget *ct_button;
2375 vbox = scrolled_notebook_page(notebook, _("Windows"));
2377 group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
2379 ct_button = pref_checkbox_new_int(group, _("Remember session"),
2380 options->save_window_positions, &c_options->save_window_positions);
2382 button = pref_checkbox_new_int(group, _("Use saved window positions also for new windows"),
2383 options->use_saved_window_positions_for_new_windows, &c_options->use_saved_window_positions_for_new_windows);
2384 pref_checkbox_link_sensitivity(ct_button, button);
2386 button = pref_checkbox_new_int(group, _("Remember window workspace"),
2387 options->save_window_workspace, &c_options->save_window_workspace);
2388 pref_checkbox_link_sensitivity(ct_button, button);
2390 pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
2391 options->tools_restore_state, &c_options->tools_restore_state);
2393 pref_checkbox_new_int(group, _("Remember dialog window positions"),
2394 options->save_dialog_window_positions, &c_options->save_dialog_window_positions);
2396 pref_checkbox_new_int(group, _("Show window IDs"),
2397 options->show_window_ids, &c_options->show_window_ids);
2399 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2400 pref_label_new(subgroup, _("Use current layout for default: "));
2401 button = pref_button_new(subgroup, NULL, _("Set"), FALSE, G_CALLBACK(save_default_window_layout_cb), NULL);
2403 #if GTK_CHECK_VERSION(3,22,0)
2406 popover = create_popover(button, gtk_label_new(_("Current window layout\nhas been set as default")), GTK_POS_TOP);
2407 gtk_popover_set_modal(GTK_POPOVER (popover), FALSE);
2408 g_signal_connect(button, "clicked", G_CALLBACK(default_layout_changed_cb), popover);
2411 group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
2413 pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
2414 options->image.fit_window_to_image, &c_options->image.fit_window_to_image);
2416 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2417 ct_button = pref_checkbox_new_int(hbox, _("Limit size when auto-sizing window (%):"),
2418 options->image.limit_window_size, &c_options->image.limit_window_size);
2419 spin = pref_spin_new_int(hbox, NULL, NULL,
2421 options->image.max_window_size, &c_options->image.max_window_size);
2422 pref_checkbox_link_sensitivity(ct_button, spin);
2424 group = pref_group_new(vbox, FALSE, _("Full screen"), GTK_ORIENTATION_VERTICAL);
2426 c_options->fullscreen.screen = options->fullscreen.screen;
2427 c_options->fullscreen.above = options->fullscreen.above;
2428 hbox = fullscreen_prefs_selection_new(_("Location:"), &c_options->fullscreen.screen, &c_options->fullscreen.above);
2429 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2430 gtk_widget_show(hbox);
2432 pref_checkbox_new_int(group, _("Smooth image flip"),
2433 options->fullscreen.clean_flip, &c_options->fullscreen.clean_flip);
2434 pref_checkbox_new_int(group, _("Disable screen saver"),
2435 options->fullscreen.disable_saver, &c_options->fullscreen.disable_saver);
2438 #define PRE_FORMATTED_COLUMNS 5
2439 static void config_tab_osd(GtkWidget *notebook)
2445 GtkWidget *image_overlay_template_view;
2446 GtkWidget *scrolled;
2447 GtkWidget *scrolled_pre_formatted;
2448 GtkTextBuffer *buffer;
2450 GtkWidget *subgroup;
2452 vbox = scrolled_notebook_page(notebook, _("OSD"));
2454 image_overlay_template_view = gtk_text_view_new();
2456 group = pref_group_new(vbox, FALSE, _("Overlay Screen Display"), GTK_ORIENTATION_VERTICAL);
2458 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2460 scrolled_pre_formatted = osd_new(PRE_FORMATTED_COLUMNS, image_overlay_template_view);
2461 gtk_widget_set_size_request(scrolled_pre_formatted, 200, 150);
2462 gtk_box_pack_start(GTK_BOX(subgroup), scrolled_pre_formatted, FALSE, FALSE, 0);
2463 gtk_widget_show(scrolled_pre_formatted);
2464 gtk_widget_show(subgroup);
2466 pref_line(group, PREF_PAD_GAP);
2468 pref_label_new(group, _("Image overlay template"));
2470 scrolled = gtk_scrolled_window_new(NULL, NULL);
2471 gtk_widget_set_size_request(scrolled, 200, 150);
2472 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2473 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
2474 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2475 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 5);
2476 gtk_widget_show(scrolled);
2478 gtk_widget_set_tooltip_markup(image_overlay_template_view,
2479 _("Extensive formatting options are shown in the Help file"));
2481 gtk_container_add(GTK_CONTAINER(scrolled), image_overlay_template_view);
2482 gtk_widget_show(image_overlay_template_view);
2484 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2486 #if GTK_CHECK_VERSION(3,4,0)
2487 button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
2488 G_CALLBACK(image_overlay_set_font_cb), notebook);
2490 button = gtk_font_button_new();
2491 gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Image Overlay Font");
2492 gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->image_overlay.font);
2493 g_signal_connect(G_OBJECT(button), "font-set",
2494 G_CALLBACK(image_overlay_set_font_cb),NULL);
2496 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2497 gtk_widget_show(button);
2499 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Text"), FALSE,
2500 G_CALLBACK(image_overlay_set_text_colour_cb), NULL);
2501 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2502 gtk_widget_show(button);
2504 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Background"), FALSE,
2505 G_CALLBACK(image_overlay_set_background_colour_cb), NULL);
2506 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2507 gtk_widget_show(button);
2508 image_overlay_set_text_colours();
2510 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2511 G_CALLBACK(image_overlay_default_template_cb), image_overlay_template_view);
2512 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2513 gtk_widget_show(button);
2515 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
2516 G_CALLBACK(image_overlay_help_cb), NULL);
2517 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2518 gtk_widget_show(button);
2520 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_overlay_template_view));
2521 if (options->image_overlay.template_string) gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
2522 g_signal_connect(G_OBJECT(buffer), "changed",
2523 G_CALLBACK(image_overlay_template_view_changed_cb), image_overlay_template_view);
2525 pref_line(group, PREF_PAD_GAP);
2527 group = pref_group_new(vbox, FALSE, _("Exif, XMP or IPTC tags"), 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(_("%Exif.Image.Orientation%"));
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 separators"), 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(_("Separator shown only if both fields are non-null:\n%formatted.ShutterSpeed%|%formatted.ISOSpeedRating%"));
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, _("Field maximum length"), 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(_("%path:39%"));
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, _("Pre- and post- text"), 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(_("Text shown only if the field is non-null:\n%formatted.Aperture:F no. * setting%\n %formatted.Aperture:10:F no. * setting%"));
2559 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2560 gtk_widget_show(label);
2561 pref_spacer(group,TRUE);
2563 group = pref_group_new(vbox, FALSE, _("Pango markup"), GTK_ORIENTATION_VERTICAL);
2564 hbox = gtk_hbox_new(FALSE, 0);
2565 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2566 gtk_widget_show(hbox);
2567 label = gtk_label_new(_("<b>bold</b>\n<u>underline</u>\n<i>italic</i>\n<s>strikethrough</s>"));
2568 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2569 gtk_widget_show(label);
2572 static GtkTreeModel *create_class_model(void)
2574 GtkListStore *model;
2578 /* create list store */
2579 model = gtk_list_store_new(1, G_TYPE_STRING);
2580 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
2582 gtk_list_store_append(model, &iter);
2583 gtk_list_store_set(model, &iter, 0, _(format_class_list[i]), -1);
2585 return GTK_TREE_MODEL (model);
2590 static void config_tab_files(GtkWidget *notebook)
2597 GtkWidget *ct_button;
2598 GtkWidget *scrolled;
2599 GtkWidget *filter_view;
2600 GtkCellRenderer *renderer;
2601 GtkTreeSelection *selection;
2602 GtkTreeViewColumn *column;
2604 vbox = scrolled_notebook_page(notebook, _("Files"));
2606 group = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2608 pref_checkbox_new_int(group, _("Show hidden files or folders"),
2609 options->file_filter.show_hidden_files, &c_options->file_filter.show_hidden_files);
2610 pref_checkbox_new_int(group, _("Show parent folder (..)"),
2611 options->file_filter.show_parent_directory, &c_options->file_filter.show_parent_directory);
2612 pref_checkbox_new_int(group, _("Case sensitive sort"),
2613 options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
2614 pref_checkbox_new_int(group, _("Natural sort order"),
2615 options->file_sort.natural, &c_options->file_sort.natural);
2616 pref_checkbox_new_int(group, _("Disable file extension checks"),
2617 options->file_filter.disable_file_extension_checks, &c_options->file_filter.disable_file_extension_checks);
2619 ct_button = pref_checkbox_new_int(group, _("Disable File Filtering"),
2620 options->file_filter.disable, &c_options->file_filter.disable);
2623 group = pref_group_new(vbox, FALSE, _("Grouping sidecar extensions"), GTK_ORIENTATION_VERTICAL);
2625 sidecar_ext_entry = gtk_entry_new();
2626 gtk_entry_set_text(GTK_ENTRY(sidecar_ext_entry), options->sidecar.ext);
2627 gtk_box_pack_start(GTK_BOX(group), sidecar_ext_entry, FALSE, FALSE, 0);
2628 gtk_widget_show(sidecar_ext_entry);
2630 group = pref_group_new(vbox, TRUE, _("File types"), GTK_ORIENTATION_VERTICAL);
2632 frame = pref_group_parent(group);
2633 g_signal_connect(G_OBJECT(ct_button), "toggled",
2634 G_CALLBACK(filter_disable_cb), frame);
2635 gtk_widget_set_sensitive(frame, !options->file_filter.disable);
2637 scrolled = gtk_scrolled_window_new(NULL, NULL);
2638 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2639 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2640 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2641 gtk_widget_show(scrolled);
2643 filter_store = gtk_list_store_new(1, G_TYPE_POINTER);
2644 filter_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(filter_store));
2645 g_object_unref(filter_store);
2646 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
2647 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
2649 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), FALSE);
2651 column = gtk_tree_view_column_new();
2652 gtk_tree_view_column_set_title(column, _("Filter"));
2653 gtk_tree_view_column_set_resizable(column, TRUE);
2655 renderer = gtk_cell_renderer_toggle_new();
2656 g_signal_connect(G_OBJECT(renderer), "toggled",
2657 G_CALLBACK(filter_store_enable_cb), filter_store);
2658 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2659 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2660 GINT_TO_POINTER(FE_ENABLE), NULL);
2662 renderer = gtk_cell_renderer_text_new();
2663 g_signal_connect(G_OBJECT(renderer), "edited",
2664 G_CALLBACK(filter_store_ext_edit_cb), filter_store);
2665 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2666 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2667 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2668 GINT_TO_POINTER(FE_EXTENSION), NULL);
2669 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2671 column = gtk_tree_view_column_new();
2672 gtk_tree_view_column_set_title(column, _("Description"));
2673 gtk_tree_view_column_set_resizable(column, TRUE);
2674 gtk_tree_view_column_set_fixed_width(column, 200);
2675 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
2677 renderer = gtk_cell_renderer_text_new();
2678 g_signal_connect(G_OBJECT(renderer), "edited",
2679 G_CALLBACK(filter_store_desc_edit_cb), filter_store);
2680 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2681 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2682 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2683 GINT_TO_POINTER(FE_DESCRIPTION), NULL);
2684 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2686 column = gtk_tree_view_column_new();
2687 gtk_tree_view_column_set_title(column, _("Class"));
2688 gtk_tree_view_column_set_resizable(column, TRUE);
2689 renderer = gtk_cell_renderer_combo_new();
2690 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE,
2691 "model", create_class_model(),
2696 g_signal_connect(G_OBJECT(renderer), "edited",
2697 G_CALLBACK(filter_store_class_edit_cb), filter_store);
2698 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2699 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2700 GINT_TO_POINTER(FE_CLASS), NULL);
2701 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2703 column = gtk_tree_view_column_new();
2704 gtk_tree_view_column_set_title(column, _("Writable"));
2705 gtk_tree_view_column_set_resizable(column, FALSE);
2706 renderer = gtk_cell_renderer_toggle_new();
2707 g_signal_connect(G_OBJECT(renderer), "toggled",
2708 G_CALLBACK(filter_store_writable_cb), filter_store);
2709 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2710 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2711 GINT_TO_POINTER(FE_WRITABLE), NULL);
2712 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2714 column = gtk_tree_view_column_new();
2715 gtk_tree_view_column_set_title(column, _("Sidecar is allowed"));
2716 gtk_tree_view_column_set_resizable(column, FALSE);
2717 renderer = gtk_cell_renderer_toggle_new();
2718 g_signal_connect(G_OBJECT(renderer), "toggled",
2719 G_CALLBACK(filter_store_sidecar_cb), filter_store);
2720 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2721 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2722 GINT_TO_POINTER(FE_ALLOW_SIDECAR), NULL);
2723 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2726 filter_store_populate();
2727 gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
2728 gtk_widget_show(filter_view);
2730 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2732 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2733 G_CALLBACK(filter_default_cb), filter_view);
2734 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2735 gtk_widget_show(button);
2737 button = pref_button_new(NULL, GTK_STOCK_REMOVE, NULL, FALSE,
2738 G_CALLBACK(filter_remove_cb), filter_view);
2739 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2740 gtk_widget_show(button);
2742 button = pref_button_new(NULL, GTK_STOCK_ADD, NULL, FALSE,
2743 G_CALLBACK(filter_add_cb), filter_view);
2744 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2745 gtk_widget_show(button);
2749 static void config_tab_metadata(GtkWidget *notebook)
2754 GtkWidget *ct_button;
2758 vbox = scrolled_notebook_page(notebook, _("Metadata"));
2761 group = pref_group_new(vbox, FALSE, _("Metadata writing process"), GTK_ORIENTATION_VERTICAL);
2763 label = pref_label_new(group, _("Warning: Geeqie is built without Exiv2. Some options are disabled."));
2765 label = pref_label_new(group, _("Metadata are written in the following order. The process ends after first success."));
2766 #if GTK_CHECK_VERSION(3,16,0)
2767 gtk_label_set_xalign(GTK_LABEL(label), 0.0);
2768 gtk_label_set_yalign(GTK_LABEL(label), 0.5);
2770 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2773 ct_button = pref_checkbox_new_int(group, _("1) Save metadata in image files, or sidecar files, according to the XMP standard"),
2774 options->metadata.save_in_image_file, &c_options->metadata.save_in_image_file);
2776 gtk_widget_set_sensitive(ct_button, FALSE);
2779 pref_checkbox_new_int(group, _("2) Save metadata in '.metadata' folder, local to image folder (non-standard)"),
2780 options->metadata.enable_metadata_dirs, &c_options->metadata.enable_metadata_dirs);
2782 text = g_strdup_printf(_("3) Save metadata in Geeqie private directory '%s'"), get_metadata_cache_dir());
2783 label = pref_label_new(group, text);
2784 #if GTK_CHECK_VERSION(3,16,0)
2785 gtk_label_set_xalign(GTK_LABEL(label), 0.0);
2786 gtk_label_set_yalign(GTK_LABEL(label), 0.5);
2788 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2790 gtk_misc_set_padding(GTK_MISC(label), 22, 0);
2793 group = pref_group_new(vbox, FALSE, _("Step 1: Write to image files"), GTK_ORIENTATION_VERTICAL);
2795 gtk_widget_set_sensitive(group, FALSE);
2798 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2799 pref_checkbox_link_sensitivity(ct_button, hbox);
2801 pref_checkbox_new_int(hbox, _("Store metadata also in legacy IPTC tags (converted according to IPTC4XMP standard)"),
2802 options->metadata.save_legacy_IPTC, &c_options->metadata.save_legacy_IPTC);
2804 pref_checkbox_new_int(hbox, _("Warn if the image files are unwritable"),
2805 options->metadata.warn_on_write_problems, &c_options->metadata.warn_on_write_problems);
2807 pref_checkbox_new_int(hbox, _("Ask before writing to image files"),
2808 options->metadata.confirm_write, &c_options->metadata.confirm_write);
2810 pref_checkbox_new_int(hbox, _("Create sidecar files named image.ext.xmp (as opposed to image.xmp)"),
2811 options->metadata.sidecar_extended_name, &c_options->metadata.sidecar_extended_name);
2813 group = pref_group_new(vbox, FALSE, _("Step 2 and 3: write to Geeqie private files"), GTK_ORIENTATION_VERTICAL);
2815 gtk_widget_set_sensitive(group, FALSE);
2818 pref_checkbox_new_int(group, _("Use GQview legacy metadata format (supports only keywords and comments) instead of XMP"),
2819 options->metadata.save_legacy_format, &c_options->metadata.save_legacy_format);
2822 group = pref_group_new(vbox, FALSE, _("Miscellaneous"), GTK_ORIENTATION_VERTICAL);
2823 pref_checkbox_new_int(group, _("Write the same description tags (keywords, comment, etc.) to all grouped sidecars"),
2824 options->metadata.sync_grouped_files, &c_options->metadata.sync_grouped_files);
2826 pref_checkbox_new_int(group, _("Allow keywords to differ only in case"),
2827 options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
2829 ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"),
2830 options->metadata.write_orientation, &c_options->metadata.write_orientation);
2832 gtk_widget_set_sensitive(ct_button, FALSE);
2835 group = pref_group_new(vbox, FALSE, _("Auto-save options"), GTK_ORIENTATION_VERTICAL);
2837 ct_button = pref_checkbox_new_int(group, _("Write metadata after timeout"),
2838 options->metadata.confirm_after_timeout, &c_options->metadata.confirm_after_timeout);
2840 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2841 pref_checkbox_link_sensitivity(ct_button, hbox);
2843 pref_spin_new_int(hbox, _("Timeout (seconds):"), NULL, 0, 900, 1,
2844 options->metadata.confirm_timeout, &c_options->metadata.confirm_timeout);
2846 pref_checkbox_new_int(group, _("Write metadata on image change"),
2847 options->metadata.confirm_on_image_change, &c_options->metadata.confirm_on_image_change);
2849 pref_checkbox_new_int(group, _("Write metadata on directory change"),
2850 options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
2852 group = pref_group_new(vbox, FALSE, _("Pre-load metadata"), GTK_ORIENTATION_VERTICAL);
2854 ct_button = pref_checkbox_new_int(group, _("Read metadata in background"),
2855 options->read_metadata_in_idle, &c_options->read_metadata_in_idle);
2856 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");
2861 typedef struct _KeywordFindData KeywordFindData;
2862 struct _KeywordFindData
2869 GtkWidget *button_close;
2870 GtkWidget *button_stop;
2871 GtkWidget *button_start;
2872 GtkWidget *progress;
2880 guint idle_id; /* event source id */
2883 #define KEYWORD_DIALOG_WIDTH 400
2885 static void keywords_find_folder(KeywordFindData *kfd, FileData *dir_fd)
2887 GList *list_d = NULL;
2888 GList *list_f = NULL;
2892 filelist_read(dir_fd, &list_f, &list_d);
2896 filelist_read(dir_fd, &list_f, NULL);
2899 list_f = filelist_filter(list_f, FALSE);
2900 list_d = filelist_filter(list_d, TRUE);
2902 kfd->list = g_list_concat(list_f, kfd->list);
2903 kfd->list_dir = g_list_concat(list_d, kfd->list_dir);
2906 static void keywords_find_reset(KeywordFindData *kfd)
2908 filelist_free(kfd->list);
2911 filelist_free(kfd->list_dir);
2912 kfd->list_dir = NULL;
2915 static void keywords_find_close_cb(GenericDialog *fd, gpointer data)
2917 KeywordFindData *kfd = data;
2919 if (!gtk_widget_get_sensitive(kfd->button_close)) return;
2921 keywords_find_reset(kfd);
2922 generic_dialog_close(kfd->gd);
2926 static void keywords_find_finish(KeywordFindData *kfd)
2928 keywords_find_reset(kfd);
2930 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("done"));
2931 spinner_set_interval(kfd->spinner, -1);
2933 gtk_widget_set_sensitive(kfd->group, TRUE);
2934 gtk_widget_set_sensitive(kfd->button_start, TRUE);
2935 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2936 gtk_widget_set_sensitive(kfd->button_close, TRUE);
2939 static void keywords_find_stop_cb(GenericDialog *fd, gpointer data)
2941 KeywordFindData *kfd = data;
2943 g_idle_remove_by_data(kfd);
2945 keywords_find_finish(kfd);
2948 static gboolean keywords_find_file(gpointer data)
2950 KeywordFindData *kfd = data;
2952 GtkTextBuffer *buffer;
2960 fd = kfd->list->data;
2961 kfd->list = g_list_remove(kfd->list, fd);
2963 keywords = metadata_read_list(fd, KEYWORD_KEY, METADATA_PLAIN);
2964 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2968 gtk_text_buffer_get_end_iter(buffer, &iter);
2969 tmp = g_strconcat(keywords->data, "\n", NULL);
2970 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
2972 keywords = keywords->next;
2975 gtk_entry_set_text(GTK_ENTRY(kfd->progress), fd->path);
2976 file_data_unref(fd);
2977 string_list_free(keywords);
2981 else if (kfd->list_dir)
2985 fd = kfd->list_dir->data;
2986 kfd->list_dir = g_list_remove(kfd->list_dir, fd);
2988 keywords_find_folder(kfd, fd);
2990 file_data_unref(fd);
2995 keywords_find_finish(kfd);
3000 static void keywords_find_start_cb(GenericDialog *fd, gpointer data)
3002 KeywordFindData *kfd = data;
3005 if (kfd->list || !gtk_widget_get_sensitive(kfd->button_start)) return;
3007 path = remove_trailing_slash((gtk_entry_get_text(GTK_ENTRY(kfd->entry))));
3008 parse_out_relatives(path);
3012 warning_dialog(_("Invalid folder"),
3013 _("The specified folder can not be found."),
3014 GTK_STOCK_DIALOG_WARNING, kfd->gd->dialog);
3020 gtk_widget_set_sensitive(kfd->group, FALSE);
3021 gtk_widget_set_sensitive(kfd->button_start, FALSE);
3022 gtk_widget_set_sensitive(kfd->button_stop, TRUE);
3023 gtk_widget_set_sensitive(kfd->button_close, FALSE);
3024 spinner_set_interval(kfd->spinner, SPINNER_SPEED);
3026 dir_fd = file_data_new_dir(path);
3027 keywords_find_folder(kfd, dir_fd);
3028 file_data_unref(dir_fd);
3029 kfd->idle_id = g_idle_add(keywords_find_file, kfd);
3035 static void keywords_find_dialog(GtkWidget *widget, const gchar *path)
3037 KeywordFindData *kfd;
3041 kfd = g_new0(KeywordFindData, 1);
3043 kfd->gd = generic_dialog_new(_("Search for keywords"),
3044 "search_for_keywords",
3047 gtk_window_set_default_size(GTK_WINDOW(kfd->gd->dialog), KEYWORD_DIALOG_WIDTH, -1);
3048 kfd->gd->cancel_cb = keywords_find_close_cb;
3049 kfd->button_close = generic_dialog_add_button(kfd->gd, GTK_STOCK_CLOSE, NULL,
3050 keywords_find_close_cb, FALSE);
3051 kfd->button_start = generic_dialog_add_button(kfd->gd, GTK_STOCK_OK, _("S_tart"),
3052 keywords_find_start_cb, FALSE);
3053 kfd->button_stop = generic_dialog_add_button(kfd->gd, GTK_STOCK_STOP, NULL,
3054 keywords_find_stop_cb, FALSE);
3055 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
3057 generic_dialog_add_message(kfd->gd, NULL, _("Search for keywords"), NULL, FALSE);
3059 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0);
3060 pref_spacer(hbox, PREF_PAD_INDENT);
3061 kfd->group = pref_box_new(hbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
3063 hbox = pref_box_new(kfd->group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3064 pref_label_new(hbox, _("Folder:"));
3066 label = tab_completion_new(&kfd->entry, path, NULL, NULL, NULL, NULL);
3067 tab_completion_add_select_button(kfd->entry,_("Select folder") , TRUE);
3068 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
3069 gtk_widget_show(label);
3071 pref_checkbox_new_int(kfd->group, _("Include subfolders"), FALSE, &kfd->recurse);
3073 pref_line(kfd->gd->vbox, PREF_PAD_SPACE);
3074 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3076 kfd->progress = gtk_entry_new();
3077 gtk_widget_set_can_focus(kfd->progress, FALSE);
3078 gtk_editable_set_editable(GTK_EDITABLE(kfd->progress), FALSE);
3079 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("click start to begin"));
3080 gtk_box_pack_start(GTK_BOX(hbox), kfd->progress, TRUE, TRUE, 0);
3081 gtk_widget_show(kfd->progress);
3083 kfd->spinner = spinner_new(NULL, -1);
3084 gtk_box_pack_start(GTK_BOX(hbox), kfd->spinner, FALSE, FALSE, 0);
3085 gtk_widget_show(kfd->spinner);
3089 gtk_widget_show(kfd->gd->dialog);
3092 static void keywords_find_cb(GtkWidget *widget, gpointer data)
3094 const gchar *path = layout_get_path(NULL);
3096 if (!path || !*path) path = homedir();
3097 keywords_find_dialog(widget, path);
3100 static void config_tab_keywords_save()
3102 GtkTextIter start, end;
3103 GtkTextBuffer *buffer;
3104 GList *kw_list = NULL;
3110 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3111 gtk_text_buffer_get_bounds(buffer, &start, &end);
3113 buffer_text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
3115 kw_split = strtok(buffer_text, "\n");
3116 while (kw_split != NULL)
3122 if (g_strcmp0(work->data, kw_split) == 0)
3131 kw_list = g_list_append(kw_list, g_strdup(kw_split));
3133 kw_split = strtok(NULL, "\n");
3136 keyword_list_set(kw_list);
3138 string_list_free(kw_list);
3139 g_free(buffer_text);
3142 static void config_tab_keywords(GtkWidget *notebook)
3148 GtkWidget *scrolled;
3150 GtkTextBuffer *buffer;
3153 vbox = scrolled_notebook_page(notebook, _("Keywords"));
3155 group = pref_group_new(vbox, TRUE, _("Edit keywords autocompletion list"), GTK_ORIENTATION_VERTICAL);
3157 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3159 button = pref_button_new(hbox, GTK_STOCK_EXECUTE, _("Search"), FALSE,
3160 G_CALLBACK(keywords_find_cb), keyword_text);
3161 gtk_widget_set_tooltip_text(button, "Search for existing keywords");
3164 keyword_text = gtk_text_view_new();
3165 gtk_widget_set_size_request(keyword_text, 20, 20);
3166 scrolled = gtk_scrolled_window_new(NULL, NULL);
3167 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3168 gtk_widget_show(scrolled);
3170 gtk_container_add(GTK_CONTAINER(scrolled), keyword_text);
3171 gtk_widget_show(keyword_text);
3173 gtk_text_view_set_editable(GTK_TEXT_VIEW(keyword_text), TRUE);
3175 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3176 gtk_text_buffer_create_tag(buffer, "monospace",
3177 "family", "monospace", NULL);
3179 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(keyword_text), GTK_WRAP_WORD);
3180 gtk_text_buffer_get_start_iter(buffer, &iter);
3181 gtk_text_buffer_create_mark(buffer, "end", &iter, FALSE);
3184 path = g_build_filename(get_rc_dir(), "keywords", NULL);
3186 GList *kwl = keyword_list_get();
3187 kwl = g_list_first(kwl);
3190 gtk_text_buffer_get_end_iter (buffer, &iter);
3191 tmp = g_strconcat(kwl->data, "\n", NULL);
3192 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
3197 gtk_text_buffer_set_modified(buffer, FALSE);
3204 static void intent_menu_cb(GtkWidget *combo, gpointer data)
3206 gint *option = data;
3208 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
3212 *option = INTENT_PERCEPTUAL;
3215 *option = INTENT_RELATIVE_COLORIMETRIC;
3218 *option = INTENT_SATURATION;
3221 *option = INTENT_ABSOLUTE_COLORIMETRIC;
3226 static void add_intent_menu(GtkWidget *table, gint column, gint row, const gchar *text,
3227 gint option, gint *option_c)
3234 pref_table_label(table, column, row, text, 0.0);
3236 combo = gtk_combo_box_text_new();
3238 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Perceptual"));
3239 if (option == INTENT_PERCEPTUAL) current = 0;
3240 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Relative Colorimetric"));
3241 if (option == INTENT_RELATIVE_COLORIMETRIC) current = 1;
3242 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Saturation"));
3243 if (option == INTENT_SATURATION) current = 2;
3244 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Absolute Colorimetric"));
3245 if (option == INTENT_ABSOLUTE_COLORIMETRIC) current = 3;
3247 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
3249 gtk_widget_set_tooltip_text(combo,"Refer to the lcms documentation for the defaults used when the selected Intent is not available");
3251 g_signal_connect(G_OBJECT(combo), "changed",
3252 G_CALLBACK(intent_menu_cb), option_c);
3254 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
3255 gtk_widget_show(combo);
3259 static void config_tab_color(GtkWidget *notebook)
3268 vbox = scrolled_notebook_page(notebook, _("Color management"));
3270 group = pref_group_new(vbox, FALSE, _("Input profiles"), GTK_ORIENTATION_VERTICAL);
3272 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3275 table = pref_table_new(group, 3, COLOR_PROFILE_INPUTS + 1, FALSE, FALSE);
3276 gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
3278 label = pref_table_label(table, 0, 0, _("Type"), 0.0);
3279 pref_label_bold(label, TRUE, FALSE);
3281 label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
3282 pref_label_bold(label, TRUE, FALSE);
3284 label = pref_table_label(table, 2, 0, _("File"), 0.0);
3285 pref_label_bold(label, TRUE, FALSE);
3287 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
3292 buf = g_strdup_printf(_("Input %d:"), i + COLOR_PROFILE_FILE);
3293 pref_table_label(table, 0, i + 1, buf, 1.0);
3296 entry = gtk_entry_new();
3297 gtk_entry_set_max_length(GTK_ENTRY(entry), EDITOR_NAME_MAX_LENGTH);
3298 if (options->color_profile.input_name[i])
3300 gtk_entry_set_text(GTK_ENTRY(entry), options->color_profile.input_name[i]);
3302 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, i + 1, i + 2,
3303 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3304 gtk_widget_show(entry);
3305 color_profile_input_name_entry[i] = entry;
3307 tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, ".icc", "ICC Files", NULL);
3308 tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
3309 gtk_widget_set_size_request(entry, 160, -1);
3310 gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
3311 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3312 gtk_widget_show(tabcomp);
3313 color_profile_input_file_entry[i] = entry;
3316 group = pref_group_new(vbox, FALSE, _("Screen profile"), GTK_ORIENTATION_VERTICAL);
3318 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3320 pref_checkbox_new_int(group, _("Use system screen profile if available"),
3321 options->color_profile.use_x11_screen_profile, &c_options->color_profile.use_x11_screen_profile);
3323 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3325 pref_table_label(table, 0, 0, _("Screen:"), 1.0);
3326 tabcomp = tab_completion_new(&color_profile_screen_file_entry,
3327 options->color_profile.screen_file, NULL, ".icc", "ICC Files", NULL);
3328 tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
3329 gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
3331 add_intent_menu(table, 0, 1, _("Render Intent:"), options->color_profile.render_intent, &c_options->color_profile.render_intent);
3333 gtk_table_attach(GTK_TABLE(table), tabcomp, 1, 2,
3335 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3337 gtk_widget_show(tabcomp);
3340 /* advanced entry tab */
3341 static void use_geeqie_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 = FALSE;
3346 c_options->file_ops.no_trash = FALSE;
3350 static void use_system_trash_cb(GtkWidget *widget, gpointer data)
3352 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3354 c_options->file_ops.use_system_trash = TRUE;
3355 c_options->file_ops.no_trash = FALSE;
3359 static void use_no_cache_cb(GtkWidget *widget, gpointer data)
3361 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3363 c_options->file_ops.no_trash = TRUE;
3367 static void config_tab_behavior(GtkWidget *notebook)
3374 GtkWidget *ct_button;
3378 GtkWidget *with_rename;
3379 GtkWidget *collections_on_top;
3380 GtkWidget *hide_window_in_fullscreen;
3381 GtkWidget *checkbox;
3384 vbox = scrolled_notebook_page(notebook, _("Behavior"));
3386 group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
3388 pref_checkbox_new_int(group, _("Confirm permanent file delete"),
3389 options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
3390 pref_checkbox_new_int(group, _("Confirm move file to Trash"),
3391 options->file_ops.confirm_move_to_trash, &c_options->file_ops.confirm_move_to_trash);
3392 pref_checkbox_new_int(group, _("Enable Delete key"),
3393 options->file_ops.enable_delete_key, &c_options->file_ops.enable_delete_key);
3395 ct_button = pref_radiobutton_new(group, NULL, _("Use Geeqie trash location"),
3396 !options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_geeqie_trash_cb),NULL);
3398 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3399 pref_checkbox_link_sensitivity(ct_button, hbox);
3401 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
3402 pref_label_new(hbox, _("Folder:"));
3404 tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL, NULL, NULL);
3405 tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
3406 gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
3407 gtk_widget_show(tabcomp);
3409 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3410 pref_checkbox_link_sensitivity(ct_button, hbox);
3412 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
3413 spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MiB"),
3414 0, 2048, 1, options->file_ops.safe_delete_folder_maxsize, &c_options->file_ops.safe_delete_folder_maxsize);
3415 gtk_widget_set_tooltip_markup(spin, _("Set to 0 for unlimited size"));
3416 button = pref_button_new(NULL, NULL, _("View"), FALSE,
3417 G_CALLBACK(safe_delete_view_cb), NULL);
3418 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3419 gtk_widget_show(button);
3421 button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
3422 G_CALLBACK(safe_delete_clear_cb), NULL);
3423 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3424 pref_radiobutton_new(group, ct_button, _("Use system Trash bin"),
3425 options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_system_trash_cb), NULL);
3427 pref_radiobutton_new(group, ct_button, _("Use no trash at all"),
3428 options->file_ops.no_trash, G_CALLBACK(use_no_cache_cb), NULL);
3430 gtk_widget_show(button);
3432 pref_spacer(group, PREF_PAD_GROUP);
3435 group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
3437 pref_checkbox_new_int(group, _("Descend folders in tree view"),
3438 options->tree_descend_subdirs, &c_options->tree_descend_subdirs);
3440 pref_checkbox_new_int(group, _("In place renaming"),
3441 options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
3443 pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
3444 options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
3446 tmp = pref_checkbox_new_int(group, _("Circular selection lists"),
3447 options->circular_selection_lists, &c_options->circular_selection_lists);
3448 gtk_widget_set_tooltip_text(tmp, _("Traverse selection lists in a circular manner"));
3450 marks = pref_checkbox_new_int(group, _("Save marks on exit"),
3451 options->marks_save, &c_options->marks_save);
3452 gtk_widget_set_tooltip_text(marks,"Note that marks linked to a keyword will be saved irrespective of this setting");
3454 with_rename = pref_checkbox_new_int(group, _("Use \"With Rename\" as default for Copy/Move dialogs"),
3455 options->with_rename, &c_options->with_rename);
3456 gtk_widget_set_tooltip_text(with_rename,"Change the default button for Copy/Move dialogs");
3458 collections_on_top = pref_checkbox_new_int(group, _("Open collections on top"),
3459 options->collections_on_top, &c_options->collections_on_top);
3460 gtk_widget_set_tooltip_text(collections_on_top,"Open collections window on top");
3462 hide_window_in_fullscreen = pref_checkbox_new_int(group, _("Hide window in fullscreen"),
3463 options->hide_window_in_fullscreen, &c_options->hide_window_in_fullscreen);
3464 gtk_widget_set_tooltip_text(hide_window_in_fullscreen,"When alt-tabbing, prevent Geeqie window showing twice");
3466 pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
3467 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
3469 pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
3470 16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
3472 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3473 add_dnd_default_action_selection_menu(table, 0, 0, _("Drag`n drop default action:"), options->dnd_default_action, &c_options->dnd_default_action);
3475 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3476 add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
3478 pref_spacer(group, PREF_PAD_GROUP);
3480 group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
3482 pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
3483 options->progressive_key_scrolling, &c_options->progressive_key_scrolling);
3484 pref_spin_new_int(group, _("Keyboard scrolling step multiplier:"), NULL,
3485 1, 32, 1, options->keyboard_scroll_step, (int *)&c_options->keyboard_scroll_step);
3486 pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
3487 options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
3488 pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
3489 options->image_lm_click_nav, &c_options->image_lm_click_nav);
3490 pref_checkbox_new_int(group, _("Play video by left click on image"),
3491 options->image_l_click_video, &c_options->image_l_click_video);
3492 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3493 add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
3495 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3496 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3497 add_mouse_selection_menu(table, 0, 0, _("Mouse button Back:"), options->mouse_button_8, &c_options->mouse_button_8);
3498 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3499 add_mouse_selection_menu(table, 0, 0, _("Mouse button Forward:"), options->mouse_button_9, &c_options->mouse_button_9);
3501 pref_spacer(group, PREF_PAD_GROUP);
3503 group = pref_group_new(vbox, FALSE, _("GPU"), GTK_ORIENTATION_VERTICAL);
3505 checkbox = pref_checkbox_new_int(group, _("Override disable GPU"),
3506 options->override_disable_gpu, &c_options->override_disable_gpu);
3507 gtk_widget_set_tooltip_text(checkbox, "Contact the developers for usage");
3510 pref_spacer(group, PREF_PAD_GROUP);
3512 group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
3514 pref_spin_new_int(group, _("Debug level:"), NULL,
3515 DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
3517 pref_checkbox_new_int(group, _("Timer data"),
3518 options->log_window.timer_data, &c_options->log_window.timer_data);
3520 pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
3521 1, 99999, 1, options->log_window_lines, &options->log_window_lines);
3525 /* accelerators tab */
3526 static void config_tab_accelerators(GtkWidget *notebook)
3532 GtkWidget *scrolled;
3533 GtkWidget *accel_view;
3534 GtkCellRenderer *renderer;
3535 GtkTreeSelection *selection;
3536 GtkTreeViewColumn *column;
3538 vbox = scrolled_notebook_page(notebook, _("Keyboard"));
3540 group = pref_group_new(vbox, TRUE, _("Accelerators"), GTK_ORIENTATION_VERTICAL);
3542 scrolled = gtk_scrolled_window_new(NULL, NULL);
3543 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
3544 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
3545 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3546 gtk_widget_show(scrolled);
3548 accel_store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
3550 accel_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(accel_store));
3551 g_object_unref(accel_store);
3552 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(accel_view));
3553 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
3555 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(accel_view), FALSE);
3557 renderer = gtk_cell_renderer_text_new();
3559 column = gtk_tree_view_column_new_with_attributes(_("Action"),
3564 gtk_tree_view_column_set_sort_column_id(column, AE_ACTION);
3565 gtk_tree_view_column_set_resizable(column, TRUE);
3566 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3569 renderer = gtk_cell_renderer_accel_new();
3570 g_signal_connect(G_OBJECT(renderer), "accel-cleared",
3571 G_CALLBACK(accel_store_cleared_cb), accel_store);
3572 g_signal_connect(G_OBJECT(renderer), "accel-edited",
3573 G_CALLBACK(accel_store_edited_cb), accel_store);
3576 g_object_set (renderer,
3578 "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
3581 column = gtk_tree_view_column_new_with_attributes(_("KEY"),
3586 gtk_tree_view_column_set_sort_column_id(column, AE_KEY);
3587 gtk_tree_view_column_set_resizable(column, TRUE);
3588 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3590 renderer = gtk_cell_renderer_text_new();
3592 column = gtk_tree_view_column_new_with_attributes(_("Tooltip"),
3597 gtk_tree_view_column_set_sort_column_id(column, AE_TOOLTIP);
3598 gtk_tree_view_column_set_resizable(column, TRUE);
3599 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3601 renderer = gtk_cell_renderer_text_new();
3603 column = gtk_tree_view_column_new_with_attributes("Accel",
3608 gtk_tree_view_column_set_sort_column_id(column, AE_ACCEL);
3609 gtk_tree_view_column_set_resizable(column, TRUE);
3610 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3612 accel_store_populate();
3613 gtk_container_add(GTK_CONTAINER(scrolled), accel_view);
3614 gtk_widget_show(accel_view);
3616 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3618 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
3619 G_CALLBACK(accel_default_cb), accel_view);
3620 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3621 gtk_widget_show(button);
3623 button = pref_button_new(NULL, NULL, _("Reset selected"), FALSE,
3624 G_CALLBACK(accel_reset_cb), accel_view);
3625 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3626 gtk_widget_show(button);
3629 /* toolbar main tab */
3630 static void config_tab_toolbar_main(GtkWidget *notebook)
3633 GtkWidget *toolbardata;
3636 lw = layout_window_list->data;
3638 vbox = scrolled_notebook_page(notebook, _("Toolbar Main"));
3640 toolbardata = toolbar_select_new(lw, TOOLBAR_MAIN);
3641 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3642 gtk_widget_show(vbox);
3645 /* toolbar status tab */
3646 static void config_tab_toolbar_status(GtkWidget *notebook)
3649 GtkWidget *toolbardata;
3652 lw = layout_window_list->data;
3654 vbox = scrolled_notebook_page(notebook, _("Toolbar Status"));
3656 toolbardata = toolbar_select_new(lw, TOOLBAR_STATUS);
3657 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3658 gtk_widget_show(vbox);
3662 static gint extension_sort_cb(gconstpointer a, gconstpointer b)
3664 return g_strcmp0((gchar *)a, (gchar *)b);
3667 static void config_tab_advanced(GtkWidget *notebook)
3671 GSList *formats_list;
3672 GList *extensions_list = NULL;
3675 GdkPixbufFormat *fm;
3677 GString *types_string = g_string_new(NULL);
3679 vbox = scrolled_notebook_page(notebook, _("Advanced"));
3680 group = pref_group_new(vbox, FALSE, _("External preview extraction"), GTK_ORIENTATION_VERTICAL);
3682 pref_checkbox_new_int(group, _("Use external preview extraction - Requires restart"), options->external_preview.enable, &c_options->external_preview.enable);
3684 pref_spacer(group, PREF_PAD_GROUP);
3686 formats_list = gdk_pixbuf_get_formats();
3688 while (formats_list)
3690 fm = formats_list->data;
3691 extensions = gdk_pixbuf_format_get_extensions(fm);
3694 while (extensions[i])
3696 extensions_list = g_list_insert_sorted(extensions_list, g_strdup(extensions[i]), extension_sort_cb);
3700 g_strfreev(extensions);
3701 formats_list = formats_list->next;
3704 while (extensions_list)
3706 if (types_string->len == 0)
3708 types_string = g_string_append(types_string, extensions_list->data);
3712 types_string = g_string_append(types_string, ", ");
3713 types_string = g_string_append(types_string, extensions_list->data);
3716 extensions_list = extensions_list->next;
3719 types_string = g_string_prepend(types_string, _("Usable file types:\n"));
3720 pref_label_new(group, types_string->str);
3721 GtkWidget *types_string_label = gtk_label_new(types_string->str);
3722 gtk_label_set_line_wrap(GTK_LABEL(types_string_label), TRUE);
3724 pref_spacer(group, PREF_PAD_GROUP);
3726 group = pref_group_new(vbox, FALSE, _("File identification tool"), GTK_ORIENTATION_VERTICAL);
3727 external_preview_select_entry = gtk_entry_new();
3728 tabcomp = tab_completion_new(&external_preview_select_entry, options->external_preview.select, NULL, NULL, NULL, NULL);
3729 tab_completion_add_select_button(external_preview_select_entry, _("Select file identification tool"), FALSE);
3730 gtk_box_pack_start(GTK_BOX(group), tabcomp, TRUE, TRUE, 0);
3731 gtk_widget_show(tabcomp);
3733 group = pref_group_new(vbox, FALSE, _("Preview extraction tool"), GTK_ORIENTATION_VERTICAL);
3734 external_preview_extract_entry = gtk_entry_new();
3735 tabcomp = tab_completion_new(&external_preview_extract_entry, options->external_preview.extract, NULL, NULL, NULL, NULL);
3736 tab_completion_add_select_button(external_preview_extract_entry, _("Select preview extraction tool"), FALSE);
3737 gtk_box_pack_start(GTK_BOX(group), tabcomp, TRUE, TRUE, 0);
3738 gtk_widget_show(tabcomp);
3740 gtk_widget_show(vbox);
3742 g_slist_free(formats_list);
3743 string_list_free(extensions_list);
3744 g_string_free(types_string, TRUE);
3748 static void config_tab_stereo(GtkWidget *notebook)
3756 GtkWidget *fs_button;
3757 vbox = scrolled_notebook_page(notebook, _("Stereo"));
3759 group = pref_group_new(vbox, FALSE, _("Windowed stereo mode"), GTK_ORIENTATION_VERTICAL);
3761 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3762 add_stereo_mode_menu(table, 0, 0, _("Windowed stereo mode"), options->stereo.mode, &c_options->stereo.mode, FALSE);
3764 table = pref_table_new(group, 2, 2, TRUE, FALSE);
3765 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3766 pref_checkbox_new_int(box, _("Mirror left image"),
3767 options->stereo.mode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.mirror_left);
3768 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3769 pref_checkbox_new_int(box, _("Flip left image"),
3770 options->stereo.mode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.flip_left);
3771 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3772 pref_checkbox_new_int(box, _("Mirror right image"),
3773 options->stereo.mode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.mirror_right);
3774 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3775 pref_checkbox_new_int(box, _("Flip right image"),
3776 options->stereo.mode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.flip_right);
3777 pref_checkbox_new_int(group, _("Swap left and right images"),
3778 options->stereo.mode & PR_STEREO_SWAP, &c_options->stereo.tmp.swap);
3779 pref_checkbox_new_int(group, _("Disable stereo mode on single image source"),
3780 options->stereo.mode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.temp_disable);
3782 group = pref_group_new(vbox, FALSE, _("Fullscreen stereo mode"), GTK_ORIENTATION_VERTICAL);
3783 fs_button = pref_checkbox_new_int(group, _("Use different settings for fullscreen"),
3784 options->stereo.enable_fsmode, &c_options->stereo.enable_fsmode);
3785 box2 = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
3786 pref_checkbox_link_sensitivity(fs_button, box2);
3787 table = pref_table_new(box2, 2, 1, FALSE, FALSE);
3788 add_stereo_mode_menu(table, 0, 0, _("Fullscreen stereo mode"), options->stereo.fsmode, &c_options->stereo.fsmode, TRUE);
3789 table = pref_table_new(box2, 2, 2, TRUE, FALSE);
3790 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3791 pref_checkbox_new_int(box, _("Mirror left image"),
3792 options->stereo.fsmode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.fs_mirror_left);
3793 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3794 pref_checkbox_new_int(box, _("Flip left image"),
3795 options->stereo.fsmode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.fs_flip_left);
3796 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3797 pref_checkbox_new_int(box, _("Mirror right image"),
3798 options->stereo.fsmode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.fs_mirror_right);
3799 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3800 pref_checkbox_new_int(box, _("Flip right image"),
3801 options->stereo.fsmode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.fs_flip_right);
3802 pref_checkbox_new_int(box2, _("Swap left and right images"),
3803 options->stereo.fsmode & PR_STEREO_SWAP, &c_options->stereo.tmp.fs_swap);
3804 pref_checkbox_new_int(box2, _("Disable stereo mode on single image source"),
3805 options->stereo.fsmode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.fs_temp_disable);
3807 group2 = pref_group_new(box2, FALSE, _("Fixed position"), GTK_ORIENTATION_VERTICAL);
3808 table = pref_table_new(group2, 5, 3, FALSE, FALSE);
3809 pref_table_spin_new_int(table, 0, 0, _("Width"), NULL,
3810 1, 5000, 1, options->stereo.fixed_w, &c_options->stereo.fixed_w);
3811 pref_table_spin_new_int(table, 3, 0, _("Height"), NULL,
3812 1, 5000, 1, options->stereo.fixed_h, &c_options->stereo.fixed_h);
3813 pref_table_spin_new_int(table, 0, 1, _("Left X"), NULL,
3814 0, 5000, 1, options->stereo.fixed_x1, &c_options->stereo.fixed_x1);
3815 pref_table_spin_new_int(table, 3, 1, _("Left Y"), NULL,
3816 0, 5000, 1, options->stereo.fixed_y1, &c_options->stereo.fixed_y1);
3817 pref_table_spin_new_int(table, 0, 2, _("Right X"), NULL,
3818 0, 5000, 1, options->stereo.fixed_x2, &c_options->stereo.fixed_x2);
3819 pref_table_spin_new_int(table, 3, 2, _("Right Y"), NULL,
3820 0, 5000, 1, options->stereo.fixed_y2, &c_options->stereo.fixed_y2);
3824 /* Main preferences window */
3825 static void config_window_create(LayoutWindow *lw)
3827 GtkWidget *win_vbox;
3829 GtkWidget *notebook;
3831 GtkWidget *ct_button;
3833 if (!c_options) c_options = init_options(NULL);
3835 configwindow = window_new(GTK_WINDOW_TOPLEVEL, "preferences", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Preferences"));
3836 DEBUG_NAME(configwindow);
3837 gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
3838 g_signal_connect(G_OBJECT(configwindow), "delete_event",
3839 G_CALLBACK(config_window_delete), NULL);
3840 if (options->save_dialog_window_positions)
3842 gtk_window_resize(GTK_WINDOW(configwindow), lw->options.preferences_window.w, lw->options.preferences_window.h);
3843 gtk_window_move(GTK_WINDOW(configwindow), lw->options.preferences_window.x, lw->options.preferences_window.y);
3847 gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
3849 gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
3850 gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
3852 win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
3853 gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
3854 gtk_widget_show(win_vbox);
3856 notebook = gtk_notebook_new();
3857 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_LEFT);
3858 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE);
3859 gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
3861 config_tab_general(notebook);
3862 config_tab_image(notebook);
3863 config_tab_osd(notebook);
3864 config_tab_windows(notebook);
3865 config_tab_accelerators(notebook);
3866 config_tab_files(notebook);
3867 config_tab_metadata(notebook);
3868 config_tab_keywords(notebook);
3869 config_tab_color(notebook);
3870 config_tab_stereo(notebook);
3871 config_tab_behavior(notebook);
3872 config_tab_toolbar_main(notebook);
3873 config_tab_toolbar_status(notebook);
3874 config_tab_advanced(notebook);
3876 gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), lw->options.preferences_window.page_number);
3878 hbox = gtk_hbutton_box_new();
3879 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
3880 gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
3881 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
3882 gtk_widget_show(hbox);
3884 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
3885 G_CALLBACK(config_window_help_cb), notebook);
3886 gtk_container_add(GTK_CONTAINER(hbox), button);
3887 gtk_widget_set_can_default(button, TRUE);
3888 gtk_widget_show(button);
3890 button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
3891 G_CALLBACK(config_window_ok_cb), notebook);
3892 gtk_container_add(GTK_CONTAINER(hbox), button);
3893 gtk_widget_set_can_default(button, TRUE);
3894 gtk_widget_grab_default(button);
3895 gtk_widget_show(button);
3899 button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
3900 G_CALLBACK(config_window_close_cb), NULL);
3901 gtk_container_add(GTK_CONTAINER(hbox), button);
3902 gtk_widget_set_can_default(button, TRUE);
3903 gtk_widget_show(button);
3905 if (!generic_dialog_get_alternative_button_order(configwindow))
3907 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
3910 gtk_widget_show(notebook);
3912 gtk_widget_show(configwindow);
3916 *-----------------------------------------------------------------------------
3917 * config window show (public)
3918 *-----------------------------------------------------------------------------
3921 void show_config_window(LayoutWindow *lw)
3925 gtk_window_present(GTK_WINDOW(configwindow));
3929 config_window_create(lw);
3938 void show_about_window(LayoutWindow *lw)
3940 GdkPixbuf *pixbuf_logo;
3941 GdkPixbuf *pixbuf_icon;
3942 gchar *authors[1000];
3947 gchar *timezone_path;
3951 #define LINE_LENGTH 1000
3952 gchar line[LINE_LENGTH];
3954 copyright = g_string_new(NULL);
3955 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");
3957 path = path_from_utf8(TIMEZONE_DATABASE);
3958 basename = g_path_get_basename(path);
3959 timezone_path = g_build_filename(get_rc_dir(), basename, NULL);
3960 if (g_file_test(timezone_path, G_FILE_TEST_EXISTS))
3962 cd = ZDOpenDatabase(timezone_path);
3965 copyright = g_string_append(copyright, ZDGetNotice(cd));
3966 ZDCloseDatabase(cd);
3970 g_free(timezone_path);
3974 path = g_build_filename(gq_helpdir, "AUTHORS", NULL);
3975 fp = fopen(path, "r");
3978 while(fgets(line, LINE_LENGTH, fp))
3980 /* get rid of ending \n from fgets */
3981 line[strlen(line) - 1] = '\0';
3982 authors[i_authors] = g_strdup(line);
3985 authors[i_authors] = NULL;
3990 comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
3991 "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
3993 pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
3994 pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
3995 gtk_show_about_dialog(GTK_WINDOW(lw->window),
3996 "title", _("About Geeqie"),
3998 "program-name", GQ_APPNAME,
4000 "logo", pixbuf_logo,
4001 "icon", pixbuf_icon,
4002 "website", GQ_WEBSITE,
4003 "website-label", "Website",
4004 "comments", comment,
4006 "translator-credits", _("translator-credits"),
4007 "wrap-license", TRUE,
4008 "license", copyright->str,
4011 g_string_free(copyright, TRUE);
4014 while(n < i_authors)
4024 static void image_overlay_set_text_colours()
4026 c_options->image_overlay.text_red = options->image_overlay.text_red;
4027 c_options->image_overlay.text_green = options->image_overlay.text_green;
4028 c_options->image_overlay.text_blue = options->image_overlay.text_blue;
4029 c_options->image_overlay.text_alpha = options->image_overlay.text_alpha;
4030 c_options->image_overlay.background_red = options->image_overlay.background_red;
4031 c_options->image_overlay.background_green = options->image_overlay.background_green;
4032 c_options->image_overlay.background_blue = options->image_overlay.background_blue;
4033 c_options->image_overlay.background_alpha = options->image_overlay.background_alpha;
4037 *-----------------------------------------------------------------------------
4038 * timezone database routines
4039 *-----------------------------------------------------------------------------
4042 static void timezone_async_ready_cb(GObject *source_object, GAsyncResult *res, gpointer data)
4044 GError *error = NULL;
4046 gchar *tmp_filename;
4048 if (!g_cancellable_is_cancelled(tz->cancellable))
4050 generic_dialog_close(tz->gd);
4054 if (g_file_copy_finish(G_FILE(source_object), res, &error))
4056 tmp_filename = g_file_get_parse_name(tz->tmp_g_file);
4057 move_file(tmp_filename, tz->timezone_database_user);
4058 g_free(tmp_filename);
4062 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
4065 g_file_delete(tz->tmp_g_file, NULL, &error);
4066 g_object_unref(tz->tmp_g_file);
4067 tz->tmp_g_file = NULL;
4068 g_object_unref(tz->cancellable);
4069 g_object_unref(tz->timezone_database_gq);
4072 static void timezone_progress_cb(goffset current_num_bytes, goffset total_num_bytes, gpointer data)
4076 if (!g_cancellable_is_cancelled(tz->cancellable))
4078 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(tz->progress), (gdouble)current_num_bytes / total_num_bytes);
4082 static void timezone_cancel_button_cb(GenericDialog *gd, gpointer data)
4086 g_cancellable_cancel(tz->cancellable);
4089 static void timezone_database_install_cb(GtkWidget *widget, gpointer data)
4092 GError *error = NULL;
4093 GFileIOStream *io_stream;
4100 tz->tmp_g_file = g_file_new_tmp("geeqie_timezone_XXXXXX", &io_stream, &error);
4104 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
4105 log_printf("Error: Download timezone database failed:\n%s", error->message);
4106 g_error_free(error);
4107 g_object_unref(tz->tmp_g_file);
4111 tz->timezone_database_gq = g_file_new_for_uri(TIMEZONE_DATABASE);
4113 tz->gd = generic_dialog_new(_("Timezone database"), "download_timezone_database", NULL, TRUE, timezone_cancel_button_cb, tz);
4115 generic_dialog_add_message(tz->gd, GTK_STOCK_DIALOG_INFO, _("Downloading timezone database"), NULL, FALSE);
4117 tz->progress = gtk_progress_bar_new();
4118 gtk_box_pack_start(GTK_BOX(tz->gd->vbox), tz->progress, FALSE, FALSE, 0);
4119 gtk_widget_show(tz->progress);
4121 gtk_widget_show(tz->gd->dialog);
4122 tz->cancellable = g_cancellable_new();
4123 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);
4125 gtk_button_set_label(GTK_BUTTON(widget), _("Update"));
4128 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */