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 {"ImageGuidelines", N_("Show guidelines"), PIXBUF_INLINE_ICON_GUIDELINES},
786 {"DrawRectangle", N_("Draw Rectangle"), PIXBUF_INLINE_ICON_DRAW_RECTANGLE},
787 {"FloatTools", N_("Float file list"), PIXBUF_INLINE_ICON_FLOAT},
788 {"SBar", N_("Info sidebar"), PIXBUF_INLINE_ICON_INFO},
789 {"SBarSort", N_("Sort manager"), PIXBUF_INLINE_ICON_SORT},
790 {"Quit", N_("Quit"), GTK_STOCK_QUIT},
794 static void mouse_buttons_selection_menu_cb(GtkWidget *combo, gpointer data)
796 gchar **option = data;
799 label = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(combo));
801 const UseableMouseItems *list = useable_mouse_items;
805 if (g_strcmp0(list->label, label) == 0)
813 *option = g_strdup(list->name);
817 static void add_mouse_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
818 gchar *option, gchar **option_c)
826 pref_table_label(table, column, row, text, 0.0);
828 combo = gtk_combo_box_text_new();
830 const UseableMouseItems *list = useable_mouse_items;
834 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), list->label);
835 if (g_strcmp0(list->name, option) == 0)
843 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
845 g_signal_connect(G_OBJECT(combo), "changed",
846 G_CALLBACK(mouse_buttons_selection_menu_cb), option_c);
848 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
849 gtk_widget_show(combo);
852 static void thumb_size_menu_cb(GtkWidget *combo, gpointer data)
856 n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
859 if ((guint) n < sizeof(thumb_size_list) / sizeof(ThumbSize))
861 c_options->thumbnails.max_width = thumb_size_list[n].w;
862 c_options->thumbnails.max_height = thumb_size_list[n].h;
866 c_options->thumbnails.max_width = options->thumbnails.max_width;
867 c_options->thumbnails.max_height = options->thumbnails.max_height;
871 static void add_thumb_size_menu(GtkWidget *table, gint column, gint row, gchar *text)
877 c_options->thumbnails.max_width = options->thumbnails.max_width;
878 c_options->thumbnails.max_height = options->thumbnails.max_height;
880 pref_table_label(table, column, row, text, 0.0);
882 combo = gtk_combo_box_text_new();
885 for (i = 0; (guint) i < sizeof(thumb_size_list) / sizeof(ThumbSize); i++)
890 w = thumb_size_list[i].w;
891 h = thumb_size_list[i].h;
893 buf = g_strdup_printf("%d x %d", w, h);
894 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
897 if (w == options->thumbnails.max_width && h == options->thumbnails.max_height) current = i;
904 buf = g_strdup_printf("%s %d x %d", _("Custom"), options->thumbnails.max_width, options->thumbnails.max_height);
905 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
911 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
912 g_signal_connect(G_OBJECT(combo), "changed",
913 G_CALLBACK(thumb_size_menu_cb), NULL);
915 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
916 gtk_widget_show(combo);
919 static void stereo_mode_menu_cb(GtkWidget *combo, gpointer data)
923 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
927 *option = PR_STEREO_NONE;
930 *option = PR_STEREO_ANAGLYPH_RC;
933 *option = PR_STEREO_ANAGLYPH_GM;
936 *option = PR_STEREO_ANAGLYPH_YB;
939 *option = PR_STEREO_ANAGLYPH_GRAY_RC;
942 *option = PR_STEREO_ANAGLYPH_GRAY_GM;
945 *option = PR_STEREO_ANAGLYPH_GRAY_YB;
948 *option = PR_STEREO_ANAGLYPH_DB_RC;
951 *option = PR_STEREO_ANAGLYPH_DB_GM;
954 *option = PR_STEREO_ANAGLYPH_DB_YB;
957 *option = PR_STEREO_HORIZ;
960 *option = PR_STEREO_HORIZ | PR_STEREO_HALF;
963 *option = PR_STEREO_VERT;
966 *option = PR_STEREO_VERT | PR_STEREO_HALF;
969 *option = PR_STEREO_FIXED;
974 static void add_stereo_mode_menu(GtkWidget *table, gint column, gint row, const gchar *text,
975 gint option, gint *option_c, gboolean add_fixed)
982 pref_table_label(table, column, row, text, 0.0);
984 combo = gtk_combo_box_text_new();
986 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Single image"));
988 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Red-Cyan"));
989 if (option & PR_STEREO_ANAGLYPH_RC) current = 1;
990 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Green-Magenta"));
991 if (option & PR_STEREO_ANAGLYPH_GM) current = 2;
992 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Yellow-Blue"));
993 if (option & PR_STEREO_ANAGLYPH_YB) current = 3;
994 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Red-Cyan"));
995 if (option & PR_STEREO_ANAGLYPH_GRAY_RC) current = 4;
996 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Green-Magenta"));
997 if (option & PR_STEREO_ANAGLYPH_GRAY_GM) current = 5;
998 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Yellow-Blue"));
999 if (option & PR_STEREO_ANAGLYPH_GRAY_YB) current = 6;
1000 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Red-Cyan"));
1001 if (option & PR_STEREO_ANAGLYPH_DB_RC) current = 7;
1002 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Green-Magenta"));
1003 if (option & PR_STEREO_ANAGLYPH_DB_GM) current = 8;
1004 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Yellow-Blue"));
1005 if (option & PR_STEREO_ANAGLYPH_DB_YB) current = 9;
1007 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side"));
1008 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side Half size"));
1009 if (option & PR_STEREO_HORIZ)
1012 if (option & PR_STEREO_HALF) current = 11;
1015 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom"));
1016 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom Half size"));
1017 if (option & PR_STEREO_VERT)
1020 if (option & PR_STEREO_HALF) current = 13;
1025 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Fixed position"));
1026 if (option & PR_STEREO_FIXED) current = 14;
1029 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
1031 g_signal_connect(G_OBJECT(combo), "changed",
1032 G_CALLBACK(stereo_mode_menu_cb), option_c);
1034 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
1035 gtk_widget_show(combo);
1038 static void video_menu_cb(GtkWidget *combo, gpointer data)
1040 gchar **option = data;
1042 EditorDescription *ed = g_list_nth_data(editor_list_get(), gtk_combo_box_get_active(GTK_COMBO_BOX(combo)));
1046 static void video_menu_populate(gpointer data, gpointer user_data)
1048 GtkWidget *combo = user_data;
1049 EditorDescription *ed = data;
1051 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), ed->name);
1054 static void add_video_menu(GtkWidget *table, gint column, gint row, const gchar *text,
1055 gchar *option, gchar **option_c)
1059 /* use lists since they are sorted */
1060 GList *eds = editor_list_get();
1064 pref_table_label(table, column, row, text, 0.0);
1066 combo = gtk_combo_box_text_new();
1067 g_list_foreach(eds,video_menu_populate,(gpointer)combo);
1068 current = option ? g_list_index(eds,g_hash_table_lookup(editors,option)): -1;
1070 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
1072 g_signal_connect(G_OBJECT(combo), "changed",
1073 G_CALLBACK(video_menu_cb), option_c);
1075 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
1076 gtk_widget_show(combo);
1079 static void filter_store_populate(void)
1083 if (!filter_store) return;
1085 gtk_list_store_clear(filter_store);
1087 work = filter_get_list();
1096 gtk_list_store_append(filter_store, &iter);
1097 gtk_list_store_set(filter_store, &iter, 0, fe, -1);
1101 static void filter_store_ext_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1102 gchar *new_text, gpointer data)
1104 GtkWidget *model = data;
1105 FilterEntry *fe = data;
1109 if (!new_text || strlen(new_text) < 1) return;
1111 tpath = gtk_tree_path_new_from_string(path_str);
1112 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1113 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1115 g_free(fe->extensions);
1116 fe->extensions = g_strdup(new_text);
1118 gtk_tree_path_free(tpath);
1122 static void filter_store_class_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1123 gchar *new_text, gpointer data)
1125 GtkWidget *model = data;
1126 FilterEntry *fe = data;
1131 if (!new_text || !new_text[0]) return;
1133 tpath = gtk_tree_path_new_from_string(path_str);
1134 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1135 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1137 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
1139 if (strcmp(new_text, _(format_class_list[i])) == 0)
1146 gtk_tree_path_free(tpath);
1150 static void filter_store_desc_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1151 gchar *new_text, gpointer data)
1153 GtkWidget *model = data;
1158 if (!new_text || !new_text[0]) return;
1160 tpath = gtk_tree_path_new_from_string(path_str);
1161 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1162 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1164 g_free(fe->description);
1165 fe->description = g_strdup(new_text);
1167 gtk_tree_path_free(tpath);
1170 static void filter_store_enable_cb(GtkCellRendererToggle *renderer,
1171 gchar *path_str, gpointer data)
1173 GtkWidget *model = data;
1178 tpath = gtk_tree_path_new_from_string(path_str);
1179 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1180 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1182 fe->enabled = !fe->enabled;
1184 gtk_tree_path_free(tpath);
1188 static void filter_store_writable_cb(GtkCellRendererToggle *renderer,
1189 gchar *path_str, gpointer data)
1191 GtkWidget *model = data;
1196 tpath = gtk_tree_path_new_from_string(path_str);
1197 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1198 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1200 fe->writable = !fe->writable;
1201 if (fe->writable) fe->allow_sidecar = FALSE;
1203 gtk_tree_path_free(tpath);
1207 static void filter_store_sidecar_cb(GtkCellRendererToggle *renderer,
1208 gchar *path_str, gpointer data)
1210 GtkWidget *model = data;
1215 tpath = gtk_tree_path_new_from_string(path_str);
1216 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1217 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1219 fe->allow_sidecar = !fe->allow_sidecar;
1220 if (fe->allow_sidecar) fe->writable = FALSE;
1222 gtk_tree_path_free(tpath);
1226 static void filter_set_func(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
1227 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
1231 gtk_tree_model_get(tree_model, iter, 0, &fe, -1);
1233 switch (GPOINTER_TO_INT(data))
1236 g_object_set(GTK_CELL_RENDERER(cell),
1237 "active", fe->enabled, NULL);
1240 g_object_set(GTK_CELL_RENDERER(cell),
1241 "text", fe->extensions, NULL);
1243 case FE_DESCRIPTION:
1244 g_object_set(GTK_CELL_RENDERER(cell),
1245 "text", fe->description, NULL);
1248 g_object_set(GTK_CELL_RENDERER(cell),
1249 "text", _(format_class_list[fe->file_class]), NULL);
1252 g_object_set(GTK_CELL_RENDERER(cell),
1253 "active", fe->writable, NULL);
1255 case FE_ALLOW_SIDECAR:
1256 g_object_set(GTK_CELL_RENDERER(cell),
1257 "active", fe->allow_sidecar, NULL);
1262 static gboolean filter_add_scroll(gpointer data)
1266 GtkCellRenderer *cell;
1267 GtkTreeViewColumn *column;
1270 rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(filter_store), NULL);
1271 path = gtk_tree_path_new_from_indices(rows-1, -1);
1273 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data), 0);
1275 list_cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column));
1276 cell = g_list_last(list_cells)->data;
1278 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1279 path, column, FALSE, 0.0, 0.0 );
1280 gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(data),
1281 path, column, cell, TRUE);
1283 gtk_tree_path_free(path);
1284 g_list_free(list_cells);
1289 static void filter_add_cb(GtkWidget *widget, gpointer data)
1291 filter_add_unique("description", ".new", FORMAT_CLASS_IMAGE, TRUE, FALSE, TRUE);
1292 filter_store_populate();
1294 g_idle_add((GSourceFunc)filter_add_scroll, data);
1297 static void filter_remove_cb(GtkWidget *widget, gpointer data)
1299 GtkWidget *filter_view = data;
1300 GtkTreeSelection *selection;
1304 if (!filter_store) return;
1305 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1306 if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) return;
1307 gtk_tree_model_get(GTK_TREE_MODEL(filter_store), &iter, 0, &fe, -1);
1310 filter_remove_entry(fe);
1312 filter_store_populate();
1315 static gboolean filter_default_ok_scroll(GtkTreeView *data)
1319 GtkTreeViewColumn *column;
1321 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(filter_store), &iter);
1322 path = gtk_tree_model_get_path(GTK_TREE_MODEL(filter_store), &iter);
1323 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1325 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1329 gtk_tree_path_free(path);
1334 static void filter_default_ok_cb(GenericDialog *gd, gpointer data)
1337 filter_add_defaults();
1339 filter_store_populate();
1341 g_idle_add((GSourceFunc)filter_default_ok_scroll, gd->data);
1344 static void dummy_cancel_cb(GenericDialog *gd, gpointer data)
1346 /* no op, only so cancel button appears */
1349 static void filter_default_cb(GtkWidget *widget, gpointer data)
1353 gd = generic_dialog_new(_("Reset filters"),
1354 "reset_filter", widget, TRUE,
1355 dummy_cancel_cb, data);
1356 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset filters"),
1357 _("This will reset the file filters to the defaults.\nContinue?"), TRUE);
1358 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, filter_default_ok_cb, TRUE);
1359 gtk_widget_show(gd->dialog);
1362 static void filter_disable_cb(GtkWidget *widget, gpointer data)
1364 GtkWidget *frame = data;
1366 gtk_widget_set_sensitive(frame,
1367 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
1370 static void safe_delete_view_cb(GtkWidget *widget, gpointer data)
1372 layout_set_path(NULL, gtk_entry_get_text(GTK_ENTRY(safe_delete_path_entry)));
1375 static void safe_delete_clear_ok_cb(GenericDialog *gd, gpointer data)
1377 file_util_trash_clear();
1380 static void safe_delete_clear_cb(GtkWidget *widget, gpointer data)
1384 gd = generic_dialog_new(_("Clear trash"),
1385 "clear_trash", widget, TRUE,
1386 dummy_cancel_cb, NULL);
1387 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear trash"),
1388 _("This will remove the trash contents."), FALSE);
1389 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, safe_delete_clear_ok_cb, TRUE);
1390 entry = gtk_entry_new();
1391 gtk_widget_set_can_focus(entry, FALSE);
1392 gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE);
1393 if (options->file_ops.safe_delete_path) gtk_entry_set_text(GTK_ENTRY(entry), options->file_ops.safe_delete_path);
1394 gtk_box_pack_start(GTK_BOX(gd->vbox), entry, FALSE, FALSE, 0);
1395 gtk_widget_show(entry);
1396 gtk_widget_show(gd->dialog);
1399 static void image_overlay_template_view_changed_cb(GtkWidget *widget, gpointer data)
1401 GtkWidget *pTextView;
1402 GtkTextBuffer *pTextBuffer;
1406 pTextView = GTK_WIDGET(data);
1408 pTextBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pTextView));
1409 gtk_text_buffer_get_start_iter(pTextBuffer, &iStart);
1410 gtk_text_buffer_get_end_iter(pTextBuffer, &iEnd);
1412 set_image_overlay_template_string(&c_options->image_overlay.template_string,
1413 gtk_text_buffer_get_text(pTextBuffer, &iStart, &iEnd, TRUE));
1416 static void image_overlay_default_template_ok_cb(GenericDialog *gd, gpointer data)
1418 GtkTextView *text_view = data;
1419 GtkTextBuffer *buffer;
1421 set_default_image_overlay_template_string(&options->image_overlay.template_string);
1422 if (!configwindow) return;
1424 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
1425 gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1428 static void image_overlay_default_template_cb(GtkWidget *widget, gpointer data)
1432 gd = generic_dialog_new(_("Reset image overlay template string"),
1433 "reset_image_overlay_template_string", widget, TRUE,
1434 dummy_cancel_cb, data);
1435 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset image overlay template string"),
1436 _("This will reset the image overlay template string to the default.\nContinue?"), TRUE);
1437 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, image_overlay_default_template_ok_cb, TRUE);
1438 gtk_widget_show(gd->dialog);
1441 static void image_overlay_help_cb(GtkWidget *widget, gpointer data)
1443 help_window_show("GuideOptionsOSD.html");
1446 static void image_overlay_set_font_cb(GtkWidget *widget, gpointer data)
1448 #if GTK_CHECK_VERSION(3,4,0)
1451 PangoFontDescription *font_desc;
1453 dialog = gtk_font_chooser_dialog_new("Image Overlay Font", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1454 gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), options->image_overlay.font);
1456 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1458 font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
1459 font = pango_font_description_to_string(font_desc);
1460 g_free(c_options->image_overlay.font);
1461 c_options->image_overlay.font = g_strdup(font);
1465 gtk_widget_destroy(dialog);
1469 font = gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget));
1470 c_options->image_overlay.font = g_strdup(font);
1474 static void image_overlay_set_text_colour_cb(GtkWidget *widget, gpointer data)
1477 #if GTK_CHECK_VERSION(3,4,0)
1480 dialog = gtk_color_chooser_dialog_new("Image Overlay Text Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1481 colour.red = options->image_overlay.text_red;
1482 colour.green = options->image_overlay.text_green;
1483 colour.blue = options->image_overlay.text_blue;
1484 colour.alpha = options->image_overlay.text_alpha;
1485 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1486 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1488 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1490 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1491 c_options->image_overlay.text_red = colour.red*255;
1492 c_options->image_overlay.text_green = colour.green*255;
1493 c_options->image_overlay.text_blue = colour.blue*255;
1494 c_options->image_overlay.text_alpha = colour.alpha*255;
1496 gtk_widget_destroy(dialog);
1499 GtkColorSelection *colorsel;
1501 dialog = gtk_color_selection_dialog_new("Image Overlay Text Colour");
1502 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1503 colour.red = options->image_overlay.text_red*257;
1504 colour.green = options->image_overlay.text_green*257;
1505 colour.blue = options->image_overlay.text_blue*257;
1506 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1507 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1508 gtk_color_selection_set_current_color(colorsel, &colour);
1509 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.text_alpha*257);
1511 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1513 gtk_color_selection_get_current_color(colorsel, &colour);
1514 c_options->image_overlay.text_red = colour.red/257;
1515 c_options->image_overlay.text_green = colour.green/257;
1516 c_options->image_overlay.text_blue = colour.blue/257;
1517 c_options->image_overlay.text_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1519 gtk_widget_destroy (dialog);
1524 static void image_overlay_set_background_colour_cb(GtkWidget *widget, gpointer data)
1527 #if GTK_CHECK_VERSION(3,4,0)
1530 dialog = gtk_color_chooser_dialog_new("Image Overlay Background Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1531 colour.red = options->image_overlay.background_red;
1532 colour.green = options->image_overlay.background_green;
1533 colour.blue = options->image_overlay.background_blue;
1534 colour.alpha = options->image_overlay.background_alpha;
1535 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1536 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1538 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1540 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1541 c_options->image_overlay.background_red = colour.red*255;
1542 c_options->image_overlay.background_green = colour.green*255;
1543 c_options->image_overlay.background_blue = colour.blue*255;
1544 c_options->image_overlay.background_alpha = colour.alpha*255;
1546 gtk_widget_destroy(dialog);
1549 GtkColorSelection *colorsel;
1551 dialog = gtk_color_selection_dialog_new("Image Overlay Background Colour");
1552 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1553 colour.red = options->image_overlay.background_red*257;
1554 colour.green = options->image_overlay.background_green*257;
1555 colour.blue = options->image_overlay.background_blue*257;
1556 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1557 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1558 gtk_color_selection_set_current_color(colorsel, &colour);
1559 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.background_alpha*257);
1561 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1563 gtk_color_selection_get_current_color(colorsel, &colour);
1564 c_options->image_overlay.background_red = colour.red/257;
1565 c_options->image_overlay.background_green = colour.green/257;
1566 c_options->image_overlay.background_blue = colour.blue/257;
1567 c_options->image_overlay.background_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1569 gtk_widget_destroy(dialog);
1573 static void accel_store_populate(void)
1576 GList *groups, *actions;
1578 const gchar *accel_path;
1582 if (!accel_store || !layout_window_list || !layout_window_list->data) return;
1584 gtk_tree_store_clear(accel_store);
1585 lw = layout_window_list->data; /* get the actions from the first window, it should not matter, they should be the same in all windows */
1587 g_assert(lw && lw->ui_manager);
1588 groups = gtk_ui_manager_get_action_groups(lw->ui_manager);
1591 actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
1594 action = GTK_ACTION(actions->data);
1595 accel_path = gtk_action_get_accel_path(action);
1596 if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
1598 gchar *label, *label2, *tooltip, *accel;
1599 g_object_get(action,
1600 "tooltip", &tooltip,
1604 if (pango_parse_markup(label, -1, '_', NULL, &label2, NULL, NULL) && label2)
1610 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1614 gtk_tree_store_append(accel_store, &iter, NULL);
1615 gtk_tree_store_set(accel_store, &iter,
1618 AE_TOOLTIP, tooltip ? tooltip : "",
1619 AE_ACCEL, accel_path,
1627 actions = actions->next;
1630 groups = groups->next;
1634 static void accel_store_cleared_cb(GtkCellRendererAccel *accel, gchar *path_string, gpointer user_data)
1639 static gboolean accel_remove_key_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1641 gchar *accel1 = data;
1646 gtk_tree_model_get(model, iter, AE_KEY, &accel2, -1);
1648 gtk_accelerator_parse(accel1, &key1.accel_key, &key1.accel_mods);
1649 gtk_accelerator_parse(accel2, &key2.accel_key, &key2.accel_mods);
1651 if (key1.accel_key == key2.accel_key && key1.accel_mods == key2.accel_mods)
1653 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1654 DEBUG_1("accelerator key '%s' is already used, removing.", accel1);
1663 static void accel_store_edited_cb(GtkCellRendererAccel *accel, gchar *path_string, guint accel_key, GdkModifierType accel_mods, guint hardware_keycode, gpointer user_data)
1665 GtkTreeModel *model = (GtkTreeModel *)accel_store;
1669 GtkAccelKey old_key, key;
1670 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
1672 gtk_tree_model_get_iter(model, &iter, path);
1673 gtk_tree_model_get(model, &iter, AE_ACCEL, &accel_path, -1);
1675 /* test if the accelerator can be stored without conflicts*/
1676 gtk_accel_map_lookup_entry(accel_path, &old_key);
1678 /* change the key and read it back (change may fail on keys hardcoded in gtk)*/
1679 gtk_accel_map_change_entry(accel_path, accel_key, accel_mods, TRUE);
1680 gtk_accel_map_lookup_entry(accel_path, &key);
1682 /* restore the original for now, the key will be really changed when the changes are confirmed */
1683 gtk_accel_map_change_entry(accel_path, old_key.accel_key, old_key.accel_mods, TRUE);
1685 acc = gtk_accelerator_name(key.accel_key, key.accel_mods);
1686 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, acc);
1688 gtk_tree_store_set(accel_store, &iter, AE_KEY, acc, -1);
1689 gtk_tree_path_free(path);
1693 static gboolean accel_default_scroll(GtkTreeView *data)
1697 GtkTreeViewColumn *column;
1699 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(accel_store), &iter);
1700 path = gtk_tree_model_get_path(GTK_TREE_MODEL(accel_store), &iter);
1701 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1703 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1707 gtk_tree_path_free(path);
1712 static void accel_default_cb(GtkWidget *widget, gpointer data)
1714 accel_store_populate();
1716 g_idle_add((GSourceFunc)accel_default_scroll, data);
1719 void accel_remove_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1721 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1724 void accel_reset_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1727 gchar *accel_path, *accel;
1729 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, -1);
1730 gtk_accel_map_lookup_entry(accel_path, &key);
1731 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1733 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, accel);
1735 gtk_tree_store_set(accel_store, iter, AE_KEY, accel, -1);
1740 static void accel_reset_cb(GtkWidget *widget, gpointer data)
1742 GtkTreeSelection *selection;
1744 if (!accel_store) return;
1745 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data));
1746 gtk_tree_selection_selected_foreach(selection, &accel_reset_selection, NULL);
1751 static GtkWidget *scrolled_notebook_page(GtkWidget *notebook, const gchar *title)
1755 GtkWidget *scrolled;
1756 GtkWidget *viewport;
1758 scrolled = gtk_scrolled_window_new(NULL, NULL);
1759 gtk_container_set_border_width(GTK_CONTAINER(scrolled), PREF_PAD_BORDER);
1760 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1761 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1762 label = gtk_label_new(title);
1763 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, label);
1764 gtk_widget_show(scrolled);
1766 viewport = gtk_viewport_new(NULL, NULL);
1767 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1768 gtk_container_add(GTK_CONTAINER(scrolled), viewport);
1769 gtk_widget_show(viewport);
1771 vbox = gtk_vbox_new(FALSE, 0);
1772 gtk_container_add(GTK_CONTAINER(viewport), vbox);
1773 gtk_widget_show(vbox);
1778 static void cache_standard_cb(GtkWidget *widget, gpointer data)
1780 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1782 c_options->thumbnails.spec_standard =TRUE;
1783 c_options->thumbnails.cache_into_dirs = FALSE;
1787 static void cache_geeqie_cb(GtkWidget *widget, gpointer data)
1789 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1791 c_options->thumbnails.spec_standard =FALSE;
1792 c_options->thumbnails.cache_into_dirs = FALSE;
1796 static void cache_local_cb(GtkWidget *widget, gpointer data)
1798 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1800 c_options->thumbnails.cache_into_dirs = TRUE;
1801 c_options->thumbnails.spec_standard =FALSE;
1805 static void help_search_engine_entry_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1806 GdkEvent *event, gpointer userdata)
1808 if (pos == GTK_ENTRY_ICON_PRIMARY)
1810 gtk_entry_set_text(GTK_ENTRY(userdata), HELP_SEARCH_ENGINE);
1814 gtk_entry_set_text(GTK_ENTRY(userdata), "");
1818 static void star_rating_star_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1819 GdkEvent *event, gpointer userdata)
1821 gchar *rating_symbol;
1823 if (pos == GTK_ENTRY_ICON_PRIMARY)
1825 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_STAR);
1826 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1827 g_free(rating_symbol);
1831 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1832 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1833 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1837 static void star_rating_rejected_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1838 GdkEvent *event, gpointer userdata)
1840 gchar *rating_symbol;
1842 if (pos == GTK_ENTRY_ICON_PRIMARY)
1844 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_REJECTED);
1845 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1846 g_free(rating_symbol);
1850 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1851 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1852 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1856 static guint star_rating_symbol_test(GtkWidget *widget, gpointer data)
1858 GtkContainer *hbox = data;
1859 GString *str = g_string_new(NULL);
1860 GtkEntry *hex_code_entry;
1861 gchar *hex_code_full;
1864 guint64 hex_value = 0;
1866 list = gtk_container_get_children(hbox);
1868 hex_code_entry = g_list_nth_data(list, 2);
1869 hex_code_full = g_strdup(gtk_entry_get_text(hex_code_entry));
1871 hex_code = g_strsplit(hex_code_full, "+", 2);
1872 if (hex_code[0] && hex_code[1])
1874 hex_value = strtoull(hex_code[1], NULL, 16);
1876 if (!hex_value || hex_value > 0x10FFFF)
1878 hex_value = 0x003F; // Unicode 'Question Mark'
1880 str = g_string_append_unichar(str, (gunichar)hex_value);
1881 gtk_label_set_text(g_list_nth_data(list, 1), str->str);
1883 g_strfreev(hex_code);
1884 g_string_free(str, TRUE);
1885 g_free(hex_code_full);
1890 static void star_rating_star_test_cb(GtkWidget *widget, gpointer data)
1892 guint64 star_symbol;
1894 star_symbol = star_rating_symbol_test(widget, data);
1895 c_options->star_rating.star = star_symbol;
1898 static void star_rating_rejected_test_cb(GtkWidget *widget, gpointer data)
1900 guint64 rejected_symbol;
1902 rejected_symbol = star_rating_symbol_test(widget, data);
1903 c_options->star_rating.rejected = rejected_symbol;
1906 /* general options tab */
1907 static void timezone_database_install_cb(GtkWidget *widget, gpointer data);
1908 typedef struct _TZData TZData;
1912 GCancellable *cancellable;
1914 GtkWidget *progress;
1916 GFile *timezone_database_gq;
1917 gchar *timezone_database_user;
1920 static void config_tab_general(GtkWidget *notebook)
1925 GtkWidget *group_frame;
1926 GtkWidget *subgroup;
1928 GtkWidget *ct_button;
1931 gint hours, minutes, remainder;
1933 GtkWidget *star_rating_entry;
1935 gchar *rating_symbol;
1938 GNetworkMonitor *net_mon;
1939 GSocketConnectable *geeqie_org;
1940 gboolean internet_available;
1943 vbox = scrolled_notebook_page(notebook, _("General"));
1945 group = pref_group_new(vbox, FALSE, _("Thumbnails"), GTK_ORIENTATION_VERTICAL);
1947 table = pref_table_new(group, 2, 2, FALSE, FALSE);
1948 add_thumb_size_menu(table, 0, 0, _("Size:"));
1949 add_quality_menu(table, 0, 1, _("Quality:"), options->thumbnails.quality, &c_options->thumbnails.quality);
1951 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1952 pref_label_new(hbox, _("Custom size: "));
1953 pref_spin_new_int(hbox, _("Width:"), NULL, 1, 512, 1, options->thumbnails.max_width, &c_options->thumbnails.max_width);
1954 pref_spin_new_int(hbox, _("Height:"), NULL, 1, 512, 1, options->thumbnails.max_height, &c_options->thumbnails.max_height);
1956 ct_button = pref_checkbox_new_int(group, _("Cache thumbnails and sim. files"),
1957 options->thumbnails.enable_caching, &c_options->thumbnails.enable_caching);
1959 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1960 pref_checkbox_link_sensitivity(ct_button, subgroup);
1962 c_options->thumbnails.spec_standard = options->thumbnails.spec_standard;
1963 c_options->thumbnails.cache_into_dirs = options->thumbnails.cache_into_dirs;
1964 group_frame = pref_frame_new(subgroup, TRUE, _("Use Geeqie thumbnail style and cache"),
1965 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1966 button = pref_radiobutton_new(group_frame, NULL, get_thumbnails_cache_dir(),
1967 !options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1968 G_CALLBACK(cache_geeqie_cb), NULL);
1970 group_frame = pref_frame_new(subgroup, TRUE,
1971 _("Store thumbnails local to image folder (non-standard)"),
1972 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1973 pref_radiobutton_new(group_frame, button, "*/.thumbnails",
1974 !options->thumbnails.spec_standard && options->thumbnails.cache_into_dirs,
1975 G_CALLBACK(cache_local_cb), NULL);
1977 group_frame = pref_frame_new(subgroup, TRUE,
1978 _("Use standard thumbnail style and cache, shared with other applications"),
1979 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1980 pref_radiobutton_new(group_frame, button, get_thumbnails_standard_cache_dir(),
1981 options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1982 G_CALLBACK(cache_standard_cb), NULL);
1984 pref_checkbox_new_int(group, _("Use EXIF thumbnails when available (EXIF thumbnails may be outdated)"),
1985 options->thumbnails.use_exif, &c_options->thumbnails.use_exif);
1987 pref_checkbox_new_int(group, _("Thumbnail color management"),
1988 options->thumbnails.use_color_management, &c_options->thumbnails.use_color_management);
1990 spin = pref_spin_new_int(group, _("Collection preview:"), NULL,
1992 options->thumbnails.collection_preview, &c_options->thumbnails.collection_preview);
1993 gtk_widget_set_tooltip_text(spin, _("The maximum number of thumbnails shown in a Collection preview montage"));
1995 #ifdef HAVE_FFMPEGTHUMBNAILER_METADATA
1996 pref_checkbox_new_int(group, _("Use embedded metadata in video files as thumbnails when available"),
1997 options->thumbnails.use_ft_metadata, &c_options->thumbnails.use_ft_metadata);
1999 // pref_checkbox_new_int(group, _("Ignore embedded metadata if size is too small"),
2000 // options->thumbnails.use_ft_metadata_small, &c_options->thumbnails.use_ft_metadata_small);
2003 pref_spacer(group, PREF_PAD_GROUP);
2005 group = pref_group_new(vbox, FALSE, _("Star Rating"), GTK_ORIENTATION_VERTICAL);
2007 c_options->star_rating.star = options->star_rating.star;
2008 c_options->star_rating.rejected = options->star_rating.rejected;
2010 str = g_string_new(NULL);
2011 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2012 pref_label_new(hbox, _("Star character: "));
2013 str = g_string_append_unichar(str, options->star_rating.star);
2014 pref_label_new(hbox, g_strdup(str->str));
2015 rating_symbol = g_strdup_printf("U+%X", options->star_rating.star);
2016 star_rating_entry = gtk_entry_new();
2017 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
2018 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
2019 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
2020 gtk_widget_show(star_rating_entry);
2021 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
2022 G_CALLBACK(star_rating_star_test_cb), hbox);
2023 gtk_widget_set_tooltip_text(button, _("Display selected character"));
2024 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2025 gtk_widget_show(button);
2026 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."));
2027 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2028 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2029 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2030 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2031 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2032 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2033 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2034 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2035 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
2036 G_CALLBACK(star_rating_star_icon_cb),
2039 g_string_free(str, TRUE);
2040 g_free(rating_symbol);
2042 str = g_string_new(NULL);
2043 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2044 pref_label_new(hbox, _("Rejected character: "));
2045 str = g_string_append_unichar(str, options->star_rating.rejected);
2046 pref_label_new(hbox, g_strdup(str->str));
2047 rating_symbol = g_strdup_printf("U+%X", options->star_rating.rejected);
2048 star_rating_entry = gtk_entry_new();
2049 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
2050 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
2051 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
2052 gtk_widget_show(star_rating_entry);
2053 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
2054 G_CALLBACK(star_rating_rejected_test_cb), hbox);
2055 gtk_widget_set_tooltip_text(button, _("Display selected character"));
2056 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2057 gtk_widget_show(button);
2058 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."));
2059 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2060 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2061 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2062 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2063 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2064 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2065 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2066 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2067 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
2068 G_CALLBACK(star_rating_rejected_icon_cb),
2071 g_string_free(str, TRUE);
2072 g_free(rating_symbol);
2074 pref_spacer(group, PREF_PAD_GROUP);
2076 group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
2078 c_options->slideshow.delay = options->slideshow.delay;
2079 hours = options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2080 remainder = options->slideshow.delay % (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2081 minutes = remainder / (60 * SLIDESHOW_SUBSECOND_PRECISION);
2082 seconds = (gdouble)(remainder % (60 * SLIDESHOW_SUBSECOND_PRECISION)) /
2083 SLIDESHOW_SUBSECOND_PRECISION;
2085 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2087 spin = pref_spin_new(hbox, _("Delay between image change hrs:mins:secs.dec"), NULL,
2089 options->slideshow.delay ? hours : 0.0,
2090 G_CALLBACK(slideshow_delay_hours_cb), NULL);
2091 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2092 spin = pref_spin_new(hbox, ":" , NULL,
2094 options->slideshow.delay ? minutes: 0.0,
2095 G_CALLBACK(slideshow_delay_minutes_cb), NULL);
2096 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2097 spin = pref_spin_new(hbox, ":", NULL,
2098 SLIDESHOW_MIN_SECONDS, 59, 1.0, 1,
2099 options->slideshow.delay ? seconds : 10.0,
2100 G_CALLBACK(slideshow_delay_seconds_cb), NULL);
2101 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2103 pref_checkbox_new_int(group, _("Random"), options->slideshow.random, &c_options->slideshow.random);
2104 pref_checkbox_new_int(group, _("Repeat"), options->slideshow.repeat, &c_options->slideshow.repeat);
2106 pref_spacer(group, PREF_PAD_GROUP);
2108 group = pref_group_new(vbox, FALSE, _("Image loading and caching"), GTK_ORIENTATION_VERTICAL);
2110 pref_spin_new_int(group, _("Decoded image cache size (MiB):"), NULL,
2111 0, 99999, 1, options->image.image_cache_max, &c_options->image.image_cache_max);
2112 pref_checkbox_new_int(group, _("Preload next image"),
2113 options->image.enable_read_ahead, &c_options->image.enable_read_ahead);
2115 pref_checkbox_new_int(group, _("Refresh on file change"),
2116 options->update_on_time_change, &c_options->update_on_time_change);
2119 pref_spacer(group, PREF_PAD_GROUP);
2121 group = pref_group_new(vbox, FALSE, _("Expand menu and toolbar"), GTK_ORIENTATION_VERTICAL);
2123 pref_checkbox_new_int(group, _("Expand menu and toolbar (NOTE! Geeqie must be restarted for change to take effect)"),
2124 options->expand_menu_toolbar, &c_options->expand_menu_toolbar);
2125 gtk_widget_set_tooltip_text(group, _("Expand the menu and toolbar to the full width of the window"));
2127 pref_spacer(group, PREF_PAD_GROUP);
2129 group = pref_group_new(vbox, FALSE, _("Info sidebar heights"), GTK_ORIENTATION_VERTICAL);
2130 pref_label_new(group, _("NOTE! Geeqie must be restarted for changes to take effect"));
2131 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2132 pref_spin_new_int(hbox, _("Keywords:"), NULL,
2134 options->info_keywords.height, &c_options->info_keywords.height);
2135 pref_spin_new_int(hbox, _("Title:"), NULL,
2137 options->info_title.height, &c_options->info_title.height);
2138 pref_spin_new_int(hbox, _("Comment:"), NULL,
2140 options->info_comment.height, &c_options->info_comment.height);
2141 pref_spin_new_int(hbox, _("Rating:"), NULL,
2143 options->info_rating.height, &c_options->info_rating.height);
2145 pref_spacer(group, PREF_PAD_GROUP);
2147 group = pref_group_new(vbox, FALSE, _("Show predefined keyword tree"), GTK_ORIENTATION_VERTICAL);
2149 pref_checkbox_new_int(group, _("Show predefined keyword tree (NOTE! Geeqie must be restarted for change to take effect)"),
2150 options->show_predefined_keyword_tree, &c_options->show_predefined_keyword_tree);
2152 pref_spacer(group, PREF_PAD_GROUP);
2154 net_mon = g_network_monitor_get_default();
2155 geeqie_org = g_network_address_parse_uri(GQ_WEBSITE, 80, NULL);
2156 internet_available = g_network_monitor_can_reach(net_mon, geeqie_org, NULL, NULL);
2157 g_object_unref(geeqie_org);
2159 group = pref_group_new(vbox, FALSE, _("Timezone database"), GTK_ORIENTATION_VERTICAL);
2160 hbox = pref_box_new(group, TRUE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2162 if (!internet_available)
2164 gtk_widget_set_sensitive(group, FALSE);
2167 tz = g_new0(TZData, 1);
2169 path = path_from_utf8(TIMEZONE_DATABASE);
2170 basename = g_path_get_basename(path);
2171 tz->timezone_database_user = g_build_filename(get_rc_dir(), basename, NULL);
2175 if (isfile(tz->timezone_database_user))
2177 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Update"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2181 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Install"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2184 if (!internet_available)
2186 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"));
2190 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"));
2192 gtk_widget_show(button);
2194 pref_spacer(group, PREF_PAD_GROUP);
2196 group = pref_group_new(vbox, FALSE, _("On-line help search engine"), GTK_ORIENTATION_VERTICAL);
2198 help_search_engine_entry = gtk_entry_new();
2199 gtk_entry_set_text(GTK_ENTRY(help_search_engine_entry), options->help_search_engine);
2200 gtk_box_pack_start(GTK_BOX(group), help_search_engine_entry, FALSE, FALSE, 0);
2201 gtk_widget_show(help_search_engine_entry);
2203 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"));
2205 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2206 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2207 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2208 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2209 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2210 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2211 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2212 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2213 g_signal_connect(GTK_ENTRY(help_search_engine_entry), "icon-press",
2214 G_CALLBACK(help_search_engine_entry_icon_cb),
2215 help_search_engine_entry);
2219 static void config_tab_image(GtkWidget *notebook)
2224 GtkWidget *ct_button;
2225 GtkWidget *enlargement_button;
2228 GtkWidget *two_pass;
2230 GtkWidget *gpu_accel;
2233 vbox = scrolled_notebook_page(notebook, _("Image"));
2235 group = pref_group_new(vbox, FALSE, _("Zoom"), GTK_ORIENTATION_VERTICAL);
2237 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2238 add_quality_menu(table, 0, 0, _("Quality:"), options->image.zoom_quality, &c_options->image.zoom_quality);
2239 if (options->image.use_clutter_renderer && !options->disable_gpu)
2241 gtk_widget_set_sensitive(table, FALSE);
2245 gpu_accel = pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library (Requires restart)"),
2246 options->image.use_clutter_renderer, &c_options->image.use_clutter_renderer);
2247 if (options->disable_gpu && !options->override_disable_gpu)
2249 gtk_widget_set_sensitive(gpu_accel, FALSE);
2253 two_pass = pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"),
2254 options->image.zoom_2pass, &c_options->image.zoom_2pass);
2255 if (options->image.use_clutter_renderer && !options->disable_gpu)
2257 gtk_widget_set_sensitive(two_pass, FALSE);
2260 c_options->image.zoom_increment = options->image.zoom_increment;
2261 spin = pref_spin_new(group, _("Zoom increment:"), NULL,
2262 0.01, 4.0, 0.01, 2, (gdouble)options->image.zoom_increment / 100.0,
2263 G_CALLBACK(zoom_increment_cb), NULL);
2264 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2266 group = pref_group_new(vbox, FALSE, _("Fit image to window"), GTK_ORIENTATION_VERTICAL);
2268 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2269 enlargement_button = pref_checkbox_new_int(hbox, _("Allow enlargement of image (max. size in %)"),
2270 options->image.zoom_to_fit_allow_expand, &c_options->image.zoom_to_fit_allow_expand);
2271 spin = pref_spin_new_int(hbox, NULL, NULL,
2273 options->image.max_enlargement_size, &c_options->image.max_enlargement_size);
2274 pref_checkbox_link_sensitivity(enlargement_button, spin);
2275 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."));
2277 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2278 ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (% of actual window):"),
2279 options->image.limit_autofit_size, &c_options->image.limit_autofit_size);
2280 spin = pref_spin_new_int(hbox, NULL, NULL,
2282 options->image.max_autofit_size, &c_options->image.max_autofit_size);
2283 pref_checkbox_link_sensitivity(ct_button, spin);
2284 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."));
2286 group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
2288 pref_checkbox_new_int(group, _("Use custom border color in window mode"),
2289 options->image.use_custom_border_color, &c_options->image.use_custom_border_color);
2291 pref_checkbox_new_int(group, _("Use custom border color in fullscreen mode"),
2292 options->image.use_custom_border_color_in_fullscreen, &c_options->image.use_custom_border_color_in_fullscreen);
2294 pref_color_button_new(group, _("Border color"), &options->image.border_color,
2295 G_CALLBACK(pref_color_button_set_cb), &c_options->image.border_color);
2297 c_options->image.border_color = options->image.border_color;
2299 pref_color_button_new(group, _("Alpha channel color 1"), &options->image.alpha_color_1,
2300 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_1);
2302 pref_color_button_new(group, _("Alpha channel color 2"), &options->image.alpha_color_2,
2303 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_2);
2305 c_options->image.alpha_color_1 = options->image.alpha_color_1;
2306 c_options->image.alpha_color_2 = options->image.alpha_color_2;
2308 group = pref_group_new(vbox, FALSE, _("Convenience"), GTK_ORIENTATION_VERTICAL);
2310 pref_checkbox_new_int(group, _("Auto rotate proofs using Exif information"),
2311 options->image.exif_proof_rotate_enable, &c_options->image.exif_proof_rotate_enable);
2316 static void save_default_window_layout_cb(GtkWidget *widget, gpointer data)
2318 LayoutWindow *lw = NULL;
2319 gchar *default_path;
2322 /* Get current lw */
2325 tmp_id = lw->options.id;
2326 lw->options.id = g_strdup("lw_default");
2328 default_path = g_build_filename(get_rc_dir(), DEFAULT_WINDOW_LAYOUT, NULL);
2329 save_default_layout_options_to_file(default_path, options, lw);
2330 g_free(lw->options.id);
2331 lw->options.id = tmp_id;
2332 g_free(default_path);
2335 static void config_tab_windows(GtkWidget *notebook)
2340 GtkWidget *subgroup;
2342 GtkWidget *ct_button;
2345 vbox = scrolled_notebook_page(notebook, _("Windows"));
2347 group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
2349 ct_button = pref_checkbox_new_int(group, _("Remember session"),
2350 options->save_window_positions, &c_options->save_window_positions);
2352 button = pref_checkbox_new_int(group, _("Use saved window positions also for new windows"),
2353 options->use_saved_window_positions_for_new_windows, &c_options->use_saved_window_positions_for_new_windows);
2354 pref_checkbox_link_sensitivity(ct_button, button);
2356 button = pref_checkbox_new_int(group, _("Remember window workspace"),
2357 options->save_window_workspace, &c_options->save_window_workspace);
2358 pref_checkbox_link_sensitivity(ct_button, button);
2360 pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
2361 options->tools_restore_state, &c_options->tools_restore_state);
2363 pref_checkbox_new_int(group, _("Remember dialog window positions"),
2364 options->save_dialog_window_positions, &c_options->save_dialog_window_positions);
2366 pref_checkbox_new_int(group, _("Show window IDs"),
2367 options->show_window_ids, &c_options->show_window_ids);
2369 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2370 pref_label_new(subgroup, _("Use current layout for default: "));
2371 button = pref_button_new(subgroup, NULL, _("Set"), FALSE, G_CALLBACK(save_default_window_layout_cb), NULL);
2373 group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
2375 pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
2376 options->image.fit_window_to_image, &c_options->image.fit_window_to_image);
2378 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2379 ct_button = pref_checkbox_new_int(hbox, _("Limit size when auto-sizing window (%):"),
2380 options->image.limit_window_size, &c_options->image.limit_window_size);
2381 spin = pref_spin_new_int(hbox, NULL, NULL,
2383 options->image.max_window_size, &c_options->image.max_window_size);
2384 pref_checkbox_link_sensitivity(ct_button, spin);
2386 group = pref_group_new(vbox, FALSE, _("Full screen"), GTK_ORIENTATION_VERTICAL);
2388 c_options->fullscreen.screen = options->fullscreen.screen;
2389 c_options->fullscreen.above = options->fullscreen.above;
2390 hbox = fullscreen_prefs_selection_new(_("Location:"), &c_options->fullscreen.screen, &c_options->fullscreen.above);
2391 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2392 gtk_widget_show(hbox);
2394 pref_checkbox_new_int(group, _("Smooth image flip"),
2395 options->fullscreen.clean_flip, &c_options->fullscreen.clean_flip);
2396 pref_checkbox_new_int(group, _("Disable screen saver"),
2397 options->fullscreen.disable_saver, &c_options->fullscreen.disable_saver);
2400 #define PRE_FORMATTED_COLUMNS 5
2401 static void config_tab_osd(GtkWidget *notebook)
2407 GtkWidget *image_overlay_template_view;
2408 GtkWidget *scrolled;
2409 GtkWidget *scrolled_pre_formatted;
2410 GtkTextBuffer *buffer;
2412 GtkWidget *subgroup;
2414 vbox = scrolled_notebook_page(notebook, _("OSD"));
2416 image_overlay_template_view = gtk_text_view_new();
2418 group = pref_group_new(vbox, FALSE, _("Overlay Screen Display"), GTK_ORIENTATION_VERTICAL);
2420 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2422 scrolled_pre_formatted = osd_new(PRE_FORMATTED_COLUMNS, image_overlay_template_view);
2423 gtk_widget_set_size_request(scrolled_pre_formatted, 200, 150);
2424 gtk_box_pack_start(GTK_BOX(subgroup), scrolled_pre_formatted, FALSE, FALSE, 0);
2425 gtk_widget_show(scrolled_pre_formatted);
2426 gtk_widget_show(subgroup);
2428 pref_line(group, PREF_PAD_GAP);
2430 pref_label_new(group, _("Image overlay template"));
2432 scrolled = gtk_scrolled_window_new(NULL, NULL);
2433 gtk_widget_set_size_request(scrolled, 200, 150);
2434 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2435 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
2436 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2437 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 5);
2438 gtk_widget_show(scrolled);
2440 gtk_widget_set_tooltip_markup(image_overlay_template_view,
2441 _("Extensive formatting options are shown in the Help file"));
2443 gtk_container_add(GTK_CONTAINER(scrolled), image_overlay_template_view);
2444 gtk_widget_show(image_overlay_template_view);
2446 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2448 #if GTK_CHECK_VERSION(3,4,0)
2449 button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
2450 G_CALLBACK(image_overlay_set_font_cb), notebook);
2452 button = gtk_font_button_new();
2453 gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Image Overlay Font");
2454 gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->image_overlay.font);
2455 g_signal_connect(G_OBJECT(button), "font-set",
2456 G_CALLBACK(image_overlay_set_font_cb),NULL);
2458 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2459 gtk_widget_show(button);
2461 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Text"), FALSE,
2462 G_CALLBACK(image_overlay_set_text_colour_cb), NULL);
2463 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2464 gtk_widget_show(button);
2466 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Background"), FALSE,
2467 G_CALLBACK(image_overlay_set_background_colour_cb), NULL);
2468 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2469 gtk_widget_show(button);
2470 image_overlay_set_text_colours();
2472 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2473 G_CALLBACK(image_overlay_default_template_cb), image_overlay_template_view);
2474 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2475 gtk_widget_show(button);
2477 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
2478 G_CALLBACK(image_overlay_help_cb), NULL);
2479 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2480 gtk_widget_show(button);
2482 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_overlay_template_view));
2483 if (options->image_overlay.template_string) gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
2484 g_signal_connect(G_OBJECT(buffer), "changed",
2485 G_CALLBACK(image_overlay_template_view_changed_cb), image_overlay_template_view);
2487 pref_line(group, PREF_PAD_GAP);
2489 group = pref_group_new(vbox, FALSE, _("Exif, XMP or IPTC tags"), GTK_ORIENTATION_VERTICAL);
2490 hbox = gtk_hbox_new(FALSE, 0);
2491 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2492 gtk_widget_show(hbox);
2493 label = gtk_label_new(_("%Exif.Image.Orientation%"));
2494 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2495 gtk_widget_show(label);
2496 pref_spacer(group,TRUE);
2498 group = pref_group_new(vbox, FALSE, _("Field separators"), GTK_ORIENTATION_VERTICAL);
2499 hbox = gtk_hbox_new(FALSE, 0);
2500 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2501 gtk_widget_show(hbox);
2502 label = gtk_label_new(_("Separator shown only if both fields are non-null:\n%formatted.ShutterSpeed%|%formatted.ISOSpeedRating%"));
2503 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2504 gtk_widget_show(label);
2505 pref_spacer(group,TRUE);
2507 group = pref_group_new(vbox, FALSE, _("Field maximum length"), GTK_ORIENTATION_VERTICAL);
2508 hbox = gtk_hbox_new(FALSE, 0);
2509 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2510 gtk_widget_show(hbox);
2511 label = gtk_label_new(_("%path:39%"));
2512 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2513 gtk_widget_show(label);
2514 pref_spacer(group,TRUE);
2516 group = pref_group_new(vbox, FALSE, _("Pre- and post- text"), GTK_ORIENTATION_VERTICAL);
2517 hbox = gtk_hbox_new(FALSE, 0);
2518 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2519 gtk_widget_show(hbox);
2520 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%"));
2521 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2522 gtk_widget_show(label);
2523 pref_spacer(group,TRUE);
2525 group = pref_group_new(vbox, FALSE, _("Pango markup"), GTK_ORIENTATION_VERTICAL);
2526 hbox = gtk_hbox_new(FALSE, 0);
2527 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2528 gtk_widget_show(hbox);
2529 label = gtk_label_new(_("<b>bold</b>\n<u>underline</u>\n<i>italic</i>\n<s>strikethrough</s>"));
2530 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2531 gtk_widget_show(label);
2534 static GtkTreeModel *create_class_model(void)
2536 GtkListStore *model;
2540 /* create list store */
2541 model = gtk_list_store_new(1, G_TYPE_STRING);
2542 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
2544 gtk_list_store_append(model, &iter);
2545 gtk_list_store_set(model, &iter, 0, _(format_class_list[i]), -1);
2547 return GTK_TREE_MODEL (model);
2552 static void config_tab_files(GtkWidget *notebook)
2559 GtkWidget *ct_button;
2560 GtkWidget *scrolled;
2561 GtkWidget *filter_view;
2562 GtkCellRenderer *renderer;
2563 GtkTreeSelection *selection;
2564 GtkTreeViewColumn *column;
2566 vbox = scrolled_notebook_page(notebook, _("Files"));
2568 group = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2570 pref_checkbox_new_int(group, _("Show hidden files or folders"),
2571 options->file_filter.show_hidden_files, &c_options->file_filter.show_hidden_files);
2572 pref_checkbox_new_int(group, _("Show parent folder (..)"),
2573 options->file_filter.show_parent_directory, &c_options->file_filter.show_parent_directory);
2574 pref_checkbox_new_int(group, _("Case sensitive sort"),
2575 options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
2576 pref_checkbox_new_int(group, _("Natural sort order"),
2577 options->file_sort.natural, &c_options->file_sort.natural);
2578 pref_checkbox_new_int(group, _("Disable file extension checks"),
2579 options->file_filter.disable_file_extension_checks, &c_options->file_filter.disable_file_extension_checks);
2581 ct_button = pref_checkbox_new_int(group, _("Disable File Filtering"),
2582 options->file_filter.disable, &c_options->file_filter.disable);
2585 group = pref_group_new(vbox, FALSE, _("Grouping sidecar extensions"), GTK_ORIENTATION_VERTICAL);
2587 sidecar_ext_entry = gtk_entry_new();
2588 gtk_entry_set_text(GTK_ENTRY(sidecar_ext_entry), options->sidecar.ext);
2589 gtk_box_pack_start(GTK_BOX(group), sidecar_ext_entry, FALSE, FALSE, 0);
2590 gtk_widget_show(sidecar_ext_entry);
2592 group = pref_group_new(vbox, TRUE, _("File types"), GTK_ORIENTATION_VERTICAL);
2594 frame = pref_group_parent(group);
2595 g_signal_connect(G_OBJECT(ct_button), "toggled",
2596 G_CALLBACK(filter_disable_cb), frame);
2597 gtk_widget_set_sensitive(frame, !options->file_filter.disable);
2599 scrolled = gtk_scrolled_window_new(NULL, NULL);
2600 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2601 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2602 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2603 gtk_widget_show(scrolled);
2605 filter_store = gtk_list_store_new(1, G_TYPE_POINTER);
2606 filter_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(filter_store));
2607 g_object_unref(filter_store);
2608 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
2609 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
2611 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), FALSE);
2613 column = gtk_tree_view_column_new();
2614 gtk_tree_view_column_set_title(column, _("Filter"));
2615 gtk_tree_view_column_set_resizable(column, TRUE);
2617 renderer = gtk_cell_renderer_toggle_new();
2618 g_signal_connect(G_OBJECT(renderer), "toggled",
2619 G_CALLBACK(filter_store_enable_cb), filter_store);
2620 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2621 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2622 GINT_TO_POINTER(FE_ENABLE), NULL);
2624 renderer = gtk_cell_renderer_text_new();
2625 g_signal_connect(G_OBJECT(renderer), "edited",
2626 G_CALLBACK(filter_store_ext_edit_cb), filter_store);
2627 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2628 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2629 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2630 GINT_TO_POINTER(FE_EXTENSION), NULL);
2631 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2633 column = gtk_tree_view_column_new();
2634 gtk_tree_view_column_set_title(column, _("Description"));
2635 gtk_tree_view_column_set_resizable(column, TRUE);
2636 gtk_tree_view_column_set_fixed_width(column, 200);
2637 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
2639 renderer = gtk_cell_renderer_text_new();
2640 g_signal_connect(G_OBJECT(renderer), "edited",
2641 G_CALLBACK(filter_store_desc_edit_cb), filter_store);
2642 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2643 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2644 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2645 GINT_TO_POINTER(FE_DESCRIPTION), NULL);
2646 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2648 column = gtk_tree_view_column_new();
2649 gtk_tree_view_column_set_title(column, _("Class"));
2650 gtk_tree_view_column_set_resizable(column, TRUE);
2651 renderer = gtk_cell_renderer_combo_new();
2652 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE,
2653 "model", create_class_model(),
2658 g_signal_connect(G_OBJECT(renderer), "edited",
2659 G_CALLBACK(filter_store_class_edit_cb), filter_store);
2660 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2661 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2662 GINT_TO_POINTER(FE_CLASS), NULL);
2663 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2665 column = gtk_tree_view_column_new();
2666 gtk_tree_view_column_set_title(column, _("Writable"));
2667 gtk_tree_view_column_set_resizable(column, FALSE);
2668 renderer = gtk_cell_renderer_toggle_new();
2669 g_signal_connect(G_OBJECT(renderer), "toggled",
2670 G_CALLBACK(filter_store_writable_cb), filter_store);
2671 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2672 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2673 GINT_TO_POINTER(FE_WRITABLE), NULL);
2674 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2676 column = gtk_tree_view_column_new();
2677 gtk_tree_view_column_set_title(column, _("Sidecar is allowed"));
2678 gtk_tree_view_column_set_resizable(column, FALSE);
2679 renderer = gtk_cell_renderer_toggle_new();
2680 g_signal_connect(G_OBJECT(renderer), "toggled",
2681 G_CALLBACK(filter_store_sidecar_cb), filter_store);
2682 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2683 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2684 GINT_TO_POINTER(FE_ALLOW_SIDECAR), NULL);
2685 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2688 filter_store_populate();
2689 gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
2690 gtk_widget_show(filter_view);
2692 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2694 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2695 G_CALLBACK(filter_default_cb), filter_view);
2696 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2697 gtk_widget_show(button);
2699 button = pref_button_new(NULL, GTK_STOCK_REMOVE, NULL, FALSE,
2700 G_CALLBACK(filter_remove_cb), filter_view);
2701 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2702 gtk_widget_show(button);
2704 button = pref_button_new(NULL, GTK_STOCK_ADD, NULL, FALSE,
2705 G_CALLBACK(filter_add_cb), filter_view);
2706 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2707 gtk_widget_show(button);
2711 static void config_tab_metadata(GtkWidget *notebook)
2716 GtkWidget *ct_button;
2720 vbox = scrolled_notebook_page(notebook, _("Metadata"));
2723 group = pref_group_new(vbox, FALSE, _("Metadata writing process"), GTK_ORIENTATION_VERTICAL);
2725 label = pref_label_new(group, _("Warning: Geeqie is built without Exiv2. Some options are disabled."));
2727 label = pref_label_new(group, _("Metadata are written in the following order. The process ends after first success."));
2728 #if GTK_CHECK_VERSION(3,16,0)
2729 gtk_label_set_xalign(GTK_LABEL(label), 0.0);
2730 gtk_label_set_yalign(GTK_LABEL(label), 0.5);
2732 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2735 ct_button = pref_checkbox_new_int(group, _("1) Save metadata in image files, or sidecar files, according to the XMP standard"),
2736 options->metadata.save_in_image_file, &c_options->metadata.save_in_image_file);
2738 gtk_widget_set_sensitive(ct_button, FALSE);
2741 pref_checkbox_new_int(group, _("2) Save metadata in '.metadata' folder, local to image folder (non-standard)"),
2742 options->metadata.enable_metadata_dirs, &c_options->metadata.enable_metadata_dirs);
2744 text = g_strdup_printf(_("3) Save metadata in Geeqie private directory '%s'"), get_metadata_cache_dir());
2745 label = pref_label_new(group, text);
2746 #if GTK_CHECK_VERSION(3,16,0)
2747 gtk_label_set_xalign(GTK_LABEL(label), 0.0);
2748 gtk_label_set_yalign(GTK_LABEL(label), 0.5);
2750 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2752 gtk_misc_set_padding(GTK_MISC(label), 22, 0);
2755 group = pref_group_new(vbox, FALSE, _("Step 1: Write to image files"), GTK_ORIENTATION_VERTICAL);
2757 gtk_widget_set_sensitive(group, FALSE);
2760 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2761 pref_checkbox_link_sensitivity(ct_button, hbox);
2763 pref_checkbox_new_int(hbox, _("Store metadata also in legacy IPTC tags (converted according to IPTC4XMP standard)"),
2764 options->metadata.save_legacy_IPTC, &c_options->metadata.save_legacy_IPTC);
2766 pref_checkbox_new_int(hbox, _("Warn if the image files are unwritable"),
2767 options->metadata.warn_on_write_problems, &c_options->metadata.warn_on_write_problems);
2769 pref_checkbox_new_int(hbox, _("Ask before writing to image files"),
2770 options->metadata.confirm_write, &c_options->metadata.confirm_write);
2772 pref_checkbox_new_int(hbox, _("Create sidecar files named image.ext.xmp (as opposed to image.xmp)"),
2773 options->metadata.sidecar_extended_name, &c_options->metadata.sidecar_extended_name);
2775 group = pref_group_new(vbox, FALSE, _("Step 2 and 3: write to Geeqie private files"), GTK_ORIENTATION_VERTICAL);
2777 gtk_widget_set_sensitive(group, FALSE);
2780 pref_checkbox_new_int(group, _("Use GQview legacy metadata format (supports only keywords and comments) instead of XMP"),
2781 options->metadata.save_legacy_format, &c_options->metadata.save_legacy_format);
2784 group = pref_group_new(vbox, FALSE, _("Miscellaneous"), GTK_ORIENTATION_VERTICAL);
2785 pref_checkbox_new_int(group, _("Write the same description tags (keywords, comment, etc.) to all grouped sidecars"),
2786 options->metadata.sync_grouped_files, &c_options->metadata.sync_grouped_files);
2788 pref_checkbox_new_int(group, _("Allow keywords to differ only in case"),
2789 options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
2791 ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"),
2792 options->metadata.write_orientation, &c_options->metadata.write_orientation);
2794 gtk_widget_set_sensitive(ct_button, FALSE);
2797 group = pref_group_new(vbox, FALSE, _("Auto-save options"), GTK_ORIENTATION_VERTICAL);
2799 ct_button = pref_checkbox_new_int(group, _("Write metadata after timeout"),
2800 options->metadata.confirm_after_timeout, &c_options->metadata.confirm_after_timeout);
2802 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2803 pref_checkbox_link_sensitivity(ct_button, hbox);
2805 pref_spin_new_int(hbox, _("Timeout (seconds):"), NULL, 0, 900, 1,
2806 options->metadata.confirm_timeout, &c_options->metadata.confirm_timeout);
2808 pref_checkbox_new_int(group, _("Write metadata on image change"),
2809 options->metadata.confirm_on_image_change, &c_options->metadata.confirm_on_image_change);
2811 pref_checkbox_new_int(group, _("Write metadata on directory change"),
2812 options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
2814 group = pref_group_new(vbox, FALSE, _("Pre-load metadata"), GTK_ORIENTATION_VERTICAL);
2816 ct_button = pref_checkbox_new_int(group, _("Read metadata in background"),
2817 options->read_metadata_in_idle, &c_options->read_metadata_in_idle);
2818 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");
2823 typedef struct _KeywordFindData KeywordFindData;
2824 struct _KeywordFindData
2831 GtkWidget *button_close;
2832 GtkWidget *button_stop;
2833 GtkWidget *button_start;
2834 GtkWidget *progress;
2842 guint idle_id; /* event source id */
2845 #define KEYWORD_DIALOG_WIDTH 400
2847 static void keywords_find_folder(KeywordFindData *kfd, FileData *dir_fd)
2849 GList *list_d = NULL;
2850 GList *list_f = NULL;
2854 filelist_read(dir_fd, &list_f, &list_d);
2858 filelist_read(dir_fd, &list_f, NULL);
2861 list_f = filelist_filter(list_f, FALSE);
2862 list_d = filelist_filter(list_d, TRUE);
2864 kfd->list = g_list_concat(list_f, kfd->list);
2865 kfd->list_dir = g_list_concat(list_d, kfd->list_dir);
2868 static void keywords_find_reset(KeywordFindData *kfd)
2870 filelist_free(kfd->list);
2873 filelist_free(kfd->list_dir);
2874 kfd->list_dir = NULL;
2877 static void keywords_find_close_cb(GenericDialog *fd, gpointer data)
2879 KeywordFindData *kfd = data;
2881 if (!gtk_widget_get_sensitive(kfd->button_close)) return;
2883 keywords_find_reset(kfd);
2884 generic_dialog_close(kfd->gd);
2888 static void keywords_find_finish(KeywordFindData *kfd)
2890 keywords_find_reset(kfd);
2892 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("done"));
2893 spinner_set_interval(kfd->spinner, -1);
2895 gtk_widget_set_sensitive(kfd->group, TRUE);
2896 gtk_widget_set_sensitive(kfd->button_start, TRUE);
2897 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2898 gtk_widget_set_sensitive(kfd->button_close, TRUE);
2901 static void keywords_find_stop_cb(GenericDialog *fd, gpointer data)
2903 KeywordFindData *kfd = data;
2905 g_idle_remove_by_data(kfd);
2907 keywords_find_finish(kfd);
2910 static gboolean keywords_find_file(gpointer data)
2912 KeywordFindData *kfd = data;
2914 GtkTextBuffer *buffer;
2922 fd = kfd->list->data;
2923 kfd->list = g_list_remove(kfd->list, fd);
2925 keywords = metadata_read_list(fd, KEYWORD_KEY, METADATA_PLAIN);
2926 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2930 gtk_text_buffer_get_end_iter(buffer, &iter);
2931 tmp = g_strconcat(keywords->data, "\n", NULL);
2932 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
2934 keywords = keywords->next;
2937 gtk_entry_set_text(GTK_ENTRY(kfd->progress), fd->path);
2938 file_data_unref(fd);
2939 string_list_free(keywords);
2943 else if (kfd->list_dir)
2947 fd = kfd->list_dir->data;
2948 kfd->list_dir = g_list_remove(kfd->list_dir, fd);
2950 keywords_find_folder(kfd, fd);
2952 file_data_unref(fd);
2957 keywords_find_finish(kfd);
2962 static void keywords_find_start_cb(GenericDialog *fd, gpointer data)
2964 KeywordFindData *kfd = data;
2967 if (kfd->list || !gtk_widget_get_sensitive(kfd->button_start)) return;
2969 path = remove_trailing_slash((gtk_entry_get_text(GTK_ENTRY(kfd->entry))));
2970 parse_out_relatives(path);
2974 warning_dialog(_("Invalid folder"),
2975 _("The specified folder can not be found."),
2976 GTK_STOCK_DIALOG_WARNING, kfd->gd->dialog);
2982 gtk_widget_set_sensitive(kfd->group, FALSE);
2983 gtk_widget_set_sensitive(kfd->button_start, FALSE);
2984 gtk_widget_set_sensitive(kfd->button_stop, TRUE);
2985 gtk_widget_set_sensitive(kfd->button_close, FALSE);
2986 spinner_set_interval(kfd->spinner, SPINNER_SPEED);
2988 dir_fd = file_data_new_dir(path);
2989 keywords_find_folder(kfd, dir_fd);
2990 file_data_unref(dir_fd);
2991 kfd->idle_id = g_idle_add(keywords_find_file, kfd);
2997 static void keywords_find_dialog(GtkWidget *widget, const gchar *path)
2999 KeywordFindData *kfd;
3003 kfd = g_new0(KeywordFindData, 1);
3005 kfd->gd = generic_dialog_new(_("Search for keywords"),
3006 "search_for_keywords",
3009 gtk_window_set_default_size(GTK_WINDOW(kfd->gd->dialog), KEYWORD_DIALOG_WIDTH, -1);
3010 kfd->gd->cancel_cb = keywords_find_close_cb;
3011 kfd->button_close = generic_dialog_add_button(kfd->gd, GTK_STOCK_CLOSE, NULL,
3012 keywords_find_close_cb, FALSE);
3013 kfd->button_start = generic_dialog_add_button(kfd->gd, GTK_STOCK_OK, _("S_tart"),
3014 keywords_find_start_cb, FALSE);
3015 kfd->button_stop = generic_dialog_add_button(kfd->gd, GTK_STOCK_STOP, NULL,
3016 keywords_find_stop_cb, FALSE);
3017 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
3019 generic_dialog_add_message(kfd->gd, NULL, _("Search for keywords"), NULL, FALSE);
3021 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0);
3022 pref_spacer(hbox, PREF_PAD_INDENT);
3023 kfd->group = pref_box_new(hbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
3025 hbox = pref_box_new(kfd->group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3026 pref_label_new(hbox, _("Folder:"));
3028 label = tab_completion_new(&kfd->entry, path, NULL, NULL, NULL, NULL);
3029 tab_completion_add_select_button(kfd->entry,_("Select folder") , TRUE);
3030 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
3031 gtk_widget_show(label);
3033 pref_checkbox_new_int(kfd->group, _("Include subfolders"), FALSE, &kfd->recurse);
3035 pref_line(kfd->gd->vbox, PREF_PAD_SPACE);
3036 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3038 kfd->progress = gtk_entry_new();
3039 gtk_widget_set_can_focus(kfd->progress, FALSE);
3040 gtk_editable_set_editable(GTK_EDITABLE(kfd->progress), FALSE);
3041 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("click start to begin"));
3042 gtk_box_pack_start(GTK_BOX(hbox), kfd->progress, TRUE, TRUE, 0);
3043 gtk_widget_show(kfd->progress);
3045 kfd->spinner = spinner_new(NULL, -1);
3046 gtk_box_pack_start(GTK_BOX(hbox), kfd->spinner, FALSE, FALSE, 0);
3047 gtk_widget_show(kfd->spinner);
3051 gtk_widget_show(kfd->gd->dialog);
3054 static void keywords_find_cb(GtkWidget *widget, gpointer data)
3056 const gchar *path = layout_get_path(NULL);
3058 if (!path || !*path) path = homedir();
3059 keywords_find_dialog(widget, path);
3062 static void config_tab_keywords_save()
3064 GtkTextIter start, end;
3065 GtkTextBuffer *buffer;
3066 GList *kw_list = NULL;
3072 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3073 gtk_text_buffer_get_bounds(buffer, &start, &end);
3075 buffer_text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
3077 kw_split = strtok(buffer_text, "\n");
3078 while (kw_split != NULL)
3084 if (g_strcmp0(work->data, kw_split) == 0)
3093 kw_list = g_list_append(kw_list, g_strdup(kw_split));
3095 kw_split = strtok(NULL, "\n");
3098 keyword_list_set(kw_list);
3100 string_list_free(kw_list);
3101 g_free(buffer_text);
3104 static void config_tab_keywords(GtkWidget *notebook)
3110 GtkWidget *scrolled;
3112 GtkTextBuffer *buffer;
3115 vbox = scrolled_notebook_page(notebook, _("Keywords"));
3117 group = pref_group_new(vbox, TRUE, _("Edit keywords autocompletion list"), GTK_ORIENTATION_VERTICAL);
3119 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3121 button = pref_button_new(hbox, GTK_STOCK_EXECUTE, _("Search"), FALSE,
3122 G_CALLBACK(keywords_find_cb), keyword_text);
3123 gtk_widget_set_tooltip_text(button, "Search for existing keywords");
3126 keyword_text = gtk_text_view_new();
3127 gtk_widget_set_size_request(keyword_text, 20, 20);
3128 scrolled = gtk_scrolled_window_new(NULL, NULL);
3129 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3130 gtk_widget_show(scrolled);
3132 gtk_container_add(GTK_CONTAINER(scrolled), keyword_text);
3133 gtk_widget_show(keyword_text);
3135 gtk_text_view_set_editable(GTK_TEXT_VIEW(keyword_text), TRUE);
3137 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3138 gtk_text_buffer_create_tag(buffer, "monospace",
3139 "family", "monospace", NULL);
3141 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(keyword_text), GTK_WRAP_WORD);
3142 gtk_text_buffer_get_start_iter(buffer, &iter);
3143 gtk_text_buffer_create_mark(buffer, "end", &iter, FALSE);
3146 path = g_build_filename(get_rc_dir(), "keywords", NULL);
3148 GList *kwl = keyword_list_get();
3149 kwl = g_list_first(kwl);
3152 gtk_text_buffer_get_end_iter (buffer, &iter);
3153 tmp = g_strconcat(kwl->data, "\n", NULL);
3154 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
3159 gtk_text_buffer_set_modified(buffer, FALSE);
3166 static void intent_menu_cb(GtkWidget *combo, gpointer data)
3168 gint *option = data;
3170 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
3174 *option = INTENT_PERCEPTUAL;
3177 *option = INTENT_RELATIVE_COLORIMETRIC;
3180 *option = INTENT_SATURATION;
3183 *option = INTENT_ABSOLUTE_COLORIMETRIC;
3188 static void add_intent_menu(GtkWidget *table, gint column, gint row, const gchar *text,
3189 gint option, gint *option_c)
3196 pref_table_label(table, column, row, text, 0.0);
3198 combo = gtk_combo_box_text_new();
3200 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Perceptual"));
3201 if (option == INTENT_PERCEPTUAL) current = 0;
3202 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Relative Colorimetric"));
3203 if (option == INTENT_RELATIVE_COLORIMETRIC) current = 1;
3204 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Saturation"));
3205 if (option == INTENT_SATURATION) current = 2;
3206 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Absolute Colorimetric"));
3207 if (option == INTENT_ABSOLUTE_COLORIMETRIC) current = 3;
3209 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
3211 gtk_widget_set_tooltip_text(combo,"Refer to the lcms documentation for the defaults used when the selected Intent is not available");
3213 g_signal_connect(G_OBJECT(combo), "changed",
3214 G_CALLBACK(intent_menu_cb), option_c);
3216 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
3217 gtk_widget_show(combo);
3221 static void config_tab_color(GtkWidget *notebook)
3230 vbox = scrolled_notebook_page(notebook, _("Color management"));
3232 group = pref_group_new(vbox, FALSE, _("Input profiles"), GTK_ORIENTATION_VERTICAL);
3234 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3237 table = pref_table_new(group, 3, COLOR_PROFILE_INPUTS + 1, FALSE, FALSE);
3238 gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
3240 label = pref_table_label(table, 0, 0, _("Type"), 0.0);
3241 pref_label_bold(label, TRUE, FALSE);
3243 label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
3244 pref_label_bold(label, TRUE, FALSE);
3246 label = pref_table_label(table, 2, 0, _("File"), 0.0);
3247 pref_label_bold(label, TRUE, FALSE);
3249 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
3254 buf = g_strdup_printf(_("Input %d:"), i + COLOR_PROFILE_FILE);
3255 pref_table_label(table, 0, i + 1, buf, 1.0);
3258 entry = gtk_entry_new();
3259 gtk_entry_set_max_length(GTK_ENTRY(entry), EDITOR_NAME_MAX_LENGTH);
3260 if (options->color_profile.input_name[i])
3262 gtk_entry_set_text(GTK_ENTRY(entry), options->color_profile.input_name[i]);
3264 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, i + 1, i + 2,
3265 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3266 gtk_widget_show(entry);
3267 color_profile_input_name_entry[i] = entry;
3269 tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, ".icc", "ICC Files", NULL);
3270 tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
3271 gtk_widget_set_size_request(entry, 160, -1);
3272 gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
3273 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3274 gtk_widget_show(tabcomp);
3275 color_profile_input_file_entry[i] = entry;
3278 group = pref_group_new(vbox, FALSE, _("Screen profile"), GTK_ORIENTATION_VERTICAL);
3280 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3282 pref_checkbox_new_int(group, _("Use system screen profile if available"),
3283 options->color_profile.use_x11_screen_profile, &c_options->color_profile.use_x11_screen_profile);
3285 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3287 pref_table_label(table, 0, 0, _("Screen:"), 1.0);
3288 tabcomp = tab_completion_new(&color_profile_screen_file_entry,
3289 options->color_profile.screen_file, NULL, ".icc", "ICC Files", NULL);
3290 tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
3291 gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
3293 add_intent_menu(table, 0, 1, _("Render Intent:"), options->color_profile.render_intent, &c_options->color_profile.render_intent);
3295 gtk_table_attach(GTK_TABLE(table), tabcomp, 1, 2,
3297 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3299 gtk_widget_show(tabcomp);
3302 /* advanced entry tab */
3303 static void use_geeqie_trash_cb(GtkWidget *widget, gpointer data)
3305 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3307 c_options->file_ops.use_system_trash = FALSE;
3308 c_options->file_ops.no_trash = FALSE;
3312 static void use_system_trash_cb(GtkWidget *widget, gpointer data)
3314 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3316 c_options->file_ops.use_system_trash = TRUE;
3317 c_options->file_ops.no_trash = FALSE;
3321 static void use_no_cache_cb(GtkWidget *widget, gpointer data)
3323 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3325 c_options->file_ops.no_trash = TRUE;
3329 static void config_tab_behavior(GtkWidget *notebook)
3336 GtkWidget *ct_button;
3340 GtkWidget *with_rename;
3341 GtkWidget *collections_on_top;
3342 GtkWidget *hide_window_in_fullscreen;
3343 GtkWidget *checkbox;
3346 vbox = scrolled_notebook_page(notebook, _("Behavior"));
3348 group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
3350 pref_checkbox_new_int(group, _("Confirm permanent file delete"),
3351 options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
3352 pref_checkbox_new_int(group, _("Confirm move file to Trash"),
3353 options->file_ops.confirm_move_to_trash, &c_options->file_ops.confirm_move_to_trash);
3354 pref_checkbox_new_int(group, _("Enable Delete key"),
3355 options->file_ops.enable_delete_key, &c_options->file_ops.enable_delete_key);
3357 ct_button = pref_radiobutton_new(group, NULL, _("Use Geeqie trash location"),
3358 !options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_geeqie_trash_cb),NULL);
3360 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3361 pref_checkbox_link_sensitivity(ct_button, hbox);
3363 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
3364 pref_label_new(hbox, _("Folder:"));
3366 tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL, NULL, NULL);
3367 tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
3368 gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
3369 gtk_widget_show(tabcomp);
3371 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3372 pref_checkbox_link_sensitivity(ct_button, hbox);
3374 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
3375 spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MiB"),
3376 0, 2048, 1, options->file_ops.safe_delete_folder_maxsize, &c_options->file_ops.safe_delete_folder_maxsize);
3377 gtk_widget_set_tooltip_markup(spin, _("Set to 0 for unlimited size"));
3378 button = pref_button_new(NULL, NULL, _("View"), FALSE,
3379 G_CALLBACK(safe_delete_view_cb), NULL);
3380 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3381 gtk_widget_show(button);
3383 button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
3384 G_CALLBACK(safe_delete_clear_cb), NULL);
3385 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3386 pref_radiobutton_new(group, ct_button, _("Use system Trash bin"),
3387 options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_system_trash_cb), NULL);
3389 pref_radiobutton_new(group, ct_button, _("Use no trash at all"),
3390 options->file_ops.no_trash, G_CALLBACK(use_no_cache_cb), NULL);
3392 gtk_widget_show(button);
3394 pref_spacer(group, PREF_PAD_GROUP);
3397 group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
3399 pref_checkbox_new_int(group, _("Descend folders in tree view"),
3400 options->tree_descend_subdirs, &c_options->tree_descend_subdirs);
3402 pref_checkbox_new_int(group, _("In place renaming"),
3403 options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
3405 pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
3406 options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
3408 tmp = pref_checkbox_new_int(group, _("Circular selection lists"),
3409 options->circular_selection_lists, &c_options->circular_selection_lists);
3410 gtk_widget_set_tooltip_text(tmp, _("Traverse selection lists in a circular manner"));
3412 marks = pref_checkbox_new_int(group, _("Save marks on exit"),
3413 options->marks_save, &c_options->marks_save);
3414 gtk_widget_set_tooltip_text(marks,"Note that marks linked to a keyword will be saved irrespective of this setting");
3416 with_rename = pref_checkbox_new_int(group, _("Use \"With Rename\" as default for Copy/Move dialogs"),
3417 options->with_rename, &c_options->with_rename);
3418 gtk_widget_set_tooltip_text(with_rename,"Change the default button for Copy/Move dialogs");
3420 collections_on_top = pref_checkbox_new_int(group, _("Open collections on top"),
3421 options->collections_on_top, &c_options->collections_on_top);
3422 gtk_widget_set_tooltip_text(collections_on_top,"Open collections window on top");
3424 hide_window_in_fullscreen = pref_checkbox_new_int(group, _("Hide window in fullscreen"),
3425 options->hide_window_in_fullscreen, &c_options->hide_window_in_fullscreen);
3426 gtk_widget_set_tooltip_text(hide_window_in_fullscreen,"When alt-tabbing, prevent Geeqie window showing twice");
3428 pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
3429 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
3431 pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
3432 16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
3434 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3435 add_dnd_default_action_selection_menu(table, 0, 0, _("Drag`n drop default action:"), options->dnd_default_action, &c_options->dnd_default_action);
3437 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3438 add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
3440 pref_spacer(group, PREF_PAD_GROUP);
3442 group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
3444 pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
3445 options->progressive_key_scrolling, &c_options->progressive_key_scrolling);
3446 pref_spin_new_int(group, _("Keyboard scrolling step multiplier:"), NULL,
3447 1, 32, 1, options->keyboard_scroll_step, (int *)&c_options->keyboard_scroll_step);
3448 pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
3449 options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
3450 pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
3451 options->image_lm_click_nav, &c_options->image_lm_click_nav);
3452 pref_checkbox_new_int(group, _("Play video by left click on image"),
3453 options->image_l_click_video, &c_options->image_l_click_video);
3454 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3455 add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
3457 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3458 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3459 add_mouse_selection_menu(table, 0, 0, _("Mouse button Back:"), options->mouse_button_8, &c_options->mouse_button_8);
3460 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3461 add_mouse_selection_menu(table, 0, 0, _("Mouse button Forward:"), options->mouse_button_9, &c_options->mouse_button_9);
3463 pref_spacer(group, PREF_PAD_GROUP);
3465 group = pref_group_new(vbox, FALSE, _("GPU"), GTK_ORIENTATION_VERTICAL);
3467 checkbox = pref_checkbox_new_int(group, _("Override disable GPU"),
3468 options->override_disable_gpu, &c_options->override_disable_gpu);
3469 gtk_widget_set_tooltip_text(checkbox, "Contact the developers for usage");
3472 pref_spacer(group, PREF_PAD_GROUP);
3474 group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
3476 pref_spin_new_int(group, _("Debug level:"), NULL,
3477 DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
3479 pref_checkbox_new_int(group, _("Timer data"),
3480 options->log_window.timer_data, &c_options->log_window.timer_data);
3482 pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
3483 1, 99999, 1, options->log_window_lines, &options->log_window_lines);
3487 /* accelerators tab */
3488 static void config_tab_accelerators(GtkWidget *notebook)
3494 GtkWidget *scrolled;
3495 GtkWidget *accel_view;
3496 GtkCellRenderer *renderer;
3497 GtkTreeSelection *selection;
3498 GtkTreeViewColumn *column;
3500 vbox = scrolled_notebook_page(notebook, _("Keyboard"));
3502 group = pref_group_new(vbox, TRUE, _("Accelerators"), GTK_ORIENTATION_VERTICAL);
3504 scrolled = gtk_scrolled_window_new(NULL, NULL);
3505 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
3506 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
3507 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3508 gtk_widget_show(scrolled);
3510 accel_store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
3512 accel_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(accel_store));
3513 g_object_unref(accel_store);
3514 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(accel_view));
3515 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
3517 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(accel_view), FALSE);
3519 renderer = gtk_cell_renderer_text_new();
3521 column = gtk_tree_view_column_new_with_attributes(_("Action"),
3526 gtk_tree_view_column_set_sort_column_id(column, AE_ACTION);
3527 gtk_tree_view_column_set_resizable(column, TRUE);
3528 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3531 renderer = gtk_cell_renderer_accel_new();
3532 g_signal_connect(G_OBJECT(renderer), "accel-cleared",
3533 G_CALLBACK(accel_store_cleared_cb), accel_store);
3534 g_signal_connect(G_OBJECT(renderer), "accel-edited",
3535 G_CALLBACK(accel_store_edited_cb), accel_store);
3538 g_object_set (renderer,
3540 "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
3543 column = gtk_tree_view_column_new_with_attributes(_("KEY"),
3548 gtk_tree_view_column_set_sort_column_id(column, AE_KEY);
3549 gtk_tree_view_column_set_resizable(column, TRUE);
3550 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3552 renderer = gtk_cell_renderer_text_new();
3554 column = gtk_tree_view_column_new_with_attributes(_("Tooltip"),
3559 gtk_tree_view_column_set_sort_column_id(column, AE_TOOLTIP);
3560 gtk_tree_view_column_set_resizable(column, TRUE);
3561 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3563 renderer = gtk_cell_renderer_text_new();
3565 column = gtk_tree_view_column_new_with_attributes("Accel",
3570 gtk_tree_view_column_set_sort_column_id(column, AE_ACCEL);
3571 gtk_tree_view_column_set_resizable(column, TRUE);
3572 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3574 accel_store_populate();
3575 gtk_container_add(GTK_CONTAINER(scrolled), accel_view);
3576 gtk_widget_show(accel_view);
3578 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3580 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
3581 G_CALLBACK(accel_default_cb), accel_view);
3582 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3583 gtk_widget_show(button);
3585 button = pref_button_new(NULL, NULL, _("Reset selected"), FALSE,
3586 G_CALLBACK(accel_reset_cb), accel_view);
3587 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3588 gtk_widget_show(button);
3591 /* toolbar main tab */
3592 static void config_tab_toolbar_main(GtkWidget *notebook)
3595 GtkWidget *toolbardata;
3598 lw = layout_window_list->data;
3600 vbox = scrolled_notebook_page(notebook, _("Toolbar Main"));
3602 toolbardata = toolbar_select_new(lw, TOOLBAR_MAIN);
3603 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3604 gtk_widget_show(vbox);
3607 /* toolbar status tab */
3608 static void config_tab_toolbar_status(GtkWidget *notebook)
3611 GtkWidget *toolbardata;
3614 lw = layout_window_list->data;
3616 vbox = scrolled_notebook_page(notebook, _("Toolbar Status"));
3618 toolbardata = toolbar_select_new(lw, TOOLBAR_STATUS);
3619 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3620 gtk_widget_show(vbox);
3624 static gint extension_sort_cb(gconstpointer a, gconstpointer b)
3626 return g_strcmp0((gchar *)a, (gchar *)b);
3629 static void config_tab_advanced(GtkWidget *notebook)
3633 GSList *formats_list;
3634 GList *extensions_list = NULL;
3637 GdkPixbufFormat *fm;
3639 GString *types_string = g_string_new(NULL);
3641 vbox = scrolled_notebook_page(notebook, _("Advanced"));
3642 group = pref_group_new(vbox, FALSE, _("External preview extraction"), GTK_ORIENTATION_VERTICAL);
3644 pref_checkbox_new_int(group, _("Use external preview extraction - Requires restart"), options->external_preview.enable, &c_options->external_preview.enable);
3646 pref_spacer(group, PREF_PAD_GROUP);
3648 formats_list = gdk_pixbuf_get_formats();
3650 while (formats_list)
3652 fm = formats_list->data;
3653 extensions = gdk_pixbuf_format_get_extensions(fm);
3656 while (extensions[i])
3658 extensions_list = g_list_insert_sorted(extensions_list, g_strdup(extensions[i]), extension_sort_cb);
3662 g_strfreev(extensions);
3663 formats_list = formats_list->next;
3666 while (extensions_list)
3668 if (types_string->len == 0)
3670 types_string = g_string_append(types_string, extensions_list->data);
3674 types_string = g_string_append(types_string, ", ");
3675 types_string = g_string_append(types_string, extensions_list->data);
3678 extensions_list = extensions_list->next;
3681 types_string = g_string_prepend(types_string, _("Usable file types:\n"));
3682 pref_label_new(group, types_string->str);
3683 GtkWidget *types_string_label = gtk_label_new(types_string->str);
3684 gtk_label_set_line_wrap(GTK_LABEL(types_string_label), TRUE);
3686 pref_spacer(group, PREF_PAD_GROUP);
3688 group = pref_group_new(vbox, FALSE, _("File identification tool"), GTK_ORIENTATION_VERTICAL);
3689 external_preview_select_entry = gtk_entry_new();
3690 tabcomp = tab_completion_new(&external_preview_select_entry, options->external_preview.select, NULL, NULL, NULL, NULL);
3691 tab_completion_add_select_button(external_preview_select_entry, _("Select file identification tool"), FALSE);
3692 gtk_box_pack_start(GTK_BOX(group), tabcomp, TRUE, TRUE, 0);
3693 gtk_widget_show(tabcomp);
3695 group = pref_group_new(vbox, FALSE, _("Preview extraction tool"), GTK_ORIENTATION_VERTICAL);
3696 external_preview_extract_entry = gtk_entry_new();
3697 tabcomp = tab_completion_new(&external_preview_extract_entry, options->external_preview.extract, NULL, NULL, NULL, NULL);
3698 tab_completion_add_select_button(external_preview_extract_entry, _("Select preview extraction tool"), FALSE);
3699 gtk_box_pack_start(GTK_BOX(group), tabcomp, TRUE, TRUE, 0);
3700 gtk_widget_show(tabcomp);
3702 gtk_widget_show(vbox);
3704 g_slist_free(formats_list);
3705 string_list_free(extensions_list);
3706 g_string_free(types_string, TRUE);
3710 static void config_tab_stereo(GtkWidget *notebook)
3718 GtkWidget *fs_button;
3719 vbox = scrolled_notebook_page(notebook, _("Stereo"));
3721 group = pref_group_new(vbox, FALSE, _("Windowed stereo mode"), GTK_ORIENTATION_VERTICAL);
3723 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3724 add_stereo_mode_menu(table, 0, 0, _("Windowed stereo mode"), options->stereo.mode, &c_options->stereo.mode, FALSE);
3726 table = pref_table_new(group, 2, 2, TRUE, FALSE);
3727 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3728 pref_checkbox_new_int(box, _("Mirror left image"),
3729 options->stereo.mode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.mirror_left);
3730 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3731 pref_checkbox_new_int(box, _("Flip left image"),
3732 options->stereo.mode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.flip_left);
3733 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3734 pref_checkbox_new_int(box, _("Mirror right image"),
3735 options->stereo.mode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.mirror_right);
3736 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3737 pref_checkbox_new_int(box, _("Flip right image"),
3738 options->stereo.mode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.flip_right);
3739 pref_checkbox_new_int(group, _("Swap left and right images"),
3740 options->stereo.mode & PR_STEREO_SWAP, &c_options->stereo.tmp.swap);
3741 pref_checkbox_new_int(group, _("Disable stereo mode on single image source"),
3742 options->stereo.mode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.temp_disable);
3744 group = pref_group_new(vbox, FALSE, _("Fullscreen stereo mode"), GTK_ORIENTATION_VERTICAL);
3745 fs_button = pref_checkbox_new_int(group, _("Use different settings for fullscreen"),
3746 options->stereo.enable_fsmode, &c_options->stereo.enable_fsmode);
3747 box2 = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
3748 pref_checkbox_link_sensitivity(fs_button, box2);
3749 table = pref_table_new(box2, 2, 1, FALSE, FALSE);
3750 add_stereo_mode_menu(table, 0, 0, _("Fullscreen stereo mode"), options->stereo.fsmode, &c_options->stereo.fsmode, TRUE);
3751 table = pref_table_new(box2, 2, 2, TRUE, FALSE);
3752 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3753 pref_checkbox_new_int(box, _("Mirror left image"),
3754 options->stereo.fsmode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.fs_mirror_left);
3755 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3756 pref_checkbox_new_int(box, _("Flip left image"),
3757 options->stereo.fsmode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.fs_flip_left);
3758 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3759 pref_checkbox_new_int(box, _("Mirror right image"),
3760 options->stereo.fsmode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.fs_mirror_right);
3761 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3762 pref_checkbox_new_int(box, _("Flip right image"),
3763 options->stereo.fsmode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.fs_flip_right);
3764 pref_checkbox_new_int(box2, _("Swap left and right images"),
3765 options->stereo.fsmode & PR_STEREO_SWAP, &c_options->stereo.tmp.fs_swap);
3766 pref_checkbox_new_int(box2, _("Disable stereo mode on single image source"),
3767 options->stereo.fsmode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.fs_temp_disable);
3769 group2 = pref_group_new(box2, FALSE, _("Fixed position"), GTK_ORIENTATION_VERTICAL);
3770 table = pref_table_new(group2, 5, 3, FALSE, FALSE);
3771 pref_table_spin_new_int(table, 0, 0, _("Width"), NULL,
3772 1, 5000, 1, options->stereo.fixed_w, &c_options->stereo.fixed_w);
3773 pref_table_spin_new_int(table, 3, 0, _("Height"), NULL,
3774 1, 5000, 1, options->stereo.fixed_h, &c_options->stereo.fixed_h);
3775 pref_table_spin_new_int(table, 0, 1, _("Left X"), NULL,
3776 0, 5000, 1, options->stereo.fixed_x1, &c_options->stereo.fixed_x1);
3777 pref_table_spin_new_int(table, 3, 1, _("Left Y"), NULL,
3778 0, 5000, 1, options->stereo.fixed_y1, &c_options->stereo.fixed_y1);
3779 pref_table_spin_new_int(table, 0, 2, _("Right X"), NULL,
3780 0, 5000, 1, options->stereo.fixed_x2, &c_options->stereo.fixed_x2);
3781 pref_table_spin_new_int(table, 3, 2, _("Right Y"), NULL,
3782 0, 5000, 1, options->stereo.fixed_y2, &c_options->stereo.fixed_y2);
3786 /* Main preferences window */
3787 static void config_window_create(LayoutWindow *lw)
3789 GtkWidget *win_vbox;
3791 GtkWidget *notebook;
3793 GtkWidget *ct_button;
3795 if (!c_options) c_options = init_options(NULL);
3797 configwindow = window_new(GTK_WINDOW_TOPLEVEL, "preferences", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Preferences"));
3798 DEBUG_NAME(configwindow);
3799 gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
3800 g_signal_connect(G_OBJECT(configwindow), "delete_event",
3801 G_CALLBACK(config_window_delete), NULL);
3802 if (options->save_dialog_window_positions)
3804 gtk_window_resize(GTK_WINDOW(configwindow), lw->options.preferences_window.w, lw->options.preferences_window.h);
3805 gtk_window_move(GTK_WINDOW(configwindow), lw->options.preferences_window.x, lw->options.preferences_window.y);
3809 gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
3811 gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
3812 gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
3814 win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
3815 gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
3816 gtk_widget_show(win_vbox);
3818 notebook = gtk_notebook_new();
3819 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_LEFT);
3820 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE);
3821 gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
3823 config_tab_general(notebook);
3824 config_tab_image(notebook);
3825 config_tab_osd(notebook);
3826 config_tab_windows(notebook);
3827 config_tab_accelerators(notebook);
3828 config_tab_files(notebook);
3829 config_tab_metadata(notebook);
3830 config_tab_keywords(notebook);
3831 config_tab_color(notebook);
3832 config_tab_stereo(notebook);
3833 config_tab_behavior(notebook);
3834 config_tab_toolbar_main(notebook);
3835 config_tab_toolbar_status(notebook);
3836 config_tab_advanced(notebook);
3838 gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), lw->options.preferences_window.page_number);
3840 hbox = gtk_hbutton_box_new();
3841 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
3842 gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
3843 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
3844 gtk_widget_show(hbox);
3846 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
3847 G_CALLBACK(config_window_help_cb), notebook);
3848 gtk_container_add(GTK_CONTAINER(hbox), button);
3849 gtk_widget_set_can_default(button, TRUE);
3850 gtk_widget_show(button);
3852 button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
3853 G_CALLBACK(config_window_ok_cb), notebook);
3854 gtk_container_add(GTK_CONTAINER(hbox), button);
3855 gtk_widget_set_can_default(button, TRUE);
3856 gtk_widget_grab_default(button);
3857 gtk_widget_show(button);
3861 button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
3862 G_CALLBACK(config_window_close_cb), NULL);
3863 gtk_container_add(GTK_CONTAINER(hbox), button);
3864 gtk_widget_set_can_default(button, TRUE);
3865 gtk_widget_show(button);
3867 if (!generic_dialog_get_alternative_button_order(configwindow))
3869 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
3872 gtk_widget_show(notebook);
3874 gtk_widget_show(configwindow);
3878 *-----------------------------------------------------------------------------
3879 * config window show (public)
3880 *-----------------------------------------------------------------------------
3883 void show_config_window(LayoutWindow *lw)
3887 gtk_window_present(GTK_WINDOW(configwindow));
3891 config_window_create(lw);
3900 void show_about_window(LayoutWindow *lw)
3902 GdkPixbuf *pixbuf_logo;
3903 GdkPixbuf *pixbuf_icon;
3904 gchar *authors[1000];
3909 gchar *timezone_path;
3913 #define LINE_LENGTH 1000
3914 gchar line[LINE_LENGTH];
3916 copyright = g_string_new(NULL);
3917 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");
3919 path = path_from_utf8(TIMEZONE_DATABASE);
3920 basename = g_path_get_basename(path);
3921 timezone_path = g_build_filename(get_rc_dir(), basename, NULL);
3922 if (g_file_test(timezone_path, G_FILE_TEST_EXISTS))
3924 cd = ZDOpenDatabase(timezone_path);
3927 copyright = g_string_append(copyright, ZDGetNotice(cd));
3928 ZDCloseDatabase(cd);
3932 g_free(timezone_path);
3936 path = g_build_filename(gq_helpdir, "AUTHORS", NULL);
3937 fp = fopen(path, "r");
3940 while(fgets(line, LINE_LENGTH, fp))
3942 /* get rid of ending \n from fgets */
3943 line[strlen(line) - 1] = '\0';
3944 authors[i_authors] = g_strdup(line);
3947 authors[i_authors] = NULL;
3952 comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
3953 "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
3955 pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
3956 pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
3957 gtk_show_about_dialog(GTK_WINDOW(lw->window),
3958 "title", _("About Geeqie"),
3960 "program-name", GQ_APPNAME,
3962 "logo", pixbuf_logo,
3963 "icon", pixbuf_icon,
3964 "website", GQ_WEBSITE,
3965 "website-label", "Website",
3966 "comments", comment,
3968 "translator-credits", _("translator-credits"),
3969 "wrap-license", TRUE,
3970 "license", copyright->str,
3973 g_string_free(copyright, TRUE);
3976 while(n < i_authors)
3986 static void image_overlay_set_text_colours()
3988 c_options->image_overlay.text_red = options->image_overlay.text_red;
3989 c_options->image_overlay.text_green = options->image_overlay.text_green;
3990 c_options->image_overlay.text_blue = options->image_overlay.text_blue;
3991 c_options->image_overlay.text_alpha = options->image_overlay.text_alpha;
3992 c_options->image_overlay.background_red = options->image_overlay.background_red;
3993 c_options->image_overlay.background_green = options->image_overlay.background_green;
3994 c_options->image_overlay.background_blue = options->image_overlay.background_blue;
3995 c_options->image_overlay.background_alpha = options->image_overlay.background_alpha;
3999 *-----------------------------------------------------------------------------
4000 * timezone database routines
4001 *-----------------------------------------------------------------------------
4004 static void timezone_async_ready_cb(GObject *source_object, GAsyncResult *res, gpointer data)
4006 GError *error = NULL;
4008 gchar *tmp_filename;
4010 if (!g_cancellable_is_cancelled(tz->cancellable))
4012 generic_dialog_close(tz->gd);
4016 if (g_file_copy_finish(G_FILE(source_object), res, &error))
4018 tmp_filename = g_file_get_parse_name(tz->tmp_g_file);
4019 move_file(tmp_filename, tz->timezone_database_user);
4020 g_free(tmp_filename);
4024 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
4027 g_file_delete(tz->tmp_g_file, NULL, &error);
4028 g_object_unref(tz->tmp_g_file);
4029 tz->tmp_g_file = NULL;
4030 g_object_unref(tz->cancellable);
4031 g_object_unref(tz->timezone_database_gq);
4034 static void timezone_progress_cb(goffset current_num_bytes, goffset total_num_bytes, gpointer data)
4038 if (!g_cancellable_is_cancelled(tz->cancellable))
4040 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(tz->progress), (gdouble)current_num_bytes / total_num_bytes);
4044 static void timezone_cancel_button_cb(GenericDialog *gd, gpointer data)
4048 g_cancellable_cancel(tz->cancellable);
4051 static void timezone_database_install_cb(GtkWidget *widget, gpointer data)
4054 GError *error = NULL;
4055 GFileIOStream *io_stream;
4062 tz->tmp_g_file = g_file_new_tmp("geeqie_timezone_XXXXXX", &io_stream, &error);
4066 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
4067 log_printf("Error: Download timezone database failed:\n%s", error->message);
4068 g_error_free(error);
4069 g_object_unref(tz->tmp_g_file);
4073 tz->timezone_database_gq = g_file_new_for_uri(TIMEZONE_DATABASE);
4075 tz->gd = generic_dialog_new(_("Timezone database"), "download_timezone_database", NULL, TRUE, timezone_cancel_button_cb, tz);
4077 generic_dialog_add_message(tz->gd, GTK_STOCK_DIALOG_INFO, _("Downloading timezone database"), NULL, FALSE);
4079 tz->progress = gtk_progress_bar_new();
4080 gtk_box_pack_start(GTK_BOX(tz->gd->vbox), tz->progress, FALSE, FALSE, 0);
4081 gtk_widget_show(tz->progress);
4083 gtk_widget_show(tz->gd->dialog);
4084 tz->cancellable = g_cancellable_new();
4085 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);
4087 gtk_button_set_label(GTK_BUTTON(widget), _("Update"));
4090 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */