2 * Copyright (C) 2006 John Ellis
3 * Copyright (C) 2008 - 2016 The Geeqie Team
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include "preferences.h"
26 #include "bar_keywords.h"
28 #include "cache_maint.h"
33 #include "filefilter.h"
34 #include "fullscreen.h"
36 #include "image-overlay.h"
37 #include "color-man.h"
39 #include "layout_config.h"
40 #include "layout_util.h"
44 #include "pixbuf_util.h"
46 #include "slideshow.h"
50 #include "ui_fileops.h"
52 #include "ui_spinner.h"
53 #include "ui_tabcomp.h"
54 #include "ui_utildlg.h"
56 #include "zonedetect.h"
66 #define EDITOR_NAME_MAX_LENGTH 32
67 #define EDITOR_COMMAND_MAX_LENGTH 1024
69 static void image_overlay_set_text_colours();
71 GtkWidget *keyword_text;
72 static void config_tab_keywords_save();
74 typedef struct _ThumbSize ThumbSize;
81 static ThumbSize thumb_size_list[] =
115 gchar *format_class_list[] = {
125 /* config memory values */
126 static ConfOptions *c_options = NULL;
133 static GtkWidget *configwindow = NULL;
134 static GtkListStore *filter_store = NULL;
135 static GtkTreeStore *accel_store = NULL;
137 static GtkWidget *safe_delete_path_entry;
139 static GtkWidget *color_profile_input_file_entry[COLOR_PROFILE_INPUTS];
140 static GtkWidget *color_profile_input_name_entry[COLOR_PROFILE_INPUTS];
141 static GtkWidget *color_profile_screen_file_entry;
142 static GtkWidget *external_preview_select_entry;
143 static GtkWidget *external_preview_extract_entry;
145 static GtkWidget *sidecar_ext_entry;
146 static GtkWidget *help_search_engine_entry;
149 #define CONFIG_WINDOW_DEF_WIDTH 700
150 #define CONFIG_WINDOW_DEF_HEIGHT 600
153 *-----------------------------------------------------------------------------
154 * option widget callbacks (private)
155 *-----------------------------------------------------------------------------
158 static void zoom_increment_cb(GtkWidget *spin, gpointer data)
160 c_options->image.zoom_increment = (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) * 100.0 + 0.01);
163 static void slideshow_delay_hours_cb(GtkWidget *spin, gpointer data)
165 gint mins_secs_tenths, delay;
167 mins_secs_tenths = c_options->slideshow.delay %
168 (3600 * SLIDESHOW_SUBSECOND_PRECISION);
170 delay = (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
171 (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
174 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
175 SLIDESHOW_SUBSECOND_PRECISION;
178 static void slideshow_delay_minutes_cb(GtkWidget *spin, gpointer data)
180 gint hours, secs_tenths, delay;
182 hours = c_options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
183 secs_tenths = c_options->slideshow.delay % (60 * SLIDESHOW_SUBSECOND_PRECISION);
185 delay = hours * (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
186 (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
187 (60 * SLIDESHOW_SUBSECOND_PRECISION) + secs_tenths);
189 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
190 SLIDESHOW_SUBSECOND_PRECISION;
193 static void slideshow_delay_seconds_cb(GtkWidget *spin, gpointer data)
195 gint hours_mins, delay;
197 hours_mins = c_options->slideshow.delay / (60 * SLIDESHOW_SUBSECOND_PRECISION);
199 delay = (hours_mins * (60 * SLIDESHOW_SUBSECOND_PRECISION)) +
200 (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
201 (gdouble)(SLIDESHOW_SUBSECOND_PRECISION) + 0.01);
203 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
204 SLIDESHOW_SUBSECOND_PRECISION;
208 *-----------------------------------------------------------------------------
209 * sync program to config window routine (private)
210 *-----------------------------------------------------------------------------
213 void config_entry_to_option(GtkWidget *entry, gchar **option, gchar *(*func)(const gchar *))
219 buf = gtk_entry_get_text(GTK_ENTRY(entry));
220 if (buf && strlen(buf) > 0)
225 *option = g_strdup(buf);
230 static gboolean accel_apply_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
232 gchar *accel_path, *accel;
234 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, AE_KEY, &accel, -1);
236 if (accel_path && accel_path[0])
239 gtk_accelerator_parse(accel, &key.accel_key, &key.accel_mods);
240 gtk_accel_map_change_entry(accel_path, key.accel_key, key.accel_mods, TRUE);
250 static void config_window_apply(void)
252 gboolean refresh = FALSE;
257 config_entry_to_option(safe_delete_path_entry, &options->file_ops.safe_delete_path, remove_trailing_slash);
259 if (options->file_filter.show_hidden_files != c_options->file_filter.show_hidden_files) refresh = TRUE;
260 if (options->file_filter.show_parent_directory != c_options->file_filter.show_parent_directory) refresh = TRUE;
261 if (options->file_filter.show_dot_directory != c_options->file_filter.show_dot_directory) refresh = TRUE;
262 if (options->file_sort.case_sensitive != c_options->file_sort.case_sensitive) refresh = TRUE;
263 if (options->file_sort.natural != c_options->file_sort.natural) refresh = TRUE;
264 if (options->file_filter.disable_file_extension_checks != c_options->file_filter.disable_file_extension_checks) refresh = TRUE;
265 if (options->file_filter.disable != c_options->file_filter.disable) refresh = TRUE;
267 options->file_ops.confirm_delete = c_options->file_ops.confirm_delete;
268 options->file_ops.enable_delete_key = c_options->file_ops.enable_delete_key;
269 options->file_ops.confirm_move_to_trash = c_options->file_ops.confirm_move_to_trash;
270 options->file_ops.use_system_trash = c_options->file_ops.use_system_trash;
271 options->file_ops.no_trash = c_options->file_ops.no_trash;
272 options->file_ops.safe_delete_folder_maxsize = c_options->file_ops.safe_delete_folder_maxsize;
273 options->tools_restore_state = c_options->tools_restore_state;
274 options->save_window_positions = c_options->save_window_positions;
275 options->use_saved_window_positions_for_new_windows = c_options->use_saved_window_positions_for_new_windows;
276 options->save_window_workspace = c_options->save_window_workspace;
277 options->save_dialog_window_positions = c_options->save_dialog_window_positions;
278 options->show_window_ids = c_options->show_window_ids;
279 options->image.scroll_reset_method = c_options->image.scroll_reset_method;
280 options->image.zoom_2pass = c_options->image.zoom_2pass;
281 options->image.fit_window_to_image = c_options->image.fit_window_to_image;
282 options->image.limit_window_size = c_options->image.limit_window_size;
283 options->image.zoom_to_fit_allow_expand = c_options->image.zoom_to_fit_allow_expand;
284 options->image.max_window_size = c_options->image.max_window_size;
285 options->image.limit_autofit_size = c_options->image.limit_autofit_size;
286 options->image.max_autofit_size = c_options->image.max_autofit_size;
287 options->image.max_enlargement_size = c_options->image.max_enlargement_size;
288 options->image.use_clutter_renderer = c_options->image.use_clutter_renderer;
289 options->image.tile_size = c_options->image.tile_size;
290 options->progressive_key_scrolling = c_options->progressive_key_scrolling;
291 options->keyboard_scroll_step = c_options->keyboard_scroll_step;
293 if (options->thumbnails.max_width != c_options->thumbnails.max_width
294 || options->thumbnails.max_height != c_options->thumbnails.max_height
295 || options->thumbnails.quality != c_options->thumbnails.quality)
297 thumb_format_changed = TRUE;
299 options->thumbnails.max_width = c_options->thumbnails.max_width;
300 options->thumbnails.max_height = c_options->thumbnails.max_height;
301 options->thumbnails.quality = c_options->thumbnails.quality;
303 options->thumbnails.enable_caching = c_options->thumbnails.enable_caching;
304 options->thumbnails.cache_into_dirs = c_options->thumbnails.cache_into_dirs;
305 options->thumbnails.use_exif = c_options->thumbnails.use_exif;
306 options->thumbnails.use_color_management = c_options->thumbnails.use_color_management;
307 options->thumbnails.collection_preview = c_options->thumbnails.collection_preview;
308 options->thumbnails.use_ft_metadata = c_options->thumbnails.use_ft_metadata;
309 // options->thumbnails.use_ft_metadata_small = c_options->thumbnails.use_ft_metadata_small;
310 options->thumbnails.spec_standard = c_options->thumbnails.spec_standard;
311 options->metadata.enable_metadata_dirs = c_options->metadata.enable_metadata_dirs;
312 options->file_filter.show_hidden_files = c_options->file_filter.show_hidden_files;
313 options->file_filter.show_parent_directory = c_options->file_filter.show_parent_directory;
314 options->file_filter.show_dot_directory = c_options->file_filter.show_dot_directory;
315 options->file_filter.disable_file_extension_checks = c_options->file_filter.disable_file_extension_checks;
317 options->file_sort.case_sensitive = c_options->file_sort.case_sensitive;
318 options->file_sort.natural = c_options->file_sort.natural;
319 options->file_filter.disable = c_options->file_filter.disable;
321 config_entry_to_option(sidecar_ext_entry, &options->sidecar.ext, NULL);
322 sidecar_ext_parse(options->sidecar.ext);
324 options->slideshow.random = c_options->slideshow.random;
325 options->slideshow.repeat = c_options->slideshow.repeat;
326 options->slideshow.delay = c_options->slideshow.delay;
328 options->mousewheel_scrolls = c_options->mousewheel_scrolls;
329 options->image_lm_click_nav = c_options->image_lm_click_nav;
330 options->image_l_click_video = c_options->image_l_click_video;
331 options->image_l_click_video_editor = c_options->image_l_click_video_editor;
333 options->file_ops.enable_in_place_rename = c_options->file_ops.enable_in_place_rename;
335 options->image.tile_cache_max = c_options->image.tile_cache_max;
336 options->image.image_cache_max = c_options->image.image_cache_max;
338 options->image.zoom_quality = c_options->image.zoom_quality;
340 options->image.zoom_increment = c_options->image.zoom_increment;
342 options->image.enable_read_ahead = c_options->image.enable_read_ahead;
345 if (options->image.use_custom_border_color != c_options->image.use_custom_border_color
346 || options->image.use_custom_border_color_in_fullscreen != c_options->image.use_custom_border_color_in_fullscreen
347 || !gdk_color_equal(&options->image.border_color, &c_options->image.border_color))
349 options->image.use_custom_border_color_in_fullscreen = c_options->image.use_custom_border_color_in_fullscreen;
350 options->image.use_custom_border_color = c_options->image.use_custom_border_color;
351 options->image.border_color = c_options->image.border_color;
352 layout_colors_update();
353 view_window_colors_update();
356 options->image.alpha_color_1 = c_options->image.alpha_color_1;
357 options->image.alpha_color_2 = c_options->image.alpha_color_2;
359 options->fullscreen.screen = c_options->fullscreen.screen;
360 options->fullscreen.clean_flip = c_options->fullscreen.clean_flip;
361 options->fullscreen.disable_saver = c_options->fullscreen.disable_saver;
362 options->fullscreen.above = c_options->fullscreen.above;
363 if (c_options->image_overlay.template_string)
364 set_image_overlay_template_string(&options->image_overlay.template_string,
365 c_options->image_overlay.template_string);
366 if (c_options->image_overlay.font)
367 set_image_overlay_font_string(&options->image_overlay.font,
368 c_options->image_overlay.font);
369 options->image_overlay.text_red = c_options->image_overlay.text_red;
370 options->image_overlay.text_green = c_options->image_overlay.text_green;
371 options->image_overlay.text_blue = c_options->image_overlay.text_blue;
372 options->image_overlay.text_alpha = c_options->image_overlay.text_alpha;
373 options->image_overlay.background_red = c_options->image_overlay.background_red;
374 options->image_overlay.background_green = c_options->image_overlay.background_green;
375 options->image_overlay.background_blue = c_options->image_overlay.background_blue;
376 options->image_overlay.background_alpha = c_options->image_overlay.background_alpha;
377 options->update_on_time_change = c_options->update_on_time_change;
378 options->image.exif_proof_rotate_enable = c_options->image.exif_proof_rotate_enable;
380 options->duplicates_similarity_threshold = c_options->duplicates_similarity_threshold;
381 options->rot_invariant_sim = c_options->rot_invariant_sim;
383 options->tree_descend_subdirs = c_options->tree_descend_subdirs;
385 options->view_dir_list_single_click_enter = c_options->view_dir_list_single_click_enter;
386 options->circular_selection_lists = c_options->circular_selection_lists;
388 options->open_recent_list_maxsize = c_options->open_recent_list_maxsize;
389 options->dnd_icon_size = c_options->dnd_icon_size;
390 options->clipboard_selection = c_options->clipboard_selection;
391 options->dnd_default_action = c_options->dnd_default_action;
393 options->metadata.save_in_image_file = c_options->metadata.save_in_image_file;
394 options->metadata.save_legacy_IPTC = c_options->metadata.save_legacy_IPTC;
395 options->metadata.warn_on_write_problems = c_options->metadata.warn_on_write_problems;
396 options->metadata.save_legacy_format = c_options->metadata.save_legacy_format;
397 options->metadata.sync_grouped_files = c_options->metadata.sync_grouped_files;
398 options->metadata.confirm_write = c_options->metadata.confirm_write;
399 options->metadata.sidecar_extended_name = c_options->metadata.sidecar_extended_name;
400 options->metadata.confirm_timeout = c_options->metadata.confirm_timeout;
401 options->metadata.confirm_after_timeout = c_options->metadata.confirm_after_timeout;
402 options->metadata.confirm_on_image_change = c_options->metadata.confirm_on_image_change;
403 options->metadata.confirm_on_dir_change = c_options->metadata.confirm_on_dir_change;
404 options->metadata.keywords_case_sensitive = c_options->metadata.keywords_case_sensitive;
405 options->metadata.write_orientation = c_options->metadata.write_orientation;
406 options->stereo.mode = (c_options->stereo.mode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
407 (c_options->stereo.tmp.mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
408 (c_options->stereo.tmp.flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
409 (c_options->stereo.tmp.mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
410 (c_options->stereo.tmp.flip_left ? PR_STEREO_FLIP_LEFT : 0) |
411 (c_options->stereo.tmp.swap ? PR_STEREO_SWAP : 0) |
412 (c_options->stereo.tmp.temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
413 options->stereo.fsmode = (c_options->stereo.fsmode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
414 (c_options->stereo.tmp.fs_mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
415 (c_options->stereo.tmp.fs_flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
416 (c_options->stereo.tmp.fs_mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
417 (c_options->stereo.tmp.fs_flip_left ? PR_STEREO_FLIP_LEFT : 0) |
418 (c_options->stereo.tmp.fs_swap ? PR_STEREO_SWAP : 0) |
419 (c_options->stereo.tmp.fs_temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
420 options->stereo.enable_fsmode = c_options->stereo.enable_fsmode;
421 options->stereo.fixed_w = c_options->stereo.fixed_w;
422 options->stereo.fixed_h = c_options->stereo.fixed_h;
423 options->stereo.fixed_x1 = c_options->stereo.fixed_x1;
424 options->stereo.fixed_y1 = c_options->stereo.fixed_y1;
425 options->stereo.fixed_x2 = c_options->stereo.fixed_x2;
426 options->stereo.fixed_y2 = c_options->stereo.fixed_y2;
428 options->info_keywords.height = c_options->info_keywords.height;
429 options->info_title.height = c_options->info_title.height;
430 options->info_comment.height = c_options->info_comment.height;
431 options->info_rating.height = c_options->info_rating.height;
433 options->show_predefined_keyword_tree = c_options->show_predefined_keyword_tree;
434 options->expand_menu_toolbar = c_options->expand_menu_toolbar;
436 options->marks_save = c_options->marks_save;
437 options->with_rename = c_options->with_rename;
438 options->collections_on_top = c_options->collections_on_top;
439 options->hide_window_in_fullscreen = c_options->hide_window_in_fullscreen;
440 config_entry_to_option(help_search_engine_entry, &options->help_search_engine, NULL);
442 options->external_preview.enable = c_options->external_preview.enable;
443 config_entry_to_option(external_preview_select_entry, &options->external_preview.select, NULL);
444 config_entry_to_option(external_preview_extract_entry, &options->external_preview.extract, NULL);
446 options->read_metadata_in_idle = c_options->read_metadata_in_idle;
448 options->star_rating.star = c_options->star_rating.star;
449 options->star_rating.rejected = c_options->star_rating.rejected;
451 options->threads.duplicates = c_options->threads.duplicates > 0 ? c_options->threads.duplicates : -1;
454 set_debug_level(debug_c);
458 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
460 config_entry_to_option(color_profile_input_name_entry[i], &options->color_profile.input_name[i], NULL);
461 config_entry_to_option(color_profile_input_file_entry[i], &options->color_profile.input_file[i], NULL);
463 config_entry_to_option(color_profile_screen_file_entry, &options->color_profile.screen_file, NULL);
464 options->color_profile.use_x11_screen_profile = c_options->color_profile.use_x11_screen_profile;
465 if (options->color_profile.render_intent != c_options->color_profile.render_intent)
467 options->color_profile.render_intent = c_options->color_profile.render_intent;
472 options->mouse_button_8 = c_options->mouse_button_8;
473 options->mouse_button_9 = c_options->mouse_button_9;
475 options->override_disable_gpu = c_options->override_disable_gpu;
477 config_tab_keywords_save();
479 image_options_sync();
484 layout_refresh(NULL);
487 if (accel_store) gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_apply_cb, NULL);
489 toolbar_apply(TOOLBAR_MAIN);
490 toolbar_apply(TOOLBAR_STATUS);
494 *-----------------------------------------------------------------------------
495 * config window main button callbacks (private)
496 *-----------------------------------------------------------------------------
499 static void config_window_close_cb(GtkWidget *widget, gpointer data)
501 gtk_widget_destroy(configwindow);
506 static void config_window_help_cb(GtkWidget *widget, gpointer data)
508 GtkWidget *notebook = data;
511 static gchar *html_section[] =
513 "GuideOptionsGeneral.html",
514 "GuideOptionsImage.html",
515 "GuideOptionsOSD.html",
516 "GuideOptionsWindow.html",
517 "GuideOptionsKeyboard.html",
518 "GuideOptionsFiltering.html",
519 "GuideOptionsMetadata.html",
520 "GuideOptionsKeywords.html",
521 "GuideOptionsColor.html",
522 "GuideOptionsStereo.html",
523 "GuideOptionsBehavior.html",
524 "GuideOptionsToolbar.html",
525 "GuideOptionsToolbar.html",
526 "GuideOptionsAdvanced.html"
529 i = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
530 help_window_show(html_section[i]);
533 static gboolean config_window_delete(GtkWidget *widget, GdkEventAny *event, gpointer data)
535 config_window_close_cb(NULL, NULL);
539 static void config_window_ok_cb(GtkWidget *widget, gpointer data)
542 GtkNotebook *notebook = data;
550 lw = layout_window_list->data;
552 window = gtk_widget_get_window(widget);
553 gdk_window_get_root_origin(window, &x, &y);
554 w = gdk_window_get_width(window);
555 h = gdk_window_get_height(window);
556 page_number = gtk_notebook_get_current_page(notebook);
558 lw->options.preferences_window.x = x;
559 lw->options.preferences_window.y = y;
560 lw->options.preferences_window.w = w;
561 lw->options.preferences_window.h = h;
562 lw->options.preferences_window.page_number = page_number;
564 config_window_apply();
565 layout_util_sync(lw);
566 save_options(options);
567 config_window_close_cb(NULL, NULL);
571 *-----------------------------------------------------------------------------
572 * config window setup (private)
573 *-----------------------------------------------------------------------------
576 static void quality_menu_cb(GtkWidget *combo, gpointer data)
580 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
584 *option = GDK_INTERP_NEAREST;
587 *option = GDK_INTERP_TILES;
590 *option = GDK_INTERP_BILINEAR;
595 static void dnd_default_action_selection_menu_cb(GtkWidget *combo, gpointer data)
599 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
603 *option = DND_ACTION_ASK;
606 *option = DND_ACTION_COPY;
609 *option = DND_ACTION_MOVE;
613 static void clipboard_selection_menu_cb(GtkWidget *combo, gpointer data)
617 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
620 *option = CLIPBOARD_PRIMARY;
623 *option = CLIPBOARD_CLIPBOARD;
626 *option = CLIPBOARD_BOTH;
629 *option = CLIPBOARD_BOTH;
633 static void add_quality_menu(GtkWidget *table, gint column, gint row, const gchar *text,
634 guint option, guint *option_c)
641 pref_table_label(table, column, row, text, 0.0);
643 combo = gtk_combo_box_text_new();
645 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Nearest (worst, but fastest)"));
646 if (option == GDK_INTERP_NEAREST) current = 0;
647 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Tiles"));
648 if (option == GDK_INTERP_TILES) current = 1;
649 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Bilinear (best, but slowest)"));
650 if (option == GDK_INTERP_BILINEAR) current = 2;
652 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
654 g_signal_connect(G_OBJECT(combo), "changed",
655 G_CALLBACK(quality_menu_cb), option_c);
657 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
658 gtk_widget_show(combo);
661 static void add_dnd_default_action_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text, DnDAction option, DnDAction *option_c)
668 pref_table_label(table, column, row, text, 0.0);
670 combo = gtk_combo_box_text_new();
672 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Ask"));
673 if (option == DND_ACTION_ASK) current = 0;
674 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Copy"));
675 if (option == DND_ACTION_COPY) current = 1;
676 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Move"));
677 if (option == DND_ACTION_MOVE) current = 2;
679 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
681 g_signal_connect(G_OBJECT(combo), "changed",
682 G_CALLBACK(dnd_default_action_selection_menu_cb), option_c);
684 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
685 gtk_widget_show(combo);
688 static void add_clipboard_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
689 gint option, gint *option_c)
696 pref_table_label(table, column, row, text, 0.0);
698 combo = gtk_combo_box_text_new();
700 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Primary"));
701 if (option == CLIPBOARD_PRIMARY) current = 0;
702 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Clipboard"));
703 if (option == CLIPBOARD_CLIPBOARD) current = 1;
704 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Both"));
705 if (option == CLIPBOARD_BOTH) current = 2;
707 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
709 g_signal_connect(G_OBJECT(combo), "changed",
710 G_CALLBACK(clipboard_selection_menu_cb), option_c);
712 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
713 gtk_widget_show(combo);
716 typedef struct _UseableMouseItems UseableMouseItems;
717 struct _UseableMouseItems
719 gchar *name; /* GtkActionEntry terminology */
724 static const UseableMouseItems useable_mouse_items[] = {
726 {"FirstImage", N_("First Image"), GTK_STOCK_GOTO_TOP},
727 {"PrevImage", N_("Previous Image"), GTK_STOCK_GO_UP},
728 {"NextImage", N_("Next Image"), GTK_STOCK_GO_DOWN},
729 {"LastImage", N_("Last Image"), GTK_STOCK_GOTO_BOTTOM},
730 {"Back", N_("Back"), GTK_STOCK_GO_BACK},
731 {"Forward", N_("Forward"), GTK_STOCK_GO_FORWARD},
732 {"Home", N_("Home"), GTK_STOCK_HOME},
733 {"Up", N_("Up"), GTK_STOCK_GO_UP},
734 {"FirstPage", N_("First page"), GTK_STOCK_MEDIA_PREVIOUS},
735 {"LastPage", N_("Last Page"), GTK_STOCK_MEDIA_NEXT},
736 {"NextPage", N_("Next page"), GTK_STOCK_MEDIA_FORWARD},
737 {"PrevPage", N_("Previous Page"), GTK_STOCK_MEDIA_REWIND},
738 {"NewWindow", N_("New _window"), GTK_STOCK_NEW},
739 {"NewCollection", N_("New collection"), GTK_STOCK_INDEX},
740 {"OpenCollection", N_("Open collection"), GTK_STOCK_OPEN},
741 {"Search", N_("Search"), GTK_STOCK_FIND},
742 {"FindDupes", N_("Find duplicates"), GTK_STOCK_FIND},
743 {"NewFolder", N_("New folder"),GTK_STOCK_DIRECTORY},
744 {"Copy", N_("Copy"), GTK_STOCK_COPY},
745 {"Move", N_("Move"), PIXBUF_INLINE_ICON_MOVE},
746 {"Rename", N_("Rename"), PIXBUF_INLINE_ICON_RENAME},
747 {"Delete", N_("Delete"), GTK_STOCK_DELETE},
748 {"CloseWindow", N_("Close Window"), GTK_STOCK_CLOSE},
749 {"PanView", N_("Pan view"), PIXBUF_INLINE_ICON_PANORAMA},
750 {"SelectAll", N_("Select all"), PIXBUF_INLINE_ICON_SELECT_ALL},
751 {"SelectNone", N_("Select none"), PIXBUF_INLINE_ICON_SELECT_NONE},
752 {"SelectInvert", N_("Select invert"), PIXBUF_INLINE_ICON_SELECT_INVERT},
753 {"ShowFileFilter", N_("Show file filter"), PIXBUF_INLINE_ICON_FILE_FILTER},
754 {"RectangularSelection", N_("Select rectangle"), PIXBUF_INLINE_ICON_SELECT_RECTANGLE},
755 {"Print", N_("Print"), GTK_STOCK_PRINT},
756 {"Preferences", N_("Preferences"), GTK_STOCK_PREFERENCES},
757 {"LayoutConfig", N_("Configure this window"), GTK_STOCK_PREFERENCES},
758 {"Maintenance", N_("Cache maintenance"), PIXBUF_INLINE_ICON_MAINTENANCE},
759 {"RotateCW", N_("Rotate clockwise 90°"), PIXBUF_INLINE_ICON_CW},
760 {"RotateCCW", N_("Rotate counterclockwise 90°"), PIXBUF_INLINE_ICON_CCW},
761 {"Rotate180", N_("Rotate 180°"), PIXBUF_INLINE_ICON_180},
762 {"Mirror", N_("Mirror"), PIXBUF_INLINE_ICON_MIRROR},
763 {"Flip", N_("Flip"), PIXBUF_INLINE_ICON_FLIP},
764 {"AlterNone", N_("Original state"), PIXBUF_INLINE_ICON_ORIGINAL},
765 {"ZoomIn", N_("Zoom in"), GTK_STOCK_ZOOM_IN},
766 {"ZoomOut", N_("Zoom out"), GTK_STOCK_ZOOM_OUT},
767 {"Zoom100", N_("Zoom 1:1"), GTK_STOCK_ZOOM_100},
768 {"ZoomFit", N_("Zoom to fit"), GTK_STOCK_ZOOM_FIT},
769 {"ZoomFillHor", N_("Fit Horizontaly"), PIXBUF_INLINE_ICON_ZOOMFILLHOR},
770 {"ZoomFillVert", N_("Fit vertically"), PIXBUF_INLINE_ICON_ZOOMFILLVERT},
771 {"Zoom200", N_("Zoom 2:1"), GTK_STOCK_FILE},
772 {"Zoom300", N_("Zoom 3:1"), GTK_STOCK_FILE},
773 {"Zoom400", N_("Zoom 4:1"), GTK_STOCK_FILE},
774 {"Zoom50", N_("Zoom 1:2"), GTK_STOCK_FILE},
775 {"Zoom33", N_("Zoom1:3"), GTK_STOCK_FILE},
776 {"Zoom25", N_("Zoom 1:4"), GTK_STOCK_FILE},
777 {"ConnectZoomIn", N_("Connected Zoom in"), GTK_STOCK_ZOOM_IN},
778 {"SplitPaneSync", N_("Split Pane Sync"), PIXBUF_INLINE_SPLIT_PANE_SYNC},
779 {"Grayscale", N_("Grayscale"), PIXBUF_INLINE_ICON_GRAYSCALE},
780 {"OverUnderExposed", N_("Over Under Exposed"), PIXBUF_INLINE_ICON_EXPOSURE},
781 {"HideTools", N_("Hide file list"), PIXBUF_INLINE_ICON_HIDETOOLS},
782 {"SlideShowPause", N_("Pause slideshow"), GTK_STOCK_MEDIA_PAUSE},
783 {"SlideShowFaster", N_("Slideshow Faster"), GTK_STOCK_FILE},
784 {"SlideShowSlower", N_("Slideshow Slower"), GTK_STOCK_FILE},
785 {"Refresh", N_("Refresh"), GTK_STOCK_REFRESH},
786 {"HelpContents", N_("Help"), GTK_STOCK_HELP},
787 {"ExifWin", N_("Exif window"), PIXBUF_INLINE_ICON_EXIF},
788 {"Thumbnails", N_("Show thumbnails"), PIXBUF_INLINE_ICON_THUMB},
789 {"ShowMarks", N_("Show marks"), PIXBUF_INLINE_ICON_MARKS},
790 {"DrawRectangle", N_("Draw Rectangle"), PIXBUF_INLINE_ICON_DRAW_RECTANGLE},
791 {"FloatTools", N_("Float file list"), PIXBUF_INLINE_ICON_FLOAT},
792 {"SBar", N_("Info sidebar"), PIXBUF_INLINE_ICON_INFO},
793 {"SBarSort", N_("Sort manager"), PIXBUF_INLINE_ICON_SORT},
794 {"Quit", N_("Quit"), GTK_STOCK_QUIT},
798 static void mouse_buttons_selection_menu_cb(GtkWidget *combo, gpointer data)
800 gchar **option = data;
803 label = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(combo));
805 const UseableMouseItems *list = useable_mouse_items;
809 if (g_strcmp0(list->label, label) == 0)
817 *option = g_strdup(list->name);
821 static void add_mouse_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
822 gchar *option, gchar **option_c)
830 pref_table_label(table, column, row, text, 0.0);
832 combo = gtk_combo_box_text_new();
834 const UseableMouseItems *list = useable_mouse_items;
838 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), list->label);
839 if (g_strcmp0(list->name, option) == 0)
847 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
849 g_signal_connect(G_OBJECT(combo), "changed",
850 G_CALLBACK(mouse_buttons_selection_menu_cb), option_c);
852 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
853 gtk_widget_show(combo);
856 static void thumb_size_menu_cb(GtkWidget *combo, gpointer data)
860 n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
863 if ((guint) n < sizeof(thumb_size_list) / sizeof(ThumbSize))
865 c_options->thumbnails.max_width = thumb_size_list[n].w;
866 c_options->thumbnails.max_height = thumb_size_list[n].h;
870 c_options->thumbnails.max_width = options->thumbnails.max_width;
871 c_options->thumbnails.max_height = options->thumbnails.max_height;
875 static void add_thumb_size_menu(GtkWidget *table, gint column, gint row, gchar *text)
881 c_options->thumbnails.max_width = options->thumbnails.max_width;
882 c_options->thumbnails.max_height = options->thumbnails.max_height;
884 pref_table_label(table, column, row, text, 0.0);
886 combo = gtk_combo_box_text_new();
889 for (i = 0; (guint) i < sizeof(thumb_size_list) / sizeof(ThumbSize); i++)
894 w = thumb_size_list[i].w;
895 h = thumb_size_list[i].h;
897 buf = g_strdup_printf("%d x %d", w, h);
898 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
901 if (w == options->thumbnails.max_width && h == options->thumbnails.max_height) current = i;
908 buf = g_strdup_printf("%s %d x %d", _("Custom"), options->thumbnails.max_width, options->thumbnails.max_height);
909 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
915 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
916 g_signal_connect(G_OBJECT(combo), "changed",
917 G_CALLBACK(thumb_size_menu_cb), NULL);
919 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
920 gtk_widget_show(combo);
923 static void stereo_mode_menu_cb(GtkWidget *combo, gpointer data)
927 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
931 *option = PR_STEREO_NONE;
934 *option = PR_STEREO_ANAGLYPH_RC;
937 *option = PR_STEREO_ANAGLYPH_GM;
940 *option = PR_STEREO_ANAGLYPH_YB;
943 *option = PR_STEREO_ANAGLYPH_GRAY_RC;
946 *option = PR_STEREO_ANAGLYPH_GRAY_GM;
949 *option = PR_STEREO_ANAGLYPH_GRAY_YB;
952 *option = PR_STEREO_ANAGLYPH_DB_RC;
955 *option = PR_STEREO_ANAGLYPH_DB_GM;
958 *option = PR_STEREO_ANAGLYPH_DB_YB;
961 *option = PR_STEREO_HORIZ;
964 *option = PR_STEREO_HORIZ | PR_STEREO_HALF;
967 *option = PR_STEREO_VERT;
970 *option = PR_STEREO_VERT | PR_STEREO_HALF;
973 *option = PR_STEREO_FIXED;
978 static void add_stereo_mode_menu(GtkWidget *table, gint column, gint row, const gchar *text,
979 gint option, gint *option_c, gboolean add_fixed)
986 pref_table_label(table, column, row, text, 0.0);
988 combo = gtk_combo_box_text_new();
990 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Single image"));
992 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Red-Cyan"));
993 if (option & PR_STEREO_ANAGLYPH_RC) current = 1;
994 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Green-Magenta"));
995 if (option & PR_STEREO_ANAGLYPH_GM) current = 2;
996 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Yellow-Blue"));
997 if (option & PR_STEREO_ANAGLYPH_YB) current = 3;
998 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Red-Cyan"));
999 if (option & PR_STEREO_ANAGLYPH_GRAY_RC) current = 4;
1000 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Green-Magenta"));
1001 if (option & PR_STEREO_ANAGLYPH_GRAY_GM) current = 5;
1002 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Yellow-Blue"));
1003 if (option & PR_STEREO_ANAGLYPH_GRAY_YB) current = 6;
1004 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Red-Cyan"));
1005 if (option & PR_STEREO_ANAGLYPH_DB_RC) current = 7;
1006 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Green-Magenta"));
1007 if (option & PR_STEREO_ANAGLYPH_DB_GM) current = 8;
1008 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Yellow-Blue"));
1009 if (option & PR_STEREO_ANAGLYPH_DB_YB) current = 9;
1011 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side"));
1012 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side Half size"));
1013 if (option & PR_STEREO_HORIZ)
1016 if (option & PR_STEREO_HALF) current = 11;
1019 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom"));
1020 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom Half size"));
1021 if (option & PR_STEREO_VERT)
1024 if (option & PR_STEREO_HALF) current = 13;
1029 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Fixed position"));
1030 if (option & PR_STEREO_FIXED) current = 14;
1033 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
1035 g_signal_connect(G_OBJECT(combo), "changed",
1036 G_CALLBACK(stereo_mode_menu_cb), option_c);
1038 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
1039 gtk_widget_show(combo);
1042 static void video_menu_cb(GtkWidget *combo, gpointer data)
1044 gchar **option = data;
1046 EditorDescription *ed = g_list_nth_data(editor_list_get(), gtk_combo_box_get_active(GTK_COMBO_BOX(combo)));
1050 static void video_menu_populate(gpointer data, gpointer user_data)
1052 GtkWidget *combo = user_data;
1053 EditorDescription *ed = data;
1055 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), ed->name);
1058 static void add_video_menu(GtkWidget *table, gint column, gint row, const gchar *text,
1059 gchar *option, gchar **option_c)
1063 /* use lists since they are sorted */
1064 GList *eds = editor_list_get();
1068 pref_table_label(table, column, row, text, 0.0);
1070 combo = gtk_combo_box_text_new();
1071 g_list_foreach(eds,video_menu_populate,(gpointer)combo);
1072 current = option ? g_list_index(eds,g_hash_table_lookup(editors,option)): -1;
1074 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
1076 g_signal_connect(G_OBJECT(combo), "changed",
1077 G_CALLBACK(video_menu_cb), option_c);
1079 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
1080 gtk_widget_show(combo);
1083 static void filter_store_populate(void)
1087 if (!filter_store) return;
1089 gtk_list_store_clear(filter_store);
1091 work = filter_get_list();
1100 gtk_list_store_append(filter_store, &iter);
1101 gtk_list_store_set(filter_store, &iter, 0, fe, -1);
1105 static void filter_store_ext_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1106 gchar *new_text, gpointer data)
1108 GtkWidget *model = data;
1109 FilterEntry *fe = data;
1113 if (!new_text || strlen(new_text) < 1) return;
1115 tpath = gtk_tree_path_new_from_string(path_str);
1116 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1117 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1119 g_free(fe->extensions);
1120 fe->extensions = g_strdup(new_text);
1122 gtk_tree_path_free(tpath);
1126 static void filter_store_class_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1127 gchar *new_text, gpointer data)
1129 GtkWidget *model = data;
1130 FilterEntry *fe = data;
1135 if (!new_text || !new_text[0]) return;
1137 tpath = gtk_tree_path_new_from_string(path_str);
1138 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1139 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1141 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
1143 if (strcmp(new_text, _(format_class_list[i])) == 0)
1150 gtk_tree_path_free(tpath);
1154 static void filter_store_desc_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1155 gchar *new_text, gpointer data)
1157 GtkWidget *model = data;
1162 if (!new_text || !new_text[0]) return;
1164 tpath = gtk_tree_path_new_from_string(path_str);
1165 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1166 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1168 g_free(fe->description);
1169 fe->description = g_strdup(new_text);
1171 gtk_tree_path_free(tpath);
1174 static void filter_store_enable_cb(GtkCellRendererToggle *renderer,
1175 gchar *path_str, gpointer data)
1177 GtkWidget *model = data;
1182 tpath = gtk_tree_path_new_from_string(path_str);
1183 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1184 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1186 fe->enabled = !fe->enabled;
1188 gtk_tree_path_free(tpath);
1192 static void filter_store_writable_cb(GtkCellRendererToggle *renderer,
1193 gchar *path_str, gpointer data)
1195 GtkWidget *model = data;
1200 tpath = gtk_tree_path_new_from_string(path_str);
1201 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1202 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1204 fe->writable = !fe->writable;
1205 if (fe->writable) fe->allow_sidecar = FALSE;
1207 gtk_tree_path_free(tpath);
1211 static void filter_store_sidecar_cb(GtkCellRendererToggle *renderer,
1212 gchar *path_str, gpointer data)
1214 GtkWidget *model = data;
1219 tpath = gtk_tree_path_new_from_string(path_str);
1220 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1221 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1223 fe->allow_sidecar = !fe->allow_sidecar;
1224 if (fe->allow_sidecar) fe->writable = FALSE;
1226 gtk_tree_path_free(tpath);
1230 static void filter_set_func(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
1231 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
1235 gtk_tree_model_get(tree_model, iter, 0, &fe, -1);
1237 switch (GPOINTER_TO_INT(data))
1240 g_object_set(GTK_CELL_RENDERER(cell),
1241 "active", fe->enabled, NULL);
1244 g_object_set(GTK_CELL_RENDERER(cell),
1245 "text", fe->extensions, NULL);
1247 case FE_DESCRIPTION:
1248 g_object_set(GTK_CELL_RENDERER(cell),
1249 "text", fe->description, NULL);
1252 g_object_set(GTK_CELL_RENDERER(cell),
1253 "text", _(format_class_list[fe->file_class]), NULL);
1256 g_object_set(GTK_CELL_RENDERER(cell),
1257 "active", fe->writable, NULL);
1259 case FE_ALLOW_SIDECAR:
1260 g_object_set(GTK_CELL_RENDERER(cell),
1261 "active", fe->allow_sidecar, NULL);
1266 static gboolean filter_add_scroll(gpointer data)
1270 GtkCellRenderer *cell;
1271 GtkTreeViewColumn *column;
1274 rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(filter_store), NULL);
1275 path = gtk_tree_path_new_from_indices(rows-1, -1);
1277 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data), 0);
1279 list_cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column));
1280 cell = g_list_last(list_cells)->data;
1282 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1283 path, column, FALSE, 0.0, 0.0 );
1284 gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(data),
1285 path, column, cell, TRUE);
1287 gtk_tree_path_free(path);
1288 g_list_free(list_cells);
1293 static void filter_add_cb(GtkWidget *widget, gpointer data)
1295 filter_add_unique("description", ".new", FORMAT_CLASS_IMAGE, TRUE, FALSE, TRUE);
1296 filter_store_populate();
1298 g_idle_add((GSourceFunc)filter_add_scroll, data);
1301 static void filter_remove_cb(GtkWidget *widget, gpointer data)
1303 GtkWidget *filter_view = data;
1304 GtkTreeSelection *selection;
1308 if (!filter_store) return;
1309 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1310 if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) return;
1311 gtk_tree_model_get(GTK_TREE_MODEL(filter_store), &iter, 0, &fe, -1);
1314 filter_remove_entry(fe);
1316 filter_store_populate();
1319 static gboolean filter_default_ok_scroll(GtkTreeView *data)
1323 GtkTreeViewColumn *column;
1325 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(filter_store), &iter);
1326 path = gtk_tree_model_get_path(GTK_TREE_MODEL(filter_store), &iter);
1327 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1329 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1333 gtk_tree_path_free(path);
1338 static void filter_default_ok_cb(GenericDialog *gd, gpointer data)
1341 filter_add_defaults();
1343 filter_store_populate();
1345 g_idle_add((GSourceFunc)filter_default_ok_scroll, gd->data);
1348 static void dummy_cancel_cb(GenericDialog *gd, gpointer data)
1350 /* no op, only so cancel button appears */
1353 static void filter_default_cb(GtkWidget *widget, gpointer data)
1357 gd = generic_dialog_new(_("Reset filters"),
1358 "reset_filter", widget, TRUE,
1359 dummy_cancel_cb, data);
1360 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset filters"),
1361 _("This will reset the file filters to the defaults.\nContinue?"), TRUE);
1362 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, filter_default_ok_cb, TRUE);
1363 gtk_widget_show(gd->dialog);
1366 static void filter_disable_cb(GtkWidget *widget, gpointer data)
1368 GtkWidget *frame = data;
1370 gtk_widget_set_sensitive(frame,
1371 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
1374 static void safe_delete_view_cb(GtkWidget *widget, gpointer data)
1376 layout_set_path(NULL, gtk_entry_get_text(GTK_ENTRY(safe_delete_path_entry)));
1379 static void safe_delete_clear_ok_cb(GenericDialog *gd, gpointer data)
1381 file_util_trash_clear();
1384 static void safe_delete_clear_cb(GtkWidget *widget, gpointer data)
1388 gd = generic_dialog_new(_("Clear trash"),
1389 "clear_trash", widget, TRUE,
1390 dummy_cancel_cb, NULL);
1391 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear trash"),
1392 _("This will remove the trash contents."), FALSE);
1393 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, safe_delete_clear_ok_cb, TRUE);
1394 entry = gtk_entry_new();
1395 gtk_widget_set_can_focus(entry, FALSE);
1396 gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE);
1397 if (options->file_ops.safe_delete_path) gtk_entry_set_text(GTK_ENTRY(entry), options->file_ops.safe_delete_path);
1398 gtk_box_pack_start(GTK_BOX(gd->vbox), entry, FALSE, FALSE, 0);
1399 gtk_widget_show(entry);
1400 gtk_widget_show(gd->dialog);
1403 static void image_overlay_template_view_changed_cb(GtkWidget *widget, gpointer data)
1405 GtkWidget *pTextView;
1406 GtkTextBuffer *pTextBuffer;
1410 pTextView = GTK_WIDGET(data);
1412 pTextBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pTextView));
1413 gtk_text_buffer_get_start_iter(pTextBuffer, &iStart);
1414 gtk_text_buffer_get_end_iter(pTextBuffer, &iEnd);
1416 set_image_overlay_template_string(&c_options->image_overlay.template_string,
1417 gtk_text_buffer_get_text(pTextBuffer, &iStart, &iEnd, TRUE));
1420 static void image_overlay_default_template_ok_cb(GenericDialog *gd, gpointer data)
1422 GtkTextView *text_view = data;
1423 GtkTextBuffer *buffer;
1425 set_default_image_overlay_template_string(&options->image_overlay.template_string);
1426 if (!configwindow) return;
1428 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
1429 gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1432 static void image_overlay_default_template_cb(GtkWidget *widget, gpointer data)
1436 gd = generic_dialog_new(_("Reset image overlay template string"),
1437 "reset_image_overlay_template_string", widget, TRUE,
1438 dummy_cancel_cb, data);
1439 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset image overlay template string"),
1440 _("This will reset the image overlay template string to the default.\nContinue?"), TRUE);
1441 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, image_overlay_default_template_ok_cb, TRUE);
1442 gtk_widget_show(gd->dialog);
1445 static void image_overlay_help_cb(GtkWidget *widget, gpointer data)
1447 help_window_show("GuideOptionsOSD.html");
1450 static void image_overlay_set_font_cb(GtkWidget *widget, gpointer data)
1452 #if GTK_CHECK_VERSION(3,4,0)
1455 PangoFontDescription *font_desc;
1457 dialog = gtk_font_chooser_dialog_new("Image Overlay Font", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1458 gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), options->image_overlay.font);
1460 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1462 font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
1463 font = pango_font_description_to_string(font_desc);
1464 g_free(c_options->image_overlay.font);
1465 c_options->image_overlay.font = g_strdup(font);
1469 gtk_widget_destroy(dialog);
1473 font = gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget));
1474 c_options->image_overlay.font = g_strdup(font);
1478 static void image_overlay_set_text_colour_cb(GtkWidget *widget, gpointer data)
1481 #if GTK_CHECK_VERSION(3,4,0)
1484 dialog = gtk_color_chooser_dialog_new("Image Overlay Text Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1485 colour.red = options->image_overlay.text_red;
1486 colour.green = options->image_overlay.text_green;
1487 colour.blue = options->image_overlay.text_blue;
1488 colour.alpha = options->image_overlay.text_alpha;
1489 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1490 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1492 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1494 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1495 c_options->image_overlay.text_red = colour.red*255;
1496 c_options->image_overlay.text_green = colour.green*255;
1497 c_options->image_overlay.text_blue = colour.blue*255;
1498 c_options->image_overlay.text_alpha = colour.alpha*255;
1500 gtk_widget_destroy(dialog);
1503 GtkColorSelection *colorsel;
1505 dialog = gtk_color_selection_dialog_new("Image Overlay Text Colour");
1506 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1507 colour.red = options->image_overlay.text_red*257;
1508 colour.green = options->image_overlay.text_green*257;
1509 colour.blue = options->image_overlay.text_blue*257;
1510 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1511 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1512 gtk_color_selection_set_current_color(colorsel, &colour);
1513 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.text_alpha*257);
1515 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1517 gtk_color_selection_get_current_color(colorsel, &colour);
1518 c_options->image_overlay.text_red = colour.red/257;
1519 c_options->image_overlay.text_green = colour.green/257;
1520 c_options->image_overlay.text_blue = colour.blue/257;
1521 c_options->image_overlay.text_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1523 gtk_widget_destroy (dialog);
1528 static void image_overlay_set_background_colour_cb(GtkWidget *widget, gpointer data)
1531 #if GTK_CHECK_VERSION(3,4,0)
1534 dialog = gtk_color_chooser_dialog_new("Image Overlay Background Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1535 colour.red = options->image_overlay.background_red;
1536 colour.green = options->image_overlay.background_green;
1537 colour.blue = options->image_overlay.background_blue;
1538 colour.alpha = options->image_overlay.background_alpha;
1539 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1540 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1542 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1544 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1545 c_options->image_overlay.background_red = colour.red*255;
1546 c_options->image_overlay.background_green = colour.green*255;
1547 c_options->image_overlay.background_blue = colour.blue*255;
1548 c_options->image_overlay.background_alpha = colour.alpha*255;
1550 gtk_widget_destroy(dialog);
1553 GtkColorSelection *colorsel;
1555 dialog = gtk_color_selection_dialog_new("Image Overlay Background Colour");
1556 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1557 colour.red = options->image_overlay.background_red*257;
1558 colour.green = options->image_overlay.background_green*257;
1559 colour.blue = options->image_overlay.background_blue*257;
1560 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1561 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1562 gtk_color_selection_set_current_color(colorsel, &colour);
1563 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.background_alpha*257);
1565 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1567 gtk_color_selection_get_current_color(colorsel, &colour);
1568 c_options->image_overlay.background_red = colour.red/257;
1569 c_options->image_overlay.background_green = colour.green/257;
1570 c_options->image_overlay.background_blue = colour.blue/257;
1571 c_options->image_overlay.background_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1573 gtk_widget_destroy(dialog);
1577 static void accel_store_populate(void)
1580 GList *groups, *actions;
1582 const gchar *accel_path;
1586 if (!accel_store || !layout_window_list || !layout_window_list->data) return;
1588 gtk_tree_store_clear(accel_store);
1589 lw = layout_window_list->data; /* get the actions from the first window, it should not matter, they should be the same in all windows */
1591 g_assert(lw && lw->ui_manager);
1592 groups = gtk_ui_manager_get_action_groups(lw->ui_manager);
1595 actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
1598 action = GTK_ACTION(actions->data);
1599 accel_path = gtk_action_get_accel_path(action);
1600 if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
1602 gchar *label, *label2, *tooltip, *accel;
1603 g_object_get(action,
1604 "tooltip", &tooltip,
1608 if (pango_parse_markup(label, -1, '_', NULL, &label2, NULL, NULL) && label2)
1614 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1618 gtk_tree_store_append(accel_store, &iter, NULL);
1619 gtk_tree_store_set(accel_store, &iter,
1622 AE_TOOLTIP, tooltip ? tooltip : "",
1623 AE_ACCEL, accel_path,
1631 actions = actions->next;
1634 groups = groups->next;
1638 static void accel_store_cleared_cb(GtkCellRendererAccel *accel, gchar *path_string, gpointer user_data)
1643 static gboolean accel_remove_key_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1645 gchar *accel1 = data;
1650 gtk_tree_model_get(model, iter, AE_KEY, &accel2, -1);
1652 gtk_accelerator_parse(accel1, &key1.accel_key, &key1.accel_mods);
1653 gtk_accelerator_parse(accel2, &key2.accel_key, &key2.accel_mods);
1655 if (key1.accel_key == key2.accel_key && key1.accel_mods == key2.accel_mods)
1657 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1658 DEBUG_1("accelerator key '%s' is already used, removing.", accel1);
1667 static void accel_store_edited_cb(GtkCellRendererAccel *accel, gchar *path_string, guint accel_key, GdkModifierType accel_mods, guint hardware_keycode, gpointer user_data)
1669 GtkTreeModel *model = (GtkTreeModel *)accel_store;
1673 GtkAccelKey old_key, key;
1674 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
1676 gtk_tree_model_get_iter(model, &iter, path);
1677 gtk_tree_model_get(model, &iter, AE_ACCEL, &accel_path, -1);
1679 /* test if the accelerator can be stored without conflicts*/
1680 gtk_accel_map_lookup_entry(accel_path, &old_key);
1682 /* change the key and read it back (change may fail on keys hardcoded in gtk)*/
1683 gtk_accel_map_change_entry(accel_path, accel_key, accel_mods, TRUE);
1684 gtk_accel_map_lookup_entry(accel_path, &key);
1686 /* restore the original for now, the key will be really changed when the changes are confirmed */
1687 gtk_accel_map_change_entry(accel_path, old_key.accel_key, old_key.accel_mods, TRUE);
1689 acc = gtk_accelerator_name(key.accel_key, key.accel_mods);
1690 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, acc);
1692 gtk_tree_store_set(accel_store, &iter, AE_KEY, acc, -1);
1693 gtk_tree_path_free(path);
1697 static gboolean accel_default_scroll(GtkTreeView *data)
1701 GtkTreeViewColumn *column;
1703 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(accel_store), &iter);
1704 path = gtk_tree_model_get_path(GTK_TREE_MODEL(accel_store), &iter);
1705 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1707 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1711 gtk_tree_path_free(path);
1716 static void accel_default_cb(GtkWidget *widget, gpointer data)
1718 accel_store_populate();
1720 g_idle_add((GSourceFunc)accel_default_scroll, data);
1723 void accel_remove_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1725 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1728 void accel_reset_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1731 gchar *accel_path, *accel;
1733 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, -1);
1734 gtk_accel_map_lookup_entry(accel_path, &key);
1735 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1737 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, accel);
1739 gtk_tree_store_set(accel_store, iter, AE_KEY, accel, -1);
1744 static void accel_reset_cb(GtkWidget *widget, gpointer data)
1746 GtkTreeSelection *selection;
1748 if (!accel_store) return;
1749 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data));
1750 gtk_tree_selection_selected_foreach(selection, &accel_reset_selection, NULL);
1755 static GtkWidget *scrolled_notebook_page(GtkWidget *notebook, const gchar *title)
1759 GtkWidget *scrolled;
1760 GtkWidget *viewport;
1762 scrolled = gtk_scrolled_window_new(NULL, NULL);
1763 gtk_container_set_border_width(GTK_CONTAINER(scrolled), PREF_PAD_BORDER);
1764 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1765 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1766 label = gtk_label_new(title);
1767 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, label);
1768 gtk_widget_show(scrolled);
1770 viewport = gtk_viewport_new(NULL, NULL);
1771 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1772 gtk_container_add(GTK_CONTAINER(scrolled), viewport);
1773 gtk_widget_show(viewport);
1775 vbox = gtk_vbox_new(FALSE, 0);
1776 gtk_container_add(GTK_CONTAINER(viewport), vbox);
1777 gtk_widget_show(vbox);
1782 static void cache_standard_cb(GtkWidget *widget, gpointer data)
1784 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1786 c_options->thumbnails.spec_standard =TRUE;
1787 c_options->thumbnails.cache_into_dirs = FALSE;
1791 static void cache_geeqie_cb(GtkWidget *widget, gpointer data)
1793 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1795 c_options->thumbnails.spec_standard =FALSE;
1796 c_options->thumbnails.cache_into_dirs = FALSE;
1800 static void cache_local_cb(GtkWidget *widget, gpointer data)
1802 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1804 c_options->thumbnails.cache_into_dirs = TRUE;
1805 c_options->thumbnails.spec_standard =FALSE;
1809 static void help_search_engine_entry_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1810 GdkEvent *event, gpointer userdata)
1812 if (pos == GTK_ENTRY_ICON_PRIMARY)
1814 gtk_entry_set_text(GTK_ENTRY(userdata), HELP_SEARCH_ENGINE);
1818 gtk_entry_set_text(GTK_ENTRY(userdata), "");
1822 static void star_rating_star_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1823 GdkEvent *event, gpointer userdata)
1825 gchar *rating_symbol;
1827 if (pos == GTK_ENTRY_ICON_PRIMARY)
1829 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_STAR);
1830 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1831 g_free(rating_symbol);
1835 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1836 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1837 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1841 static void star_rating_rejected_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1842 GdkEvent *event, gpointer userdata)
1844 gchar *rating_symbol;
1846 if (pos == GTK_ENTRY_ICON_PRIMARY)
1848 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_REJECTED);
1849 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1850 g_free(rating_symbol);
1854 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1855 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1856 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1860 static guint star_rating_symbol_test(GtkWidget *widget, gpointer data)
1862 GtkContainer *hbox = data;
1863 GString *str = g_string_new(NULL);
1864 GtkEntry *hex_code_entry;
1865 gchar *hex_code_full;
1868 guint64 hex_value = 0;
1870 list = gtk_container_get_children(hbox);
1872 hex_code_entry = g_list_nth_data(list, 2);
1873 hex_code_full = g_strdup(gtk_entry_get_text(hex_code_entry));
1875 hex_code = g_strsplit(hex_code_full, "+", 2);
1876 if (hex_code[0] && hex_code[1])
1878 hex_value = strtoull(hex_code[1], NULL, 16);
1880 if (!hex_value || hex_value > 0x10FFFF)
1882 hex_value = 0x003F; // Unicode 'Question Mark'
1884 str = g_string_append_unichar(str, (gunichar)hex_value);
1885 gtk_label_set_text(g_list_nth_data(list, 1), str->str);
1887 g_strfreev(hex_code);
1888 g_string_free(str, TRUE);
1889 g_free(hex_code_full);
1894 static void star_rating_star_test_cb(GtkWidget *widget, gpointer data)
1896 guint64 star_symbol;
1898 star_symbol = star_rating_symbol_test(widget, data);
1899 c_options->star_rating.star = star_symbol;
1902 static void star_rating_rejected_test_cb(GtkWidget *widget, gpointer data)
1904 guint64 rejected_symbol;
1906 rejected_symbol = star_rating_symbol_test(widget, data);
1907 c_options->star_rating.rejected = rejected_symbol;
1910 /* general options tab */
1911 static void timezone_database_install_cb(GtkWidget *widget, gpointer data);
1912 typedef struct _TZData TZData;
1916 GCancellable *cancellable;
1918 GtkWidget *progress;
1920 GFile *timezone_database_gq;
1921 gchar *timezone_database_user;
1924 static void config_tab_general(GtkWidget *notebook)
1929 GtkWidget *group_frame;
1930 GtkWidget *subgroup;
1932 GtkWidget *ct_button;
1935 gint hours, minutes, remainder;
1937 GtkWidget *star_rating_entry;
1939 gchar *rating_symbol;
1942 GNetworkMonitor *net_mon;
1943 GSocketConnectable *geeqie_org;
1944 gboolean internet_available;
1947 vbox = scrolled_notebook_page(notebook, _("General"));
1949 group = pref_group_new(vbox, FALSE, _("Thumbnails"), GTK_ORIENTATION_VERTICAL);
1951 table = pref_table_new(group, 2, 2, FALSE, FALSE);
1952 add_thumb_size_menu(table, 0, 0, _("Size:"));
1953 add_quality_menu(table, 0, 1, _("Quality:"), options->thumbnails.quality, &c_options->thumbnails.quality);
1955 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1956 pref_label_new(hbox, _("Custom size: "));
1957 pref_spin_new_int(hbox, _("Width:"), NULL, 1, 512, 1, options->thumbnails.max_width, &c_options->thumbnails.max_width);
1958 pref_spin_new_int(hbox, _("Height:"), NULL, 1, 512, 1, options->thumbnails.max_height, &c_options->thumbnails.max_height);
1960 ct_button = pref_checkbox_new_int(group, _("Cache thumbnails and sim. files"),
1961 options->thumbnails.enable_caching, &c_options->thumbnails.enable_caching);
1963 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1964 pref_checkbox_link_sensitivity(ct_button, subgroup);
1966 c_options->thumbnails.spec_standard = options->thumbnails.spec_standard;
1967 c_options->thumbnails.cache_into_dirs = options->thumbnails.cache_into_dirs;
1968 group_frame = pref_frame_new(subgroup, TRUE, _("Use Geeqie thumbnail style and cache"),
1969 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1970 button = pref_radiobutton_new(group_frame, NULL, get_thumbnails_cache_dir(),
1971 !options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1972 G_CALLBACK(cache_geeqie_cb), NULL);
1974 group_frame = pref_frame_new(subgroup, TRUE,
1975 _("Store thumbnails local to image folder (non-standard)"),
1976 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1977 pref_radiobutton_new(group_frame, button, "*/.thumbnails",
1978 !options->thumbnails.spec_standard && options->thumbnails.cache_into_dirs,
1979 G_CALLBACK(cache_local_cb), NULL);
1981 group_frame = pref_frame_new(subgroup, TRUE,
1982 _("Use standard thumbnail style and cache, shared with other applications"),
1983 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1984 pref_radiobutton_new(group_frame, button, get_thumbnails_standard_cache_dir(),
1985 options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1986 G_CALLBACK(cache_standard_cb), NULL);
1988 pref_checkbox_new_int(group, _("Use EXIF thumbnails when available (EXIF thumbnails may be outdated)"),
1989 options->thumbnails.use_exif, &c_options->thumbnails.use_exif);
1991 pref_checkbox_new_int(group, _("Thumbnail color management"),
1992 options->thumbnails.use_color_management, &c_options->thumbnails.use_color_management);
1994 spin = pref_spin_new_int(group, _("Collection preview:"), NULL,
1996 options->thumbnails.collection_preview, &c_options->thumbnails.collection_preview);
1997 gtk_widget_set_tooltip_text(spin, _("The maximum number of thumbnails shown in a Collection preview montage"));
1999 #ifdef HAVE_FFMPEGTHUMBNAILER_METADATA
2000 pref_checkbox_new_int(group, _("Use embedded metadata in video files as thumbnails when available"),
2001 options->thumbnails.use_ft_metadata, &c_options->thumbnails.use_ft_metadata);
2003 // pref_checkbox_new_int(group, _("Ignore embedded metadata if size is too small"),
2004 // options->thumbnails.use_ft_metadata_small, &c_options->thumbnails.use_ft_metadata_small);
2007 pref_spacer(group, PREF_PAD_GROUP);
2009 group = pref_group_new(vbox, FALSE, _("Star Rating"), GTK_ORIENTATION_VERTICAL);
2011 c_options->star_rating.star = options->star_rating.star;
2012 c_options->star_rating.rejected = options->star_rating.rejected;
2014 str = g_string_new(NULL);
2015 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2016 pref_label_new(hbox, _("Star character: "));
2017 str = g_string_append_unichar(str, options->star_rating.star);
2018 pref_label_new(hbox, g_strdup(str->str));
2019 rating_symbol = g_strdup_printf("U+%X", options->star_rating.star);
2020 star_rating_entry = gtk_entry_new();
2021 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
2022 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
2023 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
2024 gtk_widget_show(star_rating_entry);
2025 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
2026 G_CALLBACK(star_rating_star_test_cb), hbox);
2027 gtk_widget_set_tooltip_text(button, _("Display selected character"));
2028 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2029 gtk_widget_show(button);
2030 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."));
2031 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2032 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2033 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2034 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2035 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2036 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2037 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2038 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2039 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
2040 G_CALLBACK(star_rating_star_icon_cb),
2043 g_string_free(str, TRUE);
2044 g_free(rating_symbol);
2046 str = g_string_new(NULL);
2047 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2048 pref_label_new(hbox, _("Rejected character: "));
2049 str = g_string_append_unichar(str, options->star_rating.rejected);
2050 pref_label_new(hbox, g_strdup(str->str));
2051 rating_symbol = g_strdup_printf("U+%X", options->star_rating.rejected);
2052 star_rating_entry = gtk_entry_new();
2053 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
2054 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
2055 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
2056 gtk_widget_show(star_rating_entry);
2057 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
2058 G_CALLBACK(star_rating_rejected_test_cb), hbox);
2059 gtk_widget_set_tooltip_text(button, _("Display selected character"));
2060 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2061 gtk_widget_show(button);
2062 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."));
2063 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2064 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2065 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2066 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2067 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2068 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2069 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2070 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2071 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
2072 G_CALLBACK(star_rating_rejected_icon_cb),
2075 g_string_free(str, TRUE);
2076 g_free(rating_symbol);
2078 pref_spacer(group, PREF_PAD_GROUP);
2080 group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
2082 c_options->slideshow.delay = options->slideshow.delay;
2083 hours = options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2084 remainder = options->slideshow.delay % (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2085 minutes = remainder / (60 * SLIDESHOW_SUBSECOND_PRECISION);
2086 seconds = (gdouble)(remainder % (60 * SLIDESHOW_SUBSECOND_PRECISION)) /
2087 SLIDESHOW_SUBSECOND_PRECISION;
2089 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2091 spin = pref_spin_new(hbox, _("Delay between image change hrs:mins:secs.dec"), NULL,
2093 options->slideshow.delay ? hours : 0.0,
2094 G_CALLBACK(slideshow_delay_hours_cb), NULL);
2095 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2096 spin = pref_spin_new(hbox, ":" , NULL,
2098 options->slideshow.delay ? minutes: 0.0,
2099 G_CALLBACK(slideshow_delay_minutes_cb), NULL);
2100 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2101 spin = pref_spin_new(hbox, ":", NULL,
2102 SLIDESHOW_MIN_SECONDS, 59, 1.0, 1,
2103 options->slideshow.delay ? seconds : 10.0,
2104 G_CALLBACK(slideshow_delay_seconds_cb), NULL);
2105 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2107 pref_checkbox_new_int(group, _("Random"), options->slideshow.random, &c_options->slideshow.random);
2108 pref_checkbox_new_int(group, _("Repeat"), options->slideshow.repeat, &c_options->slideshow.repeat);
2110 pref_spacer(group, PREF_PAD_GROUP);
2112 group = pref_group_new(vbox, FALSE, _("Image loading and caching"), GTK_ORIENTATION_VERTICAL);
2114 pref_spin_new_int(group, _("Decoded image cache size (MiB):"), NULL,
2115 0, 99999, 1, options->image.image_cache_max, &c_options->image.image_cache_max);
2116 pref_checkbox_new_int(group, _("Preload next image"),
2117 options->image.enable_read_ahead, &c_options->image.enable_read_ahead);
2119 pref_checkbox_new_int(group, _("Refresh on file change"),
2120 options->update_on_time_change, &c_options->update_on_time_change);
2123 pref_spacer(group, PREF_PAD_GROUP);
2125 group = pref_group_new(vbox, FALSE, _("Expand menu and toolbar"), GTK_ORIENTATION_VERTICAL);
2127 pref_checkbox_new_int(group, _("Expand menu and toolbar (NOTE! Geeqie must be restarted for change to take effect)"),
2128 options->expand_menu_toolbar, &c_options->expand_menu_toolbar);
2129 gtk_widget_set_tooltip_text(group, _("Expand the menu and toolbar to the full width of the window"));
2131 pref_spacer(group, PREF_PAD_GROUP);
2133 group = pref_group_new(vbox, FALSE, _("Info sidebar heights"), GTK_ORIENTATION_VERTICAL);
2134 pref_label_new(group, _("NOTE! Geeqie must be restarted for changes to take effect"));
2135 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2136 pref_spin_new_int(hbox, _("Keywords:"), NULL,
2138 options->info_keywords.height, &c_options->info_keywords.height);
2139 pref_spin_new_int(hbox, _("Title:"), NULL,
2141 options->info_title.height, &c_options->info_title.height);
2142 pref_spin_new_int(hbox, _("Comment:"), NULL,
2144 options->info_comment.height, &c_options->info_comment.height);
2145 pref_spin_new_int(hbox, _("Rating:"), NULL,
2147 options->info_rating.height, &c_options->info_rating.height);
2149 pref_spacer(group, PREF_PAD_GROUP);
2151 group = pref_group_new(vbox, FALSE, _("Show predefined keyword tree"), GTK_ORIENTATION_VERTICAL);
2153 pref_checkbox_new_int(group, _("Show predefined keyword tree (NOTE! Geeqie must be restarted for change to take effect)"),
2154 options->show_predefined_keyword_tree, &c_options->show_predefined_keyword_tree);
2156 pref_spacer(group, PREF_PAD_GROUP);
2158 net_mon = g_network_monitor_get_default();
2159 geeqie_org = g_network_address_parse_uri(GQ_WEBSITE, 80, NULL);
2160 internet_available = g_network_monitor_can_reach(net_mon, geeqie_org, NULL, NULL);
2161 g_object_unref(geeqie_org);
2163 group = pref_group_new(vbox, FALSE, _("Timezone database"), GTK_ORIENTATION_VERTICAL);
2164 hbox = pref_box_new(group, TRUE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2166 if (!internet_available)
2168 gtk_widget_set_sensitive(group, FALSE);
2171 tz = g_new0(TZData, 1);
2173 path = path_from_utf8(TIMEZONE_DATABASE);
2174 basename = g_path_get_basename(path);
2175 tz->timezone_database_user = g_build_filename(get_rc_dir(), basename, NULL);
2179 if (isfile(tz->timezone_database_user))
2181 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Update"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2185 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Install"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2188 if (!internet_available)
2190 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"));
2194 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"));
2196 gtk_widget_show(button);
2198 pref_spacer(group, PREF_PAD_GROUP);
2200 group = pref_group_new(vbox, FALSE, _("On-line help search engine"), GTK_ORIENTATION_VERTICAL);
2202 help_search_engine_entry = gtk_entry_new();
2203 gtk_entry_set_text(GTK_ENTRY(help_search_engine_entry), options->help_search_engine);
2204 gtk_box_pack_start(GTK_BOX(group), help_search_engine_entry, FALSE, FALSE, 0);
2205 gtk_widget_show(help_search_engine_entry);
2207 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"));
2209 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2210 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2211 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2212 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2213 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2214 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2215 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2216 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2217 g_signal_connect(GTK_ENTRY(help_search_engine_entry), "icon-press",
2218 G_CALLBACK(help_search_engine_entry_icon_cb),
2219 help_search_engine_entry);
2223 static void config_tab_image(GtkWidget *notebook)
2228 GtkWidget *ct_button;
2229 GtkWidget *enlargement_button;
2232 GtkWidget *two_pass;
2234 GtkWidget *gpu_accel;
2237 vbox = scrolled_notebook_page(notebook, _("Image"));
2239 group = pref_group_new(vbox, FALSE, _("Zoom"), GTK_ORIENTATION_VERTICAL);
2241 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2242 add_quality_menu(table, 0, 0, _("Quality:"), options->image.zoom_quality, &c_options->image.zoom_quality);
2243 if (options->image.use_clutter_renderer && !options->disable_gpu)
2245 gtk_widget_set_sensitive(table, FALSE);
2249 gpu_accel = pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library (Requires restart)"),
2250 options->image.use_clutter_renderer, &c_options->image.use_clutter_renderer);
2251 if (options->disable_gpu && !options->override_disable_gpu)
2253 gtk_widget_set_sensitive(gpu_accel, FALSE);
2257 two_pass = pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"),
2258 options->image.zoom_2pass, &c_options->image.zoom_2pass);
2259 if (options->image.use_clutter_renderer && !options->disable_gpu)
2261 gtk_widget_set_sensitive(two_pass, FALSE);
2264 c_options->image.zoom_increment = options->image.zoom_increment;
2265 spin = pref_spin_new(group, _("Zoom increment:"), NULL,
2266 0.01, 4.0, 0.01, 2, (gdouble)options->image.zoom_increment / 100.0,
2267 G_CALLBACK(zoom_increment_cb), NULL);
2268 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2270 group = pref_group_new(vbox, FALSE, _("Fit image to window"), GTK_ORIENTATION_VERTICAL);
2272 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2273 enlargement_button = pref_checkbox_new_int(hbox, _("Allow enlargement of image (max. size in %)"),
2274 options->image.zoom_to_fit_allow_expand, &c_options->image.zoom_to_fit_allow_expand);
2275 spin = pref_spin_new_int(hbox, NULL, NULL,
2277 options->image.max_enlargement_size, &c_options->image.max_enlargement_size);
2278 pref_checkbox_link_sensitivity(enlargement_button, spin);
2279 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."));
2281 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2282 ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (% of actual window):"),
2283 options->image.limit_autofit_size, &c_options->image.limit_autofit_size);
2284 spin = pref_spin_new_int(hbox, NULL, NULL,
2286 options->image.max_autofit_size, &c_options->image.max_autofit_size);
2287 pref_checkbox_link_sensitivity(ct_button, spin);
2288 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."));
2290 group = pref_group_new(vbox, FALSE, _("Tile size"), GTK_ORIENTATION_VERTICAL);
2291 gtk_widget_set_sensitive(group, !options->image.use_clutter_renderer);
2293 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2294 spin = pref_spin_new_int(hbox, _("Pixels"), _("(Requires restart)"),
2296 options->image.tile_size, &c_options->image.tile_size);
2297 gtk_widget_set_tooltip_text(GTK_WIDGET(hbox), _("This value changes the size of the tiles large images are split into. Increasing the size of the tiles will reduce the tiling effect seen on image changes, but will also slightly increase the delay before the first part of a large image is seen."));
2299 group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
2301 pref_checkbox_new_int(group, _("Use custom border color in window mode"),
2302 options->image.use_custom_border_color, &c_options->image.use_custom_border_color);
2304 pref_checkbox_new_int(group, _("Use custom border color in fullscreen mode"),
2305 options->image.use_custom_border_color_in_fullscreen, &c_options->image.use_custom_border_color_in_fullscreen);
2307 pref_color_button_new(group, _("Border color"), &options->image.border_color,
2308 G_CALLBACK(pref_color_button_set_cb), &c_options->image.border_color);
2310 c_options->image.border_color = options->image.border_color;
2312 pref_color_button_new(group, _("Alpha channel color 1"), &options->image.alpha_color_1,
2313 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_1);
2315 pref_color_button_new(group, _("Alpha channel color 2"), &options->image.alpha_color_2,
2316 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_2);
2318 c_options->image.alpha_color_1 = options->image.alpha_color_1;
2319 c_options->image.alpha_color_2 = options->image.alpha_color_2;
2321 group = pref_group_new(vbox, FALSE, _("Convenience"), GTK_ORIENTATION_VERTICAL);
2323 pref_checkbox_new_int(group, _("Auto rotate proofs using Exif information"),
2324 options->image.exif_proof_rotate_enable, &c_options->image.exif_proof_rotate_enable);
2329 static void save_default_window_layout_cb(GtkWidget *widget, gpointer data)
2331 LayoutWindow *lw = NULL;
2332 gchar *default_path;
2335 /* Get current lw */
2338 tmp_id = lw->options.id;
2339 lw->options.id = g_strdup("lw_default");
2341 default_path = g_build_filename(get_rc_dir(), DEFAULT_WINDOW_LAYOUT, NULL);
2342 save_default_layout_options_to_file(default_path, options, lw);
2343 g_free(lw->options.id);
2344 lw->options.id = tmp_id;
2345 g_free(default_path);
2348 #if GTK_CHECK_VERSION(3,22,0)
2349 static gboolean popover_cb(gpointer data)
2351 GtkPopover *popover = data;
2353 gtk_popover_popdown(popover);
2358 static void default_layout_changed_cb(GtkWidget *button, GtkPopover *popover)
2360 gtk_popover_popup(popover);
2362 g_timeout_add(2000, popover_cb, popover);
2365 static GtkWidget *create_popover(GtkWidget *parent, GtkWidget *child, GtkPositionType pos)
2369 popover = gtk_popover_new(parent);
2370 gtk_popover_set_position(GTK_POPOVER (popover), pos);
2371 gtk_container_add (GTK_CONTAINER(popover), child);
2372 gtk_container_set_border_width(GTK_CONTAINER (popover), 6);
2373 gtk_widget_show (child);
2379 static void config_tab_windows(GtkWidget *notebook)
2384 GtkWidget *subgroup;
2386 GtkWidget *ct_button;
2389 vbox = scrolled_notebook_page(notebook, _("Windows"));
2391 group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
2393 ct_button = pref_checkbox_new_int(group, _("Remember session"),
2394 options->save_window_positions, &c_options->save_window_positions);
2396 button = pref_checkbox_new_int(group, _("Use saved window positions also for new windows"),
2397 options->use_saved_window_positions_for_new_windows, &c_options->use_saved_window_positions_for_new_windows);
2398 pref_checkbox_link_sensitivity(ct_button, button);
2400 button = pref_checkbox_new_int(group, _("Remember window workspace"),
2401 options->save_window_workspace, &c_options->save_window_workspace);
2402 pref_checkbox_link_sensitivity(ct_button, button);
2404 pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
2405 options->tools_restore_state, &c_options->tools_restore_state);
2407 pref_checkbox_new_int(group, _("Remember dialog window positions"),
2408 options->save_dialog_window_positions, &c_options->save_dialog_window_positions);
2410 pref_checkbox_new_int(group, _("Show window IDs"),
2411 options->show_window_ids, &c_options->show_window_ids);
2413 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2414 pref_label_new(subgroup, _("Use current layout for default: "));
2415 button = pref_button_new(subgroup, NULL, _("Set"), FALSE, G_CALLBACK(save_default_window_layout_cb), NULL);
2417 #if GTK_CHECK_VERSION(3,22,0)
2420 popover = create_popover(button, gtk_label_new(_("Current window layout\nhas been set as default")), GTK_POS_TOP);
2421 gtk_popover_set_modal(GTK_POPOVER (popover), FALSE);
2422 g_signal_connect(button, "clicked", G_CALLBACK(default_layout_changed_cb), popover);
2425 group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
2427 pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
2428 options->image.fit_window_to_image, &c_options->image.fit_window_to_image);
2430 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2431 ct_button = pref_checkbox_new_int(hbox, _("Limit size when auto-sizing window (%):"),
2432 options->image.limit_window_size, &c_options->image.limit_window_size);
2433 spin = pref_spin_new_int(hbox, NULL, NULL,
2435 options->image.max_window_size, &c_options->image.max_window_size);
2436 pref_checkbox_link_sensitivity(ct_button, spin);
2438 group = pref_group_new(vbox, FALSE, _("Full screen"), GTK_ORIENTATION_VERTICAL);
2440 c_options->fullscreen.screen = options->fullscreen.screen;
2441 c_options->fullscreen.above = options->fullscreen.above;
2442 hbox = fullscreen_prefs_selection_new(_("Location:"), &c_options->fullscreen.screen, &c_options->fullscreen.above);
2443 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2444 gtk_widget_show(hbox);
2446 pref_checkbox_new_int(group, _("Smooth image flip"),
2447 options->fullscreen.clean_flip, &c_options->fullscreen.clean_flip);
2448 pref_checkbox_new_int(group, _("Disable screen saver"),
2449 options->fullscreen.disable_saver, &c_options->fullscreen.disable_saver);
2452 #define PRE_FORMATTED_COLUMNS 5
2453 static void config_tab_osd(GtkWidget *notebook)
2459 GtkWidget *image_overlay_template_view;
2460 GtkWidget *scrolled;
2461 GtkWidget *scrolled_pre_formatted;
2462 GtkTextBuffer *buffer;
2464 GtkWidget *subgroup;
2466 vbox = scrolled_notebook_page(notebook, _("OSD"));
2468 image_overlay_template_view = gtk_text_view_new();
2470 group = pref_group_new(vbox, FALSE, _("Overlay Screen Display"), GTK_ORIENTATION_VERTICAL);
2472 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2474 scrolled_pre_formatted = osd_new(PRE_FORMATTED_COLUMNS, image_overlay_template_view);
2475 gtk_widget_set_size_request(scrolled_pre_formatted, 200, 150);
2476 gtk_box_pack_start(GTK_BOX(subgroup), scrolled_pre_formatted, FALSE, FALSE, 0);
2477 gtk_widget_show(scrolled_pre_formatted);
2478 gtk_widget_show(subgroup);
2480 pref_line(group, PREF_PAD_GAP);
2482 pref_label_new(group, _("Image overlay template"));
2484 scrolled = gtk_scrolled_window_new(NULL, NULL);
2485 gtk_widget_set_size_request(scrolled, 200, 150);
2486 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2487 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
2488 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2489 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 5);
2490 gtk_widget_show(scrolled);
2492 gtk_widget_set_tooltip_markup(image_overlay_template_view,
2493 _("Extensive formatting options are shown in the Help file"));
2495 gtk_container_add(GTK_CONTAINER(scrolled), image_overlay_template_view);
2496 gtk_widget_show(image_overlay_template_view);
2498 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2500 #if GTK_CHECK_VERSION(3,4,0)
2501 button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
2502 G_CALLBACK(image_overlay_set_font_cb), notebook);
2504 button = gtk_font_button_new();
2505 gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Image Overlay Font");
2506 gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->image_overlay.font);
2507 g_signal_connect(G_OBJECT(button), "font-set",
2508 G_CALLBACK(image_overlay_set_font_cb),NULL);
2510 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2511 gtk_widget_show(button);
2513 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Text"), FALSE,
2514 G_CALLBACK(image_overlay_set_text_colour_cb), NULL);
2515 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2516 gtk_widget_show(button);
2518 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Background"), FALSE,
2519 G_CALLBACK(image_overlay_set_background_colour_cb), NULL);
2520 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2521 gtk_widget_show(button);
2522 image_overlay_set_text_colours();
2524 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2525 G_CALLBACK(image_overlay_default_template_cb), image_overlay_template_view);
2526 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2527 gtk_widget_show(button);
2529 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
2530 G_CALLBACK(image_overlay_help_cb), NULL);
2531 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2532 gtk_widget_show(button);
2534 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_overlay_template_view));
2535 if (options->image_overlay.template_string) gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
2536 g_signal_connect(G_OBJECT(buffer), "changed",
2537 G_CALLBACK(image_overlay_template_view_changed_cb), image_overlay_template_view);
2539 pref_line(group, PREF_PAD_GAP);
2541 group = pref_group_new(vbox, FALSE, _("Exif, XMP or IPTC tags"), GTK_ORIENTATION_VERTICAL);
2542 hbox = gtk_hbox_new(FALSE, 0);
2543 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2544 gtk_widget_show(hbox);
2545 label = gtk_label_new(_("%Exif.Image.Orientation%"));
2546 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2547 gtk_widget_show(label);
2548 pref_spacer(group,TRUE);
2550 group = pref_group_new(vbox, FALSE, _("Field separators"), GTK_ORIENTATION_VERTICAL);
2551 hbox = gtk_hbox_new(FALSE, 0);
2552 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2553 gtk_widget_show(hbox);
2554 label = gtk_label_new(_("Separator shown only if both fields are non-null:\n%formatted.ShutterSpeed%|%formatted.ISOSpeedRating%"));
2555 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2556 gtk_widget_show(label);
2557 pref_spacer(group,TRUE);
2559 group = pref_group_new(vbox, FALSE, _("Field maximum length"), GTK_ORIENTATION_VERTICAL);
2560 hbox = gtk_hbox_new(FALSE, 0);
2561 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2562 gtk_widget_show(hbox);
2563 label = gtk_label_new(_("%path:39%"));
2564 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2565 gtk_widget_show(label);
2566 pref_spacer(group,TRUE);
2568 group = pref_group_new(vbox, FALSE, _("Pre- and post- text"), GTK_ORIENTATION_VERTICAL);
2569 hbox = gtk_hbox_new(FALSE, 0);
2570 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2571 gtk_widget_show(hbox);
2572 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%"));
2573 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2574 gtk_widget_show(label);
2575 pref_spacer(group,TRUE);
2577 group = pref_group_new(vbox, FALSE, _("Pango markup"), GTK_ORIENTATION_VERTICAL);
2578 hbox = gtk_hbox_new(FALSE, 0);
2579 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2580 gtk_widget_show(hbox);
2581 label = gtk_label_new(_("<b>bold</b>\n<u>underline</u>\n<i>italic</i>\n<s>strikethrough</s>"));
2582 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2583 gtk_widget_show(label);
2586 static GtkTreeModel *create_class_model(void)
2588 GtkListStore *model;
2592 /* create list store */
2593 model = gtk_list_store_new(1, G_TYPE_STRING);
2594 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
2596 gtk_list_store_append(model, &iter);
2597 gtk_list_store_set(model, &iter, 0, _(format_class_list[i]), -1);
2599 return GTK_TREE_MODEL (model);
2604 static void config_tab_files(GtkWidget *notebook)
2611 GtkWidget *ct_button;
2612 GtkWidget *scrolled;
2613 GtkWidget *filter_view;
2614 GtkCellRenderer *renderer;
2615 GtkTreeSelection *selection;
2616 GtkTreeViewColumn *column;
2618 vbox = scrolled_notebook_page(notebook, _("Files"));
2620 group = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2622 pref_checkbox_new_int(group, _("Show hidden files or folders"),
2623 options->file_filter.show_hidden_files, &c_options->file_filter.show_hidden_files);
2624 pref_checkbox_new_int(group, _("Show parent folder (..)"),
2625 options->file_filter.show_parent_directory, &c_options->file_filter.show_parent_directory);
2626 pref_checkbox_new_int(group, _("Case sensitive sort"),
2627 options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
2628 pref_checkbox_new_int(group, _("Natural sort order"),
2629 options->file_sort.natural, &c_options->file_sort.natural);
2630 pref_checkbox_new_int(group, _("Disable file extension checks"),
2631 options->file_filter.disable_file_extension_checks, &c_options->file_filter.disable_file_extension_checks);
2633 ct_button = pref_checkbox_new_int(group, _("Disable File Filtering"),
2634 options->file_filter.disable, &c_options->file_filter.disable);
2637 group = pref_group_new(vbox, FALSE, _("Grouping sidecar extensions"), GTK_ORIENTATION_VERTICAL);
2639 sidecar_ext_entry = gtk_entry_new();
2640 gtk_entry_set_text(GTK_ENTRY(sidecar_ext_entry), options->sidecar.ext);
2641 gtk_box_pack_start(GTK_BOX(group), sidecar_ext_entry, FALSE, FALSE, 0);
2642 gtk_widget_show(sidecar_ext_entry);
2644 group = pref_group_new(vbox, TRUE, _("File types"), GTK_ORIENTATION_VERTICAL);
2646 frame = pref_group_parent(group);
2647 g_signal_connect(G_OBJECT(ct_button), "toggled",
2648 G_CALLBACK(filter_disable_cb), frame);
2649 gtk_widget_set_sensitive(frame, !options->file_filter.disable);
2651 scrolled = gtk_scrolled_window_new(NULL, NULL);
2652 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2653 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2654 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2655 gtk_widget_show(scrolled);
2657 filter_store = gtk_list_store_new(1, G_TYPE_POINTER);
2658 filter_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(filter_store));
2659 g_object_unref(filter_store);
2660 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
2661 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
2663 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), FALSE);
2665 column = gtk_tree_view_column_new();
2666 gtk_tree_view_column_set_title(column, _("Filter"));
2667 gtk_tree_view_column_set_resizable(column, TRUE);
2669 renderer = gtk_cell_renderer_toggle_new();
2670 g_signal_connect(G_OBJECT(renderer), "toggled",
2671 G_CALLBACK(filter_store_enable_cb), filter_store);
2672 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2673 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2674 GINT_TO_POINTER(FE_ENABLE), NULL);
2676 renderer = gtk_cell_renderer_text_new();
2677 g_signal_connect(G_OBJECT(renderer), "edited",
2678 G_CALLBACK(filter_store_ext_edit_cb), filter_store);
2679 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2680 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2681 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2682 GINT_TO_POINTER(FE_EXTENSION), NULL);
2683 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2685 column = gtk_tree_view_column_new();
2686 gtk_tree_view_column_set_title(column, _("Description"));
2687 gtk_tree_view_column_set_resizable(column, TRUE);
2688 gtk_tree_view_column_set_fixed_width(column, 200);
2689 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
2691 renderer = gtk_cell_renderer_text_new();
2692 g_signal_connect(G_OBJECT(renderer), "edited",
2693 G_CALLBACK(filter_store_desc_edit_cb), filter_store);
2694 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2695 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2696 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2697 GINT_TO_POINTER(FE_DESCRIPTION), NULL);
2698 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2700 column = gtk_tree_view_column_new();
2701 gtk_tree_view_column_set_title(column, _("Class"));
2702 gtk_tree_view_column_set_resizable(column, TRUE);
2703 renderer = gtk_cell_renderer_combo_new();
2704 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE,
2705 "model", create_class_model(),
2710 g_signal_connect(G_OBJECT(renderer), "edited",
2711 G_CALLBACK(filter_store_class_edit_cb), filter_store);
2712 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2713 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2714 GINT_TO_POINTER(FE_CLASS), NULL);
2715 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2717 column = gtk_tree_view_column_new();
2718 gtk_tree_view_column_set_title(column, _("Writable"));
2719 gtk_tree_view_column_set_resizable(column, FALSE);
2720 renderer = gtk_cell_renderer_toggle_new();
2721 g_signal_connect(G_OBJECT(renderer), "toggled",
2722 G_CALLBACK(filter_store_writable_cb), filter_store);
2723 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2724 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2725 GINT_TO_POINTER(FE_WRITABLE), NULL);
2726 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2728 column = gtk_tree_view_column_new();
2729 gtk_tree_view_column_set_title(column, _("Sidecar is allowed"));
2730 gtk_tree_view_column_set_resizable(column, FALSE);
2731 renderer = gtk_cell_renderer_toggle_new();
2732 g_signal_connect(G_OBJECT(renderer), "toggled",
2733 G_CALLBACK(filter_store_sidecar_cb), filter_store);
2734 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2735 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2736 GINT_TO_POINTER(FE_ALLOW_SIDECAR), NULL);
2737 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2740 filter_store_populate();
2741 gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
2742 gtk_widget_show(filter_view);
2744 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2746 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2747 G_CALLBACK(filter_default_cb), filter_view);
2748 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2749 gtk_widget_show(button);
2751 button = pref_button_new(NULL, GTK_STOCK_REMOVE, NULL, FALSE,
2752 G_CALLBACK(filter_remove_cb), filter_view);
2753 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2754 gtk_widget_show(button);
2756 button = pref_button_new(NULL, GTK_STOCK_ADD, NULL, FALSE,
2757 G_CALLBACK(filter_add_cb), filter_view);
2758 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2759 gtk_widget_show(button);
2763 static void config_tab_metadata(GtkWidget *notebook)
2768 GtkWidget *ct_button;
2772 vbox = scrolled_notebook_page(notebook, _("Metadata"));
2775 group = pref_group_new(vbox, FALSE, _("Metadata writing process"), GTK_ORIENTATION_VERTICAL);
2777 label = pref_label_new(group, _("Warning: Geeqie is built without Exiv2. Some options are disabled."));
2779 label = pref_label_new(group, _("Metadata are written in the following order. The process ends after first success."));
2780 #if GTK_CHECK_VERSION(3,16,0)
2781 gtk_label_set_xalign(GTK_LABEL(label), 0.0);
2782 gtk_label_set_yalign(GTK_LABEL(label), 0.5);
2784 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2787 ct_button = pref_checkbox_new_int(group, _("1) Save metadata in image files, or sidecar files, according to the XMP standard"),
2788 options->metadata.save_in_image_file, &c_options->metadata.save_in_image_file);
2790 gtk_widget_set_sensitive(ct_button, FALSE);
2793 pref_checkbox_new_int(group, _("2) Save metadata in '.metadata' folder, local to image folder (non-standard)"),
2794 options->metadata.enable_metadata_dirs, &c_options->metadata.enable_metadata_dirs);
2796 text = g_strdup_printf(_("3) Save metadata in Geeqie private directory '%s'"), get_metadata_cache_dir());
2797 label = pref_label_new(group, text);
2798 #if GTK_CHECK_VERSION(3,16,0)
2799 gtk_label_set_xalign(GTK_LABEL(label), 0.0);
2800 gtk_label_set_yalign(GTK_LABEL(label), 0.5);
2802 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2804 gtk_misc_set_padding(GTK_MISC(label), 22, 0);
2807 group = pref_group_new(vbox, FALSE, _("Step 1: Write to image files"), GTK_ORIENTATION_VERTICAL);
2809 gtk_widget_set_sensitive(group, FALSE);
2812 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2813 pref_checkbox_link_sensitivity(ct_button, hbox);
2815 pref_checkbox_new_int(hbox, _("Store metadata also in legacy IPTC tags (converted according to IPTC4XMP standard)"),
2816 options->metadata.save_legacy_IPTC, &c_options->metadata.save_legacy_IPTC);
2818 pref_checkbox_new_int(hbox, _("Warn if the image files are unwritable"),
2819 options->metadata.warn_on_write_problems, &c_options->metadata.warn_on_write_problems);
2821 pref_checkbox_new_int(hbox, _("Ask before writing to image files"),
2822 options->metadata.confirm_write, &c_options->metadata.confirm_write);
2824 pref_checkbox_new_int(hbox, _("Create sidecar files named image.ext.xmp (as opposed to image.xmp)"),
2825 options->metadata.sidecar_extended_name, &c_options->metadata.sidecar_extended_name);
2827 group = pref_group_new(vbox, FALSE, _("Step 2 and 3: write to Geeqie private files"), GTK_ORIENTATION_VERTICAL);
2829 gtk_widget_set_sensitive(group, FALSE);
2832 pref_checkbox_new_int(group, _("Use GQview legacy metadata format (supports only keywords and comments) instead of XMP"),
2833 options->metadata.save_legacy_format, &c_options->metadata.save_legacy_format);
2836 group = pref_group_new(vbox, FALSE, _("Miscellaneous"), GTK_ORIENTATION_VERTICAL);
2837 pref_checkbox_new_int(group, _("Write the same description tags (keywords, comment, etc.) to all grouped sidecars"),
2838 options->metadata.sync_grouped_files, &c_options->metadata.sync_grouped_files);
2840 pref_checkbox_new_int(group, _("Allow keywords to differ only in case"),
2841 options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
2843 ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"),
2844 options->metadata.write_orientation, &c_options->metadata.write_orientation);
2846 gtk_widget_set_sensitive(ct_button, FALSE);
2849 group = pref_group_new(vbox, FALSE, _("Auto-save options"), GTK_ORIENTATION_VERTICAL);
2851 ct_button = pref_checkbox_new_int(group, _("Write metadata after timeout"),
2852 options->metadata.confirm_after_timeout, &c_options->metadata.confirm_after_timeout);
2854 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2855 pref_checkbox_link_sensitivity(ct_button, hbox);
2857 pref_spin_new_int(hbox, _("Timeout (seconds):"), NULL, 0, 900, 1,
2858 options->metadata.confirm_timeout, &c_options->metadata.confirm_timeout);
2860 pref_checkbox_new_int(group, _("Write metadata on image change"),
2861 options->metadata.confirm_on_image_change, &c_options->metadata.confirm_on_image_change);
2863 pref_checkbox_new_int(group, _("Write metadata on directory change"),
2864 options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
2866 group = pref_group_new(vbox, FALSE, _("Pre-load metadata"), GTK_ORIENTATION_VERTICAL);
2868 ct_button = pref_checkbox_new_int(group, _("Read metadata in background"),
2869 options->read_metadata_in_idle, &c_options->read_metadata_in_idle);
2870 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");
2875 typedef struct _KeywordFindData KeywordFindData;
2876 struct _KeywordFindData
2883 GtkWidget *button_close;
2884 GtkWidget *button_stop;
2885 GtkWidget *button_start;
2886 GtkWidget *progress;
2894 guint idle_id; /* event source id */
2897 #define KEYWORD_DIALOG_WIDTH 400
2899 static void keywords_find_folder(KeywordFindData *kfd, FileData *dir_fd)
2901 GList *list_d = NULL;
2902 GList *list_f = NULL;
2906 filelist_read(dir_fd, &list_f, &list_d);
2910 filelist_read(dir_fd, &list_f, NULL);
2913 list_f = filelist_filter(list_f, FALSE);
2914 list_d = filelist_filter(list_d, TRUE);
2916 kfd->list = g_list_concat(list_f, kfd->list);
2917 kfd->list_dir = g_list_concat(list_d, kfd->list_dir);
2920 static void keywords_find_reset(KeywordFindData *kfd)
2922 filelist_free(kfd->list);
2925 filelist_free(kfd->list_dir);
2926 kfd->list_dir = NULL;
2929 static void keywords_find_close_cb(GenericDialog *fd, gpointer data)
2931 KeywordFindData *kfd = data;
2933 if (!gtk_widget_get_sensitive(kfd->button_close)) return;
2935 keywords_find_reset(kfd);
2936 generic_dialog_close(kfd->gd);
2940 static void keywords_find_finish(KeywordFindData *kfd)
2942 keywords_find_reset(kfd);
2944 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("done"));
2945 spinner_set_interval(kfd->spinner, -1);
2947 gtk_widget_set_sensitive(kfd->group, TRUE);
2948 gtk_widget_set_sensitive(kfd->button_start, TRUE);
2949 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2950 gtk_widget_set_sensitive(kfd->button_close, TRUE);
2953 static void keywords_find_stop_cb(GenericDialog *fd, gpointer data)
2955 KeywordFindData *kfd = data;
2957 g_idle_remove_by_data(kfd);
2959 keywords_find_finish(kfd);
2962 static gboolean keywords_find_file(gpointer data)
2964 KeywordFindData *kfd = data;
2966 GtkTextBuffer *buffer;
2974 fd = kfd->list->data;
2975 kfd->list = g_list_remove(kfd->list, fd);
2977 keywords = metadata_read_list(fd, KEYWORD_KEY, METADATA_PLAIN);
2978 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2982 gtk_text_buffer_get_end_iter(buffer, &iter);
2983 tmp = g_strconcat(keywords->data, "\n", NULL);
2984 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
2986 keywords = keywords->next;
2989 gtk_entry_set_text(GTK_ENTRY(kfd->progress), fd->path);
2990 file_data_unref(fd);
2991 string_list_free(keywords);
2995 else if (kfd->list_dir)
2999 fd = kfd->list_dir->data;
3000 kfd->list_dir = g_list_remove(kfd->list_dir, fd);
3002 keywords_find_folder(kfd, fd);
3004 file_data_unref(fd);
3009 keywords_find_finish(kfd);
3014 static void keywords_find_start_cb(GenericDialog *fd, gpointer data)
3016 KeywordFindData *kfd = data;
3019 if (kfd->list || !gtk_widget_get_sensitive(kfd->button_start)) return;
3021 path = remove_trailing_slash((gtk_entry_get_text(GTK_ENTRY(kfd->entry))));
3022 parse_out_relatives(path);
3026 warning_dialog(_("Invalid folder"),
3027 _("The specified folder can not be found."),
3028 GTK_STOCK_DIALOG_WARNING, kfd->gd->dialog);
3034 gtk_widget_set_sensitive(kfd->group, FALSE);
3035 gtk_widget_set_sensitive(kfd->button_start, FALSE);
3036 gtk_widget_set_sensitive(kfd->button_stop, TRUE);
3037 gtk_widget_set_sensitive(kfd->button_close, FALSE);
3038 spinner_set_interval(kfd->spinner, SPINNER_SPEED);
3040 dir_fd = file_data_new_dir(path);
3041 keywords_find_folder(kfd, dir_fd);
3042 file_data_unref(dir_fd);
3043 kfd->idle_id = g_idle_add(keywords_find_file, kfd);
3049 static void keywords_find_dialog(GtkWidget *widget, const gchar *path)
3051 KeywordFindData *kfd;
3055 kfd = g_new0(KeywordFindData, 1);
3057 kfd->gd = generic_dialog_new(_("Search for keywords"),
3058 "search_for_keywords",
3061 gtk_window_set_default_size(GTK_WINDOW(kfd->gd->dialog), KEYWORD_DIALOG_WIDTH, -1);
3062 kfd->gd->cancel_cb = keywords_find_close_cb;
3063 kfd->button_close = generic_dialog_add_button(kfd->gd, GTK_STOCK_CLOSE, NULL,
3064 keywords_find_close_cb, FALSE);
3065 kfd->button_start = generic_dialog_add_button(kfd->gd, GTK_STOCK_OK, _("S_tart"),
3066 keywords_find_start_cb, FALSE);
3067 kfd->button_stop = generic_dialog_add_button(kfd->gd, GTK_STOCK_STOP, NULL,
3068 keywords_find_stop_cb, FALSE);
3069 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
3071 generic_dialog_add_message(kfd->gd, NULL, _("Search for keywords"), NULL, FALSE);
3073 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0);
3074 pref_spacer(hbox, PREF_PAD_INDENT);
3075 kfd->group = pref_box_new(hbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
3077 hbox = pref_box_new(kfd->group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3078 pref_label_new(hbox, _("Folder:"));
3080 label = tab_completion_new(&kfd->entry, path, NULL, NULL, NULL, NULL);
3081 tab_completion_add_select_button(kfd->entry,_("Select folder") , TRUE);
3082 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
3083 gtk_widget_show(label);
3085 pref_checkbox_new_int(kfd->group, _("Include subfolders"), FALSE, &kfd->recurse);
3087 pref_line(kfd->gd->vbox, PREF_PAD_SPACE);
3088 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3090 kfd->progress = gtk_entry_new();
3091 gtk_widget_set_can_focus(kfd->progress, FALSE);
3092 gtk_editable_set_editable(GTK_EDITABLE(kfd->progress), FALSE);
3093 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("click start to begin"));
3094 gtk_box_pack_start(GTK_BOX(hbox), kfd->progress, TRUE, TRUE, 0);
3095 gtk_widget_show(kfd->progress);
3097 kfd->spinner = spinner_new(NULL, -1);
3098 gtk_box_pack_start(GTK_BOX(hbox), kfd->spinner, FALSE, FALSE, 0);
3099 gtk_widget_show(kfd->spinner);
3103 gtk_widget_show(kfd->gd->dialog);
3106 static void keywords_find_cb(GtkWidget *widget, gpointer data)
3108 const gchar *path = layout_get_path(NULL);
3110 if (!path || !*path) path = homedir();
3111 keywords_find_dialog(widget, path);
3114 static void config_tab_keywords_save()
3116 GtkTextIter start, end;
3117 GtkTextBuffer *buffer;
3118 GList *kw_list = NULL;
3124 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3125 gtk_text_buffer_get_bounds(buffer, &start, &end);
3127 buffer_text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
3129 kw_split = strtok(buffer_text, "\n");
3130 while (kw_split != NULL)
3136 if (g_strcmp0(work->data, kw_split) == 0)
3145 kw_list = g_list_append(kw_list, g_strdup(kw_split));
3147 kw_split = strtok(NULL, "\n");
3150 keyword_list_set(kw_list);
3152 string_list_free(kw_list);
3153 g_free(buffer_text);
3156 static void config_tab_keywords(GtkWidget *notebook)
3162 GtkWidget *scrolled;
3164 GtkTextBuffer *buffer;
3167 vbox = scrolled_notebook_page(notebook, _("Keywords"));
3169 group = pref_group_new(vbox, TRUE, _("Edit keywords autocompletion list"), GTK_ORIENTATION_VERTICAL);
3171 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3173 button = pref_button_new(hbox, GTK_STOCK_EXECUTE, _("Search"), FALSE,
3174 G_CALLBACK(keywords_find_cb), keyword_text);
3175 gtk_widget_set_tooltip_text(button, "Search for existing keywords");
3178 keyword_text = gtk_text_view_new();
3179 gtk_widget_set_size_request(keyword_text, 20, 20);
3180 scrolled = gtk_scrolled_window_new(NULL, NULL);
3181 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3182 gtk_widget_show(scrolled);
3184 gtk_container_add(GTK_CONTAINER(scrolled), keyword_text);
3185 gtk_widget_show(keyword_text);
3187 gtk_text_view_set_editable(GTK_TEXT_VIEW(keyword_text), TRUE);
3189 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3190 gtk_text_buffer_create_tag(buffer, "monospace",
3191 "family", "monospace", NULL);
3193 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(keyword_text), GTK_WRAP_WORD);
3194 gtk_text_buffer_get_start_iter(buffer, &iter);
3195 gtk_text_buffer_create_mark(buffer, "end", &iter, FALSE);
3198 path = g_build_filename(get_rc_dir(), "keywords", NULL);
3200 GList *kwl = keyword_list_get();
3201 kwl = g_list_first(kwl);
3204 gtk_text_buffer_get_end_iter (buffer, &iter);
3205 tmp = g_strconcat(kwl->data, "\n", NULL);
3206 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
3211 gtk_text_buffer_set_modified(buffer, FALSE);
3218 static void intent_menu_cb(GtkWidget *combo, gpointer data)
3220 gint *option = data;
3222 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
3226 *option = INTENT_PERCEPTUAL;
3229 *option = INTENT_RELATIVE_COLORIMETRIC;
3232 *option = INTENT_SATURATION;
3235 *option = INTENT_ABSOLUTE_COLORIMETRIC;
3240 static void add_intent_menu(GtkWidget *table, gint column, gint row, const gchar *text,
3241 gint option, gint *option_c)
3248 pref_table_label(table, column, row, text, 0.0);
3250 combo = gtk_combo_box_text_new();
3252 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Perceptual"));
3253 if (option == INTENT_PERCEPTUAL) current = 0;
3254 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Relative Colorimetric"));
3255 if (option == INTENT_RELATIVE_COLORIMETRIC) current = 1;
3256 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Saturation"));
3257 if (option == INTENT_SATURATION) current = 2;
3258 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Absolute Colorimetric"));
3259 if (option == INTENT_ABSOLUTE_COLORIMETRIC) current = 3;
3261 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
3263 gtk_widget_set_tooltip_text(combo,"Refer to the lcms documentation for the defaults used when the selected Intent is not available");
3265 g_signal_connect(G_OBJECT(combo), "changed",
3266 G_CALLBACK(intent_menu_cb), option_c);
3268 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
3269 gtk_widget_show(combo);
3273 static void config_tab_color(GtkWidget *notebook)
3282 vbox = scrolled_notebook_page(notebook, _("Color management"));
3284 group = pref_group_new(vbox, FALSE, _("Input profiles"), GTK_ORIENTATION_VERTICAL);
3286 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3289 table = pref_table_new(group, 3, COLOR_PROFILE_INPUTS + 1, FALSE, FALSE);
3290 gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
3292 label = pref_table_label(table, 0, 0, _("Type"), 0.0);
3293 pref_label_bold(label, TRUE, FALSE);
3295 label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
3296 pref_label_bold(label, TRUE, FALSE);
3298 label = pref_table_label(table, 2, 0, _("File"), 0.0);
3299 pref_label_bold(label, TRUE, FALSE);
3301 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
3306 buf = g_strdup_printf(_("Input %d:"), i + COLOR_PROFILE_FILE);
3307 pref_table_label(table, 0, i + 1, buf, 1.0);
3310 entry = gtk_entry_new();
3311 gtk_entry_set_max_length(GTK_ENTRY(entry), EDITOR_NAME_MAX_LENGTH);
3312 if (options->color_profile.input_name[i])
3314 gtk_entry_set_text(GTK_ENTRY(entry), options->color_profile.input_name[i]);
3316 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, i + 1, i + 2,
3317 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3318 gtk_widget_show(entry);
3319 color_profile_input_name_entry[i] = entry;
3321 tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, ".icc", "ICC Files", NULL);
3322 tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
3323 gtk_widget_set_size_request(entry, 160, -1);
3324 gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
3325 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3326 gtk_widget_show(tabcomp);
3327 color_profile_input_file_entry[i] = entry;
3330 group = pref_group_new(vbox, FALSE, _("Screen profile"), GTK_ORIENTATION_VERTICAL);
3332 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3334 pref_checkbox_new_int(group, _("Use system screen profile if available"),
3335 options->color_profile.use_x11_screen_profile, &c_options->color_profile.use_x11_screen_profile);
3337 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3339 pref_table_label(table, 0, 0, _("Screen:"), 1.0);
3340 tabcomp = tab_completion_new(&color_profile_screen_file_entry,
3341 options->color_profile.screen_file, NULL, ".icc", "ICC Files", NULL);
3342 tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
3343 gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
3345 add_intent_menu(table, 0, 1, _("Render Intent:"), options->color_profile.render_intent, &c_options->color_profile.render_intent);
3347 gtk_table_attach(GTK_TABLE(table), tabcomp, 1, 2,
3349 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3351 gtk_widget_show(tabcomp);
3354 /* advanced entry tab */
3355 static void use_geeqie_trash_cb(GtkWidget *widget, gpointer data)
3357 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3359 c_options->file_ops.use_system_trash = FALSE;
3360 c_options->file_ops.no_trash = FALSE;
3364 static void use_system_trash_cb(GtkWidget *widget, gpointer data)
3366 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3368 c_options->file_ops.use_system_trash = TRUE;
3369 c_options->file_ops.no_trash = FALSE;
3373 static void use_no_cache_cb(GtkWidget *widget, gpointer data)
3375 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3377 c_options->file_ops.no_trash = TRUE;
3381 static void config_tab_behavior(GtkWidget *notebook)
3388 GtkWidget *ct_button;
3392 GtkWidget *with_rename;
3393 GtkWidget *collections_on_top;
3394 GtkWidget *hide_window_in_fullscreen;
3395 GtkWidget *checkbox;
3398 vbox = scrolled_notebook_page(notebook, _("Behavior"));
3400 group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
3402 pref_checkbox_new_int(group, _("Confirm permanent file delete"),
3403 options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
3404 pref_checkbox_new_int(group, _("Confirm move file to Trash"),
3405 options->file_ops.confirm_move_to_trash, &c_options->file_ops.confirm_move_to_trash);
3406 pref_checkbox_new_int(group, _("Enable Delete key"),
3407 options->file_ops.enable_delete_key, &c_options->file_ops.enable_delete_key);
3409 ct_button = pref_radiobutton_new(group, NULL, _("Use Geeqie trash location"),
3410 !options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_geeqie_trash_cb),NULL);
3412 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3413 pref_checkbox_link_sensitivity(ct_button, hbox);
3415 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
3416 pref_label_new(hbox, _("Folder:"));
3418 tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL, NULL, NULL);
3419 tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
3420 gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
3421 gtk_widget_show(tabcomp);
3423 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3424 pref_checkbox_link_sensitivity(ct_button, hbox);
3426 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
3427 spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MiB"),
3428 0, 2048, 1, options->file_ops.safe_delete_folder_maxsize, &c_options->file_ops.safe_delete_folder_maxsize);
3429 gtk_widget_set_tooltip_markup(spin, _("Set to 0 for unlimited size"));
3430 button = pref_button_new(NULL, NULL, _("View"), FALSE,
3431 G_CALLBACK(safe_delete_view_cb), NULL);
3432 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3433 gtk_widget_show(button);
3435 button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
3436 G_CALLBACK(safe_delete_clear_cb), NULL);
3437 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3438 pref_radiobutton_new(group, ct_button, _("Use system Trash bin"),
3439 options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_system_trash_cb), NULL);
3441 pref_radiobutton_new(group, ct_button, _("Use no trash at all"),
3442 options->file_ops.no_trash, G_CALLBACK(use_no_cache_cb), NULL);
3444 gtk_widget_show(button);
3446 pref_spacer(group, PREF_PAD_GROUP);
3449 group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
3451 pref_checkbox_new_int(group, _("Descend folders in tree view"),
3452 options->tree_descend_subdirs, &c_options->tree_descend_subdirs);
3454 pref_checkbox_new_int(group, _("In place renaming"),
3455 options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
3457 pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
3458 options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
3460 tmp = pref_checkbox_new_int(group, _("Circular selection lists"),
3461 options->circular_selection_lists, &c_options->circular_selection_lists);
3462 gtk_widget_set_tooltip_text(tmp, _("Traverse selection lists in a circular manner"));
3464 marks = pref_checkbox_new_int(group, _("Save marks on exit"),
3465 options->marks_save, &c_options->marks_save);
3466 gtk_widget_set_tooltip_text(marks,"Note that marks linked to a keyword will be saved irrespective of this setting");
3468 with_rename = pref_checkbox_new_int(group, _("Use \"With Rename\" as default for Copy/Move dialogs"),
3469 options->with_rename, &c_options->with_rename);
3470 gtk_widget_set_tooltip_text(with_rename,"Change the default button for Copy/Move dialogs");
3472 collections_on_top = pref_checkbox_new_int(group, _("Open collections on top"),
3473 options->collections_on_top, &c_options->collections_on_top);
3474 gtk_widget_set_tooltip_text(collections_on_top,"Open collections window on top");
3476 hide_window_in_fullscreen = pref_checkbox_new_int(group, _("Hide window in fullscreen"),
3477 options->hide_window_in_fullscreen, &c_options->hide_window_in_fullscreen);
3478 gtk_widget_set_tooltip_text(hide_window_in_fullscreen,"When alt-tabbing, prevent Geeqie window showing twice");
3480 pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
3481 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
3483 pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
3484 16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
3486 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3487 add_dnd_default_action_selection_menu(table, 0, 0, _("Drag`n drop default action:"), options->dnd_default_action, &c_options->dnd_default_action);
3489 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3490 add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
3492 pref_spacer(group, PREF_PAD_GROUP);
3494 group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
3496 pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
3497 options->progressive_key_scrolling, &c_options->progressive_key_scrolling);
3498 pref_spin_new_int(group, _("Keyboard scrolling step multiplier:"), NULL,
3499 1, 32, 1, options->keyboard_scroll_step, (int *)&c_options->keyboard_scroll_step);
3500 pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
3501 options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
3502 pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
3503 options->image_lm_click_nav, &c_options->image_lm_click_nav);
3504 pref_checkbox_new_int(group, _("Play video by left click on image"),
3505 options->image_l_click_video, &c_options->image_l_click_video);
3506 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3507 add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
3509 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3510 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3511 add_mouse_selection_menu(table, 0, 0, _("Mouse button Back:"), options->mouse_button_8, &c_options->mouse_button_8);
3512 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3513 add_mouse_selection_menu(table, 0, 0, _("Mouse button Forward:"), options->mouse_button_9, &c_options->mouse_button_9);
3515 pref_spacer(group, PREF_PAD_GROUP);
3517 group = pref_group_new(vbox, FALSE, _("GPU"), GTK_ORIENTATION_VERTICAL);
3519 checkbox = pref_checkbox_new_int(group, _("Override disable GPU"),
3520 options->override_disable_gpu, &c_options->override_disable_gpu);
3521 gtk_widget_set_tooltip_text(checkbox, "Contact the developers for usage");
3524 pref_spacer(group, PREF_PAD_GROUP);
3526 group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
3528 pref_spin_new_int(group, _("Debug level:"), NULL,
3529 DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
3531 pref_checkbox_new_int(group, _("Timer data"),
3532 options->log_window.timer_data, &c_options->log_window.timer_data);
3534 pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
3535 1, 99999, 1, options->log_window_lines, &options->log_window_lines);
3539 /* accelerators tab */
3540 static void config_tab_accelerators(GtkWidget *notebook)
3546 GtkWidget *scrolled;
3547 GtkWidget *accel_view;
3548 GtkCellRenderer *renderer;
3549 GtkTreeSelection *selection;
3550 GtkTreeViewColumn *column;
3552 vbox = scrolled_notebook_page(notebook, _("Keyboard"));
3554 group = pref_group_new(vbox, TRUE, _("Accelerators"), GTK_ORIENTATION_VERTICAL);
3556 scrolled = gtk_scrolled_window_new(NULL, NULL);
3557 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
3558 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
3559 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3560 gtk_widget_show(scrolled);
3562 accel_store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
3564 accel_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(accel_store));
3565 g_object_unref(accel_store);
3566 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(accel_view));
3567 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
3569 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(accel_view), FALSE);
3571 renderer = gtk_cell_renderer_text_new();
3573 column = gtk_tree_view_column_new_with_attributes(_("Action"),
3578 gtk_tree_view_column_set_sort_column_id(column, AE_ACTION);
3579 gtk_tree_view_column_set_resizable(column, TRUE);
3580 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3583 renderer = gtk_cell_renderer_accel_new();
3584 g_signal_connect(G_OBJECT(renderer), "accel-cleared",
3585 G_CALLBACK(accel_store_cleared_cb), accel_store);
3586 g_signal_connect(G_OBJECT(renderer), "accel-edited",
3587 G_CALLBACK(accel_store_edited_cb), accel_store);
3590 g_object_set (renderer,
3592 "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
3595 column = gtk_tree_view_column_new_with_attributes(_("KEY"),
3600 gtk_tree_view_column_set_sort_column_id(column, AE_KEY);
3601 gtk_tree_view_column_set_resizable(column, TRUE);
3602 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3604 renderer = gtk_cell_renderer_text_new();
3606 column = gtk_tree_view_column_new_with_attributes(_("Tooltip"),
3611 gtk_tree_view_column_set_sort_column_id(column, AE_TOOLTIP);
3612 gtk_tree_view_column_set_resizable(column, TRUE);
3613 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3615 renderer = gtk_cell_renderer_text_new();
3617 column = gtk_tree_view_column_new_with_attributes("Accel",
3622 gtk_tree_view_column_set_sort_column_id(column, AE_ACCEL);
3623 gtk_tree_view_column_set_resizable(column, TRUE);
3624 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3626 accel_store_populate();
3627 gtk_container_add(GTK_CONTAINER(scrolled), accel_view);
3628 gtk_widget_show(accel_view);
3630 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3632 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
3633 G_CALLBACK(accel_default_cb), accel_view);
3634 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3635 gtk_widget_show(button);
3637 button = pref_button_new(NULL, NULL, _("Reset selected"), FALSE,
3638 G_CALLBACK(accel_reset_cb), accel_view);
3639 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3640 gtk_widget_show(button);
3643 /* toolbar main tab */
3644 static void config_tab_toolbar_main(GtkWidget *notebook)
3647 GtkWidget *toolbardata;
3650 lw = layout_window_list->data;
3652 vbox = scrolled_notebook_page(notebook, _("Toolbar Main"));
3654 toolbardata = toolbar_select_new(lw, TOOLBAR_MAIN);
3655 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3656 gtk_widget_show(vbox);
3659 /* toolbar status tab */
3660 static void config_tab_toolbar_status(GtkWidget *notebook)
3663 GtkWidget *toolbardata;
3666 lw = layout_window_list->data;
3668 vbox = scrolled_notebook_page(notebook, _("Toolbar Status"));
3670 toolbardata = toolbar_select_new(lw, TOOLBAR_STATUS);
3671 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3672 gtk_widget_show(vbox);
3676 static gint extension_sort_cb(gconstpointer a, gconstpointer b)
3678 return g_strcmp0((gchar *)a, (gchar *)b);
3681 static void config_tab_advanced(GtkWidget *notebook)
3685 GSList *formats_list;
3686 GList *extensions_list = NULL;
3689 GdkPixbufFormat *fm;
3691 GString *types_string = g_string_new(NULL);
3692 GtkWidget *types_string_label;
3693 GtkWidget *threads_string_label;
3694 GtkWidget *dupes_threads_spin;
3696 vbox = scrolled_notebook_page(notebook, _("Advanced"));
3697 group = pref_group_new(vbox, FALSE, _("External preview extraction"), GTK_ORIENTATION_VERTICAL);
3699 pref_checkbox_new_int(group, _("Use external preview extraction - Requires restart"), options->external_preview.enable, &c_options->external_preview.enable);
3701 pref_spacer(group, PREF_PAD_GROUP);
3703 formats_list = gdk_pixbuf_get_formats();
3705 while (formats_list)
3707 fm = formats_list->data;
3708 extensions = gdk_pixbuf_format_get_extensions(fm);
3711 while (extensions[i])
3713 extensions_list = g_list_insert_sorted(extensions_list, g_strdup(extensions[i]), extension_sort_cb);
3717 g_strfreev(extensions);
3718 formats_list = formats_list->next;
3721 while (extensions_list)
3723 if (types_string->len == 0)
3725 types_string = g_string_append(types_string, extensions_list->data);
3729 types_string = g_string_append(types_string, ", ");
3730 types_string = g_string_append(types_string, extensions_list->data);
3733 extensions_list = extensions_list->next;
3736 types_string = g_string_prepend(types_string, _("Usable file types:\n"));
3737 types_string_label = pref_label_new(group, types_string->str);
3738 gtk_label_set_line_wrap(GTK_LABEL(types_string_label), TRUE);
3740 pref_spacer(group, PREF_PAD_GROUP);
3742 group = pref_group_new(vbox, FALSE, _("File identification tool"), GTK_ORIENTATION_VERTICAL);
3743 external_preview_select_entry = gtk_entry_new();
3744 tabcomp = tab_completion_new(&external_preview_select_entry, options->external_preview.select, NULL, NULL, NULL, NULL);
3745 tab_completion_add_select_button(external_preview_select_entry, _("Select file identification tool"), FALSE);
3746 gtk_box_pack_start(GTK_BOX(group), tabcomp, TRUE, TRUE, 0);
3747 gtk_widget_show(tabcomp);
3749 group = pref_group_new(vbox, FALSE, _("Preview extraction tool"), GTK_ORIENTATION_VERTICAL);
3750 external_preview_extract_entry = gtk_entry_new();
3751 tabcomp = tab_completion_new(&external_preview_extract_entry, options->external_preview.extract, NULL, NULL, NULL, NULL);
3752 tab_completion_add_select_button(external_preview_extract_entry, _("Select preview extraction tool"), FALSE);
3753 gtk_box_pack_start(GTK_BOX(group), tabcomp, TRUE, TRUE, 0);
3754 gtk_widget_show(tabcomp);
3756 gtk_widget_show(vbox);
3758 g_slist_free(formats_list);
3759 string_list_free(extensions_list);
3760 g_string_free(types_string, TRUE);
3762 pref_spacer(group, PREF_PAD_GROUP);
3764 pref_line(vbox, PREF_PAD_SPACE);
3765 group = pref_group_new(vbox, FALSE, _("Thread pool limits"), GTK_ORIENTATION_VERTICAL);
3767 threads_string_label = pref_label_new(group, "This option limits the number of threads (or cpu cores)\nthat Geeqie will use when running duplicate checks. The default value is 0, which means all available cores will be used.");
3768 gtk_label_set_line_wrap(GTK_LABEL(threads_string_label), TRUE);
3770 pref_spacer(vbox, PREF_PAD_GROUP);
3772 dupes_threads_spin = pref_spin_new_int(vbox, _("Duplicate check:"), _("max. threads"), 0, get_cpu_cores(), 1, options->threads.duplicates, &c_options->threads.duplicates);
3773 gtk_widget_set_tooltip_markup(dupes_threads_spin, _("Set to 0 for unlimited"));
3777 static void config_tab_stereo(GtkWidget *notebook)
3785 GtkWidget *fs_button;
3786 vbox = scrolled_notebook_page(notebook, _("Stereo"));
3788 group = pref_group_new(vbox, FALSE, _("Windowed stereo mode"), GTK_ORIENTATION_VERTICAL);
3790 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3791 add_stereo_mode_menu(table, 0, 0, _("Windowed stereo mode"), options->stereo.mode, &c_options->stereo.mode, FALSE);
3793 table = pref_table_new(group, 2, 2, TRUE, FALSE);
3794 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3795 pref_checkbox_new_int(box, _("Mirror left image"),
3796 options->stereo.mode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.mirror_left);
3797 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3798 pref_checkbox_new_int(box, _("Flip left image"),
3799 options->stereo.mode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.flip_left);
3800 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3801 pref_checkbox_new_int(box, _("Mirror right image"),
3802 options->stereo.mode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.mirror_right);
3803 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3804 pref_checkbox_new_int(box, _("Flip right image"),
3805 options->stereo.mode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.flip_right);
3806 pref_checkbox_new_int(group, _("Swap left and right images"),
3807 options->stereo.mode & PR_STEREO_SWAP, &c_options->stereo.tmp.swap);
3808 pref_checkbox_new_int(group, _("Disable stereo mode on single image source"),
3809 options->stereo.mode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.temp_disable);
3811 group = pref_group_new(vbox, FALSE, _("Fullscreen stereo mode"), GTK_ORIENTATION_VERTICAL);
3812 fs_button = pref_checkbox_new_int(group, _("Use different settings for fullscreen"),
3813 options->stereo.enable_fsmode, &c_options->stereo.enable_fsmode);
3814 box2 = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
3815 pref_checkbox_link_sensitivity(fs_button, box2);
3816 table = pref_table_new(box2, 2, 1, FALSE, FALSE);
3817 add_stereo_mode_menu(table, 0, 0, _("Fullscreen stereo mode"), options->stereo.fsmode, &c_options->stereo.fsmode, TRUE);
3818 table = pref_table_new(box2, 2, 2, TRUE, FALSE);
3819 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3820 pref_checkbox_new_int(box, _("Mirror left image"),
3821 options->stereo.fsmode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.fs_mirror_left);
3822 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3823 pref_checkbox_new_int(box, _("Flip left image"),
3824 options->stereo.fsmode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.fs_flip_left);
3825 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3826 pref_checkbox_new_int(box, _("Mirror right image"),
3827 options->stereo.fsmode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.fs_mirror_right);
3828 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3829 pref_checkbox_new_int(box, _("Flip right image"),
3830 options->stereo.fsmode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.fs_flip_right);
3831 pref_checkbox_new_int(box2, _("Swap left and right images"),
3832 options->stereo.fsmode & PR_STEREO_SWAP, &c_options->stereo.tmp.fs_swap);
3833 pref_checkbox_new_int(box2, _("Disable stereo mode on single image source"),
3834 options->stereo.fsmode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.fs_temp_disable);
3836 group2 = pref_group_new(box2, FALSE, _("Fixed position"), GTK_ORIENTATION_VERTICAL);
3837 table = pref_table_new(group2, 5, 3, FALSE, FALSE);
3838 pref_table_spin_new_int(table, 0, 0, _("Width"), NULL,
3839 1, 5000, 1, options->stereo.fixed_w, &c_options->stereo.fixed_w);
3840 pref_table_spin_new_int(table, 3, 0, _("Height"), NULL,
3841 1, 5000, 1, options->stereo.fixed_h, &c_options->stereo.fixed_h);
3842 pref_table_spin_new_int(table, 0, 1, _("Left X"), NULL,
3843 0, 5000, 1, options->stereo.fixed_x1, &c_options->stereo.fixed_x1);
3844 pref_table_spin_new_int(table, 3, 1, _("Left Y"), NULL,
3845 0, 5000, 1, options->stereo.fixed_y1, &c_options->stereo.fixed_y1);
3846 pref_table_spin_new_int(table, 0, 2, _("Right X"), NULL,
3847 0, 5000, 1, options->stereo.fixed_x2, &c_options->stereo.fixed_x2);
3848 pref_table_spin_new_int(table, 3, 2, _("Right Y"), NULL,
3849 0, 5000, 1, options->stereo.fixed_y2, &c_options->stereo.fixed_y2);
3853 /* Main preferences window */
3854 static void config_window_create(LayoutWindow *lw)
3856 GtkWidget *win_vbox;
3858 GtkWidget *notebook;
3860 GtkWidget *ct_button;
3862 if (!c_options) c_options = init_options(NULL);
3864 configwindow = window_new(GTK_WINDOW_TOPLEVEL, "preferences", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Preferences"));
3865 DEBUG_NAME(configwindow);
3866 gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
3867 g_signal_connect(G_OBJECT(configwindow), "delete_event",
3868 G_CALLBACK(config_window_delete), NULL);
3869 if (options->save_dialog_window_positions)
3871 gtk_window_resize(GTK_WINDOW(configwindow), lw->options.preferences_window.w, lw->options.preferences_window.h);
3872 gtk_window_move(GTK_WINDOW(configwindow), lw->options.preferences_window.x, lw->options.preferences_window.y);
3876 gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
3878 gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
3879 gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
3881 win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
3882 gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
3883 gtk_widget_show(win_vbox);
3885 notebook = gtk_notebook_new();
3886 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_LEFT);
3887 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE);
3888 gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
3890 config_tab_general(notebook);
3891 config_tab_image(notebook);
3892 config_tab_osd(notebook);
3893 config_tab_windows(notebook);
3894 config_tab_accelerators(notebook);
3895 config_tab_files(notebook);
3896 config_tab_metadata(notebook);
3897 config_tab_keywords(notebook);
3898 config_tab_color(notebook);
3899 config_tab_stereo(notebook);
3900 config_tab_behavior(notebook);
3901 config_tab_toolbar_main(notebook);
3902 config_tab_toolbar_status(notebook);
3903 config_tab_advanced(notebook);
3905 gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), lw->options.preferences_window.page_number);
3907 hbox = gtk_hbutton_box_new();
3908 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
3909 gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
3910 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
3911 gtk_widget_show(hbox);
3913 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
3914 G_CALLBACK(config_window_help_cb), notebook);
3915 gtk_container_add(GTK_CONTAINER(hbox), button);
3916 gtk_widget_set_can_default(button, TRUE);
3917 gtk_widget_show(button);
3919 button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
3920 G_CALLBACK(config_window_ok_cb), notebook);
3921 gtk_container_add(GTK_CONTAINER(hbox), button);
3922 gtk_widget_set_can_default(button, TRUE);
3923 gtk_widget_grab_default(button);
3924 gtk_widget_show(button);
3928 button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
3929 G_CALLBACK(config_window_close_cb), NULL);
3930 gtk_container_add(GTK_CONTAINER(hbox), button);
3931 gtk_widget_set_can_default(button, TRUE);
3932 gtk_widget_show(button);
3934 if (!generic_dialog_get_alternative_button_order(configwindow))
3936 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
3939 gtk_widget_show(notebook);
3941 gtk_widget_show(configwindow);
3945 *-----------------------------------------------------------------------------
3946 * config window show (public)
3947 *-----------------------------------------------------------------------------
3950 void show_config_window(LayoutWindow *lw)
3954 gtk_window_present(GTK_WINDOW(configwindow));
3958 config_window_create(lw);
3967 void show_about_window(LayoutWindow *lw)
3969 GdkPixbuf *pixbuf_logo;
3970 GdkPixbuf *pixbuf_icon;
3971 gchar *authors[1000];
3976 gchar *timezone_path;
3980 #define LINE_LENGTH 1000
3981 gchar line[LINE_LENGTH];
3983 copyright = g_string_new(NULL);
3984 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");
3986 path = path_from_utf8(TIMEZONE_DATABASE);
3987 basename = g_path_get_basename(path);
3988 timezone_path = g_build_filename(get_rc_dir(), basename, NULL);
3989 if (g_file_test(timezone_path, G_FILE_TEST_EXISTS))
3991 cd = ZDOpenDatabase(timezone_path);
3994 copyright = g_string_append(copyright, ZDGetNotice(cd));
3995 ZDCloseDatabase(cd);
3999 g_free(timezone_path);
4003 path = g_build_filename(gq_helpdir, "AUTHORS", NULL);
4004 fp = fopen(path, "r");
4007 while(fgets(line, LINE_LENGTH, fp))
4009 /* get rid of ending \n from fgets */
4010 line[strlen(line) - 1] = '\0';
4011 authors[i_authors] = g_strdup(line);
4014 authors[i_authors] = NULL;
4019 comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
4020 "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
4022 pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
4023 pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
4024 gtk_show_about_dialog(GTK_WINDOW(lw->window),
4025 "title", _("About Geeqie"),
4027 "program-name", GQ_APPNAME,
4029 "logo", pixbuf_logo,
4030 "icon", pixbuf_icon,
4031 "website", GQ_WEBSITE,
4032 "website-label", "Website",
4033 "comments", comment,
4035 "translator-credits", _("translator-credits"),
4036 "wrap-license", TRUE,
4037 "license", copyright->str,
4040 g_string_free(copyright, TRUE);
4043 while(n < i_authors)
4053 static void image_overlay_set_text_colours()
4055 c_options->image_overlay.text_red = options->image_overlay.text_red;
4056 c_options->image_overlay.text_green = options->image_overlay.text_green;
4057 c_options->image_overlay.text_blue = options->image_overlay.text_blue;
4058 c_options->image_overlay.text_alpha = options->image_overlay.text_alpha;
4059 c_options->image_overlay.background_red = options->image_overlay.background_red;
4060 c_options->image_overlay.background_green = options->image_overlay.background_green;
4061 c_options->image_overlay.background_blue = options->image_overlay.background_blue;
4062 c_options->image_overlay.background_alpha = options->image_overlay.background_alpha;
4066 *-----------------------------------------------------------------------------
4067 * timezone database routines
4068 *-----------------------------------------------------------------------------
4071 static void timezone_async_ready_cb(GObject *source_object, GAsyncResult *res, gpointer data)
4073 GError *error = NULL;
4075 gchar *tmp_filename;
4077 if (!g_cancellable_is_cancelled(tz->cancellable))
4079 generic_dialog_close(tz->gd);
4083 if (g_file_copy_finish(G_FILE(source_object), res, &error))
4085 tmp_filename = g_file_get_parse_name(tz->tmp_g_file);
4086 move_file(tmp_filename, tz->timezone_database_user);
4087 g_free(tmp_filename);
4091 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
4094 g_file_delete(tz->tmp_g_file, NULL, &error);
4095 g_object_unref(tz->tmp_g_file);
4096 tz->tmp_g_file = NULL;
4097 g_object_unref(tz->cancellable);
4098 g_object_unref(tz->timezone_database_gq);
4101 static void timezone_progress_cb(goffset current_num_bytes, goffset total_num_bytes, gpointer data)
4105 if (!g_cancellable_is_cancelled(tz->cancellable))
4107 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(tz->progress), (gdouble)current_num_bytes / total_num_bytes);
4111 static void timezone_cancel_button_cb(GenericDialog *gd, gpointer data)
4115 g_cancellable_cancel(tz->cancellable);
4118 static void timezone_database_install_cb(GtkWidget *widget, gpointer data)
4121 GError *error = NULL;
4122 GFileIOStream *io_stream;
4129 tz->tmp_g_file = g_file_new_tmp("geeqie_timezone_XXXXXX", &io_stream, &error);
4133 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
4134 log_printf("Error: Download timezone database failed:\n%s", error->message);
4135 g_error_free(error);
4136 g_object_unref(tz->tmp_g_file);
4140 tz->timezone_database_gq = g_file_new_for_uri(TIMEZONE_DATABASE);
4142 tz->gd = generic_dialog_new(_("Timezone database"), "download_timezone_database", NULL, TRUE, timezone_cancel_button_cb, tz);
4144 generic_dialog_add_message(tz->gd, GTK_STOCK_DIALOG_INFO, _("Downloading timezone database"), NULL, FALSE);
4146 tz->progress = gtk_progress_bar_new();
4147 gtk_box_pack_start(GTK_BOX(tz->gd->vbox), tz->progress, FALSE, FALSE, 0);
4148 gtk_widget_show(tz->progress);
4150 gtk_widget_show(tz->gd->dialog);
4151 tz->cancellable = g_cancellable_new();
4152 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);
4154 gtk_button_set_label(GTK_BUTTON(widget), _("Update"));
4157 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */