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"
44 #include "slideshow.h"
48 #include "ui_fileops.h"
50 #include "ui_spinner.h"
51 #include "ui_tabcomp.h"
52 #include "ui_utildlg.h"
54 #include "zonedetect.h"
64 #define EDITOR_NAME_MAX_LENGTH 32
65 #define EDITOR_COMMAND_MAX_LENGTH 1024
67 static void image_overlay_set_text_colours();
69 GtkWidget *keyword_text;
70 static void config_tab_keywords_save();
72 typedef struct _ThumbSize ThumbSize;
79 static ThumbSize thumb_size_list[] =
113 gchar *format_class_list[] = {
123 /* config memory values */
124 static ConfOptions *c_options = NULL;
131 static GtkWidget *configwindow = NULL;
132 static GtkListStore *filter_store = NULL;
133 static GtkTreeStore *accel_store = NULL;
135 static GtkWidget *safe_delete_path_entry;
137 static GtkWidget *color_profile_input_file_entry[COLOR_PROFILE_INPUTS];
138 static GtkWidget *color_profile_input_name_entry[COLOR_PROFILE_INPUTS];
139 static GtkWidget *color_profile_screen_file_entry;
140 static GtkWidget *external_preview_select_entry;
141 static GtkWidget *external_preview_extract_entry;
143 static GtkWidget *sidecar_ext_entry;
144 static GtkWidget *help_search_engine_entry;
147 #define CONFIG_WINDOW_DEF_WIDTH 700
148 #define CONFIG_WINDOW_DEF_HEIGHT 600
151 *-----------------------------------------------------------------------------
152 * option widget callbacks (private)
153 *-----------------------------------------------------------------------------
156 static void zoom_increment_cb(GtkWidget *spin, gpointer data)
158 c_options->image.zoom_increment = (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) * 100.0 + 0.01);
161 static void slideshow_delay_hours_cb(GtkWidget *spin, gpointer data)
163 gint mins_secs_tenths, delay;
165 mins_secs_tenths = c_options->slideshow.delay %
166 (3600 * SLIDESHOW_SUBSECOND_PRECISION);
168 delay = (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
169 (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
172 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
173 SLIDESHOW_SUBSECOND_PRECISION;
176 static void slideshow_delay_minutes_cb(GtkWidget *spin, gpointer data)
178 gint hours, secs_tenths, delay;
180 hours = c_options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
181 secs_tenths = c_options->slideshow.delay % (60 * SLIDESHOW_SUBSECOND_PRECISION);
183 delay = hours * (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
184 (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
185 (60 * SLIDESHOW_SUBSECOND_PRECISION) + secs_tenths);
187 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
188 SLIDESHOW_SUBSECOND_PRECISION;
191 static void slideshow_delay_seconds_cb(GtkWidget *spin, gpointer data)
193 gint hours_mins, delay;
195 hours_mins = c_options->slideshow.delay / (60 * SLIDESHOW_SUBSECOND_PRECISION);
197 delay = (hours_mins * (60 * SLIDESHOW_SUBSECOND_PRECISION)) +
198 (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
199 (gdouble)(SLIDESHOW_SUBSECOND_PRECISION) + 0.01);
201 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
202 SLIDESHOW_SUBSECOND_PRECISION;
206 *-----------------------------------------------------------------------------
207 * sync program to config window routine (private)
208 *-----------------------------------------------------------------------------
211 void config_entry_to_option(GtkWidget *entry, gchar **option, gchar *(*func)(const gchar *))
217 buf = gtk_entry_get_text(GTK_ENTRY(entry));
218 if (buf && strlen(buf) > 0)
223 *option = g_strdup(buf);
228 static gboolean accel_apply_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
230 gchar *accel_path, *accel;
232 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, AE_KEY, &accel, -1);
234 if (accel_path && accel_path[0])
237 gtk_accelerator_parse(accel, &key.accel_key, &key.accel_mods);
238 gtk_accel_map_change_entry(accel_path, key.accel_key, key.accel_mods, TRUE);
248 static void config_window_apply(void)
250 gboolean refresh = FALSE;
255 config_entry_to_option(safe_delete_path_entry, &options->file_ops.safe_delete_path, remove_trailing_slash);
257 if (options->file_filter.show_hidden_files != c_options->file_filter.show_hidden_files) refresh = TRUE;
258 if (options->file_filter.show_parent_directory != c_options->file_filter.show_parent_directory) refresh = TRUE;
259 if (options->file_filter.show_dot_directory != c_options->file_filter.show_dot_directory) refresh = TRUE;
260 if (options->file_sort.case_sensitive != c_options->file_sort.case_sensitive) refresh = TRUE;
261 if (options->file_sort.natural != c_options->file_sort.natural) refresh = TRUE;
262 if (options->file_filter.disable_file_extension_checks != c_options->file_filter.disable_file_extension_checks) refresh = TRUE;
263 if (options->file_filter.disable != c_options->file_filter.disable) refresh = TRUE;
265 options->file_ops.confirm_delete = c_options->file_ops.confirm_delete;
266 options->file_ops.enable_delete_key = c_options->file_ops.enable_delete_key;
267 options->file_ops.confirm_move_to_trash = c_options->file_ops.confirm_move_to_trash;
268 options->file_ops.use_system_trash = c_options->file_ops.use_system_trash;
269 options->file_ops.no_trash = c_options->file_ops.no_trash;
270 options->file_ops.safe_delete_folder_maxsize = c_options->file_ops.safe_delete_folder_maxsize;
271 options->tools_restore_state = c_options->tools_restore_state;
272 options->save_window_positions = c_options->save_window_positions;
273 options->use_saved_window_positions_for_new_windows = c_options->use_saved_window_positions_for_new_windows;
274 options->save_window_workspace = c_options->save_window_workspace;
275 options->save_dialog_window_positions = c_options->save_dialog_window_positions;
276 options->show_window_ids = c_options->show_window_ids;
277 options->image.scroll_reset_method = c_options->image.scroll_reset_method;
278 options->image.zoom_2pass = c_options->image.zoom_2pass;
279 options->image.fit_window_to_image = c_options->image.fit_window_to_image;
280 options->image.limit_window_size = c_options->image.limit_window_size;
281 options->image.zoom_to_fit_allow_expand = c_options->image.zoom_to_fit_allow_expand;
282 options->image.max_window_size = c_options->image.max_window_size;
283 options->image.limit_autofit_size = c_options->image.limit_autofit_size;
284 options->image.max_autofit_size = c_options->image.max_autofit_size;
285 options->image.max_enlargement_size = c_options->image.max_enlargement_size;
286 options->image.use_clutter_renderer = c_options->image.use_clutter_renderer;
287 options->progressive_key_scrolling = c_options->progressive_key_scrolling;
288 options->keyboard_scroll_step = c_options->keyboard_scroll_step;
290 if (options->thumbnails.max_width != c_options->thumbnails.max_width
291 || options->thumbnails.max_height != c_options->thumbnails.max_height
292 || options->thumbnails.quality != c_options->thumbnails.quality)
294 thumb_format_changed = TRUE;
296 options->thumbnails.max_width = c_options->thumbnails.max_width;
297 options->thumbnails.max_height = c_options->thumbnails.max_height;
298 options->thumbnails.quality = c_options->thumbnails.quality;
300 options->thumbnails.enable_caching = c_options->thumbnails.enable_caching;
301 options->thumbnails.cache_into_dirs = c_options->thumbnails.cache_into_dirs;
302 options->thumbnails.use_exif = c_options->thumbnails.use_exif;
303 options->thumbnails.use_color_management = c_options->thumbnails.use_color_management;
304 options->thumbnails.collection_preview = c_options->thumbnails.collection_preview;
305 options->thumbnails.use_ft_metadata = c_options->thumbnails.use_ft_metadata;
306 // options->thumbnails.use_ft_metadata_small = c_options->thumbnails.use_ft_metadata_small;
307 options->thumbnails.spec_standard = c_options->thumbnails.spec_standard;
308 options->metadata.enable_metadata_dirs = c_options->metadata.enable_metadata_dirs;
309 options->file_filter.show_hidden_files = c_options->file_filter.show_hidden_files;
310 options->file_filter.show_parent_directory = c_options->file_filter.show_parent_directory;
311 options->file_filter.show_dot_directory = c_options->file_filter.show_dot_directory;
312 options->file_filter.disable_file_extension_checks = c_options->file_filter.disable_file_extension_checks;
314 options->file_sort.case_sensitive = c_options->file_sort.case_sensitive;
315 options->file_sort.natural = c_options->file_sort.natural;
316 options->file_filter.disable = c_options->file_filter.disable;
318 config_entry_to_option(sidecar_ext_entry, &options->sidecar.ext, NULL);
319 sidecar_ext_parse(options->sidecar.ext);
321 options->slideshow.random = c_options->slideshow.random;
322 options->slideshow.repeat = c_options->slideshow.repeat;
323 options->slideshow.delay = c_options->slideshow.delay;
325 options->mousewheel_scrolls = c_options->mousewheel_scrolls;
326 options->image_lm_click_nav = c_options->image_lm_click_nav;
327 options->image_l_click_video = c_options->image_l_click_video;
328 options->image_l_click_video_editor = c_options->image_l_click_video_editor;
330 options->file_ops.enable_in_place_rename = c_options->file_ops.enable_in_place_rename;
332 options->image.tile_cache_max = c_options->image.tile_cache_max;
333 options->image.image_cache_max = c_options->image.image_cache_max;
335 options->image.zoom_quality = c_options->image.zoom_quality;
337 options->image.zoom_increment = c_options->image.zoom_increment;
339 options->image.enable_read_ahead = c_options->image.enable_read_ahead;
342 if (options->image.use_custom_border_color != c_options->image.use_custom_border_color
343 || options->image.use_custom_border_color_in_fullscreen != c_options->image.use_custom_border_color_in_fullscreen
344 || !gdk_color_equal(&options->image.border_color, &c_options->image.border_color))
346 options->image.use_custom_border_color_in_fullscreen = c_options->image.use_custom_border_color_in_fullscreen;
347 options->image.use_custom_border_color = c_options->image.use_custom_border_color;
348 options->image.border_color = c_options->image.border_color;
349 layout_colors_update();
350 view_window_colors_update();
353 options->image.alpha_color_1 = c_options->image.alpha_color_1;
354 options->image.alpha_color_2 = c_options->image.alpha_color_2;
356 options->fullscreen.screen = c_options->fullscreen.screen;
357 options->fullscreen.clean_flip = c_options->fullscreen.clean_flip;
358 options->fullscreen.disable_saver = c_options->fullscreen.disable_saver;
359 options->fullscreen.above = c_options->fullscreen.above;
360 if (c_options->image_overlay.template_string)
361 set_image_overlay_template_string(&options->image_overlay.template_string,
362 c_options->image_overlay.template_string);
363 if (c_options->image_overlay.font)
364 set_image_overlay_font_string(&options->image_overlay.font,
365 c_options->image_overlay.font);
366 options->image_overlay.text_red = c_options->image_overlay.text_red;
367 options->image_overlay.text_green = c_options->image_overlay.text_green;
368 options->image_overlay.text_blue = c_options->image_overlay.text_blue;
369 options->image_overlay.text_alpha = c_options->image_overlay.text_alpha;
370 options->image_overlay.background_red = c_options->image_overlay.background_red;
371 options->image_overlay.background_green = c_options->image_overlay.background_green;
372 options->image_overlay.background_blue = c_options->image_overlay.background_blue;
373 options->image_overlay.background_alpha = c_options->image_overlay.background_alpha;
374 options->update_on_time_change = c_options->update_on_time_change;
375 options->image.exif_proof_rotate_enable = c_options->image.exif_proof_rotate_enable;
377 options->duplicates_similarity_threshold = c_options->duplicates_similarity_threshold;
378 options->rot_invariant_sim = c_options->rot_invariant_sim;
380 options->tree_descend_subdirs = c_options->tree_descend_subdirs;
382 options->view_dir_list_single_click_enter = c_options->view_dir_list_single_click_enter;
383 options->circular_selection_lists = c_options->circular_selection_lists;
385 options->open_recent_list_maxsize = c_options->open_recent_list_maxsize;
386 options->dnd_icon_size = c_options->dnd_icon_size;
387 options->clipboard_selection = c_options->clipboard_selection;
388 options->dnd_default_action = c_options->dnd_default_action;
390 options->metadata.save_in_image_file = c_options->metadata.save_in_image_file;
391 options->metadata.save_legacy_IPTC = c_options->metadata.save_legacy_IPTC;
392 options->metadata.warn_on_write_problems = c_options->metadata.warn_on_write_problems;
393 options->metadata.save_legacy_format = c_options->metadata.save_legacy_format;
394 options->metadata.sync_grouped_files = c_options->metadata.sync_grouped_files;
395 options->metadata.confirm_write = c_options->metadata.confirm_write;
396 options->metadata.sidecar_extended_name = c_options->metadata.sidecar_extended_name;
397 options->metadata.confirm_timeout = c_options->metadata.confirm_timeout;
398 options->metadata.confirm_after_timeout = c_options->metadata.confirm_after_timeout;
399 options->metadata.confirm_on_image_change = c_options->metadata.confirm_on_image_change;
400 options->metadata.confirm_on_dir_change = c_options->metadata.confirm_on_dir_change;
401 options->metadata.keywords_case_sensitive = c_options->metadata.keywords_case_sensitive;
402 options->metadata.write_orientation = c_options->metadata.write_orientation;
403 options->stereo.mode = (c_options->stereo.mode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
404 (c_options->stereo.tmp.mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
405 (c_options->stereo.tmp.flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
406 (c_options->stereo.tmp.mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
407 (c_options->stereo.tmp.flip_left ? PR_STEREO_FLIP_LEFT : 0) |
408 (c_options->stereo.tmp.swap ? PR_STEREO_SWAP : 0) |
409 (c_options->stereo.tmp.temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
410 options->stereo.fsmode = (c_options->stereo.fsmode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
411 (c_options->stereo.tmp.fs_mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
412 (c_options->stereo.tmp.fs_flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
413 (c_options->stereo.tmp.fs_mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
414 (c_options->stereo.tmp.fs_flip_left ? PR_STEREO_FLIP_LEFT : 0) |
415 (c_options->stereo.tmp.fs_swap ? PR_STEREO_SWAP : 0) |
416 (c_options->stereo.tmp.fs_temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
417 options->stereo.enable_fsmode = c_options->stereo.enable_fsmode;
418 options->stereo.fixed_w = c_options->stereo.fixed_w;
419 options->stereo.fixed_h = c_options->stereo.fixed_h;
420 options->stereo.fixed_x1 = c_options->stereo.fixed_x1;
421 options->stereo.fixed_y1 = c_options->stereo.fixed_y1;
422 options->stereo.fixed_x2 = c_options->stereo.fixed_x2;
423 options->stereo.fixed_y2 = c_options->stereo.fixed_y2;
425 options->info_keywords.height = c_options->info_keywords.height;
426 options->info_title.height = c_options->info_title.height;
427 options->info_comment.height = c_options->info_comment.height;
428 options->info_rating.height = c_options->info_rating.height;
430 options->show_predefined_keyword_tree = c_options->show_predefined_keyword_tree;
431 options->expand_menu_toolbar = c_options->expand_menu_toolbar;
433 options->marks_save = c_options->marks_save;
434 options->with_rename = c_options->with_rename;
435 options->collections_on_top = c_options->collections_on_top;
436 options->hide_window_in_fullscreen = c_options->hide_window_in_fullscreen;
437 config_entry_to_option(help_search_engine_entry, &options->help_search_engine, NULL);
439 options->external_preview.enable = c_options->external_preview.enable;
440 config_entry_to_option(external_preview_select_entry, &options->external_preview.select, NULL);
441 config_entry_to_option(external_preview_extract_entry, &options->external_preview.extract, NULL);
443 options->read_metadata_in_idle = c_options->read_metadata_in_idle;
445 options->star_rating.star = c_options->star_rating.star;
446 options->star_rating.rejected = c_options->star_rating.rejected;
448 set_debug_level(debug_c);
452 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
454 config_entry_to_option(color_profile_input_name_entry[i], &options->color_profile.input_name[i], NULL);
455 config_entry_to_option(color_profile_input_file_entry[i], &options->color_profile.input_file[i], NULL);
457 config_entry_to_option(color_profile_screen_file_entry, &options->color_profile.screen_file, NULL);
458 options->color_profile.use_x11_screen_profile = c_options->color_profile.use_x11_screen_profile;
459 if (options->color_profile.render_intent != c_options->color_profile.render_intent)
461 options->color_profile.render_intent = c_options->color_profile.render_intent;
466 options->mouse_button_8 = c_options->mouse_button_8;
467 options->mouse_button_9 = c_options->mouse_button_9;
469 options->override_disable_gpu = c_options->override_disable_gpu;
471 config_tab_keywords_save();
473 image_options_sync();
478 layout_refresh(NULL);
481 if (accel_store) gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_apply_cb, NULL);
483 toolbar_apply(TOOLBAR_MAIN);
484 toolbar_apply(TOOLBAR_STATUS);
488 *-----------------------------------------------------------------------------
489 * config window main button callbacks (private)
490 *-----------------------------------------------------------------------------
493 static void config_window_close_cb(GtkWidget *widget, gpointer data)
495 gtk_widget_destroy(configwindow);
500 static void config_window_help_cb(GtkWidget *widget, gpointer data)
502 GtkWidget *notebook = data;
505 static gchar *html_section[] =
507 "GuideOptionsGeneral.html",
508 "GuideOptionsImage.html",
509 "GuideOptionsOSD.html",
510 "GuideOptionsWindow.html",
511 "GuideOptionsKeyboard.html",
512 "GuideOptionsFiltering.html",
513 "GuideOptionsMetadata.html",
514 "GuideOptionsKeywords.html",
515 "GuideOptionsColor.html",
516 "GuideOptionsStereo.html",
517 "GuideOptionsBehavior.html",
518 "GuideOptionsToolbar.html",
519 "GuideOptionsToolbar.html",
520 "GuideOptionsAdvanced.html"
523 i = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
524 help_window_show(html_section[i]);
527 static gboolean config_window_delete(GtkWidget *widget, GdkEventAny *event, gpointer data)
529 config_window_close_cb(NULL, NULL);
533 static void config_window_ok_cb(GtkWidget *widget, gpointer data)
536 GtkNotebook *notebook = data;
544 lw = layout_window_list->data;
546 window = gtk_widget_get_window(widget);
547 gdk_window_get_root_origin(window, &x, &y);
548 w = gdk_window_get_width(window);
549 h = gdk_window_get_height(window);
550 page_number = gtk_notebook_get_current_page(notebook);
552 lw->options.preferences_window.x = x;
553 lw->options.preferences_window.y = y;
554 lw->options.preferences_window.w = w;
555 lw->options.preferences_window.h = h;
556 lw->options.preferences_window.page_number = page_number;
558 config_window_apply();
559 layout_util_sync(lw);
560 save_options(options);
561 config_window_close_cb(NULL, NULL);
565 *-----------------------------------------------------------------------------
566 * config window setup (private)
567 *-----------------------------------------------------------------------------
570 static void quality_menu_cb(GtkWidget *combo, gpointer data)
574 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
578 *option = GDK_INTERP_NEAREST;
581 *option = GDK_INTERP_TILES;
584 *option = GDK_INTERP_BILINEAR;
589 static void dnd_default_action_selection_menu_cb(GtkWidget *combo, gpointer data)
593 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
597 *option = DND_ACTION_ASK;
600 *option = DND_ACTION_COPY;
603 *option = DND_ACTION_MOVE;
607 static void clipboard_selection_menu_cb(GtkWidget *combo, gpointer data)
611 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
614 *option = CLIPBOARD_PRIMARY;
617 *option = CLIPBOARD_CLIPBOARD;
620 *option = CLIPBOARD_BOTH;
623 *option = CLIPBOARD_BOTH;
627 static void add_quality_menu(GtkWidget *table, gint column, gint row, const gchar *text,
628 guint option, guint *option_c)
635 pref_table_label(table, column, row, text, 0.0);
637 combo = gtk_combo_box_text_new();
639 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Nearest (worst, but fastest)"));
640 if (option == GDK_INTERP_NEAREST) current = 0;
641 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Tiles"));
642 if (option == GDK_INTERP_TILES) current = 1;
643 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Bilinear (best, but slowest)"));
644 if (option == GDK_INTERP_BILINEAR) current = 2;
646 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
648 g_signal_connect(G_OBJECT(combo), "changed",
649 G_CALLBACK(quality_menu_cb), option_c);
651 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
652 gtk_widget_show(combo);
655 static void add_dnd_default_action_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text, DnDAction option, DnDAction *option_c)
662 pref_table_label(table, column, row, text, 0.0);
664 combo = gtk_combo_box_text_new();
666 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Ask"));
667 if (option == DND_ACTION_ASK) current = 0;
668 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Copy"));
669 if (option == DND_ACTION_COPY) current = 1;
670 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Move"));
671 if (option == DND_ACTION_MOVE) current = 2;
673 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
675 g_signal_connect(G_OBJECT(combo), "changed",
676 G_CALLBACK(dnd_default_action_selection_menu_cb), option_c);
678 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
679 gtk_widget_show(combo);
682 static void add_clipboard_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
683 gint option, gint *option_c)
690 pref_table_label(table, column, row, text, 0.0);
692 combo = gtk_combo_box_text_new();
694 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Primary"));
695 if (option == CLIPBOARD_PRIMARY) current = 0;
696 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Clipboard"));
697 if (option == CLIPBOARD_CLIPBOARD) current = 1;
698 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Both"));
699 if (option == CLIPBOARD_BOTH) current = 2;
701 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
703 g_signal_connect(G_OBJECT(combo), "changed",
704 G_CALLBACK(clipboard_selection_menu_cb), option_c);
706 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
707 gtk_widget_show(combo);
710 typedef struct _UseableMouseItems UseableMouseItems;
711 struct _UseableMouseItems
713 gchar *name; /* GtkActionEntry terminology */
718 static const UseableMouseItems useable_mouse_items[] = {
720 {"FirstImage", N_("First Image"), GTK_STOCK_GOTO_TOP},
721 {"PrevImage", N_("Previous Image"), GTK_STOCK_GO_UP},
722 {"NextImage", N_("Next Image"), GTK_STOCK_GO_DOWN},
723 {"LastImage", N_("Last Image"), GTK_STOCK_GOTO_BOTTOM},
724 {"Back", N_("Back"), GTK_STOCK_GO_BACK},
725 {"Forward", N_("Forward"), GTK_STOCK_GO_FORWARD},
726 {"Home", N_("Home"), GTK_STOCK_HOME},
727 {"Up", N_("Up"), GTK_STOCK_GO_UP},
728 {"FirstPage", N_("First page"), GTK_STOCK_MEDIA_PREVIOUS},
729 {"LastPage", N_("Last Page"), GTK_STOCK_MEDIA_NEXT},
730 {"NextPage", N_("Next page"), GTK_STOCK_MEDIA_FORWARD},
731 {"PrevPage", N_("Previous Page"), GTK_STOCK_MEDIA_REWIND},
732 {"NewWindow", N_("New _window"), GTK_STOCK_NEW},
733 {"NewCollection", N_("New collection"), GTK_STOCK_INDEX},
734 {"OpenCollection", N_("Open collection"), GTK_STOCK_OPEN},
735 {"Search", N_("Search"), GTK_STOCK_FIND},
736 {"FindDupes", N_("Find duplicates"), GTK_STOCK_FIND},
737 {"NewFolder", N_("New folder"),GTK_STOCK_DIRECTORY},
738 {"Copy", N_("Copy"), GTK_STOCK_COPY},
739 {"Move", N_("Move"), PIXBUF_INLINE_ICON_MOVE},
740 {"Rename", N_("Rename"), PIXBUF_INLINE_ICON_RENAME},
741 {"Delete", N_("Delete"), GTK_STOCK_DELETE},
742 {"CloseWindow", N_("Close Window"), GTK_STOCK_CLOSE},
743 {"PanView", N_("Pan view"), PIXBUF_INLINE_ICON_PANORAMA},
744 {"SelectAll", N_("Select all"), PIXBUF_INLINE_ICON_SELECT_ALL},
745 {"SelectNone", N_("Select none"), PIXBUF_INLINE_ICON_SELECT_NONE},
746 {"SelectInvert", N_("Select invert"), PIXBUF_INLINE_ICON_SELECT_INVERT},
747 {"ShowFileFilter", N_("Show file filter"), PIXBUF_INLINE_ICON_FILE_FILTER},
748 {"RectangularSelection", N_("Select rectangle"), PIXBUF_INLINE_ICON_SELECT_RECTANGLE},
749 {"Print", N_("Print"), GTK_STOCK_PRINT},
750 {"Preferences", N_("Preferences"), GTK_STOCK_PREFERENCES},
751 {"LayoutConfig", N_("Configure this window"), GTK_STOCK_PREFERENCES},
752 {"Maintenance", N_("Cache maintenance"), PIXBUF_INLINE_ICON_MAINTENANCE},
753 {"RotateCW", N_("Rotate clockwise 90°"), PIXBUF_INLINE_ICON_CW},
754 {"RotateCCW", N_("Rotate counterclockwise 90°"), PIXBUF_INLINE_ICON_CCW},
755 {"Rotate180", N_("Rotate 180°"), PIXBUF_INLINE_ICON_180},
756 {"Mirror", N_("Mirror"), PIXBUF_INLINE_ICON_MIRROR},
757 {"Flip", N_("Flip"), PIXBUF_INLINE_ICON_FLIP},
758 {"AlterNone", N_("Original state"), PIXBUF_INLINE_ICON_ORIGINAL},
759 {"ZoomIn", N_("Zoom in"), GTK_STOCK_ZOOM_IN},
760 {"ZoomOut", N_("Zoom out"), GTK_STOCK_ZOOM_OUT},
761 {"Zoom100", N_("Zoom 1:1"), GTK_STOCK_ZOOM_100},
762 {"ZoomFit", N_("Zoom to fit"), GTK_STOCK_ZOOM_FIT},
763 {"ZoomFillHor", N_("Fit Horizontaly"), PIXBUF_INLINE_ICON_ZOOMFILLHOR},
764 {"ZoomFillVert", N_("Fit vertically"), PIXBUF_INLINE_ICON_ZOOMFILLVERT},
765 {"Zoom200", N_("Zoom 2:1"), GTK_STOCK_FILE},
766 {"Zoom300", N_("Zoom 3:1"), GTK_STOCK_FILE},
767 {"Zoom400", N_("Zoom 4:1"), GTK_STOCK_FILE},
768 {"Zoom50", N_("Zoom 1:2"), GTK_STOCK_FILE},
769 {"Zoom33", N_("Zoom1:3"), GTK_STOCK_FILE},
770 {"Zoom25", N_("Zoom 1:4"), GTK_STOCK_FILE},
771 {"ConnectZoomIn", N_("Connected Zoom in"), GTK_STOCK_ZOOM_IN},
772 {"SplitPaneSync", N_("Split Pane Sync"), PIXBUF_INLINE_SPLIT_PANE_SYNC},
773 {"Grayscale", N_("Grayscale"), PIXBUF_INLINE_ICON_GRAYSCALE},
774 {"OverUnderExposed", N_("Over Under Exposed"), PIXBUF_INLINE_ICON_EXPOSURE},
775 {"HideTools", N_("Hide file list"), PIXBUF_INLINE_ICON_HIDETOOLS},
776 {"SlideShowPause", N_("Pause slideshow"), GTK_STOCK_MEDIA_PAUSE},
777 {"SlideShowFaster", N_("Slideshow Faster"), GTK_STOCK_FILE},
778 {"SlideShowSlower", N_("Slideshow Slower"), GTK_STOCK_FILE},
779 {"Refresh", N_("Refresh"), GTK_STOCK_REFRESH},
780 {"HelpContents", N_("Help"), GTK_STOCK_HELP},
781 {"ExifWin", N_("Exif window"), PIXBUF_INLINE_ICON_EXIF},
782 {"Thumbnails", N_("Show thumbnails"), PIXBUF_INLINE_ICON_THUMB},
783 {"ShowMarks", N_("Show marks"), PIXBUF_INLINE_ICON_MARKS},
784 {"ImageGuidelines", N_("Show guidelines"), PIXBUF_INLINE_ICON_GUIDELINES},
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);
2314 static void config_tab_windows(GtkWidget *notebook)
2320 GtkWidget *ct_button;
2323 vbox = scrolled_notebook_page(notebook, _("Windows"));
2325 group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
2327 ct_button = pref_checkbox_new_int(group, _("Remember window positions"),
2328 options->save_window_positions, &c_options->save_window_positions);
2330 button = pref_checkbox_new_int(group, _("Use saved window positions also for new windows"),
2331 options->use_saved_window_positions_for_new_windows, &c_options->use_saved_window_positions_for_new_windows);
2332 pref_checkbox_link_sensitivity(ct_button, button);
2334 button = pref_checkbox_new_int(group, _("Remember window workspace"),
2335 options->save_window_workspace, &c_options->save_window_workspace);
2336 pref_checkbox_link_sensitivity(ct_button, button);
2338 pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
2339 options->tools_restore_state, &c_options->tools_restore_state);
2341 pref_checkbox_new_int(group, _("Remember dialog window positions"),
2342 options->save_dialog_window_positions, &c_options->save_dialog_window_positions);
2344 pref_checkbox_new_int(group, _("Show window IDs"),
2345 options->show_window_ids, &c_options->show_window_ids);
2347 group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
2349 pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
2350 options->image.fit_window_to_image, &c_options->image.fit_window_to_image);
2352 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2353 ct_button = pref_checkbox_new_int(hbox, _("Limit size when auto-sizing window (%):"),
2354 options->image.limit_window_size, &c_options->image.limit_window_size);
2355 spin = pref_spin_new_int(hbox, NULL, NULL,
2357 options->image.max_window_size, &c_options->image.max_window_size);
2358 pref_checkbox_link_sensitivity(ct_button, spin);
2360 group = pref_group_new(vbox, FALSE, _("Full screen"), GTK_ORIENTATION_VERTICAL);
2362 c_options->fullscreen.screen = options->fullscreen.screen;
2363 c_options->fullscreen.above = options->fullscreen.above;
2364 hbox = fullscreen_prefs_selection_new(_("Location:"), &c_options->fullscreen.screen, &c_options->fullscreen.above);
2365 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2366 gtk_widget_show(hbox);
2368 pref_checkbox_new_int(group, _("Smooth image flip"),
2369 options->fullscreen.clean_flip, &c_options->fullscreen.clean_flip);
2370 pref_checkbox_new_int(group, _("Disable screen saver"),
2371 options->fullscreen.disable_saver, &c_options->fullscreen.disable_saver);
2374 #define PRE_FORMATTED_COLUMNS 5
2375 static void config_tab_osd(GtkWidget *notebook)
2381 GtkWidget *image_overlay_template_view;
2382 GtkWidget *scrolled;
2383 GtkWidget *scrolled_pre_formatted;
2384 GtkTextBuffer *buffer;
2386 GtkWidget *subgroup;
2388 vbox = scrolled_notebook_page(notebook, _("OSD"));
2390 image_overlay_template_view = gtk_text_view_new();
2392 group = pref_group_new(vbox, FALSE, _("Overlay Screen Display"), GTK_ORIENTATION_VERTICAL);
2394 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2396 scrolled_pre_formatted = osd_new(PRE_FORMATTED_COLUMNS, image_overlay_template_view);
2397 gtk_widget_set_size_request(scrolled_pre_formatted, 200, 150);
2398 gtk_box_pack_start(GTK_BOX(subgroup), scrolled_pre_formatted, FALSE, FALSE, 0);
2399 gtk_widget_show(scrolled_pre_formatted);
2400 gtk_widget_show(subgroup);
2402 pref_line(group, PREF_PAD_GAP);
2404 pref_label_new(group, _("Image overlay template"));
2406 scrolled = gtk_scrolled_window_new(NULL, NULL);
2407 gtk_widget_set_size_request(scrolled, 200, 150);
2408 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2409 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
2410 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2411 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 5);
2412 gtk_widget_show(scrolled);
2414 gtk_widget_set_tooltip_markup(image_overlay_template_view,
2415 _("Extensive formatting options are shown in the Help file"));
2417 gtk_container_add(GTK_CONTAINER(scrolled), image_overlay_template_view);
2418 gtk_widget_show(image_overlay_template_view);
2420 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2422 #if GTK_CHECK_VERSION(3,4,0)
2423 button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
2424 G_CALLBACK(image_overlay_set_font_cb), notebook);
2426 button = gtk_font_button_new();
2427 gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Image Overlay Font");
2428 gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->image_overlay.font);
2429 g_signal_connect(G_OBJECT(button), "font-set",
2430 G_CALLBACK(image_overlay_set_font_cb),NULL);
2432 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2433 gtk_widget_show(button);
2435 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Text"), FALSE,
2436 G_CALLBACK(image_overlay_set_text_colour_cb), NULL);
2437 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2438 gtk_widget_show(button);
2440 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Background"), FALSE,
2441 G_CALLBACK(image_overlay_set_background_colour_cb), NULL);
2442 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2443 gtk_widget_show(button);
2444 image_overlay_set_text_colours();
2446 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2447 G_CALLBACK(image_overlay_default_template_cb), image_overlay_template_view);
2448 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2449 gtk_widget_show(button);
2451 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
2452 G_CALLBACK(image_overlay_help_cb), NULL);
2453 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2454 gtk_widget_show(button);
2456 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_overlay_template_view));
2457 if (options->image_overlay.template_string) gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
2458 g_signal_connect(G_OBJECT(buffer), "changed",
2459 G_CALLBACK(image_overlay_template_view_changed_cb), image_overlay_template_view);
2461 pref_line(group, PREF_PAD_GAP);
2463 group = pref_group_new(vbox, FALSE, _("Exif, XMP or IPTC tags"), GTK_ORIENTATION_VERTICAL);
2464 hbox = gtk_hbox_new(FALSE, 0);
2465 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2466 gtk_widget_show(hbox);
2467 label = gtk_label_new(_("%Exif.Image.Orientation%"));
2468 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2469 gtk_widget_show(label);
2470 pref_spacer(group,TRUE);
2472 group = pref_group_new(vbox, FALSE, _("Field separators"), GTK_ORIENTATION_VERTICAL);
2473 hbox = gtk_hbox_new(FALSE, 0);
2474 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2475 gtk_widget_show(hbox);
2476 label = gtk_label_new(_("Separator shown only if both fields are non-null:\n%formatted.ShutterSpeed%|%formatted.ISOSpeedRating%"));
2477 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2478 gtk_widget_show(label);
2479 pref_spacer(group,TRUE);
2481 group = pref_group_new(vbox, FALSE, _("Field maximum length"), GTK_ORIENTATION_VERTICAL);
2482 hbox = gtk_hbox_new(FALSE, 0);
2483 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2484 gtk_widget_show(hbox);
2485 label = gtk_label_new(_("%path:39%"));
2486 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2487 gtk_widget_show(label);
2488 pref_spacer(group,TRUE);
2490 group = pref_group_new(vbox, FALSE, _("Pre- and post- text"), GTK_ORIENTATION_VERTICAL);
2491 hbox = gtk_hbox_new(FALSE, 0);
2492 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2493 gtk_widget_show(hbox);
2494 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%"));
2495 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2496 gtk_widget_show(label);
2497 pref_spacer(group,TRUE);
2499 group = pref_group_new(vbox, FALSE, _("Pango markup"), GTK_ORIENTATION_VERTICAL);
2500 hbox = gtk_hbox_new(FALSE, 0);
2501 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2502 gtk_widget_show(hbox);
2503 label = gtk_label_new(_("<b>bold</b>\n<u>underline</u>\n<i>italic</i>\n<s>strikethrough</s>"));
2504 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2505 gtk_widget_show(label);
2508 static GtkTreeModel *create_class_model(void)
2510 GtkListStore *model;
2514 /* create list store */
2515 model = gtk_list_store_new(1, G_TYPE_STRING);
2516 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
2518 gtk_list_store_append(model, &iter);
2519 gtk_list_store_set(model, &iter, 0, _(format_class_list[i]), -1);
2521 return GTK_TREE_MODEL (model);
2526 static void config_tab_files(GtkWidget *notebook)
2533 GtkWidget *ct_button;
2534 GtkWidget *scrolled;
2535 GtkWidget *filter_view;
2536 GtkCellRenderer *renderer;
2537 GtkTreeSelection *selection;
2538 GtkTreeViewColumn *column;
2540 vbox = scrolled_notebook_page(notebook, _("Files"));
2542 group = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2544 pref_checkbox_new_int(group, _("Show hidden files or folders"),
2545 options->file_filter.show_hidden_files, &c_options->file_filter.show_hidden_files);
2546 pref_checkbox_new_int(group, _("Show parent folder (..)"),
2547 options->file_filter.show_parent_directory, &c_options->file_filter.show_parent_directory);
2548 pref_checkbox_new_int(group, _("Case sensitive sort"),
2549 options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
2550 pref_checkbox_new_int(group, _("Natural sort order"),
2551 options->file_sort.natural, &c_options->file_sort.natural);
2552 pref_checkbox_new_int(group, _("Disable file extension checks"),
2553 options->file_filter.disable_file_extension_checks, &c_options->file_filter.disable_file_extension_checks);
2555 ct_button = pref_checkbox_new_int(group, _("Disable File Filtering"),
2556 options->file_filter.disable, &c_options->file_filter.disable);
2559 group = pref_group_new(vbox, FALSE, _("Grouping sidecar extensions"), GTK_ORIENTATION_VERTICAL);
2561 sidecar_ext_entry = gtk_entry_new();
2562 gtk_entry_set_text(GTK_ENTRY(sidecar_ext_entry), options->sidecar.ext);
2563 gtk_box_pack_start(GTK_BOX(group), sidecar_ext_entry, FALSE, FALSE, 0);
2564 gtk_widget_show(sidecar_ext_entry);
2566 group = pref_group_new(vbox, TRUE, _("File types"), GTK_ORIENTATION_VERTICAL);
2568 frame = pref_group_parent(group);
2569 g_signal_connect(G_OBJECT(ct_button), "toggled",
2570 G_CALLBACK(filter_disable_cb), frame);
2571 gtk_widget_set_sensitive(frame, !options->file_filter.disable);
2573 scrolled = gtk_scrolled_window_new(NULL, NULL);
2574 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2575 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2576 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2577 gtk_widget_show(scrolled);
2579 filter_store = gtk_list_store_new(1, G_TYPE_POINTER);
2580 filter_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(filter_store));
2581 g_object_unref(filter_store);
2582 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
2583 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
2585 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), FALSE);
2587 column = gtk_tree_view_column_new();
2588 gtk_tree_view_column_set_title(column, _("Filter"));
2589 gtk_tree_view_column_set_resizable(column, TRUE);
2591 renderer = gtk_cell_renderer_toggle_new();
2592 g_signal_connect(G_OBJECT(renderer), "toggled",
2593 G_CALLBACK(filter_store_enable_cb), filter_store);
2594 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2595 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2596 GINT_TO_POINTER(FE_ENABLE), NULL);
2598 renderer = gtk_cell_renderer_text_new();
2599 g_signal_connect(G_OBJECT(renderer), "edited",
2600 G_CALLBACK(filter_store_ext_edit_cb), filter_store);
2601 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2602 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2603 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2604 GINT_TO_POINTER(FE_EXTENSION), NULL);
2605 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2607 column = gtk_tree_view_column_new();
2608 gtk_tree_view_column_set_title(column, _("Description"));
2609 gtk_tree_view_column_set_resizable(column, TRUE);
2610 gtk_tree_view_column_set_fixed_width(column, 200);
2611 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
2613 renderer = gtk_cell_renderer_text_new();
2614 g_signal_connect(G_OBJECT(renderer), "edited",
2615 G_CALLBACK(filter_store_desc_edit_cb), filter_store);
2616 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2617 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2618 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2619 GINT_TO_POINTER(FE_DESCRIPTION), NULL);
2620 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2622 column = gtk_tree_view_column_new();
2623 gtk_tree_view_column_set_title(column, _("Class"));
2624 gtk_tree_view_column_set_resizable(column, TRUE);
2625 renderer = gtk_cell_renderer_combo_new();
2626 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE,
2627 "model", create_class_model(),
2632 g_signal_connect(G_OBJECT(renderer), "edited",
2633 G_CALLBACK(filter_store_class_edit_cb), filter_store);
2634 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2635 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2636 GINT_TO_POINTER(FE_CLASS), NULL);
2637 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2639 column = gtk_tree_view_column_new();
2640 gtk_tree_view_column_set_title(column, _("Writable"));
2641 gtk_tree_view_column_set_resizable(column, FALSE);
2642 renderer = gtk_cell_renderer_toggle_new();
2643 g_signal_connect(G_OBJECT(renderer), "toggled",
2644 G_CALLBACK(filter_store_writable_cb), filter_store);
2645 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2646 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2647 GINT_TO_POINTER(FE_WRITABLE), NULL);
2648 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2650 column = gtk_tree_view_column_new();
2651 gtk_tree_view_column_set_title(column, _("Sidecar is allowed"));
2652 gtk_tree_view_column_set_resizable(column, FALSE);
2653 renderer = gtk_cell_renderer_toggle_new();
2654 g_signal_connect(G_OBJECT(renderer), "toggled",
2655 G_CALLBACK(filter_store_sidecar_cb), filter_store);
2656 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2657 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2658 GINT_TO_POINTER(FE_ALLOW_SIDECAR), NULL);
2659 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2662 filter_store_populate();
2663 gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
2664 gtk_widget_show(filter_view);
2666 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2668 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2669 G_CALLBACK(filter_default_cb), filter_view);
2670 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2671 gtk_widget_show(button);
2673 button = pref_button_new(NULL, GTK_STOCK_REMOVE, NULL, FALSE,
2674 G_CALLBACK(filter_remove_cb), filter_view);
2675 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2676 gtk_widget_show(button);
2678 button = pref_button_new(NULL, GTK_STOCK_ADD, NULL, FALSE,
2679 G_CALLBACK(filter_add_cb), filter_view);
2680 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2681 gtk_widget_show(button);
2685 static void config_tab_metadata(GtkWidget *notebook)
2690 GtkWidget *ct_button;
2694 vbox = scrolled_notebook_page(notebook, _("Metadata"));
2697 group = pref_group_new(vbox, FALSE, _("Metadata writing process"), GTK_ORIENTATION_VERTICAL);
2699 label = pref_label_new(group, _("Warning: Geeqie is built without Exiv2. Some options are disabled."));
2701 label = pref_label_new(group, _("Metadata are written in the following order. The process ends after first success."));
2702 #if GTK_CHECK_VERSION(3,16,0)
2703 gtk_label_set_xalign(GTK_LABEL(label), 0.0);
2704 gtk_label_set_yalign(GTK_LABEL(label), 0.5);
2706 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2709 ct_button = pref_checkbox_new_int(group, _("1) Save metadata in image files, or sidecar files, according to the XMP standard"),
2710 options->metadata.save_in_image_file, &c_options->metadata.save_in_image_file);
2712 gtk_widget_set_sensitive(ct_button, FALSE);
2715 pref_checkbox_new_int(group, _("2) Save metadata in '.metadata' folder, local to image folder (non-standard)"),
2716 options->metadata.enable_metadata_dirs, &c_options->metadata.enable_metadata_dirs);
2718 text = g_strdup_printf(_("3) Save metadata in Geeqie private directory '%s'"), get_metadata_cache_dir());
2719 label = pref_label_new(group, text);
2720 #if GTK_CHECK_VERSION(3,16,0)
2721 gtk_label_set_xalign(GTK_LABEL(label), 0.0);
2722 gtk_label_set_yalign(GTK_LABEL(label), 0.5);
2724 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2726 gtk_misc_set_padding(GTK_MISC(label), 22, 0);
2729 group = pref_group_new(vbox, FALSE, _("Step 1: Write to image files"), GTK_ORIENTATION_VERTICAL);
2731 gtk_widget_set_sensitive(group, FALSE);
2734 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2735 pref_checkbox_link_sensitivity(ct_button, hbox);
2737 pref_checkbox_new_int(hbox, _("Store metadata also in legacy IPTC tags (converted according to IPTC4XMP standard)"),
2738 options->metadata.save_legacy_IPTC, &c_options->metadata.save_legacy_IPTC);
2740 pref_checkbox_new_int(hbox, _("Warn if the image files are unwritable"),
2741 options->metadata.warn_on_write_problems, &c_options->metadata.warn_on_write_problems);
2743 pref_checkbox_new_int(hbox, _("Ask before writing to image files"),
2744 options->metadata.confirm_write, &c_options->metadata.confirm_write);
2746 pref_checkbox_new_int(hbox, _("Create sidecar files named image.ext.xmp (as opposed to image.xmp)"),
2747 options->metadata.sidecar_extended_name, &c_options->metadata.sidecar_extended_name);
2749 group = pref_group_new(vbox, FALSE, _("Step 2 and 3: write to Geeqie private files"), GTK_ORIENTATION_VERTICAL);
2751 gtk_widget_set_sensitive(group, FALSE);
2754 pref_checkbox_new_int(group, _("Use GQview legacy metadata format (supports only keywords and comments) instead of XMP"),
2755 options->metadata.save_legacy_format, &c_options->metadata.save_legacy_format);
2758 group = pref_group_new(vbox, FALSE, _("Miscellaneous"), GTK_ORIENTATION_VERTICAL);
2759 pref_checkbox_new_int(group, _("Write the same description tags (keywords, comment, etc.) to all grouped sidecars"),
2760 options->metadata.sync_grouped_files, &c_options->metadata.sync_grouped_files);
2762 pref_checkbox_new_int(group, _("Allow keywords to differ only in case"),
2763 options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
2765 ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"),
2766 options->metadata.write_orientation, &c_options->metadata.write_orientation);
2768 gtk_widget_set_sensitive(ct_button, FALSE);
2771 group = pref_group_new(vbox, FALSE, _("Auto-save options"), GTK_ORIENTATION_VERTICAL);
2773 ct_button = pref_checkbox_new_int(group, _("Write metadata after timeout"),
2774 options->metadata.confirm_after_timeout, &c_options->metadata.confirm_after_timeout);
2776 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2777 pref_checkbox_link_sensitivity(ct_button, hbox);
2779 pref_spin_new_int(hbox, _("Timeout (seconds):"), NULL, 0, 900, 1,
2780 options->metadata.confirm_timeout, &c_options->metadata.confirm_timeout);
2782 pref_checkbox_new_int(group, _("Write metadata on image change"),
2783 options->metadata.confirm_on_image_change, &c_options->metadata.confirm_on_image_change);
2785 pref_checkbox_new_int(group, _("Write metadata on directory change"),
2786 options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
2788 group = pref_group_new(vbox, FALSE, _("Pre-load metadata"), GTK_ORIENTATION_VERTICAL);
2790 ct_button = pref_checkbox_new_int(group, _("Read metadata in background"),
2791 options->read_metadata_in_idle, &c_options->read_metadata_in_idle);
2792 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");
2797 typedef struct _KeywordFindData KeywordFindData;
2798 struct _KeywordFindData
2805 GtkWidget *button_close;
2806 GtkWidget *button_stop;
2807 GtkWidget *button_start;
2808 GtkWidget *progress;
2816 guint idle_id; /* event source id */
2819 #define KEYWORD_DIALOG_WIDTH 400
2821 static void keywords_find_folder(KeywordFindData *kfd, FileData *dir_fd)
2823 GList *list_d = NULL;
2824 GList *list_f = NULL;
2828 filelist_read(dir_fd, &list_f, &list_d);
2832 filelist_read(dir_fd, &list_f, NULL);
2835 list_f = filelist_filter(list_f, FALSE);
2836 list_d = filelist_filter(list_d, TRUE);
2838 kfd->list = g_list_concat(list_f, kfd->list);
2839 kfd->list_dir = g_list_concat(list_d, kfd->list_dir);
2842 static void keywords_find_reset(KeywordFindData *kfd)
2844 filelist_free(kfd->list);
2847 filelist_free(kfd->list_dir);
2848 kfd->list_dir = NULL;
2851 static void keywords_find_close_cb(GenericDialog *fd, gpointer data)
2853 KeywordFindData *kfd = data;
2855 if (!gtk_widget_get_sensitive(kfd->button_close)) return;
2857 keywords_find_reset(kfd);
2858 generic_dialog_close(kfd->gd);
2862 static void keywords_find_finish(KeywordFindData *kfd)
2864 keywords_find_reset(kfd);
2866 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("done"));
2867 spinner_set_interval(kfd->spinner, -1);
2869 gtk_widget_set_sensitive(kfd->group, TRUE);
2870 gtk_widget_set_sensitive(kfd->button_start, TRUE);
2871 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2872 gtk_widget_set_sensitive(kfd->button_close, TRUE);
2875 static void keywords_find_stop_cb(GenericDialog *fd, gpointer data)
2877 KeywordFindData *kfd = data;
2879 g_idle_remove_by_data(kfd);
2881 keywords_find_finish(kfd);
2884 static gboolean keywords_find_file(gpointer data)
2886 KeywordFindData *kfd = data;
2888 GtkTextBuffer *buffer;
2896 fd = kfd->list->data;
2897 kfd->list = g_list_remove(kfd->list, fd);
2899 keywords = metadata_read_list(fd, KEYWORD_KEY, METADATA_PLAIN);
2900 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2904 gtk_text_buffer_get_end_iter(buffer, &iter);
2905 tmp = g_strconcat(keywords->data, "\n", NULL);
2906 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
2908 keywords = keywords->next;
2911 gtk_entry_set_text(GTK_ENTRY(kfd->progress), fd->path);
2912 file_data_unref(fd);
2913 string_list_free(keywords);
2917 else if (kfd->list_dir)
2921 fd = kfd->list_dir->data;
2922 kfd->list_dir = g_list_remove(kfd->list_dir, fd);
2924 keywords_find_folder(kfd, fd);
2926 file_data_unref(fd);
2931 keywords_find_finish(kfd);
2936 static void keywords_find_start_cb(GenericDialog *fd, gpointer data)
2938 KeywordFindData *kfd = data;
2941 if (kfd->list || !gtk_widget_get_sensitive(kfd->button_start)) return;
2943 path = remove_trailing_slash((gtk_entry_get_text(GTK_ENTRY(kfd->entry))));
2944 parse_out_relatives(path);
2948 warning_dialog(_("Invalid folder"),
2949 _("The specified folder can not be found."),
2950 GTK_STOCK_DIALOG_WARNING, kfd->gd->dialog);
2956 gtk_widget_set_sensitive(kfd->group, FALSE);
2957 gtk_widget_set_sensitive(kfd->button_start, FALSE);
2958 gtk_widget_set_sensitive(kfd->button_stop, TRUE);
2959 gtk_widget_set_sensitive(kfd->button_close, FALSE);
2960 spinner_set_interval(kfd->spinner, SPINNER_SPEED);
2962 dir_fd = file_data_new_dir(path);
2963 keywords_find_folder(kfd, dir_fd);
2964 file_data_unref(dir_fd);
2965 kfd->idle_id = g_idle_add(keywords_find_file, kfd);
2971 static void keywords_find_dialog(GtkWidget *widget, const gchar *path)
2973 KeywordFindData *kfd;
2977 kfd = g_new0(KeywordFindData, 1);
2979 kfd->gd = generic_dialog_new(_("Search for keywords"),
2980 "search_for_keywords",
2983 gtk_window_set_default_size(GTK_WINDOW(kfd->gd->dialog), KEYWORD_DIALOG_WIDTH, -1);
2984 kfd->gd->cancel_cb = keywords_find_close_cb;
2985 kfd->button_close = generic_dialog_add_button(kfd->gd, GTK_STOCK_CLOSE, NULL,
2986 keywords_find_close_cb, FALSE);
2987 kfd->button_start = generic_dialog_add_button(kfd->gd, GTK_STOCK_OK, _("S_tart"),
2988 keywords_find_start_cb, FALSE);
2989 kfd->button_stop = generic_dialog_add_button(kfd->gd, GTK_STOCK_STOP, NULL,
2990 keywords_find_stop_cb, FALSE);
2991 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2993 generic_dialog_add_message(kfd->gd, NULL, _("Search for keywords"), NULL, FALSE);
2995 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0);
2996 pref_spacer(hbox, PREF_PAD_INDENT);
2997 kfd->group = pref_box_new(hbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2999 hbox = pref_box_new(kfd->group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3000 pref_label_new(hbox, _("Folder:"));
3002 label = tab_completion_new(&kfd->entry, path, NULL, NULL, NULL, NULL);
3003 tab_completion_add_select_button(kfd->entry,_("Select folder") , TRUE);
3004 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
3005 gtk_widget_show(label);
3007 pref_checkbox_new_int(kfd->group, _("Include subfolders"), FALSE, &kfd->recurse);
3009 pref_line(kfd->gd->vbox, PREF_PAD_SPACE);
3010 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3012 kfd->progress = gtk_entry_new();
3013 gtk_widget_set_can_focus(kfd->progress, FALSE);
3014 gtk_editable_set_editable(GTK_EDITABLE(kfd->progress), FALSE);
3015 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("click start to begin"));
3016 gtk_box_pack_start(GTK_BOX(hbox), kfd->progress, TRUE, TRUE, 0);
3017 gtk_widget_show(kfd->progress);
3019 kfd->spinner = spinner_new(NULL, -1);
3020 gtk_box_pack_start(GTK_BOX(hbox), kfd->spinner, FALSE, FALSE, 0);
3021 gtk_widget_show(kfd->spinner);
3025 gtk_widget_show(kfd->gd->dialog);
3028 static void keywords_find_cb(GtkWidget *widget, gpointer data)
3030 const gchar *path = layout_get_path(NULL);
3032 if (!path || !*path) path = homedir();
3033 keywords_find_dialog(widget, path);
3036 static void config_tab_keywords_save()
3038 GtkTextIter start, end;
3039 GtkTextBuffer *buffer;
3040 GList *kw_list = NULL;
3046 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3047 gtk_text_buffer_get_bounds(buffer, &start, &end);
3049 buffer_text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
3051 kw_split = strtok(buffer_text, "\n");
3052 while (kw_split != NULL)
3058 if (g_strcmp0(work->data, kw_split) == 0)
3067 kw_list = g_list_append(kw_list, g_strdup(kw_split));
3069 kw_split = strtok(NULL, "\n");
3072 keyword_list_set(kw_list);
3074 string_list_free(kw_list);
3075 g_free(buffer_text);
3078 static void config_tab_keywords(GtkWidget *notebook)
3084 GtkWidget *scrolled;
3086 GtkTextBuffer *buffer;
3089 vbox = scrolled_notebook_page(notebook, _("Keywords"));
3091 group = pref_group_new(vbox, TRUE, _("Edit keywords autocompletion list"), GTK_ORIENTATION_VERTICAL);
3093 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3095 button = pref_button_new(hbox, GTK_STOCK_EXECUTE, _("Search"), FALSE,
3096 G_CALLBACK(keywords_find_cb), keyword_text);
3097 gtk_widget_set_tooltip_text(button, "Search for existing keywords");
3100 keyword_text = gtk_text_view_new();
3101 gtk_widget_set_size_request(keyword_text, 20, 20);
3102 scrolled = gtk_scrolled_window_new(NULL, NULL);
3103 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3104 gtk_widget_show(scrolled);
3106 gtk_container_add(GTK_CONTAINER(scrolled), keyword_text);
3107 gtk_widget_show(keyword_text);
3109 gtk_text_view_set_editable(GTK_TEXT_VIEW(keyword_text), TRUE);
3111 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3112 gtk_text_buffer_create_tag(buffer, "monospace",
3113 "family", "monospace", NULL);
3115 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(keyword_text), GTK_WRAP_WORD);
3116 gtk_text_buffer_get_start_iter(buffer, &iter);
3117 gtk_text_buffer_create_mark(buffer, "end", &iter, FALSE);
3120 path = g_build_filename(get_rc_dir(), "keywords", NULL);
3122 GList *kwl = keyword_list_get();
3123 kwl = g_list_first(kwl);
3126 gtk_text_buffer_get_end_iter (buffer, &iter);
3127 tmp = g_strconcat(kwl->data, "\n", NULL);
3128 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
3133 gtk_text_buffer_set_modified(buffer, FALSE);
3140 static void intent_menu_cb(GtkWidget *combo, gpointer data)
3142 gint *option = data;
3144 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
3148 *option = INTENT_PERCEPTUAL;
3151 *option = INTENT_RELATIVE_COLORIMETRIC;
3154 *option = INTENT_SATURATION;
3157 *option = INTENT_ABSOLUTE_COLORIMETRIC;
3162 static void add_intent_menu(GtkWidget *table, gint column, gint row, const gchar *text,
3163 gint option, gint *option_c)
3170 pref_table_label(table, column, row, text, 0.0);
3172 combo = gtk_combo_box_text_new();
3174 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Perceptual"));
3175 if (option == INTENT_PERCEPTUAL) current = 0;
3176 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Relative Colorimetric"));
3177 if (option == INTENT_RELATIVE_COLORIMETRIC) current = 1;
3178 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Saturation"));
3179 if (option == INTENT_SATURATION) current = 2;
3180 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Absolute Colorimetric"));
3181 if (option == INTENT_ABSOLUTE_COLORIMETRIC) current = 3;
3183 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
3185 gtk_widget_set_tooltip_text(combo,"Refer to the lcms documentation for the defaults used when the selected Intent is not available");
3187 g_signal_connect(G_OBJECT(combo), "changed",
3188 G_CALLBACK(intent_menu_cb), option_c);
3190 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
3191 gtk_widget_show(combo);
3195 static void config_tab_color(GtkWidget *notebook)
3204 vbox = scrolled_notebook_page(notebook, _("Color management"));
3206 group = pref_group_new(vbox, FALSE, _("Input profiles"), GTK_ORIENTATION_VERTICAL);
3208 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3211 table = pref_table_new(group, 3, COLOR_PROFILE_INPUTS + 1, FALSE, FALSE);
3212 gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
3214 label = pref_table_label(table, 0, 0, _("Type"), 0.0);
3215 pref_label_bold(label, TRUE, FALSE);
3217 label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
3218 pref_label_bold(label, TRUE, FALSE);
3220 label = pref_table_label(table, 2, 0, _("File"), 0.0);
3221 pref_label_bold(label, TRUE, FALSE);
3223 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
3228 buf = g_strdup_printf(_("Input %d:"), i + COLOR_PROFILE_FILE);
3229 pref_table_label(table, 0, i + 1, buf, 1.0);
3232 entry = gtk_entry_new();
3233 gtk_entry_set_max_length(GTK_ENTRY(entry), EDITOR_NAME_MAX_LENGTH);
3234 if (options->color_profile.input_name[i])
3236 gtk_entry_set_text(GTK_ENTRY(entry), options->color_profile.input_name[i]);
3238 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, i + 1, i + 2,
3239 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3240 gtk_widget_show(entry);
3241 color_profile_input_name_entry[i] = entry;
3243 tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, ".icc", "ICC Files", NULL);
3244 tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
3245 gtk_widget_set_size_request(entry, 160, -1);
3246 gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
3247 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3248 gtk_widget_show(tabcomp);
3249 color_profile_input_file_entry[i] = entry;
3252 group = pref_group_new(vbox, FALSE, _("Screen profile"), GTK_ORIENTATION_VERTICAL);
3254 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3256 pref_checkbox_new_int(group, _("Use system screen profile if available"),
3257 options->color_profile.use_x11_screen_profile, &c_options->color_profile.use_x11_screen_profile);
3259 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3261 pref_table_label(table, 0, 0, _("Screen:"), 1.0);
3262 tabcomp = tab_completion_new(&color_profile_screen_file_entry,
3263 options->color_profile.screen_file, NULL, ".icc", "ICC Files", NULL);
3264 tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
3265 gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
3267 add_intent_menu(table, 0, 1, _("Render Intent:"), options->color_profile.render_intent, &c_options->color_profile.render_intent);
3269 gtk_table_attach(GTK_TABLE(table), tabcomp, 1, 2,
3271 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3273 gtk_widget_show(tabcomp);
3276 /* advanced entry tab */
3277 static void use_geeqie_trash_cb(GtkWidget *widget, gpointer data)
3279 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3281 c_options->file_ops.use_system_trash = FALSE;
3282 c_options->file_ops.no_trash = FALSE;
3286 static void use_system_trash_cb(GtkWidget *widget, gpointer data)
3288 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3290 c_options->file_ops.use_system_trash = TRUE;
3291 c_options->file_ops.no_trash = FALSE;
3295 static void use_no_cache_cb(GtkWidget *widget, gpointer data)
3297 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3299 c_options->file_ops.no_trash = TRUE;
3303 static void config_tab_behavior(GtkWidget *notebook)
3310 GtkWidget *ct_button;
3314 GtkWidget *with_rename;
3315 GtkWidget *collections_on_top;
3316 GtkWidget *hide_window_in_fullscreen;
3317 GtkWidget *checkbox;
3320 vbox = scrolled_notebook_page(notebook, _("Behavior"));
3322 group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
3324 pref_checkbox_new_int(group, _("Confirm permanent file delete"),
3325 options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
3326 pref_checkbox_new_int(group, _("Confirm move file to Trash"),
3327 options->file_ops.confirm_move_to_trash, &c_options->file_ops.confirm_move_to_trash);
3328 pref_checkbox_new_int(group, _("Enable Delete key"),
3329 options->file_ops.enable_delete_key, &c_options->file_ops.enable_delete_key);
3331 ct_button = pref_radiobutton_new(group, NULL, _("Use Geeqie trash location"),
3332 !options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_geeqie_trash_cb),NULL);
3334 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3335 pref_checkbox_link_sensitivity(ct_button, hbox);
3337 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
3338 pref_label_new(hbox, _("Folder:"));
3340 tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL, NULL, NULL);
3341 tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
3342 gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
3343 gtk_widget_show(tabcomp);
3345 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3346 pref_checkbox_link_sensitivity(ct_button, hbox);
3348 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
3349 spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MiB"),
3350 0, 2048, 1, options->file_ops.safe_delete_folder_maxsize, &c_options->file_ops.safe_delete_folder_maxsize);
3351 gtk_widget_set_tooltip_markup(spin, _("Set to 0 for unlimited size"));
3352 button = pref_button_new(NULL, NULL, _("View"), FALSE,
3353 G_CALLBACK(safe_delete_view_cb), NULL);
3354 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3355 gtk_widget_show(button);
3357 button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
3358 G_CALLBACK(safe_delete_clear_cb), NULL);
3359 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3360 pref_radiobutton_new(group, ct_button, _("Use system Trash bin"),
3361 options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_system_trash_cb), NULL);
3363 pref_radiobutton_new(group, ct_button, _("Use no trash at all"),
3364 options->file_ops.no_trash, G_CALLBACK(use_no_cache_cb), NULL);
3366 gtk_widget_show(button);
3368 pref_spacer(group, PREF_PAD_GROUP);
3371 group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
3373 pref_checkbox_new_int(group, _("Descend folders in tree view"),
3374 options->tree_descend_subdirs, &c_options->tree_descend_subdirs);
3376 pref_checkbox_new_int(group, _("In place renaming"),
3377 options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
3379 pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
3380 options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
3382 tmp = pref_checkbox_new_int(group, _("Circular selection lists"),
3383 options->circular_selection_lists, &c_options->circular_selection_lists);
3384 gtk_widget_set_tooltip_text(tmp, _("Traverse selection lists in a circular manner"));
3386 marks = pref_checkbox_new_int(group, _("Save marks on exit"),
3387 options->marks_save, &c_options->marks_save);
3388 gtk_widget_set_tooltip_text(marks,"Note that marks linked to a keyword will be saved irrespective of this setting");
3390 with_rename = pref_checkbox_new_int(group, _("Use \"With Rename\" as default for Copy/Move dialogs"),
3391 options->with_rename, &c_options->with_rename);
3392 gtk_widget_set_tooltip_text(with_rename,"Change the default button for Copy/Move dialogs");
3394 collections_on_top = pref_checkbox_new_int(group, _("Open collections on top"),
3395 options->collections_on_top, &c_options->collections_on_top);
3396 gtk_widget_set_tooltip_text(collections_on_top,"Open collections window on top");
3398 hide_window_in_fullscreen = pref_checkbox_new_int(group, _("Hide window in fullscreen"),
3399 options->hide_window_in_fullscreen, &c_options->hide_window_in_fullscreen);
3400 gtk_widget_set_tooltip_text(hide_window_in_fullscreen,"When alt-tabbing, prevent Geeqie window showing twice");
3402 pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
3403 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
3405 pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
3406 16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
3408 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3409 add_dnd_default_action_selection_menu(table, 0, 0, _("Drag`n drop default action:"), options->dnd_default_action, &c_options->dnd_default_action);
3411 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3412 add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
3414 pref_spacer(group, PREF_PAD_GROUP);
3416 group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
3418 pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
3419 options->progressive_key_scrolling, &c_options->progressive_key_scrolling);
3420 pref_spin_new_int(group, _("Keyboard scrolling step multiplier:"), NULL,
3421 1, 32, 1, options->keyboard_scroll_step, (int *)&c_options->keyboard_scroll_step);
3422 pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
3423 options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
3424 pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
3425 options->image_lm_click_nav, &c_options->image_lm_click_nav);
3426 pref_checkbox_new_int(group, _("Play video by left click on image"),
3427 options->image_l_click_video, &c_options->image_l_click_video);
3428 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3429 add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
3431 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3432 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3433 add_mouse_selection_menu(table, 0, 0, _("Mouse button Back:"), options->mouse_button_8, &c_options->mouse_button_8);
3434 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3435 add_mouse_selection_menu(table, 0, 0, _("Mouse button Forward:"), options->mouse_button_9, &c_options->mouse_button_9);
3437 pref_spacer(group, PREF_PAD_GROUP);
3439 group = pref_group_new(vbox, FALSE, _("GPU"), GTK_ORIENTATION_VERTICAL);
3441 checkbox = pref_checkbox_new_int(group, _("Override disable GPU"),
3442 options->override_disable_gpu, &c_options->override_disable_gpu);
3443 gtk_widget_set_tooltip_text(checkbox, "Contact the developers for usage");
3446 pref_spacer(group, PREF_PAD_GROUP);
3448 group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
3450 pref_spin_new_int(group, _("Debug level:"), NULL,
3451 DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
3453 pref_checkbox_new_int(group, _("Timer data"),
3454 options->log_window.timer_data, &c_options->log_window.timer_data);
3456 pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
3457 1, 99999, 1, options->log_window_lines, &options->log_window_lines);
3461 /* accelerators tab */
3462 static void config_tab_accelerators(GtkWidget *notebook)
3468 GtkWidget *scrolled;
3469 GtkWidget *accel_view;
3470 GtkCellRenderer *renderer;
3471 GtkTreeSelection *selection;
3472 GtkTreeViewColumn *column;
3474 vbox = scrolled_notebook_page(notebook, _("Keyboard"));
3476 group = pref_group_new(vbox, TRUE, _("Accelerators"), GTK_ORIENTATION_VERTICAL);
3478 scrolled = gtk_scrolled_window_new(NULL, NULL);
3479 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
3480 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
3481 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3482 gtk_widget_show(scrolled);
3484 accel_store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
3486 accel_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(accel_store));
3487 g_object_unref(accel_store);
3488 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(accel_view));
3489 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
3491 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(accel_view), FALSE);
3493 renderer = gtk_cell_renderer_text_new();
3495 column = gtk_tree_view_column_new_with_attributes(_("Action"),
3500 gtk_tree_view_column_set_sort_column_id(column, AE_ACTION);
3501 gtk_tree_view_column_set_resizable(column, TRUE);
3502 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3505 renderer = gtk_cell_renderer_accel_new();
3506 g_signal_connect(G_OBJECT(renderer), "accel-cleared",
3507 G_CALLBACK(accel_store_cleared_cb), accel_store);
3508 g_signal_connect(G_OBJECT(renderer), "accel-edited",
3509 G_CALLBACK(accel_store_edited_cb), accel_store);
3512 g_object_set (renderer,
3514 "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
3517 column = gtk_tree_view_column_new_with_attributes(_("KEY"),
3522 gtk_tree_view_column_set_sort_column_id(column, AE_KEY);
3523 gtk_tree_view_column_set_resizable(column, TRUE);
3524 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3526 renderer = gtk_cell_renderer_text_new();
3528 column = gtk_tree_view_column_new_with_attributes(_("Tooltip"),
3533 gtk_tree_view_column_set_sort_column_id(column, AE_TOOLTIP);
3534 gtk_tree_view_column_set_resizable(column, TRUE);
3535 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3537 renderer = gtk_cell_renderer_text_new();
3539 column = gtk_tree_view_column_new_with_attributes("Accel",
3544 gtk_tree_view_column_set_sort_column_id(column, AE_ACCEL);
3545 gtk_tree_view_column_set_resizable(column, TRUE);
3546 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3548 accel_store_populate();
3549 gtk_container_add(GTK_CONTAINER(scrolled), accel_view);
3550 gtk_widget_show(accel_view);
3552 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3554 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
3555 G_CALLBACK(accel_default_cb), accel_view);
3556 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3557 gtk_widget_show(button);
3559 button = pref_button_new(NULL, NULL, _("Reset selected"), FALSE,
3560 G_CALLBACK(accel_reset_cb), accel_view);
3561 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3562 gtk_widget_show(button);
3565 /* toolbar main tab */
3566 static void config_tab_toolbar_main(GtkWidget *notebook)
3569 GtkWidget *toolbardata;
3572 lw = layout_window_list->data;
3574 vbox = scrolled_notebook_page(notebook, _("Toolbar Main"));
3576 toolbardata = toolbar_select_new(lw, TOOLBAR_MAIN);
3577 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3578 gtk_widget_show(vbox);
3581 /* toolbar status tab */
3582 static void config_tab_toolbar_status(GtkWidget *notebook)
3585 GtkWidget *toolbardata;
3588 lw = layout_window_list->data;
3590 vbox = scrolled_notebook_page(notebook, _("Toolbar Status"));
3592 toolbardata = toolbar_select_new(lw, TOOLBAR_STATUS);
3593 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3594 gtk_widget_show(vbox);
3598 static gint extension_sort_cb(gconstpointer a, gconstpointer b)
3600 return g_strcmp0((gchar *)a, (gchar *)b);
3603 static void config_tab_advanced(GtkWidget *notebook)
3607 GSList *formats_list;
3608 GList *extensions_list = NULL;
3611 GdkPixbufFormat *fm;
3613 GString *types_string = g_string_new(NULL);
3615 vbox = scrolled_notebook_page(notebook, _("Advanced"));
3616 group = pref_group_new(vbox, FALSE, _("External preview extraction"), GTK_ORIENTATION_VERTICAL);
3618 pref_checkbox_new_int(group, _("Use external preview extraction - Requires restart"), options->external_preview.enable, &c_options->external_preview.enable);
3620 pref_spacer(group, PREF_PAD_GROUP);
3622 formats_list = gdk_pixbuf_get_formats();
3624 while (formats_list)
3626 fm = formats_list->data;
3627 extensions = gdk_pixbuf_format_get_extensions(fm);
3630 while (extensions[i])
3632 extensions_list = g_list_insert_sorted(extensions_list, g_strdup(extensions[i]), extension_sort_cb);
3636 g_strfreev(extensions);
3637 formats_list = formats_list->next;
3640 while (extensions_list)
3642 if (types_string->len == 0)
3644 types_string = g_string_append(types_string, extensions_list->data);
3648 types_string = g_string_append(types_string, ", ");
3649 types_string = g_string_append(types_string, extensions_list->data);
3652 extensions_list = extensions_list->next;
3655 types_string = g_string_prepend(types_string, _("Usable file types:\n"));
3656 pref_label_new(group, types_string->str);
3657 GtkWidget *types_string_label = gtk_label_new(types_string->str);
3658 gtk_label_set_line_wrap(GTK_LABEL(types_string_label), TRUE);
3660 pref_spacer(group, PREF_PAD_GROUP);
3662 group = pref_group_new(vbox, FALSE, _("File identification tool"), GTK_ORIENTATION_VERTICAL);
3663 external_preview_select_entry = gtk_entry_new();
3664 tabcomp = tab_completion_new(&external_preview_select_entry, options->external_preview.select, NULL, NULL, NULL, NULL);
3665 tab_completion_add_select_button(external_preview_select_entry, _("Select file identification tool"), FALSE);
3666 gtk_box_pack_start(GTK_BOX(group), tabcomp, TRUE, TRUE, 0);
3667 gtk_widget_show(tabcomp);
3669 group = pref_group_new(vbox, FALSE, _("Preview extraction tool"), GTK_ORIENTATION_VERTICAL);
3670 external_preview_extract_entry = gtk_entry_new();
3671 tabcomp = tab_completion_new(&external_preview_extract_entry, options->external_preview.extract, NULL, NULL, NULL, NULL);
3672 tab_completion_add_select_button(external_preview_extract_entry, _("Select preview extraction tool"), FALSE);
3673 gtk_box_pack_start(GTK_BOX(group), tabcomp, TRUE, TRUE, 0);
3674 gtk_widget_show(tabcomp);
3676 gtk_widget_show(vbox);
3678 g_slist_free(formats_list);
3679 string_list_free(extensions_list);
3680 g_string_free(types_string, TRUE);
3684 static void config_tab_stereo(GtkWidget *notebook)
3692 GtkWidget *fs_button;
3693 vbox = scrolled_notebook_page(notebook, _("Stereo"));
3695 group = pref_group_new(vbox, FALSE, _("Windowed stereo mode"), GTK_ORIENTATION_VERTICAL);
3697 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3698 add_stereo_mode_menu(table, 0, 0, _("Windowed stereo mode"), options->stereo.mode, &c_options->stereo.mode, FALSE);
3700 table = pref_table_new(group, 2, 2, TRUE, FALSE);
3701 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3702 pref_checkbox_new_int(box, _("Mirror left image"),
3703 options->stereo.mode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.mirror_left);
3704 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3705 pref_checkbox_new_int(box, _("Flip left image"),
3706 options->stereo.mode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.flip_left);
3707 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3708 pref_checkbox_new_int(box, _("Mirror right image"),
3709 options->stereo.mode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.mirror_right);
3710 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3711 pref_checkbox_new_int(box, _("Flip right image"),
3712 options->stereo.mode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.flip_right);
3713 pref_checkbox_new_int(group, _("Swap left and right images"),
3714 options->stereo.mode & PR_STEREO_SWAP, &c_options->stereo.tmp.swap);
3715 pref_checkbox_new_int(group, _("Disable stereo mode on single image source"),
3716 options->stereo.mode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.temp_disable);
3718 group = pref_group_new(vbox, FALSE, _("Fullscreen stereo mode"), GTK_ORIENTATION_VERTICAL);
3719 fs_button = pref_checkbox_new_int(group, _("Use different settings for fullscreen"),
3720 options->stereo.enable_fsmode, &c_options->stereo.enable_fsmode);
3721 box2 = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
3722 pref_checkbox_link_sensitivity(fs_button, box2);
3723 table = pref_table_new(box2, 2, 1, FALSE, FALSE);
3724 add_stereo_mode_menu(table, 0, 0, _("Fullscreen stereo mode"), options->stereo.fsmode, &c_options->stereo.fsmode, TRUE);
3725 table = pref_table_new(box2, 2, 2, TRUE, FALSE);
3726 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3727 pref_checkbox_new_int(box, _("Mirror left image"),
3728 options->stereo.fsmode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.fs_mirror_left);
3729 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3730 pref_checkbox_new_int(box, _("Flip left image"),
3731 options->stereo.fsmode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.fs_flip_left);
3732 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3733 pref_checkbox_new_int(box, _("Mirror right image"),
3734 options->stereo.fsmode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.fs_mirror_right);
3735 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3736 pref_checkbox_new_int(box, _("Flip right image"),
3737 options->stereo.fsmode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.fs_flip_right);
3738 pref_checkbox_new_int(box2, _("Swap left and right images"),
3739 options->stereo.fsmode & PR_STEREO_SWAP, &c_options->stereo.tmp.fs_swap);
3740 pref_checkbox_new_int(box2, _("Disable stereo mode on single image source"),
3741 options->stereo.fsmode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.fs_temp_disable);
3743 group2 = pref_group_new(box2, FALSE, _("Fixed position"), GTK_ORIENTATION_VERTICAL);
3744 table = pref_table_new(group2, 5, 3, FALSE, FALSE);
3745 pref_table_spin_new_int(table, 0, 0, _("Width"), NULL,
3746 1, 5000, 1, options->stereo.fixed_w, &c_options->stereo.fixed_w);
3747 pref_table_spin_new_int(table, 3, 0, _("Height"), NULL,
3748 1, 5000, 1, options->stereo.fixed_h, &c_options->stereo.fixed_h);
3749 pref_table_spin_new_int(table, 0, 1, _("Left X"), NULL,
3750 0, 5000, 1, options->stereo.fixed_x1, &c_options->stereo.fixed_x1);
3751 pref_table_spin_new_int(table, 3, 1, _("Left Y"), NULL,
3752 0, 5000, 1, options->stereo.fixed_y1, &c_options->stereo.fixed_y1);
3753 pref_table_spin_new_int(table, 0, 2, _("Right X"), NULL,
3754 0, 5000, 1, options->stereo.fixed_x2, &c_options->stereo.fixed_x2);
3755 pref_table_spin_new_int(table, 3, 2, _("Right Y"), NULL,
3756 0, 5000, 1, options->stereo.fixed_y2, &c_options->stereo.fixed_y2);
3760 /* Main preferences window */
3761 static void config_window_create(LayoutWindow *lw)
3763 GtkWidget *win_vbox;
3765 GtkWidget *notebook;
3767 GtkWidget *ct_button;
3769 if (!c_options) c_options = init_options(NULL);
3771 configwindow = window_new(GTK_WINDOW_TOPLEVEL, "preferences", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Preferences"));
3772 DEBUG_NAME(configwindow);
3773 gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
3774 g_signal_connect(G_OBJECT(configwindow), "delete_event",
3775 G_CALLBACK(config_window_delete), NULL);
3776 if (options->save_dialog_window_positions)
3778 gtk_window_resize(GTK_WINDOW(configwindow), lw->options.preferences_window.w, lw->options.preferences_window.h);
3779 gtk_window_move(GTK_WINDOW(configwindow), lw->options.preferences_window.x, lw->options.preferences_window.y);
3783 gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
3785 gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
3786 gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
3788 win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
3789 gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
3790 gtk_widget_show(win_vbox);
3792 notebook = gtk_notebook_new();
3793 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_LEFT);
3794 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE);
3795 gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
3797 config_tab_general(notebook);
3798 config_tab_image(notebook);
3799 config_tab_osd(notebook);
3800 config_tab_windows(notebook);
3801 config_tab_accelerators(notebook);
3802 config_tab_files(notebook);
3803 config_tab_metadata(notebook);
3804 config_tab_keywords(notebook);
3805 config_tab_color(notebook);
3806 config_tab_stereo(notebook);
3807 config_tab_behavior(notebook);
3808 config_tab_toolbar_main(notebook);
3809 config_tab_toolbar_status(notebook);
3810 config_tab_advanced(notebook);
3812 gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), lw->options.preferences_window.page_number);
3814 hbox = gtk_hbutton_box_new();
3815 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
3816 gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
3817 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
3818 gtk_widget_show(hbox);
3820 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
3821 G_CALLBACK(config_window_help_cb), notebook);
3822 gtk_container_add(GTK_CONTAINER(hbox), button);
3823 gtk_widget_set_can_default(button, TRUE);
3824 gtk_widget_show(button);
3826 button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
3827 G_CALLBACK(config_window_ok_cb), notebook);
3828 gtk_container_add(GTK_CONTAINER(hbox), button);
3829 gtk_widget_set_can_default(button, TRUE);
3830 gtk_widget_grab_default(button);
3831 gtk_widget_show(button);
3835 button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
3836 G_CALLBACK(config_window_close_cb), NULL);
3837 gtk_container_add(GTK_CONTAINER(hbox), button);
3838 gtk_widget_set_can_default(button, TRUE);
3839 gtk_widget_show(button);
3841 if (!generic_dialog_get_alternative_button_order(configwindow))
3843 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
3846 gtk_widget_show(notebook);
3848 gtk_widget_show(configwindow);
3852 *-----------------------------------------------------------------------------
3853 * config window show (public)
3854 *-----------------------------------------------------------------------------
3857 void show_config_window(LayoutWindow *lw)
3861 gtk_window_present(GTK_WINDOW(configwindow));
3865 config_window_create(lw);
3874 void show_about_window(LayoutWindow *lw)
3876 GdkPixbuf *pixbuf_logo;
3877 GdkPixbuf *pixbuf_icon;
3878 gchar *authors[1000];
3883 gchar *timezone_path;
3887 #define LINE_LENGTH 1000
3888 gchar line[LINE_LENGTH];
3890 copyright = g_string_new(NULL);
3891 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");
3893 path = path_from_utf8(TIMEZONE_DATABASE);
3894 basename = g_path_get_basename(path);
3895 timezone_path = g_build_filename(get_rc_dir(), basename, NULL);
3896 if (g_file_test(timezone_path, G_FILE_TEST_EXISTS))
3898 cd = ZDOpenDatabase(timezone_path);
3901 copyright = g_string_append(copyright, ZDGetNotice(cd));
3902 ZDCloseDatabase(cd);
3906 g_free(timezone_path);
3910 path = g_build_filename(gq_helpdir, "AUTHORS", NULL);
3911 fp = fopen(path, "r");
3914 while(fgets(line, LINE_LENGTH, fp))
3916 /* get rid of ending \n from fgets */
3917 line[strlen(line) - 1] = '\0';
3918 authors[i_authors] = g_strdup(line);
3921 authors[i_authors] = NULL;
3926 comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
3927 "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
3929 pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
3930 pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
3931 gtk_show_about_dialog(GTK_WINDOW(lw->window),
3932 "title", _("About Geeqie"),
3934 "program-name", GQ_APPNAME,
3936 "logo", pixbuf_logo,
3937 "icon", pixbuf_icon,
3938 "website", GQ_WEBSITE,
3939 "website-label", "Website",
3940 "comments", comment,
3942 "translator-credits", _("translator-credits"),
3943 "wrap-license", TRUE,
3944 "license", copyright->str,
3947 g_string_free(copyright, TRUE);
3950 while(n < i_authors)
3960 static void image_overlay_set_text_colours()
3962 c_options->image_overlay.text_red = options->image_overlay.text_red;
3963 c_options->image_overlay.text_green = options->image_overlay.text_green;
3964 c_options->image_overlay.text_blue = options->image_overlay.text_blue;
3965 c_options->image_overlay.text_alpha = options->image_overlay.text_alpha;
3966 c_options->image_overlay.background_red = options->image_overlay.background_red;
3967 c_options->image_overlay.background_green = options->image_overlay.background_green;
3968 c_options->image_overlay.background_blue = options->image_overlay.background_blue;
3969 c_options->image_overlay.background_alpha = options->image_overlay.background_alpha;
3973 *-----------------------------------------------------------------------------
3974 * timezone database routines
3975 *-----------------------------------------------------------------------------
3978 static void timezone_async_ready_cb(GObject *source_object, GAsyncResult *res, gpointer data)
3980 GError *error = NULL;
3982 gchar *tmp_filename;
3984 if (!g_cancellable_is_cancelled(tz->cancellable))
3986 generic_dialog_close(tz->gd);
3990 if (g_file_copy_finish(G_FILE(source_object), res, &error))
3992 tmp_filename = g_file_get_parse_name(tz->tmp_g_file);
3993 move_file(tmp_filename, tz->timezone_database_user);
3994 g_free(tmp_filename);
3998 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
4001 g_file_delete(tz->tmp_g_file, NULL, &error);
4002 g_object_unref(tz->tmp_g_file);
4003 tz->tmp_g_file = NULL;
4004 g_object_unref(tz->cancellable);
4005 g_object_unref(tz->timezone_database_gq);
4008 static void timezone_progress_cb(goffset current_num_bytes, goffset total_num_bytes, gpointer data)
4012 if (!g_cancellable_is_cancelled(tz->cancellable))
4014 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(tz->progress), (gdouble)current_num_bytes / total_num_bytes);
4018 static void timezone_cancel_button_cb(GenericDialog *gd, gpointer data)
4022 g_cancellable_cancel(tz->cancellable);
4025 static void timezone_database_install_cb(GtkWidget *widget, gpointer data)
4028 GError *error = NULL;
4029 GFileIOStream *io_stream;
4036 tz->tmp_g_file = g_file_new_tmp("geeqie_timezone_XXXXXX", &io_stream, &error);
4040 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
4041 log_printf("Error: Download timezone database failed:\n%s", error->message);
4042 g_error_free(error);
4043 g_object_unref(tz->tmp_g_file);
4047 tz->timezone_database_gq = g_file_new_for_uri(TIMEZONE_DATABASE);
4049 tz->gd = generic_dialog_new(_("Timezone database"), "download_timezone_database", NULL, TRUE, timezone_cancel_button_cb, tz);
4051 generic_dialog_add_message(tz->gd, GTK_STOCK_DIALOG_INFO, _("Downloading timezone database"), NULL, FALSE);
4053 tz->progress = gtk_progress_bar_new();
4054 gtk_box_pack_start(GTK_BOX(tz->gd->vbox), tz->progress, FALSE, FALSE, 0);
4055 gtk_widget_show(tz->progress);
4057 gtk_widget_show(tz->gd->dialog);
4058 tz->cancellable = g_cancellable_new();
4059 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);
4061 gtk_button_set_label(GTK_BUTTON(widget), _("Update"));
4064 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */