2 * Copyright (C) 2006 John Ellis
3 * Copyright (C) 2008 - 2016 The Geeqie Team
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include "preferences.h"
26 #include "bar_keywords.h"
28 #include "cache_maint.h"
33 #include "filefilter.h"
34 #include "fullscreen.h"
36 #include "image-overlay.h"
37 #include "color-man.h"
39 #include "layout_config.h"
40 #include "layout_util.h"
43 #include "pixbuf_util.h"
45 #include "slideshow.h"
49 #include "ui_fileops.h"
51 #include "ui_spinner.h"
52 #include "ui_tabcomp.h"
53 #include "ui_utildlg.h"
55 #include "zonedetect.h"
65 #define EDITOR_NAME_MAX_LENGTH 32
66 #define EDITOR_COMMAND_MAX_LENGTH 1024
68 static void image_overlay_set_text_colours();
70 GtkWidget *keyword_text;
71 static void config_tab_keywords_save();
73 typedef struct _ThumbSize ThumbSize;
80 static ThumbSize thumb_size_list[] =
114 gchar *format_class_list[] = {
124 /* config memory values */
125 static ConfOptions *c_options = NULL;
132 static GtkWidget *configwindow = NULL;
133 static GtkListStore *filter_store = NULL;
134 static GtkTreeStore *accel_store = NULL;
136 static GtkWidget *safe_delete_path_entry;
138 static GtkWidget *color_profile_input_file_entry[COLOR_PROFILE_INPUTS];
139 static GtkWidget *color_profile_input_name_entry[COLOR_PROFILE_INPUTS];
140 static GtkWidget *color_profile_screen_file_entry;
141 static GtkWidget *external_preview_select_entry;
142 static GtkWidget *external_preview_extract_entry;
144 static GtkWidget *sidecar_ext_entry;
145 static GtkWidget *help_search_engine_entry;
148 #define CONFIG_WINDOW_DEF_WIDTH 700
149 #define CONFIG_WINDOW_DEF_HEIGHT 600
152 *-----------------------------------------------------------------------------
153 * option widget callbacks (private)
154 *-----------------------------------------------------------------------------
157 static void zoom_increment_cb(GtkWidget *spin, gpointer data)
159 c_options->image.zoom_increment = (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) * 100.0 + 0.01);
162 static void slideshow_delay_hours_cb(GtkWidget *spin, gpointer data)
164 gint mins_secs_tenths, delay;
166 mins_secs_tenths = c_options->slideshow.delay %
167 (3600 * SLIDESHOW_SUBSECOND_PRECISION);
169 delay = (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
170 (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
173 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
174 SLIDESHOW_SUBSECOND_PRECISION;
177 static void slideshow_delay_minutes_cb(GtkWidget *spin, gpointer data)
179 gint hours, secs_tenths, delay;
181 hours = c_options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
182 secs_tenths = c_options->slideshow.delay % (60 * SLIDESHOW_SUBSECOND_PRECISION);
184 delay = hours * (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
185 (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
186 (60 * SLIDESHOW_SUBSECOND_PRECISION) + secs_tenths);
188 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
189 SLIDESHOW_SUBSECOND_PRECISION;
192 static void slideshow_delay_seconds_cb(GtkWidget *spin, gpointer data)
194 gint hours_mins, delay;
196 hours_mins = c_options->slideshow.delay / (60 * SLIDESHOW_SUBSECOND_PRECISION);
198 delay = (hours_mins * (60 * SLIDESHOW_SUBSECOND_PRECISION)) +
199 (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
200 (gdouble)(SLIDESHOW_SUBSECOND_PRECISION) + 0.01);
202 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
203 SLIDESHOW_SUBSECOND_PRECISION;
207 *-----------------------------------------------------------------------------
208 * sync program to config window routine (private)
209 *-----------------------------------------------------------------------------
212 void config_entry_to_option(GtkWidget *entry, gchar **option, gchar *(*func)(const gchar *))
218 buf = gtk_entry_get_text(GTK_ENTRY(entry));
219 if (buf && strlen(buf) > 0)
224 *option = g_strdup(buf);
229 static gboolean accel_apply_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
231 gchar *accel_path, *accel;
233 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, AE_KEY, &accel, -1);
235 if (accel_path && accel_path[0])
238 gtk_accelerator_parse(accel, &key.accel_key, &key.accel_mods);
239 gtk_accel_map_change_entry(accel_path, key.accel_key, key.accel_mods, TRUE);
249 static void config_window_apply(void)
251 gboolean refresh = FALSE;
256 config_entry_to_option(safe_delete_path_entry, &options->file_ops.safe_delete_path, remove_trailing_slash);
258 if (options->file_filter.show_hidden_files != c_options->file_filter.show_hidden_files) refresh = TRUE;
259 if (options->file_filter.show_parent_directory != c_options->file_filter.show_parent_directory) refresh = TRUE;
260 if (options->file_filter.show_dot_directory != c_options->file_filter.show_dot_directory) refresh = TRUE;
261 if (options->file_sort.case_sensitive != c_options->file_sort.case_sensitive) refresh = TRUE;
262 if (options->file_sort.natural != c_options->file_sort.natural) refresh = TRUE;
263 if (options->file_filter.disable_file_extension_checks != c_options->file_filter.disable_file_extension_checks) refresh = TRUE;
264 if (options->file_filter.disable != c_options->file_filter.disable) refresh = TRUE;
266 options->file_ops.confirm_delete = c_options->file_ops.confirm_delete;
267 options->file_ops.enable_delete_key = c_options->file_ops.enable_delete_key;
268 options->file_ops.confirm_move_to_trash = c_options->file_ops.confirm_move_to_trash;
269 options->file_ops.use_system_trash = c_options->file_ops.use_system_trash;
270 options->file_ops.no_trash = c_options->file_ops.no_trash;
271 options->file_ops.safe_delete_folder_maxsize = c_options->file_ops.safe_delete_folder_maxsize;
272 options->tools_restore_state = c_options->tools_restore_state;
273 options->save_window_positions = c_options->save_window_positions;
274 options->use_saved_window_positions_for_new_windows = c_options->use_saved_window_positions_for_new_windows;
275 options->save_window_workspace = c_options->save_window_workspace;
276 options->save_dialog_window_positions = c_options->save_dialog_window_positions;
277 options->show_window_ids = c_options->show_window_ids;
278 options->image.scroll_reset_method = c_options->image.scroll_reset_method;
279 options->image.zoom_2pass = c_options->image.zoom_2pass;
280 options->image.fit_window_to_image = c_options->image.fit_window_to_image;
281 options->image.limit_window_size = c_options->image.limit_window_size;
282 options->image.zoom_to_fit_allow_expand = c_options->image.zoom_to_fit_allow_expand;
283 options->image.max_window_size = c_options->image.max_window_size;
284 options->image.limit_autofit_size = c_options->image.limit_autofit_size;
285 options->image.max_autofit_size = c_options->image.max_autofit_size;
286 options->image.max_enlargement_size = c_options->image.max_enlargement_size;
287 options->image.use_clutter_renderer = c_options->image.use_clutter_renderer;
288 options->progressive_key_scrolling = c_options->progressive_key_scrolling;
289 options->keyboard_scroll_step = c_options->keyboard_scroll_step;
291 if (options->thumbnails.max_width != c_options->thumbnails.max_width
292 || options->thumbnails.max_height != c_options->thumbnails.max_height
293 || options->thumbnails.quality != c_options->thumbnails.quality)
295 thumb_format_changed = TRUE;
297 options->thumbnails.max_width = c_options->thumbnails.max_width;
298 options->thumbnails.max_height = c_options->thumbnails.max_height;
299 options->thumbnails.quality = c_options->thumbnails.quality;
301 options->thumbnails.enable_caching = c_options->thumbnails.enable_caching;
302 options->thumbnails.cache_into_dirs = c_options->thumbnails.cache_into_dirs;
303 options->thumbnails.use_exif = c_options->thumbnails.use_exif;
304 options->thumbnails.use_color_management = c_options->thumbnails.use_color_management;
305 options->thumbnails.collection_preview = c_options->thumbnails.collection_preview;
306 options->thumbnails.use_ft_metadata = c_options->thumbnails.use_ft_metadata;
307 // options->thumbnails.use_ft_metadata_small = c_options->thumbnails.use_ft_metadata_small;
308 options->thumbnails.spec_standard = c_options->thumbnails.spec_standard;
309 options->metadata.enable_metadata_dirs = c_options->metadata.enable_metadata_dirs;
310 options->file_filter.show_hidden_files = c_options->file_filter.show_hidden_files;
311 options->file_filter.show_parent_directory = c_options->file_filter.show_parent_directory;
312 options->file_filter.show_dot_directory = c_options->file_filter.show_dot_directory;
313 options->file_filter.disable_file_extension_checks = c_options->file_filter.disable_file_extension_checks;
315 options->file_sort.case_sensitive = c_options->file_sort.case_sensitive;
316 options->file_sort.natural = c_options->file_sort.natural;
317 options->file_filter.disable = c_options->file_filter.disable;
319 config_entry_to_option(sidecar_ext_entry, &options->sidecar.ext, NULL);
320 sidecar_ext_parse(options->sidecar.ext);
322 options->slideshow.random = c_options->slideshow.random;
323 options->slideshow.repeat = c_options->slideshow.repeat;
324 options->slideshow.delay = c_options->slideshow.delay;
326 options->mousewheel_scrolls = c_options->mousewheel_scrolls;
327 options->image_lm_click_nav = c_options->image_lm_click_nav;
328 options->image_l_click_video = c_options->image_l_click_video;
329 options->image_l_click_video_editor = c_options->image_l_click_video_editor;
331 options->file_ops.enable_in_place_rename = c_options->file_ops.enable_in_place_rename;
333 options->image.tile_cache_max = c_options->image.tile_cache_max;
334 options->image.image_cache_max = c_options->image.image_cache_max;
336 options->image.zoom_quality = c_options->image.zoom_quality;
338 options->image.zoom_increment = c_options->image.zoom_increment;
340 options->image.enable_read_ahead = c_options->image.enable_read_ahead;
343 if (options->image.use_custom_border_color != c_options->image.use_custom_border_color
344 || options->image.use_custom_border_color_in_fullscreen != c_options->image.use_custom_border_color_in_fullscreen
345 || !gdk_color_equal(&options->image.border_color, &c_options->image.border_color))
347 options->image.use_custom_border_color_in_fullscreen = c_options->image.use_custom_border_color_in_fullscreen;
348 options->image.use_custom_border_color = c_options->image.use_custom_border_color;
349 options->image.border_color = c_options->image.border_color;
350 layout_colors_update();
351 view_window_colors_update();
354 options->image.alpha_color_1 = c_options->image.alpha_color_1;
355 options->image.alpha_color_2 = c_options->image.alpha_color_2;
357 options->fullscreen.screen = c_options->fullscreen.screen;
358 options->fullscreen.clean_flip = c_options->fullscreen.clean_flip;
359 options->fullscreen.disable_saver = c_options->fullscreen.disable_saver;
360 options->fullscreen.above = c_options->fullscreen.above;
361 if (c_options->image_overlay.template_string)
362 set_image_overlay_template_string(&options->image_overlay.template_string,
363 c_options->image_overlay.template_string);
364 if (c_options->image_overlay.font)
365 set_image_overlay_font_string(&options->image_overlay.font,
366 c_options->image_overlay.font);
367 options->image_overlay.text_red = c_options->image_overlay.text_red;
368 options->image_overlay.text_green = c_options->image_overlay.text_green;
369 options->image_overlay.text_blue = c_options->image_overlay.text_blue;
370 options->image_overlay.text_alpha = c_options->image_overlay.text_alpha;
371 options->image_overlay.background_red = c_options->image_overlay.background_red;
372 options->image_overlay.background_green = c_options->image_overlay.background_green;
373 options->image_overlay.background_blue = c_options->image_overlay.background_blue;
374 options->image_overlay.background_alpha = c_options->image_overlay.background_alpha;
375 options->update_on_time_change = c_options->update_on_time_change;
376 options->image.exif_proof_rotate_enable = c_options->image.exif_proof_rotate_enable;
378 options->duplicates_similarity_threshold = c_options->duplicates_similarity_threshold;
379 options->rot_invariant_sim = c_options->rot_invariant_sim;
381 options->tree_descend_subdirs = c_options->tree_descend_subdirs;
383 options->view_dir_list_single_click_enter = c_options->view_dir_list_single_click_enter;
384 options->circular_selection_lists = c_options->circular_selection_lists;
386 options->open_recent_list_maxsize = c_options->open_recent_list_maxsize;
387 options->dnd_icon_size = c_options->dnd_icon_size;
388 options->clipboard_selection = c_options->clipboard_selection;
389 options->dnd_default_action = c_options->dnd_default_action;
391 options->metadata.save_in_image_file = c_options->metadata.save_in_image_file;
392 options->metadata.save_legacy_IPTC = c_options->metadata.save_legacy_IPTC;
393 options->metadata.warn_on_write_problems = c_options->metadata.warn_on_write_problems;
394 options->metadata.save_legacy_format = c_options->metadata.save_legacy_format;
395 options->metadata.sync_grouped_files = c_options->metadata.sync_grouped_files;
396 options->metadata.confirm_write = c_options->metadata.confirm_write;
397 options->metadata.sidecar_extended_name = c_options->metadata.sidecar_extended_name;
398 options->metadata.confirm_timeout = c_options->metadata.confirm_timeout;
399 options->metadata.confirm_after_timeout = c_options->metadata.confirm_after_timeout;
400 options->metadata.confirm_on_image_change = c_options->metadata.confirm_on_image_change;
401 options->metadata.confirm_on_dir_change = c_options->metadata.confirm_on_dir_change;
402 options->metadata.keywords_case_sensitive = c_options->metadata.keywords_case_sensitive;
403 options->metadata.write_orientation = c_options->metadata.write_orientation;
404 options->stereo.mode = (c_options->stereo.mode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
405 (c_options->stereo.tmp.mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
406 (c_options->stereo.tmp.flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
407 (c_options->stereo.tmp.mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
408 (c_options->stereo.tmp.flip_left ? PR_STEREO_FLIP_LEFT : 0) |
409 (c_options->stereo.tmp.swap ? PR_STEREO_SWAP : 0) |
410 (c_options->stereo.tmp.temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
411 options->stereo.fsmode = (c_options->stereo.fsmode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
412 (c_options->stereo.tmp.fs_mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
413 (c_options->stereo.tmp.fs_flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
414 (c_options->stereo.tmp.fs_mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
415 (c_options->stereo.tmp.fs_flip_left ? PR_STEREO_FLIP_LEFT : 0) |
416 (c_options->stereo.tmp.fs_swap ? PR_STEREO_SWAP : 0) |
417 (c_options->stereo.tmp.fs_temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
418 options->stereo.enable_fsmode = c_options->stereo.enable_fsmode;
419 options->stereo.fixed_w = c_options->stereo.fixed_w;
420 options->stereo.fixed_h = c_options->stereo.fixed_h;
421 options->stereo.fixed_x1 = c_options->stereo.fixed_x1;
422 options->stereo.fixed_y1 = c_options->stereo.fixed_y1;
423 options->stereo.fixed_x2 = c_options->stereo.fixed_x2;
424 options->stereo.fixed_y2 = c_options->stereo.fixed_y2;
426 options->info_keywords.height = c_options->info_keywords.height;
427 options->info_title.height = c_options->info_title.height;
428 options->info_comment.height = c_options->info_comment.height;
429 options->info_rating.height = c_options->info_rating.height;
431 options->show_predefined_keyword_tree = c_options->show_predefined_keyword_tree;
432 options->expand_menu_toolbar = c_options->expand_menu_toolbar;
434 options->marks_save = c_options->marks_save;
435 options->with_rename = c_options->with_rename;
436 options->collections_on_top = c_options->collections_on_top;
437 options->hide_window_in_fullscreen = c_options->hide_window_in_fullscreen;
438 config_entry_to_option(help_search_engine_entry, &options->help_search_engine, NULL);
440 options->external_preview.enable = c_options->external_preview.enable;
441 config_entry_to_option(external_preview_select_entry, &options->external_preview.select, NULL);
442 config_entry_to_option(external_preview_extract_entry, &options->external_preview.extract, NULL);
444 options->read_metadata_in_idle = c_options->read_metadata_in_idle;
446 options->star_rating.star = c_options->star_rating.star;
447 options->star_rating.rejected = c_options->star_rating.rejected;
449 set_debug_level(debug_c);
453 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
455 config_entry_to_option(color_profile_input_name_entry[i], &options->color_profile.input_name[i], NULL);
456 config_entry_to_option(color_profile_input_file_entry[i], &options->color_profile.input_file[i], NULL);
458 config_entry_to_option(color_profile_screen_file_entry, &options->color_profile.screen_file, NULL);
459 options->color_profile.use_x11_screen_profile = c_options->color_profile.use_x11_screen_profile;
460 if (options->color_profile.render_intent != c_options->color_profile.render_intent)
462 options->color_profile.render_intent = c_options->color_profile.render_intent;
467 options->mouse_button_8 = c_options->mouse_button_8;
468 options->mouse_button_9 = c_options->mouse_button_9;
470 options->override_disable_gpu = c_options->override_disable_gpu;
472 config_tab_keywords_save();
474 image_options_sync();
479 layout_refresh(NULL);
482 if (accel_store) gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_apply_cb, NULL);
484 toolbar_apply(TOOLBAR_MAIN);
485 toolbar_apply(TOOLBAR_STATUS);
489 *-----------------------------------------------------------------------------
490 * config window main button callbacks (private)
491 *-----------------------------------------------------------------------------
494 static void config_window_close_cb(GtkWidget *widget, gpointer data)
496 gtk_widget_destroy(configwindow);
501 static void config_window_help_cb(GtkWidget *widget, gpointer data)
503 GtkWidget *notebook = data;
506 static gchar *html_section[] =
508 "GuideOptionsGeneral.html",
509 "GuideOptionsImage.html",
510 "GuideOptionsOSD.html",
511 "GuideOptionsWindow.html",
512 "GuideOptionsKeyboard.html",
513 "GuideOptionsFiltering.html",
514 "GuideOptionsMetadata.html",
515 "GuideOptionsKeywords.html",
516 "GuideOptionsColor.html",
517 "GuideOptionsStereo.html",
518 "GuideOptionsBehavior.html",
519 "GuideOptionsToolbar.html",
520 "GuideOptionsToolbar.html",
521 "GuideOptionsAdvanced.html"
524 i = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
525 help_window_show(html_section[i]);
528 static gboolean config_window_delete(GtkWidget *widget, GdkEventAny *event, gpointer data)
530 config_window_close_cb(NULL, NULL);
534 static void config_window_ok_cb(GtkWidget *widget, gpointer data)
537 GtkNotebook *notebook = data;
545 lw = layout_window_list->data;
547 window = gtk_widget_get_window(widget);
548 gdk_window_get_root_origin(window, &x, &y);
549 w = gdk_window_get_width(window);
550 h = gdk_window_get_height(window);
551 page_number = gtk_notebook_get_current_page(notebook);
553 lw->options.preferences_window.x = x;
554 lw->options.preferences_window.y = y;
555 lw->options.preferences_window.w = w;
556 lw->options.preferences_window.h = h;
557 lw->options.preferences_window.page_number = page_number;
559 config_window_apply();
560 layout_util_sync(lw);
561 save_options(options);
562 config_window_close_cb(NULL, NULL);
566 *-----------------------------------------------------------------------------
567 * config window setup (private)
568 *-----------------------------------------------------------------------------
571 static void quality_menu_cb(GtkWidget *combo, gpointer data)
575 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
579 *option = GDK_INTERP_NEAREST;
582 *option = GDK_INTERP_TILES;
585 *option = GDK_INTERP_BILINEAR;
590 static void dnd_default_action_selection_menu_cb(GtkWidget *combo, gpointer data)
594 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
598 *option = DND_ACTION_ASK;
601 *option = DND_ACTION_COPY;
604 *option = DND_ACTION_MOVE;
608 static void clipboard_selection_menu_cb(GtkWidget *combo, gpointer data)
612 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
615 *option = CLIPBOARD_PRIMARY;
618 *option = CLIPBOARD_CLIPBOARD;
621 *option = CLIPBOARD_BOTH;
624 *option = CLIPBOARD_BOTH;
628 static void add_quality_menu(GtkWidget *table, gint column, gint row, const gchar *text,
629 guint option, guint *option_c)
636 pref_table_label(table, column, row, text, 0.0);
638 combo = gtk_combo_box_text_new();
640 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Nearest (worst, but fastest)"));
641 if (option == GDK_INTERP_NEAREST) current = 0;
642 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Tiles"));
643 if (option == GDK_INTERP_TILES) current = 1;
644 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Bilinear (best, but slowest)"));
645 if (option == GDK_INTERP_BILINEAR) current = 2;
647 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
649 g_signal_connect(G_OBJECT(combo), "changed",
650 G_CALLBACK(quality_menu_cb), option_c);
652 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
653 gtk_widget_show(combo);
656 static void add_dnd_default_action_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text, DnDAction option, DnDAction *option_c)
663 pref_table_label(table, column, row, text, 0.0);
665 combo = gtk_combo_box_text_new();
667 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Ask"));
668 if (option == DND_ACTION_ASK) current = 0;
669 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Copy"));
670 if (option == DND_ACTION_COPY) current = 1;
671 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Move"));
672 if (option == DND_ACTION_MOVE) current = 2;
674 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
676 g_signal_connect(G_OBJECT(combo), "changed",
677 G_CALLBACK(dnd_default_action_selection_menu_cb), option_c);
679 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
680 gtk_widget_show(combo);
683 static void add_clipboard_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
684 gint option, gint *option_c)
691 pref_table_label(table, column, row, text, 0.0);
693 combo = gtk_combo_box_text_new();
695 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Primary"));
696 if (option == CLIPBOARD_PRIMARY) current = 0;
697 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Clipboard"));
698 if (option == CLIPBOARD_CLIPBOARD) current = 1;
699 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Both"));
700 if (option == CLIPBOARD_BOTH) current = 2;
702 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
704 g_signal_connect(G_OBJECT(combo), "changed",
705 G_CALLBACK(clipboard_selection_menu_cb), option_c);
707 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
708 gtk_widget_show(combo);
711 typedef struct _UseableMouseItems UseableMouseItems;
712 struct _UseableMouseItems
714 gchar *name; /* GtkActionEntry terminology */
719 static const UseableMouseItems useable_mouse_items[] = {
721 {"FirstImage", N_("First Image"), GTK_STOCK_GOTO_TOP},
722 {"PrevImage", N_("Previous Image"), GTK_STOCK_GO_UP},
723 {"NextImage", N_("Next Image"), GTK_STOCK_GO_DOWN},
724 {"LastImage", N_("Last Image"), GTK_STOCK_GOTO_BOTTOM},
725 {"Back", N_("Back"), GTK_STOCK_GO_BACK},
726 {"Forward", N_("Forward"), GTK_STOCK_GO_FORWARD},
727 {"Home", N_("Home"), GTK_STOCK_HOME},
728 {"Up", N_("Up"), GTK_STOCK_GO_UP},
729 {"FirstPage", N_("First page"), GTK_STOCK_MEDIA_PREVIOUS},
730 {"LastPage", N_("Last Page"), GTK_STOCK_MEDIA_NEXT},
731 {"NextPage", N_("Next page"), GTK_STOCK_MEDIA_FORWARD},
732 {"PrevPage", N_("Previous Page"), GTK_STOCK_MEDIA_REWIND},
733 {"NewWindow", N_("New _window"), GTK_STOCK_NEW},
734 {"NewCollection", N_("New collection"), GTK_STOCK_INDEX},
735 {"OpenCollection", N_("Open collection"), GTK_STOCK_OPEN},
736 {"Search", N_("Search"), GTK_STOCK_FIND},
737 {"FindDupes", N_("Find duplicates"), GTK_STOCK_FIND},
738 {"NewFolder", N_("New folder"),GTK_STOCK_DIRECTORY},
739 {"Copy", N_("Copy"), GTK_STOCK_COPY},
740 {"Move", N_("Move"), PIXBUF_INLINE_ICON_MOVE},
741 {"Rename", N_("Rename"), PIXBUF_INLINE_ICON_RENAME},
742 {"Delete", N_("Delete"), GTK_STOCK_DELETE},
743 {"CloseWindow", N_("Close Window"), GTK_STOCK_CLOSE},
744 {"PanView", N_("Pan view"), PIXBUF_INLINE_ICON_PANORAMA},
745 {"SelectAll", N_("Select all"), PIXBUF_INLINE_ICON_SELECT_ALL},
746 {"SelectNone", N_("Select none"), PIXBUF_INLINE_ICON_SELECT_NONE},
747 {"SelectInvert", N_("Select invert"), PIXBUF_INLINE_ICON_SELECT_INVERT},
748 {"ShowFileFilter", N_("Show file filter"), PIXBUF_INLINE_ICON_FILE_FILTER},
749 {"RectangularSelection", N_("Select rectangle"), PIXBUF_INLINE_ICON_SELECT_RECTANGLE},
750 {"Print", N_("Print"), GTK_STOCK_PRINT},
751 {"Preferences", N_("Preferences"), GTK_STOCK_PREFERENCES},
752 {"LayoutConfig", N_("Configure this window"), GTK_STOCK_PREFERENCES},
753 {"Maintenance", N_("Cache maintenance"), PIXBUF_INLINE_ICON_MAINTENANCE},
754 {"RotateCW", N_("Rotate clockwise 90°"), PIXBUF_INLINE_ICON_CW},
755 {"RotateCCW", N_("Rotate counterclockwise 90°"), PIXBUF_INLINE_ICON_CCW},
756 {"Rotate180", N_("Rotate 180°"), PIXBUF_INLINE_ICON_180},
757 {"Mirror", N_("Mirror"), PIXBUF_INLINE_ICON_MIRROR},
758 {"Flip", N_("Flip"), PIXBUF_INLINE_ICON_FLIP},
759 {"AlterNone", N_("Original state"), PIXBUF_INLINE_ICON_ORIGINAL},
760 {"ZoomIn", N_("Zoom in"), GTK_STOCK_ZOOM_IN},
761 {"ZoomOut", N_("Zoom out"), GTK_STOCK_ZOOM_OUT},
762 {"Zoom100", N_("Zoom 1:1"), GTK_STOCK_ZOOM_100},
763 {"ZoomFit", N_("Zoom to fit"), GTK_STOCK_ZOOM_FIT},
764 {"ZoomFillHor", N_("Fit Horizontaly"), PIXBUF_INLINE_ICON_ZOOMFILLHOR},
765 {"ZoomFillVert", N_("Fit vertically"), PIXBUF_INLINE_ICON_ZOOMFILLVERT},
766 {"Zoom200", N_("Zoom 2:1"), GTK_STOCK_FILE},
767 {"Zoom300", N_("Zoom 3:1"), GTK_STOCK_FILE},
768 {"Zoom400", N_("Zoom 4:1"), GTK_STOCK_FILE},
769 {"Zoom50", N_("Zoom 1:2"), GTK_STOCK_FILE},
770 {"Zoom33", N_("Zoom1:3"), GTK_STOCK_FILE},
771 {"Zoom25", N_("Zoom 1:4"), GTK_STOCK_FILE},
772 {"ConnectZoomIn", N_("Connected Zoom in"), GTK_STOCK_ZOOM_IN},
773 {"SplitPaneSync", N_("Split Pane Sync"), PIXBUF_INLINE_SPLIT_PANE_SYNC},
774 {"Grayscale", N_("Grayscale"), PIXBUF_INLINE_ICON_GRAYSCALE},
775 {"OverUnderExposed", N_("Over Under Exposed"), PIXBUF_INLINE_ICON_EXPOSURE},
776 {"HideTools", N_("Hide file list"), PIXBUF_INLINE_ICON_HIDETOOLS},
777 {"SlideShowPause", N_("Pause slideshow"), GTK_STOCK_MEDIA_PAUSE},
778 {"SlideShowFaster", N_("Slideshow Faster"), GTK_STOCK_FILE},
779 {"SlideShowSlower", N_("Slideshow Slower"), GTK_STOCK_FILE},
780 {"Refresh", N_("Refresh"), GTK_STOCK_REFRESH},
781 {"HelpContents", N_("Help"), GTK_STOCK_HELP},
782 {"ExifWin", N_("Exif window"), PIXBUF_INLINE_ICON_EXIF},
783 {"Thumbnails", N_("Show thumbnails"), PIXBUF_INLINE_ICON_THUMB},
784 {"ShowMarks", N_("Show marks"), PIXBUF_INLINE_ICON_MARKS},
785 {"DrawRectangle", N_("Draw Rectangle"), PIXBUF_INLINE_ICON_DRAW_RECTANGLE},
786 {"FloatTools", N_("Float file list"), PIXBUF_INLINE_ICON_FLOAT},
787 {"SBar", N_("Info sidebar"), PIXBUF_INLINE_ICON_INFO},
788 {"SBarSort", N_("Sort manager"), PIXBUF_INLINE_ICON_SORT},
789 {"Quit", N_("Quit"), GTK_STOCK_QUIT},
793 static void mouse_buttons_selection_menu_cb(GtkWidget *combo, gpointer data)
795 gchar **option = data;
798 label = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(combo));
800 const UseableMouseItems *list = useable_mouse_items;
804 if (g_strcmp0(list->label, label) == 0)
812 *option = g_strdup(list->name);
816 static void add_mouse_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
817 gchar *option, gchar **option_c)
825 pref_table_label(table, column, row, text, 0.0);
827 combo = gtk_combo_box_text_new();
829 const UseableMouseItems *list = useable_mouse_items;
833 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), list->label);
834 if (g_strcmp0(list->name, option) == 0)
842 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
844 g_signal_connect(G_OBJECT(combo), "changed",
845 G_CALLBACK(mouse_buttons_selection_menu_cb), option_c);
847 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
848 gtk_widget_show(combo);
851 static void thumb_size_menu_cb(GtkWidget *combo, gpointer data)
855 n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
858 if ((guint) n < sizeof(thumb_size_list) / sizeof(ThumbSize))
860 c_options->thumbnails.max_width = thumb_size_list[n].w;
861 c_options->thumbnails.max_height = thumb_size_list[n].h;
865 c_options->thumbnails.max_width = options->thumbnails.max_width;
866 c_options->thumbnails.max_height = options->thumbnails.max_height;
870 static void add_thumb_size_menu(GtkWidget *table, gint column, gint row, gchar *text)
876 c_options->thumbnails.max_width = options->thumbnails.max_width;
877 c_options->thumbnails.max_height = options->thumbnails.max_height;
879 pref_table_label(table, column, row, text, 0.0);
881 combo = gtk_combo_box_text_new();
884 for (i = 0; (guint) i < sizeof(thumb_size_list) / sizeof(ThumbSize); i++)
889 w = thumb_size_list[i].w;
890 h = thumb_size_list[i].h;
892 buf = g_strdup_printf("%d x %d", w, h);
893 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
896 if (w == options->thumbnails.max_width && h == options->thumbnails.max_height) current = i;
903 buf = g_strdup_printf("%s %d x %d", _("Custom"), options->thumbnails.max_width, options->thumbnails.max_height);
904 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
910 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
911 g_signal_connect(G_OBJECT(combo), "changed",
912 G_CALLBACK(thumb_size_menu_cb), NULL);
914 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
915 gtk_widget_show(combo);
918 static void stereo_mode_menu_cb(GtkWidget *combo, gpointer data)
922 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
926 *option = PR_STEREO_NONE;
929 *option = PR_STEREO_ANAGLYPH_RC;
932 *option = PR_STEREO_ANAGLYPH_GM;
935 *option = PR_STEREO_ANAGLYPH_YB;
938 *option = PR_STEREO_ANAGLYPH_GRAY_RC;
941 *option = PR_STEREO_ANAGLYPH_GRAY_GM;
944 *option = PR_STEREO_ANAGLYPH_GRAY_YB;
947 *option = PR_STEREO_ANAGLYPH_DB_RC;
950 *option = PR_STEREO_ANAGLYPH_DB_GM;
953 *option = PR_STEREO_ANAGLYPH_DB_YB;
956 *option = PR_STEREO_HORIZ;
959 *option = PR_STEREO_HORIZ | PR_STEREO_HALF;
962 *option = PR_STEREO_VERT;
965 *option = PR_STEREO_VERT | PR_STEREO_HALF;
968 *option = PR_STEREO_FIXED;
973 static void add_stereo_mode_menu(GtkWidget *table, gint column, gint row, const gchar *text,
974 gint option, gint *option_c, gboolean add_fixed)
981 pref_table_label(table, column, row, text, 0.0);
983 combo = gtk_combo_box_text_new();
985 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Single image"));
987 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Red-Cyan"));
988 if (option & PR_STEREO_ANAGLYPH_RC) current = 1;
989 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Green-Magenta"));
990 if (option & PR_STEREO_ANAGLYPH_GM) current = 2;
991 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Yellow-Blue"));
992 if (option & PR_STEREO_ANAGLYPH_YB) current = 3;
993 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Red-Cyan"));
994 if (option & PR_STEREO_ANAGLYPH_GRAY_RC) current = 4;
995 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Green-Magenta"));
996 if (option & PR_STEREO_ANAGLYPH_GRAY_GM) current = 5;
997 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Yellow-Blue"));
998 if (option & PR_STEREO_ANAGLYPH_GRAY_YB) current = 6;
999 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Red-Cyan"));
1000 if (option & PR_STEREO_ANAGLYPH_DB_RC) current = 7;
1001 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Green-Magenta"));
1002 if (option & PR_STEREO_ANAGLYPH_DB_GM) current = 8;
1003 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Yellow-Blue"));
1004 if (option & PR_STEREO_ANAGLYPH_DB_YB) current = 9;
1006 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side"));
1007 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side Half size"));
1008 if (option & PR_STEREO_HORIZ)
1011 if (option & PR_STEREO_HALF) current = 11;
1014 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom"));
1015 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom Half size"));
1016 if (option & PR_STEREO_VERT)
1019 if (option & PR_STEREO_HALF) current = 13;
1024 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Fixed position"));
1025 if (option & PR_STEREO_FIXED) current = 14;
1028 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
1030 g_signal_connect(G_OBJECT(combo), "changed",
1031 G_CALLBACK(stereo_mode_menu_cb), option_c);
1033 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
1034 gtk_widget_show(combo);
1037 static void video_menu_cb(GtkWidget *combo, gpointer data)
1039 gchar **option = data;
1041 EditorDescription *ed = g_list_nth_data(editor_list_get(), gtk_combo_box_get_active(GTK_COMBO_BOX(combo)));
1045 static void video_menu_populate(gpointer data, gpointer user_data)
1047 GtkWidget *combo = user_data;
1048 EditorDescription *ed = data;
1050 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), ed->name);
1053 static void add_video_menu(GtkWidget *table, gint column, gint row, const gchar *text,
1054 gchar *option, gchar **option_c)
1058 /* use lists since they are sorted */
1059 GList *eds = editor_list_get();
1063 pref_table_label(table, column, row, text, 0.0);
1065 combo = gtk_combo_box_text_new();
1066 g_list_foreach(eds,video_menu_populate,(gpointer)combo);
1067 current = option ? g_list_index(eds,g_hash_table_lookup(editors,option)): -1;
1069 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
1071 g_signal_connect(G_OBJECT(combo), "changed",
1072 G_CALLBACK(video_menu_cb), option_c);
1074 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
1075 gtk_widget_show(combo);
1078 static void filter_store_populate(void)
1082 if (!filter_store) return;
1084 gtk_list_store_clear(filter_store);
1086 work = filter_get_list();
1095 gtk_list_store_append(filter_store, &iter);
1096 gtk_list_store_set(filter_store, &iter, 0, fe, -1);
1100 static void filter_store_ext_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1101 gchar *new_text, gpointer data)
1103 GtkWidget *model = data;
1104 FilterEntry *fe = data;
1108 if (!new_text || strlen(new_text) < 1) return;
1110 tpath = gtk_tree_path_new_from_string(path_str);
1111 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1112 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1114 g_free(fe->extensions);
1115 fe->extensions = g_strdup(new_text);
1117 gtk_tree_path_free(tpath);
1121 static void filter_store_class_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1122 gchar *new_text, gpointer data)
1124 GtkWidget *model = data;
1125 FilterEntry *fe = data;
1130 if (!new_text || !new_text[0]) return;
1132 tpath = gtk_tree_path_new_from_string(path_str);
1133 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1134 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1136 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
1138 if (strcmp(new_text, _(format_class_list[i])) == 0)
1145 gtk_tree_path_free(tpath);
1149 static void filter_store_desc_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1150 gchar *new_text, gpointer data)
1152 GtkWidget *model = data;
1157 if (!new_text || !new_text[0]) return;
1159 tpath = gtk_tree_path_new_from_string(path_str);
1160 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1161 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1163 g_free(fe->description);
1164 fe->description = g_strdup(new_text);
1166 gtk_tree_path_free(tpath);
1169 static void filter_store_enable_cb(GtkCellRendererToggle *renderer,
1170 gchar *path_str, gpointer data)
1172 GtkWidget *model = data;
1177 tpath = gtk_tree_path_new_from_string(path_str);
1178 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1179 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1181 fe->enabled = !fe->enabled;
1183 gtk_tree_path_free(tpath);
1187 static void filter_store_writable_cb(GtkCellRendererToggle *renderer,
1188 gchar *path_str, gpointer data)
1190 GtkWidget *model = data;
1195 tpath = gtk_tree_path_new_from_string(path_str);
1196 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1197 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1199 fe->writable = !fe->writable;
1200 if (fe->writable) fe->allow_sidecar = FALSE;
1202 gtk_tree_path_free(tpath);
1206 static void filter_store_sidecar_cb(GtkCellRendererToggle *renderer,
1207 gchar *path_str, gpointer data)
1209 GtkWidget *model = data;
1214 tpath = gtk_tree_path_new_from_string(path_str);
1215 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1216 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1218 fe->allow_sidecar = !fe->allow_sidecar;
1219 if (fe->allow_sidecar) fe->writable = FALSE;
1221 gtk_tree_path_free(tpath);
1225 static void filter_set_func(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
1226 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
1230 gtk_tree_model_get(tree_model, iter, 0, &fe, -1);
1232 switch (GPOINTER_TO_INT(data))
1235 g_object_set(GTK_CELL_RENDERER(cell),
1236 "active", fe->enabled, NULL);
1239 g_object_set(GTK_CELL_RENDERER(cell),
1240 "text", fe->extensions, NULL);
1242 case FE_DESCRIPTION:
1243 g_object_set(GTK_CELL_RENDERER(cell),
1244 "text", fe->description, NULL);
1247 g_object_set(GTK_CELL_RENDERER(cell),
1248 "text", _(format_class_list[fe->file_class]), NULL);
1251 g_object_set(GTK_CELL_RENDERER(cell),
1252 "active", fe->writable, NULL);
1254 case FE_ALLOW_SIDECAR:
1255 g_object_set(GTK_CELL_RENDERER(cell),
1256 "active", fe->allow_sidecar, NULL);
1261 static gboolean filter_add_scroll(gpointer data)
1265 GtkCellRenderer *cell;
1266 GtkTreeViewColumn *column;
1269 rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(filter_store), NULL);
1270 path = gtk_tree_path_new_from_indices(rows-1, -1);
1272 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data), 0);
1274 list_cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column));
1275 cell = g_list_last(list_cells)->data;
1277 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1278 path, column, FALSE, 0.0, 0.0 );
1279 gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(data),
1280 path, column, cell, TRUE);
1282 gtk_tree_path_free(path);
1283 g_list_free(list_cells);
1288 static void filter_add_cb(GtkWidget *widget, gpointer data)
1290 filter_add_unique("description", ".new", FORMAT_CLASS_IMAGE, TRUE, FALSE, TRUE);
1291 filter_store_populate();
1293 g_idle_add((GSourceFunc)filter_add_scroll, data);
1296 static void filter_remove_cb(GtkWidget *widget, gpointer data)
1298 GtkWidget *filter_view = data;
1299 GtkTreeSelection *selection;
1303 if (!filter_store) return;
1304 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1305 if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) return;
1306 gtk_tree_model_get(GTK_TREE_MODEL(filter_store), &iter, 0, &fe, -1);
1309 filter_remove_entry(fe);
1311 filter_store_populate();
1314 static gboolean filter_default_ok_scroll(GtkTreeView *data)
1318 GtkTreeViewColumn *column;
1320 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(filter_store), &iter);
1321 path = gtk_tree_model_get_path(GTK_TREE_MODEL(filter_store), &iter);
1322 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1324 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1328 gtk_tree_path_free(path);
1333 static void filter_default_ok_cb(GenericDialog *gd, gpointer data)
1336 filter_add_defaults();
1338 filter_store_populate();
1340 g_idle_add((GSourceFunc)filter_default_ok_scroll, gd->data);
1343 static void dummy_cancel_cb(GenericDialog *gd, gpointer data)
1345 /* no op, only so cancel button appears */
1348 static void filter_default_cb(GtkWidget *widget, gpointer data)
1352 gd = generic_dialog_new(_("Reset filters"),
1353 "reset_filter", widget, TRUE,
1354 dummy_cancel_cb, data);
1355 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset filters"),
1356 _("This will reset the file filters to the defaults.\nContinue?"), TRUE);
1357 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, filter_default_ok_cb, TRUE);
1358 gtk_widget_show(gd->dialog);
1361 static void filter_disable_cb(GtkWidget *widget, gpointer data)
1363 GtkWidget *frame = data;
1365 gtk_widget_set_sensitive(frame,
1366 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
1369 static void safe_delete_view_cb(GtkWidget *widget, gpointer data)
1371 layout_set_path(NULL, gtk_entry_get_text(GTK_ENTRY(safe_delete_path_entry)));
1374 static void safe_delete_clear_ok_cb(GenericDialog *gd, gpointer data)
1376 file_util_trash_clear();
1379 static void safe_delete_clear_cb(GtkWidget *widget, gpointer data)
1383 gd = generic_dialog_new(_("Clear trash"),
1384 "clear_trash", widget, TRUE,
1385 dummy_cancel_cb, NULL);
1386 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear trash"),
1387 _("This will remove the trash contents."), FALSE);
1388 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, safe_delete_clear_ok_cb, TRUE);
1389 entry = gtk_entry_new();
1390 gtk_widget_set_can_focus(entry, FALSE);
1391 gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE);
1392 if (options->file_ops.safe_delete_path) gtk_entry_set_text(GTK_ENTRY(entry), options->file_ops.safe_delete_path);
1393 gtk_box_pack_start(GTK_BOX(gd->vbox), entry, FALSE, FALSE, 0);
1394 gtk_widget_show(entry);
1395 gtk_widget_show(gd->dialog);
1398 static void image_overlay_template_view_changed_cb(GtkWidget *widget, gpointer data)
1400 GtkWidget *pTextView;
1401 GtkTextBuffer *pTextBuffer;
1405 pTextView = GTK_WIDGET(data);
1407 pTextBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pTextView));
1408 gtk_text_buffer_get_start_iter(pTextBuffer, &iStart);
1409 gtk_text_buffer_get_end_iter(pTextBuffer, &iEnd);
1411 set_image_overlay_template_string(&c_options->image_overlay.template_string,
1412 gtk_text_buffer_get_text(pTextBuffer, &iStart, &iEnd, TRUE));
1415 static void image_overlay_default_template_ok_cb(GenericDialog *gd, gpointer data)
1417 GtkTextView *text_view = data;
1418 GtkTextBuffer *buffer;
1420 set_default_image_overlay_template_string(&options->image_overlay.template_string);
1421 if (!configwindow) return;
1423 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
1424 gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1427 static void image_overlay_default_template_cb(GtkWidget *widget, gpointer data)
1431 gd = generic_dialog_new(_("Reset image overlay template string"),
1432 "reset_image_overlay_template_string", widget, TRUE,
1433 dummy_cancel_cb, data);
1434 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset image overlay template string"),
1435 _("This will reset the image overlay template string to the default.\nContinue?"), TRUE);
1436 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, image_overlay_default_template_ok_cb, TRUE);
1437 gtk_widget_show(gd->dialog);
1440 static void image_overlay_help_cb(GtkWidget *widget, gpointer data)
1442 help_window_show("GuideOptionsOSD.html");
1445 static void image_overlay_set_font_cb(GtkWidget *widget, gpointer data)
1447 #if GTK_CHECK_VERSION(3,4,0)
1450 PangoFontDescription *font_desc;
1452 dialog = gtk_font_chooser_dialog_new("Image Overlay Font", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1453 gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), options->image_overlay.font);
1455 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1457 font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
1458 font = pango_font_description_to_string(font_desc);
1459 g_free(c_options->image_overlay.font);
1460 c_options->image_overlay.font = g_strdup(font);
1464 gtk_widget_destroy(dialog);
1468 font = gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget));
1469 c_options->image_overlay.font = g_strdup(font);
1473 static void image_overlay_set_text_colour_cb(GtkWidget *widget, gpointer data)
1476 #if GTK_CHECK_VERSION(3,4,0)
1479 dialog = gtk_color_chooser_dialog_new("Image Overlay Text Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1480 colour.red = options->image_overlay.text_red;
1481 colour.green = options->image_overlay.text_green;
1482 colour.blue = options->image_overlay.text_blue;
1483 colour.alpha = options->image_overlay.text_alpha;
1484 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1485 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1487 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1489 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1490 c_options->image_overlay.text_red = colour.red*255;
1491 c_options->image_overlay.text_green = colour.green*255;
1492 c_options->image_overlay.text_blue = colour.blue*255;
1493 c_options->image_overlay.text_alpha = colour.alpha*255;
1495 gtk_widget_destroy(dialog);
1498 GtkColorSelection *colorsel;
1500 dialog = gtk_color_selection_dialog_new("Image Overlay Text Colour");
1501 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1502 colour.red = options->image_overlay.text_red*257;
1503 colour.green = options->image_overlay.text_green*257;
1504 colour.blue = options->image_overlay.text_blue*257;
1505 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1506 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1507 gtk_color_selection_set_current_color(colorsel, &colour);
1508 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.text_alpha*257);
1510 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1512 gtk_color_selection_get_current_color(colorsel, &colour);
1513 c_options->image_overlay.text_red = colour.red/257;
1514 c_options->image_overlay.text_green = colour.green/257;
1515 c_options->image_overlay.text_blue = colour.blue/257;
1516 c_options->image_overlay.text_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1518 gtk_widget_destroy (dialog);
1523 static void image_overlay_set_background_colour_cb(GtkWidget *widget, gpointer data)
1526 #if GTK_CHECK_VERSION(3,4,0)
1529 dialog = gtk_color_chooser_dialog_new("Image Overlay Background Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1530 colour.red = options->image_overlay.background_red;
1531 colour.green = options->image_overlay.background_green;
1532 colour.blue = options->image_overlay.background_blue;
1533 colour.alpha = options->image_overlay.background_alpha;
1534 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1535 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1537 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1539 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1540 c_options->image_overlay.background_red = colour.red*255;
1541 c_options->image_overlay.background_green = colour.green*255;
1542 c_options->image_overlay.background_blue = colour.blue*255;
1543 c_options->image_overlay.background_alpha = colour.alpha*255;
1545 gtk_widget_destroy(dialog);
1548 GtkColorSelection *colorsel;
1550 dialog = gtk_color_selection_dialog_new("Image Overlay Background Colour");
1551 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1552 colour.red = options->image_overlay.background_red*257;
1553 colour.green = options->image_overlay.background_green*257;
1554 colour.blue = options->image_overlay.background_blue*257;
1555 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1556 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1557 gtk_color_selection_set_current_color(colorsel, &colour);
1558 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.background_alpha*257);
1560 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1562 gtk_color_selection_get_current_color(colorsel, &colour);
1563 c_options->image_overlay.background_red = colour.red/257;
1564 c_options->image_overlay.background_green = colour.green/257;
1565 c_options->image_overlay.background_blue = colour.blue/257;
1566 c_options->image_overlay.background_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1568 gtk_widget_destroy(dialog);
1572 static void accel_store_populate(void)
1575 GList *groups, *actions;
1577 const gchar *accel_path;
1581 if (!accel_store || !layout_window_list || !layout_window_list->data) return;
1583 gtk_tree_store_clear(accel_store);
1584 lw = layout_window_list->data; /* get the actions from the first window, it should not matter, they should be the same in all windows */
1586 g_assert(lw && lw->ui_manager);
1587 groups = gtk_ui_manager_get_action_groups(lw->ui_manager);
1590 actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
1593 action = GTK_ACTION(actions->data);
1594 accel_path = gtk_action_get_accel_path(action);
1595 if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
1597 gchar *label, *label2, *tooltip, *accel;
1598 g_object_get(action,
1599 "tooltip", &tooltip,
1603 if (pango_parse_markup(label, -1, '_', NULL, &label2, NULL, NULL) && label2)
1609 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1613 gtk_tree_store_append(accel_store, &iter, NULL);
1614 gtk_tree_store_set(accel_store, &iter,
1617 AE_TOOLTIP, tooltip ? tooltip : "",
1618 AE_ACCEL, accel_path,
1626 actions = actions->next;
1629 groups = groups->next;
1633 static void accel_store_cleared_cb(GtkCellRendererAccel *accel, gchar *path_string, gpointer user_data)
1638 static gboolean accel_remove_key_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1640 gchar *accel1 = data;
1645 gtk_tree_model_get(model, iter, AE_KEY, &accel2, -1);
1647 gtk_accelerator_parse(accel1, &key1.accel_key, &key1.accel_mods);
1648 gtk_accelerator_parse(accel2, &key2.accel_key, &key2.accel_mods);
1650 if (key1.accel_key == key2.accel_key && key1.accel_mods == key2.accel_mods)
1652 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1653 DEBUG_1("accelerator key '%s' is already used, removing.", accel1);
1662 static void accel_store_edited_cb(GtkCellRendererAccel *accel, gchar *path_string, guint accel_key, GdkModifierType accel_mods, guint hardware_keycode, gpointer user_data)
1664 GtkTreeModel *model = (GtkTreeModel *)accel_store;
1668 GtkAccelKey old_key, key;
1669 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
1671 gtk_tree_model_get_iter(model, &iter, path);
1672 gtk_tree_model_get(model, &iter, AE_ACCEL, &accel_path, -1);
1674 /* test if the accelerator can be stored without conflicts*/
1675 gtk_accel_map_lookup_entry(accel_path, &old_key);
1677 /* change the key and read it back (change may fail on keys hardcoded in gtk)*/
1678 gtk_accel_map_change_entry(accel_path, accel_key, accel_mods, TRUE);
1679 gtk_accel_map_lookup_entry(accel_path, &key);
1681 /* restore the original for now, the key will be really changed when the changes are confirmed */
1682 gtk_accel_map_change_entry(accel_path, old_key.accel_key, old_key.accel_mods, TRUE);
1684 acc = gtk_accelerator_name(key.accel_key, key.accel_mods);
1685 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, acc);
1687 gtk_tree_store_set(accel_store, &iter, AE_KEY, acc, -1);
1688 gtk_tree_path_free(path);
1692 static gboolean accel_default_scroll(GtkTreeView *data)
1696 GtkTreeViewColumn *column;
1698 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(accel_store), &iter);
1699 path = gtk_tree_model_get_path(GTK_TREE_MODEL(accel_store), &iter);
1700 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1702 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1706 gtk_tree_path_free(path);
1711 static void accel_default_cb(GtkWidget *widget, gpointer data)
1713 accel_store_populate();
1715 g_idle_add((GSourceFunc)accel_default_scroll, data);
1718 void accel_remove_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1720 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1723 void accel_reset_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1726 gchar *accel_path, *accel;
1728 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, -1);
1729 gtk_accel_map_lookup_entry(accel_path, &key);
1730 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1732 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, accel);
1734 gtk_tree_store_set(accel_store, iter, AE_KEY, accel, -1);
1739 static void accel_reset_cb(GtkWidget *widget, gpointer data)
1741 GtkTreeSelection *selection;
1743 if (!accel_store) return;
1744 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data));
1745 gtk_tree_selection_selected_foreach(selection, &accel_reset_selection, NULL);
1750 static GtkWidget *scrolled_notebook_page(GtkWidget *notebook, const gchar *title)
1754 GtkWidget *scrolled;
1755 GtkWidget *viewport;
1757 scrolled = gtk_scrolled_window_new(NULL, NULL);
1758 gtk_container_set_border_width(GTK_CONTAINER(scrolled), PREF_PAD_BORDER);
1759 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1760 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1761 label = gtk_label_new(title);
1762 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, label);
1763 gtk_widget_show(scrolled);
1765 viewport = gtk_viewport_new(NULL, NULL);
1766 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1767 gtk_container_add(GTK_CONTAINER(scrolled), viewport);
1768 gtk_widget_show(viewport);
1770 vbox = gtk_vbox_new(FALSE, 0);
1771 gtk_container_add(GTK_CONTAINER(viewport), vbox);
1772 gtk_widget_show(vbox);
1777 static void cache_standard_cb(GtkWidget *widget, gpointer data)
1779 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1781 c_options->thumbnails.spec_standard =TRUE;
1782 c_options->thumbnails.cache_into_dirs = FALSE;
1786 static void cache_geeqie_cb(GtkWidget *widget, gpointer data)
1788 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1790 c_options->thumbnails.spec_standard =FALSE;
1791 c_options->thumbnails.cache_into_dirs = FALSE;
1795 static void cache_local_cb(GtkWidget *widget, gpointer data)
1797 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1799 c_options->thumbnails.cache_into_dirs = TRUE;
1800 c_options->thumbnails.spec_standard =FALSE;
1804 static void help_search_engine_entry_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1805 GdkEvent *event, gpointer userdata)
1807 if (pos == GTK_ENTRY_ICON_PRIMARY)
1809 gtk_entry_set_text(GTK_ENTRY(userdata), HELP_SEARCH_ENGINE);
1813 gtk_entry_set_text(GTK_ENTRY(userdata), "");
1817 static void star_rating_star_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1818 GdkEvent *event, gpointer userdata)
1820 gchar *rating_symbol;
1822 if (pos == GTK_ENTRY_ICON_PRIMARY)
1824 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_STAR);
1825 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1826 g_free(rating_symbol);
1830 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1831 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1832 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1836 static void star_rating_rejected_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1837 GdkEvent *event, gpointer userdata)
1839 gchar *rating_symbol;
1841 if (pos == GTK_ENTRY_ICON_PRIMARY)
1843 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_REJECTED);
1844 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1845 g_free(rating_symbol);
1849 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1850 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1851 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1855 static guint star_rating_symbol_test(GtkWidget *widget, gpointer data)
1857 GtkContainer *hbox = data;
1858 GString *str = g_string_new(NULL);
1859 GtkEntry *hex_code_entry;
1860 gchar *hex_code_full;
1863 guint64 hex_value = 0;
1865 list = gtk_container_get_children(hbox);
1867 hex_code_entry = g_list_nth_data(list, 2);
1868 hex_code_full = g_strdup(gtk_entry_get_text(hex_code_entry));
1870 hex_code = g_strsplit(hex_code_full, "+", 2);
1871 if (hex_code[0] && hex_code[1])
1873 hex_value = strtoull(hex_code[1], NULL, 16);
1875 if (!hex_value || hex_value > 0x10FFFF)
1877 hex_value = 0x003F; // Unicode 'Question Mark'
1879 str = g_string_append_unichar(str, (gunichar)hex_value);
1880 gtk_label_set_text(g_list_nth_data(list, 1), str->str);
1882 g_strfreev(hex_code);
1883 g_string_free(str, TRUE);
1884 g_free(hex_code_full);
1889 static void star_rating_star_test_cb(GtkWidget *widget, gpointer data)
1891 guint64 star_symbol;
1893 star_symbol = star_rating_symbol_test(widget, data);
1894 c_options->star_rating.star = star_symbol;
1897 static void star_rating_rejected_test_cb(GtkWidget *widget, gpointer data)
1899 guint64 rejected_symbol;
1901 rejected_symbol = star_rating_symbol_test(widget, data);
1902 c_options->star_rating.rejected = rejected_symbol;
1905 /* general options tab */
1906 static void timezone_database_install_cb(GtkWidget *widget, gpointer data);
1907 typedef struct _TZData TZData;
1911 GCancellable *cancellable;
1913 GtkWidget *progress;
1915 GFile *timezone_database_gq;
1916 gchar *timezone_database_user;
1919 static void config_tab_general(GtkWidget *notebook)
1924 GtkWidget *group_frame;
1925 GtkWidget *subgroup;
1927 GtkWidget *ct_button;
1930 gint hours, minutes, remainder;
1932 GtkWidget *star_rating_entry;
1934 gchar *rating_symbol;
1937 GNetworkMonitor *net_mon;
1938 GSocketConnectable *geeqie_org;
1939 gboolean internet_available;
1942 vbox = scrolled_notebook_page(notebook, _("General"));
1944 group = pref_group_new(vbox, FALSE, _("Thumbnails"), GTK_ORIENTATION_VERTICAL);
1946 table = pref_table_new(group, 2, 2, FALSE, FALSE);
1947 add_thumb_size_menu(table, 0, 0, _("Size:"));
1948 add_quality_menu(table, 0, 1, _("Quality:"), options->thumbnails.quality, &c_options->thumbnails.quality);
1950 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1951 pref_label_new(hbox, _("Custom size: "));
1952 pref_spin_new_int(hbox, _("Width:"), NULL, 1, 512, 1, options->thumbnails.max_width, &c_options->thumbnails.max_width);
1953 pref_spin_new_int(hbox, _("Height:"), NULL, 1, 512, 1, options->thumbnails.max_height, &c_options->thumbnails.max_height);
1955 ct_button = pref_checkbox_new_int(group, _("Cache thumbnails and sim. files"),
1956 options->thumbnails.enable_caching, &c_options->thumbnails.enable_caching);
1958 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1959 pref_checkbox_link_sensitivity(ct_button, subgroup);
1961 c_options->thumbnails.spec_standard = options->thumbnails.spec_standard;
1962 c_options->thumbnails.cache_into_dirs = options->thumbnails.cache_into_dirs;
1963 group_frame = pref_frame_new(subgroup, TRUE, _("Use Geeqie thumbnail style and cache"),
1964 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1965 button = pref_radiobutton_new(group_frame, NULL, get_thumbnails_cache_dir(),
1966 !options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1967 G_CALLBACK(cache_geeqie_cb), NULL);
1969 group_frame = pref_frame_new(subgroup, TRUE,
1970 _("Store thumbnails local to image folder (non-standard)"),
1971 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1972 pref_radiobutton_new(group_frame, button, "*/.thumbnails",
1973 !options->thumbnails.spec_standard && options->thumbnails.cache_into_dirs,
1974 G_CALLBACK(cache_local_cb), NULL);
1976 group_frame = pref_frame_new(subgroup, TRUE,
1977 _("Use standard thumbnail style and cache, shared with other applications"),
1978 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1979 pref_radiobutton_new(group_frame, button, get_thumbnails_standard_cache_dir(),
1980 options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1981 G_CALLBACK(cache_standard_cb), NULL);
1983 pref_checkbox_new_int(group, _("Use EXIF thumbnails when available (EXIF thumbnails may be outdated)"),
1984 options->thumbnails.use_exif, &c_options->thumbnails.use_exif);
1986 pref_checkbox_new_int(group, _("Thumbnail color management"),
1987 options->thumbnails.use_color_management, &c_options->thumbnails.use_color_management);
1989 spin = pref_spin_new_int(group, _("Collection preview:"), NULL,
1991 options->thumbnails.collection_preview, &c_options->thumbnails.collection_preview);
1992 gtk_widget_set_tooltip_text(spin, _("The maximum number of thumbnails shown in a Collection preview montage"));
1994 #ifdef HAVE_FFMPEGTHUMBNAILER_METADATA
1995 pref_checkbox_new_int(group, _("Use embedded metadata in video files as thumbnails when available"),
1996 options->thumbnails.use_ft_metadata, &c_options->thumbnails.use_ft_metadata);
1998 // pref_checkbox_new_int(group, _("Ignore embedded metadata if size is too small"),
1999 // options->thumbnails.use_ft_metadata_small, &c_options->thumbnails.use_ft_metadata_small);
2002 pref_spacer(group, PREF_PAD_GROUP);
2004 group = pref_group_new(vbox, FALSE, _("Star Rating"), GTK_ORIENTATION_VERTICAL);
2006 c_options->star_rating.star = options->star_rating.star;
2007 c_options->star_rating.rejected = options->star_rating.rejected;
2009 str = g_string_new(NULL);
2010 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2011 pref_label_new(hbox, _("Star character: "));
2012 str = g_string_append_unichar(str, options->star_rating.star);
2013 pref_label_new(hbox, g_strdup(str->str));
2014 rating_symbol = g_strdup_printf("U+%X", options->star_rating.star);
2015 star_rating_entry = gtk_entry_new();
2016 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
2017 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
2018 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
2019 gtk_widget_show(star_rating_entry);
2020 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
2021 G_CALLBACK(star_rating_star_test_cb), hbox);
2022 gtk_widget_set_tooltip_text(button, _("Display selected character"));
2023 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2024 gtk_widget_show(button);
2025 gtk_widget_set_tooltip_text(star_rating_entry, _("Hexadecimal representation of a Unicode character. A list of all Unicode characters may be found on the Internet."));
2026 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2027 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2028 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2029 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2030 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2031 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2032 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2033 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2034 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
2035 G_CALLBACK(star_rating_star_icon_cb),
2038 g_string_free(str, TRUE);
2039 g_free(rating_symbol);
2041 str = g_string_new(NULL);
2042 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2043 pref_label_new(hbox, _("Rejected character: "));
2044 str = g_string_append_unichar(str, options->star_rating.rejected);
2045 pref_label_new(hbox, g_strdup(str->str));
2046 rating_symbol = g_strdup_printf("U+%X", options->star_rating.rejected);
2047 star_rating_entry = gtk_entry_new();
2048 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
2049 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
2050 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
2051 gtk_widget_show(star_rating_entry);
2052 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
2053 G_CALLBACK(star_rating_rejected_test_cb), hbox);
2054 gtk_widget_set_tooltip_text(button, _("Display selected character"));
2055 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2056 gtk_widget_show(button);
2057 gtk_widget_set_tooltip_text(star_rating_entry, _("Hexadecimal representation of a Unicode character. A list of all Unicode characters may be found on the Internet."));
2058 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2059 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2060 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2061 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2062 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2063 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2064 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2065 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2066 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
2067 G_CALLBACK(star_rating_rejected_icon_cb),
2070 g_string_free(str, TRUE);
2071 g_free(rating_symbol);
2073 pref_spacer(group, PREF_PAD_GROUP);
2075 group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
2077 c_options->slideshow.delay = options->slideshow.delay;
2078 hours = options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2079 remainder = options->slideshow.delay % (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2080 minutes = remainder / (60 * SLIDESHOW_SUBSECOND_PRECISION);
2081 seconds = (gdouble)(remainder % (60 * SLIDESHOW_SUBSECOND_PRECISION)) /
2082 SLIDESHOW_SUBSECOND_PRECISION;
2084 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2086 spin = pref_spin_new(hbox, _("Delay between image change hrs:mins:secs.dec"), NULL,
2088 options->slideshow.delay ? hours : 0.0,
2089 G_CALLBACK(slideshow_delay_hours_cb), NULL);
2090 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2091 spin = pref_spin_new(hbox, ":" , NULL,
2093 options->slideshow.delay ? minutes: 0.0,
2094 G_CALLBACK(slideshow_delay_minutes_cb), NULL);
2095 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2096 spin = pref_spin_new(hbox, ":", NULL,
2097 SLIDESHOW_MIN_SECONDS, 59, 1.0, 1,
2098 options->slideshow.delay ? seconds : 10.0,
2099 G_CALLBACK(slideshow_delay_seconds_cb), NULL);
2100 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2102 pref_checkbox_new_int(group, _("Random"), options->slideshow.random, &c_options->slideshow.random);
2103 pref_checkbox_new_int(group, _("Repeat"), options->slideshow.repeat, &c_options->slideshow.repeat);
2105 pref_spacer(group, PREF_PAD_GROUP);
2107 group = pref_group_new(vbox, FALSE, _("Image loading and caching"), GTK_ORIENTATION_VERTICAL);
2109 pref_spin_new_int(group, _("Decoded image cache size (MiB):"), NULL,
2110 0, 99999, 1, options->image.image_cache_max, &c_options->image.image_cache_max);
2111 pref_checkbox_new_int(group, _("Preload next image"),
2112 options->image.enable_read_ahead, &c_options->image.enable_read_ahead);
2114 pref_checkbox_new_int(group, _("Refresh on file change"),
2115 options->update_on_time_change, &c_options->update_on_time_change);
2118 pref_spacer(group, PREF_PAD_GROUP);
2120 group = pref_group_new(vbox, FALSE, _("Expand menu and toolbar"), GTK_ORIENTATION_VERTICAL);
2122 pref_checkbox_new_int(group, _("Expand menu and toolbar (NOTE! Geeqie must be restarted for change to take effect)"),
2123 options->expand_menu_toolbar, &c_options->expand_menu_toolbar);
2124 gtk_widget_set_tooltip_text(group, _("Expand the menu and toolbar to the full width of the window"));
2126 pref_spacer(group, PREF_PAD_GROUP);
2128 group = pref_group_new(vbox, FALSE, _("Info sidebar heights"), GTK_ORIENTATION_VERTICAL);
2129 pref_label_new(group, _("NOTE! Geeqie must be restarted for changes to take effect"));
2130 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2131 pref_spin_new_int(hbox, _("Keywords:"), NULL,
2133 options->info_keywords.height, &c_options->info_keywords.height);
2134 pref_spin_new_int(hbox, _("Title:"), NULL,
2136 options->info_title.height, &c_options->info_title.height);
2137 pref_spin_new_int(hbox, _("Comment:"), NULL,
2139 options->info_comment.height, &c_options->info_comment.height);
2140 pref_spin_new_int(hbox, _("Rating:"), NULL,
2142 options->info_rating.height, &c_options->info_rating.height);
2144 pref_spacer(group, PREF_PAD_GROUP);
2146 group = pref_group_new(vbox, FALSE, _("Show predefined keyword tree"), GTK_ORIENTATION_VERTICAL);
2148 pref_checkbox_new_int(group, _("Show predefined keyword tree (NOTE! Geeqie must be restarted for change to take effect)"),
2149 options->show_predefined_keyword_tree, &c_options->show_predefined_keyword_tree);
2151 pref_spacer(group, PREF_PAD_GROUP);
2153 net_mon = g_network_monitor_get_default();
2154 geeqie_org = g_network_address_parse_uri(GQ_WEBSITE, 80, NULL);
2155 internet_available = g_network_monitor_can_reach(net_mon, geeqie_org, NULL, NULL);
2156 g_object_unref(geeqie_org);
2158 group = pref_group_new(vbox, FALSE, _("Timezone database"), GTK_ORIENTATION_VERTICAL);
2159 hbox = pref_box_new(group, TRUE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2161 if (!internet_available)
2163 gtk_widget_set_sensitive(group, FALSE);
2166 tz = g_new0(TZData, 1);
2168 path = path_from_utf8(TIMEZONE_DATABASE);
2169 basename = g_path_get_basename(path);
2170 tz->timezone_database_user = g_build_filename(get_rc_dir(), basename, NULL);
2174 if (isfile(tz->timezone_database_user))
2176 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Update"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2180 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Install"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2183 if (!internet_available)
2185 gtk_widget_set_tooltip_text(button, _("No Internet connection!\nThe timezone database is used to display exif time and date\ncorrected for UTC offset and Daylight Saving Time"));
2189 gtk_widget_set_tooltip_text(button, _("The timezone database is used to display exif time and date\ncorrected for UTC offset and Daylight Saving Time"));
2191 gtk_widget_show(button);
2193 pref_spacer(group, PREF_PAD_GROUP);
2195 group = pref_group_new(vbox, FALSE, _("On-line help search engine"), GTK_ORIENTATION_VERTICAL);
2197 help_search_engine_entry = gtk_entry_new();
2198 gtk_entry_set_text(GTK_ENTRY(help_search_engine_entry), options->help_search_engine);
2199 gtk_box_pack_start(GTK_BOX(group), help_search_engine_entry, FALSE, FALSE, 0);
2200 gtk_widget_show(help_search_engine_entry);
2202 gtk_widget_set_tooltip_text(help_search_engine_entry, _("The format varies between search engines, e.g the format may be:\nhttps://www.search_engine.com/search?q=site:geeqie.org/help\nhttps://www.search_engine.com/?q=site:geeqie.org/help"));
2204 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2205 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2206 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2207 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2208 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2209 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2210 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2211 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2212 g_signal_connect(GTK_ENTRY(help_search_engine_entry), "icon-press",
2213 G_CALLBACK(help_search_engine_entry_icon_cb),
2214 help_search_engine_entry);
2218 static void config_tab_image(GtkWidget *notebook)
2223 GtkWidget *ct_button;
2224 GtkWidget *enlargement_button;
2227 GtkWidget *two_pass;
2229 GtkWidget *gpu_accel;
2232 vbox = scrolled_notebook_page(notebook, _("Image"));
2234 group = pref_group_new(vbox, FALSE, _("Zoom"), GTK_ORIENTATION_VERTICAL);
2236 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2237 add_quality_menu(table, 0, 0, _("Quality:"), options->image.zoom_quality, &c_options->image.zoom_quality);
2238 if (options->image.use_clutter_renderer && !options->disable_gpu)
2240 gtk_widget_set_sensitive(table, FALSE);
2244 gpu_accel = pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library (Requires restart)"),
2245 options->image.use_clutter_renderer, &c_options->image.use_clutter_renderer);
2246 if (options->disable_gpu && !options->override_disable_gpu)
2248 gtk_widget_set_sensitive(gpu_accel, FALSE);
2252 two_pass = pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"),
2253 options->image.zoom_2pass, &c_options->image.zoom_2pass);
2254 if (options->image.use_clutter_renderer && !options->disable_gpu)
2256 gtk_widget_set_sensitive(two_pass, FALSE);
2259 c_options->image.zoom_increment = options->image.zoom_increment;
2260 spin = pref_spin_new(group, _("Zoom increment:"), NULL,
2261 0.01, 4.0, 0.01, 2, (gdouble)options->image.zoom_increment / 100.0,
2262 G_CALLBACK(zoom_increment_cb), NULL);
2263 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2265 group = pref_group_new(vbox, FALSE, _("Fit image to window"), GTK_ORIENTATION_VERTICAL);
2267 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2268 enlargement_button = pref_checkbox_new_int(hbox, _("Allow enlargement of image (max. size in %)"),
2269 options->image.zoom_to_fit_allow_expand, &c_options->image.zoom_to_fit_allow_expand);
2270 spin = pref_spin_new_int(hbox, NULL, NULL,
2272 options->image.max_enlargement_size, &c_options->image.max_enlargement_size);
2273 pref_checkbox_link_sensitivity(enlargement_button, spin);
2274 gtk_widget_set_tooltip_text(GTK_WIDGET(hbox), _("Enable this to allow Geeqie to increase the image size for images that are smaller than the current view area when the zoom is set to \"Fit image to window\". This value sets the maximum expansion permitted in percent i.e. 100% is full-size."));
2276 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2277 ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (% of actual window):"),
2278 options->image.limit_autofit_size, &c_options->image.limit_autofit_size);
2279 spin = pref_spin_new_int(hbox, NULL, NULL,
2281 options->image.max_autofit_size, &c_options->image.max_autofit_size);
2282 pref_checkbox_link_sensitivity(ct_button, spin);
2283 gtk_widget_set_tooltip_text(GTK_WIDGET(hbox), _("This value will set the virtual size of the window when \"Fit image to window\" is set. Instead of using the actual size of the window, the specified percentage of the window will be used. It allows one to keep a border around the image (values lower than 100%) or to auto zoom the image (values greater than 100%). It affects fullscreen mode too."));
2285 group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
2287 pref_checkbox_new_int(group, _("Use custom border color in window mode"),
2288 options->image.use_custom_border_color, &c_options->image.use_custom_border_color);
2290 pref_checkbox_new_int(group, _("Use custom border color in fullscreen mode"),
2291 options->image.use_custom_border_color_in_fullscreen, &c_options->image.use_custom_border_color_in_fullscreen);
2293 pref_color_button_new(group, _("Border color"), &options->image.border_color,
2294 G_CALLBACK(pref_color_button_set_cb), &c_options->image.border_color);
2296 c_options->image.border_color = options->image.border_color;
2298 pref_color_button_new(group, _("Alpha channel color 1"), &options->image.alpha_color_1,
2299 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_1);
2301 pref_color_button_new(group, _("Alpha channel color 2"), &options->image.alpha_color_2,
2302 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_2);
2304 c_options->image.alpha_color_1 = options->image.alpha_color_1;
2305 c_options->image.alpha_color_2 = options->image.alpha_color_2;
2307 group = pref_group_new(vbox, FALSE, _("Convenience"), GTK_ORIENTATION_VERTICAL);
2309 pref_checkbox_new_int(group, _("Auto rotate proofs using Exif information"),
2310 options->image.exif_proof_rotate_enable, &c_options->image.exif_proof_rotate_enable);
2315 static void save_default_window_layout_cb(GtkWidget *widget, gpointer data)
2317 LayoutWindow *lw = NULL;
2318 gchar *default_path;
2321 /* Get current lw */
2324 tmp_id = lw->options.id;
2325 lw->options.id = g_strdup("lw_default");
2327 default_path = g_build_filename(get_rc_dir(), DEFAULT_WINDOW_LAYOUT, NULL);
2328 save_default_layout_options_to_file(default_path, options, lw);
2329 g_free(lw->options.id);
2330 lw->options.id = tmp_id;
2331 g_free(default_path);
2334 static void config_tab_windows(GtkWidget *notebook)
2339 GtkWidget *subgroup;
2341 GtkWidget *ct_button;
2344 vbox = scrolled_notebook_page(notebook, _("Windows"));
2346 group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
2348 ct_button = pref_checkbox_new_int(group, _("Remember session"),
2349 options->save_window_positions, &c_options->save_window_positions);
2351 button = pref_checkbox_new_int(group, _("Use saved window positions also for new windows"),
2352 options->use_saved_window_positions_for_new_windows, &c_options->use_saved_window_positions_for_new_windows);
2353 pref_checkbox_link_sensitivity(ct_button, button);
2355 button = pref_checkbox_new_int(group, _("Remember window workspace"),
2356 options->save_window_workspace, &c_options->save_window_workspace);
2357 pref_checkbox_link_sensitivity(ct_button, button);
2359 pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
2360 options->tools_restore_state, &c_options->tools_restore_state);
2362 pref_checkbox_new_int(group, _("Remember dialog window positions"),
2363 options->save_dialog_window_positions, &c_options->save_dialog_window_positions);
2365 pref_checkbox_new_int(group, _("Show window IDs"),
2366 options->show_window_ids, &c_options->show_window_ids);
2368 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2369 pref_label_new(subgroup, _("Use current layout for default: "));
2370 button = pref_button_new(subgroup, NULL, _("Set"), FALSE, G_CALLBACK(save_default_window_layout_cb), NULL);
2372 group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
2374 pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
2375 options->image.fit_window_to_image, &c_options->image.fit_window_to_image);
2377 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2378 ct_button = pref_checkbox_new_int(hbox, _("Limit size when auto-sizing window (%):"),
2379 options->image.limit_window_size, &c_options->image.limit_window_size);
2380 spin = pref_spin_new_int(hbox, NULL, NULL,
2382 options->image.max_window_size, &c_options->image.max_window_size);
2383 pref_checkbox_link_sensitivity(ct_button, spin);
2385 group = pref_group_new(vbox, FALSE, _("Full screen"), GTK_ORIENTATION_VERTICAL);
2387 c_options->fullscreen.screen = options->fullscreen.screen;
2388 c_options->fullscreen.above = options->fullscreen.above;
2389 hbox = fullscreen_prefs_selection_new(_("Location:"), &c_options->fullscreen.screen, &c_options->fullscreen.above);
2390 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2391 gtk_widget_show(hbox);
2393 pref_checkbox_new_int(group, _("Smooth image flip"),
2394 options->fullscreen.clean_flip, &c_options->fullscreen.clean_flip);
2395 pref_checkbox_new_int(group, _("Disable screen saver"),
2396 options->fullscreen.disable_saver, &c_options->fullscreen.disable_saver);
2399 #define PRE_FORMATTED_COLUMNS 5
2400 static void config_tab_osd(GtkWidget *notebook)
2406 GtkWidget *image_overlay_template_view;
2407 GtkWidget *scrolled;
2408 GtkWidget *scrolled_pre_formatted;
2409 GtkTextBuffer *buffer;
2411 GtkWidget *subgroup;
2413 vbox = scrolled_notebook_page(notebook, _("OSD"));
2415 image_overlay_template_view = gtk_text_view_new();
2417 group = pref_group_new(vbox, FALSE, _("Overlay Screen Display"), GTK_ORIENTATION_VERTICAL);
2419 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2421 scrolled_pre_formatted = osd_new(PRE_FORMATTED_COLUMNS, image_overlay_template_view);
2422 gtk_widget_set_size_request(scrolled_pre_formatted, 200, 150);
2423 gtk_box_pack_start(GTK_BOX(subgroup), scrolled_pre_formatted, FALSE, FALSE, 0);
2424 gtk_widget_show(scrolled_pre_formatted);
2425 gtk_widget_show(subgroup);
2427 pref_line(group, PREF_PAD_GAP);
2429 pref_label_new(group, _("Image overlay template"));
2431 scrolled = gtk_scrolled_window_new(NULL, NULL);
2432 gtk_widget_set_size_request(scrolled, 200, 150);
2433 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2434 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
2435 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2436 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 5);
2437 gtk_widget_show(scrolled);
2439 gtk_widget_set_tooltip_markup(image_overlay_template_view,
2440 _("Extensive formatting options are shown in the Help file"));
2442 gtk_container_add(GTK_CONTAINER(scrolled), image_overlay_template_view);
2443 gtk_widget_show(image_overlay_template_view);
2445 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2447 #if GTK_CHECK_VERSION(3,4,0)
2448 button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
2449 G_CALLBACK(image_overlay_set_font_cb), notebook);
2451 button = gtk_font_button_new();
2452 gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Image Overlay Font");
2453 gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->image_overlay.font);
2454 g_signal_connect(G_OBJECT(button), "font-set",
2455 G_CALLBACK(image_overlay_set_font_cb),NULL);
2457 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2458 gtk_widget_show(button);
2460 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Text"), FALSE,
2461 G_CALLBACK(image_overlay_set_text_colour_cb), NULL);
2462 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2463 gtk_widget_show(button);
2465 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Background"), FALSE,
2466 G_CALLBACK(image_overlay_set_background_colour_cb), NULL);
2467 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2468 gtk_widget_show(button);
2469 image_overlay_set_text_colours();
2471 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2472 G_CALLBACK(image_overlay_default_template_cb), image_overlay_template_view);
2473 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2474 gtk_widget_show(button);
2476 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
2477 G_CALLBACK(image_overlay_help_cb), NULL);
2478 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2479 gtk_widget_show(button);
2481 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_overlay_template_view));
2482 if (options->image_overlay.template_string) gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
2483 g_signal_connect(G_OBJECT(buffer), "changed",
2484 G_CALLBACK(image_overlay_template_view_changed_cb), image_overlay_template_view);
2486 pref_line(group, PREF_PAD_GAP);
2488 group = pref_group_new(vbox, FALSE, _("Exif, XMP or IPTC tags"), GTK_ORIENTATION_VERTICAL);
2489 hbox = gtk_hbox_new(FALSE, 0);
2490 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2491 gtk_widget_show(hbox);
2492 label = gtk_label_new(_("%Exif.Image.Orientation%"));
2493 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2494 gtk_widget_show(label);
2495 pref_spacer(group,TRUE);
2497 group = pref_group_new(vbox, FALSE, _("Field separators"), GTK_ORIENTATION_VERTICAL);
2498 hbox = gtk_hbox_new(FALSE, 0);
2499 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2500 gtk_widget_show(hbox);
2501 label = gtk_label_new(_("Separator shown only if both fields are non-null:\n%formatted.ShutterSpeed%|%formatted.ISOSpeedRating%"));
2502 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2503 gtk_widget_show(label);
2504 pref_spacer(group,TRUE);
2506 group = pref_group_new(vbox, FALSE, _("Field maximum length"), GTK_ORIENTATION_VERTICAL);
2507 hbox = gtk_hbox_new(FALSE, 0);
2508 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2509 gtk_widget_show(hbox);
2510 label = gtk_label_new(_("%path:39%"));
2511 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2512 gtk_widget_show(label);
2513 pref_spacer(group,TRUE);
2515 group = pref_group_new(vbox, FALSE, _("Pre- and post- text"), GTK_ORIENTATION_VERTICAL);
2516 hbox = gtk_hbox_new(FALSE, 0);
2517 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2518 gtk_widget_show(hbox);
2519 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%"));
2520 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2521 gtk_widget_show(label);
2522 pref_spacer(group,TRUE);
2524 group = pref_group_new(vbox, FALSE, _("Pango markup"), GTK_ORIENTATION_VERTICAL);
2525 hbox = gtk_hbox_new(FALSE, 0);
2526 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2527 gtk_widget_show(hbox);
2528 label = gtk_label_new(_("<b>bold</b>\n<u>underline</u>\n<i>italic</i>\n<s>strikethrough</s>"));
2529 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2530 gtk_widget_show(label);
2533 static GtkTreeModel *create_class_model(void)
2535 GtkListStore *model;
2539 /* create list store */
2540 model = gtk_list_store_new(1, G_TYPE_STRING);
2541 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
2543 gtk_list_store_append(model, &iter);
2544 gtk_list_store_set(model, &iter, 0, _(format_class_list[i]), -1);
2546 return GTK_TREE_MODEL (model);
2551 static void config_tab_files(GtkWidget *notebook)
2558 GtkWidget *ct_button;
2559 GtkWidget *scrolled;
2560 GtkWidget *filter_view;
2561 GtkCellRenderer *renderer;
2562 GtkTreeSelection *selection;
2563 GtkTreeViewColumn *column;
2565 vbox = scrolled_notebook_page(notebook, _("Files"));
2567 group = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2569 pref_checkbox_new_int(group, _("Show hidden files or folders"),
2570 options->file_filter.show_hidden_files, &c_options->file_filter.show_hidden_files);
2571 pref_checkbox_new_int(group, _("Show parent folder (..)"),
2572 options->file_filter.show_parent_directory, &c_options->file_filter.show_parent_directory);
2573 pref_checkbox_new_int(group, _("Case sensitive sort"),
2574 options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
2575 pref_checkbox_new_int(group, _("Natural sort order"),
2576 options->file_sort.natural, &c_options->file_sort.natural);
2577 pref_checkbox_new_int(group, _("Disable file extension checks"),
2578 options->file_filter.disable_file_extension_checks, &c_options->file_filter.disable_file_extension_checks);
2580 ct_button = pref_checkbox_new_int(group, _("Disable File Filtering"),
2581 options->file_filter.disable, &c_options->file_filter.disable);
2584 group = pref_group_new(vbox, FALSE, _("Grouping sidecar extensions"), GTK_ORIENTATION_VERTICAL);
2586 sidecar_ext_entry = gtk_entry_new();
2587 gtk_entry_set_text(GTK_ENTRY(sidecar_ext_entry), options->sidecar.ext);
2588 gtk_box_pack_start(GTK_BOX(group), sidecar_ext_entry, FALSE, FALSE, 0);
2589 gtk_widget_show(sidecar_ext_entry);
2591 group = pref_group_new(vbox, TRUE, _("File types"), GTK_ORIENTATION_VERTICAL);
2593 frame = pref_group_parent(group);
2594 g_signal_connect(G_OBJECT(ct_button), "toggled",
2595 G_CALLBACK(filter_disable_cb), frame);
2596 gtk_widget_set_sensitive(frame, !options->file_filter.disable);
2598 scrolled = gtk_scrolled_window_new(NULL, NULL);
2599 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2600 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2601 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2602 gtk_widget_show(scrolled);
2604 filter_store = gtk_list_store_new(1, G_TYPE_POINTER);
2605 filter_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(filter_store));
2606 g_object_unref(filter_store);
2607 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
2608 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
2610 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), FALSE);
2612 column = gtk_tree_view_column_new();
2613 gtk_tree_view_column_set_title(column, _("Filter"));
2614 gtk_tree_view_column_set_resizable(column, TRUE);
2616 renderer = gtk_cell_renderer_toggle_new();
2617 g_signal_connect(G_OBJECT(renderer), "toggled",
2618 G_CALLBACK(filter_store_enable_cb), filter_store);
2619 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2620 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2621 GINT_TO_POINTER(FE_ENABLE), NULL);
2623 renderer = gtk_cell_renderer_text_new();
2624 g_signal_connect(G_OBJECT(renderer), "edited",
2625 G_CALLBACK(filter_store_ext_edit_cb), filter_store);
2626 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2627 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2628 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2629 GINT_TO_POINTER(FE_EXTENSION), NULL);
2630 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2632 column = gtk_tree_view_column_new();
2633 gtk_tree_view_column_set_title(column, _("Description"));
2634 gtk_tree_view_column_set_resizable(column, TRUE);
2635 gtk_tree_view_column_set_fixed_width(column, 200);
2636 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
2638 renderer = gtk_cell_renderer_text_new();
2639 g_signal_connect(G_OBJECT(renderer), "edited",
2640 G_CALLBACK(filter_store_desc_edit_cb), filter_store);
2641 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2642 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2643 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2644 GINT_TO_POINTER(FE_DESCRIPTION), NULL);
2645 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2647 column = gtk_tree_view_column_new();
2648 gtk_tree_view_column_set_title(column, _("Class"));
2649 gtk_tree_view_column_set_resizable(column, TRUE);
2650 renderer = gtk_cell_renderer_combo_new();
2651 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE,
2652 "model", create_class_model(),
2657 g_signal_connect(G_OBJECT(renderer), "edited",
2658 G_CALLBACK(filter_store_class_edit_cb), filter_store);
2659 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2660 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2661 GINT_TO_POINTER(FE_CLASS), NULL);
2662 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2664 column = gtk_tree_view_column_new();
2665 gtk_tree_view_column_set_title(column, _("Writable"));
2666 gtk_tree_view_column_set_resizable(column, FALSE);
2667 renderer = gtk_cell_renderer_toggle_new();
2668 g_signal_connect(G_OBJECT(renderer), "toggled",
2669 G_CALLBACK(filter_store_writable_cb), filter_store);
2670 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2671 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2672 GINT_TO_POINTER(FE_WRITABLE), NULL);
2673 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2675 column = gtk_tree_view_column_new();
2676 gtk_tree_view_column_set_title(column, _("Sidecar is allowed"));
2677 gtk_tree_view_column_set_resizable(column, FALSE);
2678 renderer = gtk_cell_renderer_toggle_new();
2679 g_signal_connect(G_OBJECT(renderer), "toggled",
2680 G_CALLBACK(filter_store_sidecar_cb), filter_store);
2681 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2682 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2683 GINT_TO_POINTER(FE_ALLOW_SIDECAR), NULL);
2684 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2687 filter_store_populate();
2688 gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
2689 gtk_widget_show(filter_view);
2691 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2693 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2694 G_CALLBACK(filter_default_cb), filter_view);
2695 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2696 gtk_widget_show(button);
2698 button = pref_button_new(NULL, GTK_STOCK_REMOVE, NULL, FALSE,
2699 G_CALLBACK(filter_remove_cb), filter_view);
2700 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2701 gtk_widget_show(button);
2703 button = pref_button_new(NULL, GTK_STOCK_ADD, NULL, FALSE,
2704 G_CALLBACK(filter_add_cb), filter_view);
2705 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2706 gtk_widget_show(button);
2710 static void config_tab_metadata(GtkWidget *notebook)
2715 GtkWidget *ct_button;
2719 vbox = scrolled_notebook_page(notebook, _("Metadata"));
2722 group = pref_group_new(vbox, FALSE, _("Metadata writing process"), GTK_ORIENTATION_VERTICAL);
2724 label = pref_label_new(group, _("Warning: Geeqie is built without Exiv2. Some options are disabled."));
2726 label = pref_label_new(group, _("Metadata are written in the following order. The process ends after first success."));
2727 #if GTK_CHECK_VERSION(3,16,0)
2728 gtk_label_set_xalign(GTK_LABEL(label), 0.0);
2729 gtk_label_set_yalign(GTK_LABEL(label), 0.5);
2731 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2734 ct_button = pref_checkbox_new_int(group, _("1) Save metadata in image files, or sidecar files, according to the XMP standard"),
2735 options->metadata.save_in_image_file, &c_options->metadata.save_in_image_file);
2737 gtk_widget_set_sensitive(ct_button, FALSE);
2740 pref_checkbox_new_int(group, _("2) Save metadata in '.metadata' folder, local to image folder (non-standard)"),
2741 options->metadata.enable_metadata_dirs, &c_options->metadata.enable_metadata_dirs);
2743 text = g_strdup_printf(_("3) Save metadata in Geeqie private directory '%s'"), get_metadata_cache_dir());
2744 label = pref_label_new(group, text);
2745 #if GTK_CHECK_VERSION(3,16,0)
2746 gtk_label_set_xalign(GTK_LABEL(label), 0.0);
2747 gtk_label_set_yalign(GTK_LABEL(label), 0.5);
2749 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2751 gtk_misc_set_padding(GTK_MISC(label), 22, 0);
2754 group = pref_group_new(vbox, FALSE, _("Step 1: Write to image files"), GTK_ORIENTATION_VERTICAL);
2756 gtk_widget_set_sensitive(group, FALSE);
2759 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2760 pref_checkbox_link_sensitivity(ct_button, hbox);
2762 pref_checkbox_new_int(hbox, _("Store metadata also in legacy IPTC tags (converted according to IPTC4XMP standard)"),
2763 options->metadata.save_legacy_IPTC, &c_options->metadata.save_legacy_IPTC);
2765 pref_checkbox_new_int(hbox, _("Warn if the image files are unwritable"),
2766 options->metadata.warn_on_write_problems, &c_options->metadata.warn_on_write_problems);
2768 pref_checkbox_new_int(hbox, _("Ask before writing to image files"),
2769 options->metadata.confirm_write, &c_options->metadata.confirm_write);
2771 pref_checkbox_new_int(hbox, _("Create sidecar files named image.ext.xmp (as opposed to image.xmp)"),
2772 options->metadata.sidecar_extended_name, &c_options->metadata.sidecar_extended_name);
2774 group = pref_group_new(vbox, FALSE, _("Step 2 and 3: write to Geeqie private files"), GTK_ORIENTATION_VERTICAL);
2776 gtk_widget_set_sensitive(group, FALSE);
2779 pref_checkbox_new_int(group, _("Use GQview legacy metadata format (supports only keywords and comments) instead of XMP"),
2780 options->metadata.save_legacy_format, &c_options->metadata.save_legacy_format);
2783 group = pref_group_new(vbox, FALSE, _("Miscellaneous"), GTK_ORIENTATION_VERTICAL);
2784 pref_checkbox_new_int(group, _("Write the same description tags (keywords, comment, etc.) to all grouped sidecars"),
2785 options->metadata.sync_grouped_files, &c_options->metadata.sync_grouped_files);
2787 pref_checkbox_new_int(group, _("Allow keywords to differ only in case"),
2788 options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
2790 ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"),
2791 options->metadata.write_orientation, &c_options->metadata.write_orientation);
2793 gtk_widget_set_sensitive(ct_button, FALSE);
2796 group = pref_group_new(vbox, FALSE, _("Auto-save options"), GTK_ORIENTATION_VERTICAL);
2798 ct_button = pref_checkbox_new_int(group, _("Write metadata after timeout"),
2799 options->metadata.confirm_after_timeout, &c_options->metadata.confirm_after_timeout);
2801 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2802 pref_checkbox_link_sensitivity(ct_button, hbox);
2804 pref_spin_new_int(hbox, _("Timeout (seconds):"), NULL, 0, 900, 1,
2805 options->metadata.confirm_timeout, &c_options->metadata.confirm_timeout);
2807 pref_checkbox_new_int(group, _("Write metadata on image change"),
2808 options->metadata.confirm_on_image_change, &c_options->metadata.confirm_on_image_change);
2810 pref_checkbox_new_int(group, _("Write metadata on directory change"),
2811 options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
2813 group = pref_group_new(vbox, FALSE, _("Pre-load metadata"), GTK_ORIENTATION_VERTICAL);
2815 ct_button = pref_checkbox_new_int(group, _("Read metadata in background"),
2816 options->read_metadata_in_idle, &c_options->read_metadata_in_idle);
2817 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");
2822 typedef struct _KeywordFindData KeywordFindData;
2823 struct _KeywordFindData
2830 GtkWidget *button_close;
2831 GtkWidget *button_stop;
2832 GtkWidget *button_start;
2833 GtkWidget *progress;
2841 guint idle_id; /* event source id */
2844 #define KEYWORD_DIALOG_WIDTH 400
2846 static void keywords_find_folder(KeywordFindData *kfd, FileData *dir_fd)
2848 GList *list_d = NULL;
2849 GList *list_f = NULL;
2853 filelist_read(dir_fd, &list_f, &list_d);
2857 filelist_read(dir_fd, &list_f, NULL);
2860 list_f = filelist_filter(list_f, FALSE);
2861 list_d = filelist_filter(list_d, TRUE);
2863 kfd->list = g_list_concat(list_f, kfd->list);
2864 kfd->list_dir = g_list_concat(list_d, kfd->list_dir);
2867 static void keywords_find_reset(KeywordFindData *kfd)
2869 filelist_free(kfd->list);
2872 filelist_free(kfd->list_dir);
2873 kfd->list_dir = NULL;
2876 static void keywords_find_close_cb(GenericDialog *fd, gpointer data)
2878 KeywordFindData *kfd = data;
2880 if (!gtk_widget_get_sensitive(kfd->button_close)) return;
2882 keywords_find_reset(kfd);
2883 generic_dialog_close(kfd->gd);
2887 static void keywords_find_finish(KeywordFindData *kfd)
2889 keywords_find_reset(kfd);
2891 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("done"));
2892 spinner_set_interval(kfd->spinner, -1);
2894 gtk_widget_set_sensitive(kfd->group, TRUE);
2895 gtk_widget_set_sensitive(kfd->button_start, TRUE);
2896 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2897 gtk_widget_set_sensitive(kfd->button_close, TRUE);
2900 static void keywords_find_stop_cb(GenericDialog *fd, gpointer data)
2902 KeywordFindData *kfd = data;
2904 g_idle_remove_by_data(kfd);
2906 keywords_find_finish(kfd);
2909 static gboolean keywords_find_file(gpointer data)
2911 KeywordFindData *kfd = data;
2913 GtkTextBuffer *buffer;
2921 fd = kfd->list->data;
2922 kfd->list = g_list_remove(kfd->list, fd);
2924 keywords = metadata_read_list(fd, KEYWORD_KEY, METADATA_PLAIN);
2925 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2929 gtk_text_buffer_get_end_iter(buffer, &iter);
2930 tmp = g_strconcat(keywords->data, "\n", NULL);
2931 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
2933 keywords = keywords->next;
2936 gtk_entry_set_text(GTK_ENTRY(kfd->progress), fd->path);
2937 file_data_unref(fd);
2938 string_list_free(keywords);
2942 else if (kfd->list_dir)
2946 fd = kfd->list_dir->data;
2947 kfd->list_dir = g_list_remove(kfd->list_dir, fd);
2949 keywords_find_folder(kfd, fd);
2951 file_data_unref(fd);
2956 keywords_find_finish(kfd);
2961 static void keywords_find_start_cb(GenericDialog *fd, gpointer data)
2963 KeywordFindData *kfd = data;
2966 if (kfd->list || !gtk_widget_get_sensitive(kfd->button_start)) return;
2968 path = remove_trailing_slash((gtk_entry_get_text(GTK_ENTRY(kfd->entry))));
2969 parse_out_relatives(path);
2973 warning_dialog(_("Invalid folder"),
2974 _("The specified folder can not be found."),
2975 GTK_STOCK_DIALOG_WARNING, kfd->gd->dialog);
2981 gtk_widget_set_sensitive(kfd->group, FALSE);
2982 gtk_widget_set_sensitive(kfd->button_start, FALSE);
2983 gtk_widget_set_sensitive(kfd->button_stop, TRUE);
2984 gtk_widget_set_sensitive(kfd->button_close, FALSE);
2985 spinner_set_interval(kfd->spinner, SPINNER_SPEED);
2987 dir_fd = file_data_new_dir(path);
2988 keywords_find_folder(kfd, dir_fd);
2989 file_data_unref(dir_fd);
2990 kfd->idle_id = g_idle_add(keywords_find_file, kfd);
2996 static void keywords_find_dialog(GtkWidget *widget, const gchar *path)
2998 KeywordFindData *kfd;
3002 kfd = g_new0(KeywordFindData, 1);
3004 kfd->gd = generic_dialog_new(_("Search for keywords"),
3005 "search_for_keywords",
3008 gtk_window_set_default_size(GTK_WINDOW(kfd->gd->dialog), KEYWORD_DIALOG_WIDTH, -1);
3009 kfd->gd->cancel_cb = keywords_find_close_cb;
3010 kfd->button_close = generic_dialog_add_button(kfd->gd, GTK_STOCK_CLOSE, NULL,
3011 keywords_find_close_cb, FALSE);
3012 kfd->button_start = generic_dialog_add_button(kfd->gd, GTK_STOCK_OK, _("S_tart"),
3013 keywords_find_start_cb, FALSE);
3014 kfd->button_stop = generic_dialog_add_button(kfd->gd, GTK_STOCK_STOP, NULL,
3015 keywords_find_stop_cb, FALSE);
3016 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
3018 generic_dialog_add_message(kfd->gd, NULL, _("Search for keywords"), NULL, FALSE);
3020 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0);
3021 pref_spacer(hbox, PREF_PAD_INDENT);
3022 kfd->group = pref_box_new(hbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
3024 hbox = pref_box_new(kfd->group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3025 pref_label_new(hbox, _("Folder:"));
3027 label = tab_completion_new(&kfd->entry, path, NULL, NULL, NULL, NULL);
3028 tab_completion_add_select_button(kfd->entry,_("Select folder") , TRUE);
3029 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
3030 gtk_widget_show(label);
3032 pref_checkbox_new_int(kfd->group, _("Include subfolders"), FALSE, &kfd->recurse);
3034 pref_line(kfd->gd->vbox, PREF_PAD_SPACE);
3035 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3037 kfd->progress = gtk_entry_new();
3038 gtk_widget_set_can_focus(kfd->progress, FALSE);
3039 gtk_editable_set_editable(GTK_EDITABLE(kfd->progress), FALSE);
3040 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("click start to begin"));
3041 gtk_box_pack_start(GTK_BOX(hbox), kfd->progress, TRUE, TRUE, 0);
3042 gtk_widget_show(kfd->progress);
3044 kfd->spinner = spinner_new(NULL, -1);
3045 gtk_box_pack_start(GTK_BOX(hbox), kfd->spinner, FALSE, FALSE, 0);
3046 gtk_widget_show(kfd->spinner);
3050 gtk_widget_show(kfd->gd->dialog);
3053 static void keywords_find_cb(GtkWidget *widget, gpointer data)
3055 const gchar *path = layout_get_path(NULL);
3057 if (!path || !*path) path = homedir();
3058 keywords_find_dialog(widget, path);
3061 static void config_tab_keywords_save()
3063 GtkTextIter start, end;
3064 GtkTextBuffer *buffer;
3065 GList *kw_list = NULL;
3071 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3072 gtk_text_buffer_get_bounds(buffer, &start, &end);
3074 buffer_text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
3076 kw_split = strtok(buffer_text, "\n");
3077 while (kw_split != NULL)
3083 if (g_strcmp0(work->data, kw_split) == 0)
3092 kw_list = g_list_append(kw_list, g_strdup(kw_split));
3094 kw_split = strtok(NULL, "\n");
3097 keyword_list_set(kw_list);
3099 string_list_free(kw_list);
3100 g_free(buffer_text);
3103 static void config_tab_keywords(GtkWidget *notebook)
3109 GtkWidget *scrolled;
3111 GtkTextBuffer *buffer;
3114 vbox = scrolled_notebook_page(notebook, _("Keywords"));
3116 group = pref_group_new(vbox, TRUE, _("Edit keywords autocompletion list"), GTK_ORIENTATION_VERTICAL);
3118 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3120 button = pref_button_new(hbox, GTK_STOCK_EXECUTE, _("Search"), FALSE,
3121 G_CALLBACK(keywords_find_cb), keyword_text);
3122 gtk_widget_set_tooltip_text(button, "Search for existing keywords");
3125 keyword_text = gtk_text_view_new();
3126 gtk_widget_set_size_request(keyword_text, 20, 20);
3127 scrolled = gtk_scrolled_window_new(NULL, NULL);
3128 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3129 gtk_widget_show(scrolled);
3131 gtk_container_add(GTK_CONTAINER(scrolled), keyword_text);
3132 gtk_widget_show(keyword_text);
3134 gtk_text_view_set_editable(GTK_TEXT_VIEW(keyword_text), TRUE);
3136 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3137 gtk_text_buffer_create_tag(buffer, "monospace",
3138 "family", "monospace", NULL);
3140 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(keyword_text), GTK_WRAP_WORD);
3141 gtk_text_buffer_get_start_iter(buffer, &iter);
3142 gtk_text_buffer_create_mark(buffer, "end", &iter, FALSE);
3145 path = g_build_filename(get_rc_dir(), "keywords", NULL);
3147 GList *kwl = keyword_list_get();
3148 kwl = g_list_first(kwl);
3151 gtk_text_buffer_get_end_iter (buffer, &iter);
3152 tmp = g_strconcat(kwl->data, "\n", NULL);
3153 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
3158 gtk_text_buffer_set_modified(buffer, FALSE);
3165 static void intent_menu_cb(GtkWidget *combo, gpointer data)
3167 gint *option = data;
3169 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
3173 *option = INTENT_PERCEPTUAL;
3176 *option = INTENT_RELATIVE_COLORIMETRIC;
3179 *option = INTENT_SATURATION;
3182 *option = INTENT_ABSOLUTE_COLORIMETRIC;
3187 static void add_intent_menu(GtkWidget *table, gint column, gint row, const gchar *text,
3188 gint option, gint *option_c)
3195 pref_table_label(table, column, row, text, 0.0);
3197 combo = gtk_combo_box_text_new();
3199 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Perceptual"));
3200 if (option == INTENT_PERCEPTUAL) current = 0;
3201 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Relative Colorimetric"));
3202 if (option == INTENT_RELATIVE_COLORIMETRIC) current = 1;
3203 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Saturation"));
3204 if (option == INTENT_SATURATION) current = 2;
3205 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Absolute Colorimetric"));
3206 if (option == INTENT_ABSOLUTE_COLORIMETRIC) current = 3;
3208 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
3210 gtk_widget_set_tooltip_text(combo,"Refer to the lcms documentation for the defaults used when the selected Intent is not available");
3212 g_signal_connect(G_OBJECT(combo), "changed",
3213 G_CALLBACK(intent_menu_cb), option_c);
3215 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
3216 gtk_widget_show(combo);
3220 static void config_tab_color(GtkWidget *notebook)
3229 vbox = scrolled_notebook_page(notebook, _("Color management"));
3231 group = pref_group_new(vbox, FALSE, _("Input profiles"), GTK_ORIENTATION_VERTICAL);
3233 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3236 table = pref_table_new(group, 3, COLOR_PROFILE_INPUTS + 1, FALSE, FALSE);
3237 gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
3239 label = pref_table_label(table, 0, 0, _("Type"), 0.0);
3240 pref_label_bold(label, TRUE, FALSE);
3242 label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
3243 pref_label_bold(label, TRUE, FALSE);
3245 label = pref_table_label(table, 2, 0, _("File"), 0.0);
3246 pref_label_bold(label, TRUE, FALSE);
3248 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
3253 buf = g_strdup_printf(_("Input %d:"), i + COLOR_PROFILE_FILE);
3254 pref_table_label(table, 0, i + 1, buf, 1.0);
3257 entry = gtk_entry_new();
3258 gtk_entry_set_max_length(GTK_ENTRY(entry), EDITOR_NAME_MAX_LENGTH);
3259 if (options->color_profile.input_name[i])
3261 gtk_entry_set_text(GTK_ENTRY(entry), options->color_profile.input_name[i]);
3263 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, i + 1, i + 2,
3264 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3265 gtk_widget_show(entry);
3266 color_profile_input_name_entry[i] = entry;
3268 tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, ".icc", "ICC Files", NULL);
3269 tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
3270 gtk_widget_set_size_request(entry, 160, -1);
3271 gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
3272 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3273 gtk_widget_show(tabcomp);
3274 color_profile_input_file_entry[i] = entry;
3277 group = pref_group_new(vbox, FALSE, _("Screen profile"), GTK_ORIENTATION_VERTICAL);
3279 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3281 pref_checkbox_new_int(group, _("Use system screen profile if available"),
3282 options->color_profile.use_x11_screen_profile, &c_options->color_profile.use_x11_screen_profile);
3284 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3286 pref_table_label(table, 0, 0, _("Screen:"), 1.0);
3287 tabcomp = tab_completion_new(&color_profile_screen_file_entry,
3288 options->color_profile.screen_file, NULL, ".icc", "ICC Files", NULL);
3289 tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
3290 gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
3292 add_intent_menu(table, 0, 1, _("Render Intent:"), options->color_profile.render_intent, &c_options->color_profile.render_intent);
3294 gtk_table_attach(GTK_TABLE(table), tabcomp, 1, 2,
3296 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3298 gtk_widget_show(tabcomp);
3301 /* advanced entry tab */
3302 static void use_geeqie_trash_cb(GtkWidget *widget, gpointer data)
3304 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3306 c_options->file_ops.use_system_trash = FALSE;
3307 c_options->file_ops.no_trash = FALSE;
3311 static void use_system_trash_cb(GtkWidget *widget, gpointer data)
3313 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3315 c_options->file_ops.use_system_trash = TRUE;
3316 c_options->file_ops.no_trash = FALSE;
3320 static void use_no_cache_cb(GtkWidget *widget, gpointer data)
3322 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3324 c_options->file_ops.no_trash = TRUE;
3328 static void config_tab_behavior(GtkWidget *notebook)
3335 GtkWidget *ct_button;
3339 GtkWidget *with_rename;
3340 GtkWidget *collections_on_top;
3341 GtkWidget *hide_window_in_fullscreen;
3342 GtkWidget *checkbox;
3345 vbox = scrolled_notebook_page(notebook, _("Behavior"));
3347 group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
3349 pref_checkbox_new_int(group, _("Confirm permanent file delete"),
3350 options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
3351 pref_checkbox_new_int(group, _("Confirm move file to Trash"),
3352 options->file_ops.confirm_move_to_trash, &c_options->file_ops.confirm_move_to_trash);
3353 pref_checkbox_new_int(group, _("Enable Delete key"),
3354 options->file_ops.enable_delete_key, &c_options->file_ops.enable_delete_key);
3356 ct_button = pref_radiobutton_new(group, NULL, _("Use Geeqie trash location"),
3357 !options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_geeqie_trash_cb),NULL);
3359 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3360 pref_checkbox_link_sensitivity(ct_button, hbox);
3362 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
3363 pref_label_new(hbox, _("Folder:"));
3365 tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL, NULL, NULL);
3366 tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
3367 gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
3368 gtk_widget_show(tabcomp);
3370 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3371 pref_checkbox_link_sensitivity(ct_button, hbox);
3373 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
3374 spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MiB"),
3375 0, 2048, 1, options->file_ops.safe_delete_folder_maxsize, &c_options->file_ops.safe_delete_folder_maxsize);
3376 gtk_widget_set_tooltip_markup(spin, _("Set to 0 for unlimited size"));
3377 button = pref_button_new(NULL, NULL, _("View"), FALSE,
3378 G_CALLBACK(safe_delete_view_cb), NULL);
3379 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3380 gtk_widget_show(button);
3382 button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
3383 G_CALLBACK(safe_delete_clear_cb), NULL);
3384 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3385 pref_radiobutton_new(group, ct_button, _("Use system Trash bin"),
3386 options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_system_trash_cb), NULL);
3388 pref_radiobutton_new(group, ct_button, _("Use no trash at all"),
3389 options->file_ops.no_trash, G_CALLBACK(use_no_cache_cb), NULL);
3391 gtk_widget_show(button);
3393 pref_spacer(group, PREF_PAD_GROUP);
3396 group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
3398 pref_checkbox_new_int(group, _("Descend folders in tree view"),
3399 options->tree_descend_subdirs, &c_options->tree_descend_subdirs);
3401 pref_checkbox_new_int(group, _("In place renaming"),
3402 options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
3404 pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
3405 options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
3407 tmp = pref_checkbox_new_int(group, _("Circular selection lists"),
3408 options->circular_selection_lists, &c_options->circular_selection_lists);
3409 gtk_widget_set_tooltip_text(tmp, _("Traverse selection lists in a circular manner"));
3411 marks = pref_checkbox_new_int(group, _("Save marks on exit"),
3412 options->marks_save, &c_options->marks_save);
3413 gtk_widget_set_tooltip_text(marks,"Note that marks linked to a keyword will be saved irrespective of this setting");
3415 with_rename = pref_checkbox_new_int(group, _("Use \"With Rename\" as default for Copy/Move dialogs"),
3416 options->with_rename, &c_options->with_rename);
3417 gtk_widget_set_tooltip_text(with_rename,"Change the default button for Copy/Move dialogs");
3419 collections_on_top = pref_checkbox_new_int(group, _("Open collections on top"),
3420 options->collections_on_top, &c_options->collections_on_top);
3421 gtk_widget_set_tooltip_text(collections_on_top,"Open collections window on top");
3423 hide_window_in_fullscreen = pref_checkbox_new_int(group, _("Hide window in fullscreen"),
3424 options->hide_window_in_fullscreen, &c_options->hide_window_in_fullscreen);
3425 gtk_widget_set_tooltip_text(hide_window_in_fullscreen,"When alt-tabbing, prevent Geeqie window showing twice");
3427 pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
3428 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
3430 pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
3431 16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
3433 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3434 add_dnd_default_action_selection_menu(table, 0, 0, _("Drag`n drop default action:"), options->dnd_default_action, &c_options->dnd_default_action);
3436 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3437 add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
3439 pref_spacer(group, PREF_PAD_GROUP);
3441 group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
3443 pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
3444 options->progressive_key_scrolling, &c_options->progressive_key_scrolling);
3445 pref_spin_new_int(group, _("Keyboard scrolling step multiplier:"), NULL,
3446 1, 32, 1, options->keyboard_scroll_step, (int *)&c_options->keyboard_scroll_step);
3447 pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
3448 options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
3449 pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
3450 options->image_lm_click_nav, &c_options->image_lm_click_nav);
3451 pref_checkbox_new_int(group, _("Play video by left click on image"),
3452 options->image_l_click_video, &c_options->image_l_click_video);
3453 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3454 add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
3456 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3457 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3458 add_mouse_selection_menu(table, 0, 0, _("Mouse button Back:"), options->mouse_button_8, &c_options->mouse_button_8);
3459 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3460 add_mouse_selection_menu(table, 0, 0, _("Mouse button Forward:"), options->mouse_button_9, &c_options->mouse_button_9);
3462 pref_spacer(group, PREF_PAD_GROUP);
3464 group = pref_group_new(vbox, FALSE, _("GPU"), GTK_ORIENTATION_VERTICAL);
3466 checkbox = pref_checkbox_new_int(group, _("Override disable GPU"),
3467 options->override_disable_gpu, &c_options->override_disable_gpu);
3468 gtk_widget_set_tooltip_text(checkbox, "Contact the developers for usage");
3471 pref_spacer(group, PREF_PAD_GROUP);
3473 group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
3475 pref_spin_new_int(group, _("Debug level:"), NULL,
3476 DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
3478 pref_checkbox_new_int(group, _("Timer data"),
3479 options->log_window.timer_data, &c_options->log_window.timer_data);
3481 pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
3482 1, 99999, 1, options->log_window_lines, &options->log_window_lines);
3486 /* accelerators tab */
3487 static void config_tab_accelerators(GtkWidget *notebook)
3493 GtkWidget *scrolled;
3494 GtkWidget *accel_view;
3495 GtkCellRenderer *renderer;
3496 GtkTreeSelection *selection;
3497 GtkTreeViewColumn *column;
3499 vbox = scrolled_notebook_page(notebook, _("Keyboard"));
3501 group = pref_group_new(vbox, TRUE, _("Accelerators"), GTK_ORIENTATION_VERTICAL);
3503 scrolled = gtk_scrolled_window_new(NULL, NULL);
3504 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
3505 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
3506 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3507 gtk_widget_show(scrolled);
3509 accel_store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
3511 accel_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(accel_store));
3512 g_object_unref(accel_store);
3513 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(accel_view));
3514 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
3516 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(accel_view), FALSE);
3518 renderer = gtk_cell_renderer_text_new();
3520 column = gtk_tree_view_column_new_with_attributes(_("Action"),
3525 gtk_tree_view_column_set_sort_column_id(column, AE_ACTION);
3526 gtk_tree_view_column_set_resizable(column, TRUE);
3527 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3530 renderer = gtk_cell_renderer_accel_new();
3531 g_signal_connect(G_OBJECT(renderer), "accel-cleared",
3532 G_CALLBACK(accel_store_cleared_cb), accel_store);
3533 g_signal_connect(G_OBJECT(renderer), "accel-edited",
3534 G_CALLBACK(accel_store_edited_cb), accel_store);
3537 g_object_set (renderer,
3539 "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
3542 column = gtk_tree_view_column_new_with_attributes(_("KEY"),
3547 gtk_tree_view_column_set_sort_column_id(column, AE_KEY);
3548 gtk_tree_view_column_set_resizable(column, TRUE);
3549 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3551 renderer = gtk_cell_renderer_text_new();
3553 column = gtk_tree_view_column_new_with_attributes(_("Tooltip"),
3558 gtk_tree_view_column_set_sort_column_id(column, AE_TOOLTIP);
3559 gtk_tree_view_column_set_resizable(column, TRUE);
3560 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3562 renderer = gtk_cell_renderer_text_new();
3564 column = gtk_tree_view_column_new_with_attributes("Accel",
3569 gtk_tree_view_column_set_sort_column_id(column, AE_ACCEL);
3570 gtk_tree_view_column_set_resizable(column, TRUE);
3571 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3573 accel_store_populate();
3574 gtk_container_add(GTK_CONTAINER(scrolled), accel_view);
3575 gtk_widget_show(accel_view);
3577 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3579 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
3580 G_CALLBACK(accel_default_cb), accel_view);
3581 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3582 gtk_widget_show(button);
3584 button = pref_button_new(NULL, NULL, _("Reset selected"), FALSE,
3585 G_CALLBACK(accel_reset_cb), accel_view);
3586 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3587 gtk_widget_show(button);
3590 /* toolbar main tab */
3591 static void config_tab_toolbar_main(GtkWidget *notebook)
3594 GtkWidget *toolbardata;
3597 lw = layout_window_list->data;
3599 vbox = scrolled_notebook_page(notebook, _("Toolbar Main"));
3601 toolbardata = toolbar_select_new(lw, TOOLBAR_MAIN);
3602 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3603 gtk_widget_show(vbox);
3606 /* toolbar status tab */
3607 static void config_tab_toolbar_status(GtkWidget *notebook)
3610 GtkWidget *toolbardata;
3613 lw = layout_window_list->data;
3615 vbox = scrolled_notebook_page(notebook, _("Toolbar Status"));
3617 toolbardata = toolbar_select_new(lw, TOOLBAR_STATUS);
3618 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3619 gtk_widget_show(vbox);
3623 static gint extension_sort_cb(gconstpointer a, gconstpointer b)
3625 return g_strcmp0((gchar *)a, (gchar *)b);
3628 static void config_tab_advanced(GtkWidget *notebook)
3632 GSList *formats_list;
3633 GList *extensions_list = NULL;
3636 GdkPixbufFormat *fm;
3638 GString *types_string = g_string_new(NULL);
3640 vbox = scrolled_notebook_page(notebook, _("Advanced"));
3641 group = pref_group_new(vbox, FALSE, _("External preview extraction"), GTK_ORIENTATION_VERTICAL);
3643 pref_checkbox_new_int(group, _("Use external preview extraction - Requires restart"), options->external_preview.enable, &c_options->external_preview.enable);
3645 pref_spacer(group, PREF_PAD_GROUP);
3647 formats_list = gdk_pixbuf_get_formats();
3649 while (formats_list)
3651 fm = formats_list->data;
3652 extensions = gdk_pixbuf_format_get_extensions(fm);
3655 while (extensions[i])
3657 extensions_list = g_list_insert_sorted(extensions_list, g_strdup(extensions[i]), extension_sort_cb);
3661 g_strfreev(extensions);
3662 formats_list = formats_list->next;
3665 while (extensions_list)
3667 if (types_string->len == 0)
3669 types_string = g_string_append(types_string, extensions_list->data);
3673 types_string = g_string_append(types_string, ", ");
3674 types_string = g_string_append(types_string, extensions_list->data);
3677 extensions_list = extensions_list->next;
3680 types_string = g_string_prepend(types_string, _("Usable file types:\n"));
3681 pref_label_new(group, types_string->str);
3682 GtkWidget *types_string_label = gtk_label_new(types_string->str);
3683 gtk_label_set_line_wrap(GTK_LABEL(types_string_label), TRUE);
3685 pref_spacer(group, PREF_PAD_GROUP);
3687 group = pref_group_new(vbox, FALSE, _("File identification tool"), GTK_ORIENTATION_VERTICAL);
3688 external_preview_select_entry = gtk_entry_new();
3689 tabcomp = tab_completion_new(&external_preview_select_entry, options->external_preview.select, NULL, NULL, NULL, NULL);
3690 tab_completion_add_select_button(external_preview_select_entry, _("Select file identification tool"), FALSE);
3691 gtk_box_pack_start(GTK_BOX(group), tabcomp, TRUE, TRUE, 0);
3692 gtk_widget_show(tabcomp);
3694 group = pref_group_new(vbox, FALSE, _("Preview extraction tool"), GTK_ORIENTATION_VERTICAL);
3695 external_preview_extract_entry = gtk_entry_new();
3696 tabcomp = tab_completion_new(&external_preview_extract_entry, options->external_preview.extract, NULL, NULL, NULL, NULL);
3697 tab_completion_add_select_button(external_preview_extract_entry, _("Select preview extraction tool"), FALSE);
3698 gtk_box_pack_start(GTK_BOX(group), tabcomp, TRUE, TRUE, 0);
3699 gtk_widget_show(tabcomp);
3701 gtk_widget_show(vbox);
3703 g_slist_free(formats_list);
3704 string_list_free(extensions_list);
3705 g_string_free(types_string, TRUE);
3709 static void config_tab_stereo(GtkWidget *notebook)
3717 GtkWidget *fs_button;
3718 vbox = scrolled_notebook_page(notebook, _("Stereo"));
3720 group = pref_group_new(vbox, FALSE, _("Windowed stereo mode"), GTK_ORIENTATION_VERTICAL);
3722 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3723 add_stereo_mode_menu(table, 0, 0, _("Windowed stereo mode"), options->stereo.mode, &c_options->stereo.mode, FALSE);
3725 table = pref_table_new(group, 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.mode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.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.mode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.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.mode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.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.mode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.flip_right);
3738 pref_checkbox_new_int(group, _("Swap left and right images"),
3739 options->stereo.mode & PR_STEREO_SWAP, &c_options->stereo.tmp.swap);
3740 pref_checkbox_new_int(group, _("Disable stereo mode on single image source"),
3741 options->stereo.mode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.temp_disable);
3743 group = pref_group_new(vbox, FALSE, _("Fullscreen stereo mode"), GTK_ORIENTATION_VERTICAL);
3744 fs_button = pref_checkbox_new_int(group, _("Use different settings for fullscreen"),
3745 options->stereo.enable_fsmode, &c_options->stereo.enable_fsmode);
3746 box2 = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
3747 pref_checkbox_link_sensitivity(fs_button, box2);
3748 table = pref_table_new(box2, 2, 1, FALSE, FALSE);
3749 add_stereo_mode_menu(table, 0, 0, _("Fullscreen stereo mode"), options->stereo.fsmode, &c_options->stereo.fsmode, TRUE);
3750 table = pref_table_new(box2, 2, 2, TRUE, FALSE);
3751 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3752 pref_checkbox_new_int(box, _("Mirror left image"),
3753 options->stereo.fsmode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.fs_mirror_left);
3754 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3755 pref_checkbox_new_int(box, _("Flip left image"),
3756 options->stereo.fsmode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.fs_flip_left);
3757 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3758 pref_checkbox_new_int(box, _("Mirror right image"),
3759 options->stereo.fsmode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.fs_mirror_right);
3760 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3761 pref_checkbox_new_int(box, _("Flip right image"),
3762 options->stereo.fsmode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.fs_flip_right);
3763 pref_checkbox_new_int(box2, _("Swap left and right images"),
3764 options->stereo.fsmode & PR_STEREO_SWAP, &c_options->stereo.tmp.fs_swap);
3765 pref_checkbox_new_int(box2, _("Disable stereo mode on single image source"),
3766 options->stereo.fsmode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.fs_temp_disable);
3768 group2 = pref_group_new(box2, FALSE, _("Fixed position"), GTK_ORIENTATION_VERTICAL);
3769 table = pref_table_new(group2, 5, 3, FALSE, FALSE);
3770 pref_table_spin_new_int(table, 0, 0, _("Width"), NULL,
3771 1, 5000, 1, options->stereo.fixed_w, &c_options->stereo.fixed_w);
3772 pref_table_spin_new_int(table, 3, 0, _("Height"), NULL,
3773 1, 5000, 1, options->stereo.fixed_h, &c_options->stereo.fixed_h);
3774 pref_table_spin_new_int(table, 0, 1, _("Left X"), NULL,
3775 0, 5000, 1, options->stereo.fixed_x1, &c_options->stereo.fixed_x1);
3776 pref_table_spin_new_int(table, 3, 1, _("Left Y"), NULL,
3777 0, 5000, 1, options->stereo.fixed_y1, &c_options->stereo.fixed_y1);
3778 pref_table_spin_new_int(table, 0, 2, _("Right X"), NULL,
3779 0, 5000, 1, options->stereo.fixed_x2, &c_options->stereo.fixed_x2);
3780 pref_table_spin_new_int(table, 3, 2, _("Right Y"), NULL,
3781 0, 5000, 1, options->stereo.fixed_y2, &c_options->stereo.fixed_y2);
3785 /* Main preferences window */
3786 static void config_window_create(LayoutWindow *lw)
3788 GtkWidget *win_vbox;
3790 GtkWidget *notebook;
3792 GtkWidget *ct_button;
3794 if (!c_options) c_options = init_options(NULL);
3796 configwindow = window_new(GTK_WINDOW_TOPLEVEL, "preferences", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Preferences"));
3797 DEBUG_NAME(configwindow);
3798 gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
3799 g_signal_connect(G_OBJECT(configwindow), "delete_event",
3800 G_CALLBACK(config_window_delete), NULL);
3801 if (options->save_dialog_window_positions)
3803 gtk_window_resize(GTK_WINDOW(configwindow), lw->options.preferences_window.w, lw->options.preferences_window.h);
3804 gtk_window_move(GTK_WINDOW(configwindow), lw->options.preferences_window.x, lw->options.preferences_window.y);
3808 gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
3810 gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
3811 gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
3813 win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
3814 gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
3815 gtk_widget_show(win_vbox);
3817 notebook = gtk_notebook_new();
3818 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_LEFT);
3819 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE);
3820 gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
3822 config_tab_general(notebook);
3823 config_tab_image(notebook);
3824 config_tab_osd(notebook);
3825 config_tab_windows(notebook);
3826 config_tab_accelerators(notebook);
3827 config_tab_files(notebook);
3828 config_tab_metadata(notebook);
3829 config_tab_keywords(notebook);
3830 config_tab_color(notebook);
3831 config_tab_stereo(notebook);
3832 config_tab_behavior(notebook);
3833 config_tab_toolbar_main(notebook);
3834 config_tab_toolbar_status(notebook);
3835 config_tab_advanced(notebook);
3837 gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), lw->options.preferences_window.page_number);
3839 hbox = gtk_hbutton_box_new();
3840 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
3841 gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
3842 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
3843 gtk_widget_show(hbox);
3845 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
3846 G_CALLBACK(config_window_help_cb), notebook);
3847 gtk_container_add(GTK_CONTAINER(hbox), button);
3848 gtk_widget_set_can_default(button, TRUE);
3849 gtk_widget_show(button);
3851 button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
3852 G_CALLBACK(config_window_ok_cb), notebook);
3853 gtk_container_add(GTK_CONTAINER(hbox), button);
3854 gtk_widget_set_can_default(button, TRUE);
3855 gtk_widget_grab_default(button);
3856 gtk_widget_show(button);
3860 button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
3861 G_CALLBACK(config_window_close_cb), NULL);
3862 gtk_container_add(GTK_CONTAINER(hbox), button);
3863 gtk_widget_set_can_default(button, TRUE);
3864 gtk_widget_show(button);
3866 if (!generic_dialog_get_alternative_button_order(configwindow))
3868 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
3871 gtk_widget_show(notebook);
3873 gtk_widget_show(configwindow);
3877 *-----------------------------------------------------------------------------
3878 * config window show (public)
3879 *-----------------------------------------------------------------------------
3882 void show_config_window(LayoutWindow *lw)
3886 gtk_window_present(GTK_WINDOW(configwindow));
3890 config_window_create(lw);
3899 void show_about_window(LayoutWindow *lw)
3901 GdkPixbuf *pixbuf_logo;
3902 GdkPixbuf *pixbuf_icon;
3903 gchar *authors[1000];
3908 gchar *timezone_path;
3912 #define LINE_LENGTH 1000
3913 gchar line[LINE_LENGTH];
3915 copyright = g_string_new(NULL);
3916 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");
3918 path = path_from_utf8(TIMEZONE_DATABASE);
3919 basename = g_path_get_basename(path);
3920 timezone_path = g_build_filename(get_rc_dir(), basename, NULL);
3921 if (g_file_test(timezone_path, G_FILE_TEST_EXISTS))
3923 cd = ZDOpenDatabase(timezone_path);
3926 copyright = g_string_append(copyright, ZDGetNotice(cd));
3927 ZDCloseDatabase(cd);
3931 g_free(timezone_path);
3935 path = g_build_filename(gq_helpdir, "AUTHORS", NULL);
3936 fp = fopen(path, "r");
3939 while(fgets(line, LINE_LENGTH, fp))
3941 /* get rid of ending \n from fgets */
3942 line[strlen(line) - 1] = '\0';
3943 authors[i_authors] = g_strdup(line);
3946 authors[i_authors] = NULL;
3951 comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
3952 "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
3954 pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
3955 pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
3956 gtk_show_about_dialog(GTK_WINDOW(lw->window),
3957 "title", _("About Geeqie"),
3959 "program-name", GQ_APPNAME,
3961 "logo", pixbuf_logo,
3962 "icon", pixbuf_icon,
3963 "website", GQ_WEBSITE,
3964 "website-label", "Website",
3965 "comments", comment,
3967 "translator-credits", _("translator-credits"),
3968 "wrap-license", TRUE,
3969 "license", copyright->str,
3972 g_string_free(copyright, TRUE);
3975 while(n < i_authors)
3985 static void image_overlay_set_text_colours()
3987 c_options->image_overlay.text_red = options->image_overlay.text_red;
3988 c_options->image_overlay.text_green = options->image_overlay.text_green;
3989 c_options->image_overlay.text_blue = options->image_overlay.text_blue;
3990 c_options->image_overlay.text_alpha = options->image_overlay.text_alpha;
3991 c_options->image_overlay.background_red = options->image_overlay.background_red;
3992 c_options->image_overlay.background_green = options->image_overlay.background_green;
3993 c_options->image_overlay.background_blue = options->image_overlay.background_blue;
3994 c_options->image_overlay.background_alpha = options->image_overlay.background_alpha;
3998 *-----------------------------------------------------------------------------
3999 * timezone database routines
4000 *-----------------------------------------------------------------------------
4003 static void timezone_async_ready_cb(GObject *source_object, GAsyncResult *res, gpointer data)
4005 GError *error = NULL;
4007 gchar *tmp_filename;
4009 if (!g_cancellable_is_cancelled(tz->cancellable))
4011 generic_dialog_close(tz->gd);
4015 if (g_file_copy_finish(G_FILE(source_object), res, &error))
4017 tmp_filename = g_file_get_parse_name(tz->tmp_g_file);
4018 move_file(tmp_filename, tz->timezone_database_user);
4019 g_free(tmp_filename);
4023 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
4026 g_file_delete(tz->tmp_g_file, NULL, &error);
4027 g_object_unref(tz->tmp_g_file);
4028 tz->tmp_g_file = NULL;
4029 g_object_unref(tz->cancellable);
4030 g_object_unref(tz->timezone_database_gq);
4033 static void timezone_progress_cb(goffset current_num_bytes, goffset total_num_bytes, gpointer data)
4037 if (!g_cancellable_is_cancelled(tz->cancellable))
4039 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(tz->progress), (gdouble)current_num_bytes / total_num_bytes);
4043 static void timezone_cancel_button_cb(GenericDialog *gd, gpointer data)
4047 g_cancellable_cancel(tz->cancellable);
4050 static void timezone_database_install_cb(GtkWidget *widget, gpointer data)
4053 GError *error = NULL;
4054 GFileIOStream *io_stream;
4061 tz->tmp_g_file = g_file_new_tmp("geeqie_timezone_XXXXXX", &io_stream, &error);
4065 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
4066 log_printf("Error: Download timezone database failed:\n%s", error->message);
4067 g_error_free(error);
4068 g_object_unref(tz->tmp_g_file);
4072 tz->timezone_database_gq = g_file_new_for_uri(TIMEZONE_DATABASE);
4074 tz->gd = generic_dialog_new(_("Timezone database"), "download_timezone_database", NULL, TRUE, timezone_cancel_button_cb, tz);
4076 generic_dialog_add_message(tz->gd, GTK_STOCK_DIALOG_INFO, _("Downloading timezone database"), NULL, FALSE);
4078 tz->progress = gtk_progress_bar_new();
4079 gtk_box_pack_start(GTK_BOX(tz->gd->vbox), tz->progress, FALSE, FALSE, 0);
4080 gtk_widget_show(tz->progress);
4082 gtk_widget_show(tz->gd->dialog);
4083 tz->cancellable = g_cancellable_new();
4084 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);
4086 gtk_button_set_label(GTK_BUTTON(widget), _("Update"));
4089 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */